using DS.Module.Core; using DS.Module.Core.Enums; using DS.Module.Core.Extensions; using DS.WMS.Core.Application.Dtos; using DS.WMS.Core.Application.Entity; using DS.WMS.Core.Fee.Entity; using DS.WMS.Core.Invoice.Interface; using DS.WMS.Core.Sys.Entity; using SqlSugar; namespace DS.WMS.Core.Invoice.Method { /// /// 标准(按申请)开票实现 /// public class GeneralInvoiceService : InvoiceService, IGeneralInvoiceService { /// /// 初始化 /// /// public GeneralInvoiceService(IServiceProvider provider) : base(provider) { } /// /// 获取发票申请分页列表 /// /// /// public async Task>> GetApplicationListAsync(PageRequest request) { var query = TenantDb.Queryable() .Where(a => (a.Status == InvoiceApplicationStatus.AuditPassed || a.Status == InvoiceApplicationStatus.PartialInvoiced) && SqlFunc.Subqueryable().Where(d => d.ApplicationId == a.Id && d.Category == DetailCategory.InvoiceApplication && (d.OriginalAmount - d.OriginalProcessedAmount) != 0).Any()) .Select(a => new InvoiceApplicationDto { AmountRMB = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId && y.Currency == FeeCurrency.RMB_CODE).Sum(y => y.ApplyAmount), AmountUSD = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId && y.Currency == FeeCurrency.USD_CODE).Sum(y => y.ApplyAmount), AmountOther = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId && y.Currency != FeeCurrency.RMB_CODE && y.Currency != FeeCurrency.USD_CODE).Sum(y => y.ApplyAmount), //原币金额 OriginalAmountList = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId) .GroupBy(y => y.OriginalCurrency).ToList(y => new CurrencyAmount { Currency = y.OriginalCurrency, Amount = SqlFunc.AggregateSum(y.OriginalAmount) }) }, true); var whereList = request.GetConditionalModels(Db); var result = await query.Where(whereList).ToQueryPageAsync(request.PageCondition); if (result.Data?.Count > 0) { var userIds = result.Data.Select(x => x.CreateBy).Distinct(); var users = await Db.Queryable().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync(); var orgIds = result.Data.Where(x => x.SaleDeptId.HasValue).Select(x => x.SaleDeptId) .Union(result.Data.Where(x => x.OrgId.HasValue).Select(x => x.OrgId)) .Distinct(); var orgs = await Db.Queryable().Where(x => orgIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToListAsync(); var ids = result.Data.Where(x => string.IsNullOrEmpty(x.Currency)).Select(x => x.Id); var appList = await TenantDb.Queryable().Where( x => ids.Contains(x.ApplicationId)).Select(x => new { x.ApplicationId, x.Currency }).ToListAsync(); foreach (var item in result.Data) { item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName; item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName; item.OrgName = orgs.Find(x => x.Id == item.OrgId)?.OrgName; if (string.IsNullOrEmpty(item.Currency)) { var list = appList.FindAll(x => x.ApplicationId == item.Id); item.Currency = string.Join(" ", list.Select(x => x.Currency).Distinct()); } } } return result; } /// /// 获取发票申请明细 /// /// 申请单ID /// public async Task>> GetApplicationDetailsAsync(params long[] ids) { var query = CreateApplicationDetailQuery((d, f, s) => ids.Contains(d.ApplicationId) && d.Category == DetailCategory.InvoiceApplication && (d.OriginalAmount - d.OriginalProcessedAmount) != 0); var details = await TenantDb.Queryable(query).LeftJoin((x, y) => x.ApplicationId == y.Id) .Select((x, y) => new InvoiceApplicationDetailDto { Id = x.Id, ApplicationId = x.ApplicationId, BusinessId = x.BusinessId, BusinessType = x.BusinessType, RecordId = x.RecordId, FeeName = x.FeeName, FeeType = x.FeeType, ApplyAmount = x.ApplyAmount, RestAmount = x.ApplyAmount - x.ProcessedAmount, OriginalCurrency = x.OriginalCurrency, //原始币别 ExchangeRate = x.ExchangeRate, //折算汇率 OriginalAmount = x.OriginalAmount, //原始金额 CustomerNo = x.CustomerNo, MBLNO = x.MBLNO, HBLNO = x.HBLNO, SaleName = x.SaleName, ClientName = x.ClientName, ETD = x.ETD, SourceName = x.SourceName, AuditTime = y.AuditTime }).ToListAsync(); return DataResult>.Success(details); } protected override Task PreSaveAsync(Entity.Invoice invoice) { invoice.Mode = InvoiceMode.Applcation; return Task.FromResult(DataResult.Success); } protected override async Task OnSaveAsync(Entity.Invoice invoice) { var list = invoice.Details?.Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail { Id = x.DetailId.GetValueOrDefault(), ProcessedAmount = x.ApplyAmount, OriginalProcessedAmount = x.OriginalAmount }).ToList(); if (list != null && list.Count > 0) { //增加发票申请明细的已处理金额 await TenantDb.Updateable(list) .PublicSetColumns(x => x.ProcessedAmount, "+").PublicSetColumns(x => x.OriginalProcessedAmount, "+") .UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount }) .ExecuteCommandAsync(); } } protected override Task PostSaveAsync(Entity.Invoice invoice) { return RefreshApplicationStatus([invoice], null); } protected override async Task OnDeleteDetailAsync(List invoices, DeleteOption deleteOption) { var list = invoices.SelectMany(x => x.Details).Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail { Id = x.DetailId.GetValueOrDefault(), ProcessedAmount = x.ApplyAmount, OriginalProcessedAmount = x.OriginalAmount }).ToList(); //恢复发票申请费用明细的已处理金额 await TenantDb.Updateable(list) .PublicSetColumns(x => x.ProcessedAmount, "-").PublicSetColumns(x => x.OriginalProcessedAmount, "-") .UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount }) .ExecuteCommandAsync(); //还原发票申请状态 var ids = list.Where(x => x.DetailId.HasValue).Select(x => x.DetailId).Distinct(); var details = TenantDb.Queryable().Where(x => ids.Contains(x.Id)) .Select(x => new ApplicationDetail { Id = x.Id, ApplicationId = x.ApplicationId, ProcessedAmount = x.ProcessedAmount, OriginalAmount = x.OriginalAmount, OriginalProcessedAmount = x.OriginalProcessedAmount }).ToList(); var gpList = details.GroupBy(x => x.ApplicationId); List applications = []; foreach (var gp in gpList) { var processedCount = gp.Count(x => x.OriginalAmount - x.OriginalProcessedAmount == 0); var itemCount = gp.Count(); if (itemCount == processedCount) continue; var entity = new InvoiceApplication { Id = gp.Key }; if (processedCount == 0) { entity.Status = InvoiceApplicationStatus.AuditPassed; } else if (itemCount > processedCount) { entity.Status = InvoiceApplicationStatus.PartialInvoiced; } applications.Add(entity); } if (applications.Count > 0) await TenantDb.Updateable(applications).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync(); await base.OnDeleteDetailAsync(invoices, deleteOption); } protected override Task PostDeleteAsync(List invoices, DeleteOption deleteOption) { ////获取关联的发票申请的ID //var ids = invoices.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct(); //if (deleteOption == DeleteOption.Entire) //{ // return TenantDb.Updateable() // .SetColumns(x => x.Status == InvoiceApplicationStatus.AuditPassed) // .Where(x => ids.Contains(x.Id)) // .ExecuteCommandAsync(); //} //else if (deleteOption == DeleteOption.DetailOnly) //{ // //获取关联的发票申请的明细ID // var ids2 = invoices.SelectMany(x => x.Details).Where(x => x.DetailId.HasValue).Select(x => x.DetailId.GetValueOrDefault()).Distinct(); //} //return Task.CompletedTask; return RefreshApplicationStatus(invoices, deleteOption); } //更新发票申请的状态 private async Task RefreshApplicationStatus(List invoices, DeleteOption? deleteOption) { if (invoices == null || !invoices.Any()) return; //获取关联的发票申请的ID var ids = invoices.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct().ToList(); var appDetails = await TenantDb.Queryable().Where(d => ids.Contains(d.ApplicationId)) .Select(d => new ApplicationDetail { Id = d.Id, Category = d.Category, ApplicationId = d.ApplicationId, OriginalAmount = d.OriginalAmount, OriginalProcessedAmount = d.OriginalProcessedAmount }).ToListAsync(); List list2 = new(ids.Count); foreach (var id in ids) { var entity = new InvoiceApplication { Id = id }; var details = appDetails.FindAll(x => x.ApplicationId == id); if (details.All(x => x.OriginalAmount == x.OriginalAmount - x.OriginalProcessedAmount)) { entity.Status = deleteOption.HasValue ? InvoiceApplicationStatus.AuditPassed : InvoiceApplicationStatus.Invoiced; list2.Add(entity); } else if (details.All(x => x.OriginalAmount - x.OriginalProcessedAmount == 0)) { entity.Status = deleteOption == null ? InvoiceApplicationStatus.Invoiced : InvoiceApplicationStatus.AuditPassed; list2.Add(entity); } else if (details.Exists(x => x.OriginalAmount != x.OriginalAmount - x.OriginalProcessedAmount)) { entity.Status = InvoiceApplicationStatus.PartialInvoiced; list2.Add(entity); } } await TenantDb.Updateable(list2).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync(); } } }