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.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.OriginalAmount - d.OriginalProcessedAmount) != 0).Any()) .Select(a => new InvoiceApplicationDto { Id = a.Id, ApplicationNO = a.ApplicationNO, Status = a.Status, CustomerId = a.CustomerId, CustomerName = a.CustomerName, //结算单位 InvoiceHeader = a.InvoiceHeader, ApplyAmount = a.ApplyAmount, InvoiceAmount = a.InvoiceAmount, Currency = a.Currency, Category = a.Category, OrgId = a.OrgId, //所属部门 SaleDeptId = a.SaleDeptId, //所属分部 CreateBy = a.CreateBy, //申请人 CreateTime = a.CreateTime, //申请日期 InvoiceRemark = a.InvoiceRemark, //开票要求 Note = a.Note, //原币金额 OriginalAmountList = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId) .GroupBy(y => y.OriginalCurrency).ToList(y => new CurrencyAmount { Currency = y.OriginalCurrency, Amount = y.OriginalAmount }) }); 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(); 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; } } 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, //原始金额 SaleName = x.SaleName, CustomerNo = x.CustomerNo, MBLNO = x.MBLNO, 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 Task.Factory.StartNew(UpdateInvoiceApplications, new List { invoice }); } 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(); await base.OnDeleteDetailAsync(invoices, deleteOption); } protected override Task PostDeleteAsync(List invoices, DeleteOption deleteOption) { return Task.Factory.StartNew(UpdateInvoiceApplications, invoices); } //更新发票申请的状态 void UpdateInvoiceApplications(object? state) { var list = state as IEnumerable; if (list == null || !list.Any()) return; var ids = list.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct().ToList(); var appDetails = TenantDb.Queryable().Where(d => ids.Contains(d.ApplicationId)) .Select(d => new ApplicationDetail { Id = d.Id, ApplicationId = d.ApplicationId, OriginalAmount = d.OriginalAmount, OriginalProcessedAmount = d.OriginalProcessedAmount }).ToList(); List list2 = new(ids.Count); foreach (var id in ids) { var entity = new InvoiceApplication { Id = id }; var inv = list.FirstOrDefault(x => x.Details.Any(y => y.RefId == id)); entity.AcutalInvoiceNO = inv?.InvoiceNO; var details = appDetails.FindAll(x => x.ApplicationId == id); if (details.All(x => x.OriginalAmount == x.OriginalAmount - x.OriginalProcessedAmount)) { entity.Status = InvoiceApplicationStatus.Invoiced; list2.Add(entity); } else if (details.All(x => x.OriginalAmount - x.OriginalProcessedAmount == 0)) { entity.Status = InvoiceApplicationStatus.AuditPassed; list2.Add(entity); } else if (details.Exists(x => x.OriginalAmount != x.OriginalAmount - x.OriginalProcessedAmount)) { entity.Status = InvoiceApplicationStatus.PartialInvoiced; list2.Add(entity); } } TenantDb.Updateable(list2).UpdateColumns(x => new { x.Status, x.AcutalInvoiceNO }).ExecuteCommand(); } } }