using System.Text; 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.Op.Entity; using DS.WMS.Core.Settlement.Dtos; using DS.WMS.Core.Settlement.Entity; using DS.WMS.Core.Settlement.Interface; using DS.WMS.Core.Sys.Entity; using Masuit.Tools.Systems; namespace DS.WMS.Core.Settlement.Method { /// /// 发票结算 /// public class InvoiceSettlementService : SettlementService, IInvoiceSettlementService { /// /// 初始化 /// /// public InvoiceSettlementService(IServiceProvider provider) : base(provider) { } /// /// 获取待结算的发票申请列表 /// /// /// public async Task>> GetInvoiceListAsync(PageRequest request) { var whereList = request.GetConditionalModels(Db); var result = await TenantDb.Queryable() .InnerJoin((a, d) => d.Category == DetailCategory.InvoiceApplication && a.Id == d.ApplicationId && d.OriginalAmount - d.OriginalSettlementAmount != 0) .InnerJoin((a, d, f) => (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && d.RecordId == f.Id && ((f.Amount > 0 && d.OriginalAmount - d.OriginalSettlementAmount <= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) || (f.Amount < 0 && d.OriginalAmount - d.OriginalSettlementAmount >= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)) ) .GroupBy((a, d, f) => a.Id) .Select((a, d, f) => new InvoiceApplicationDto { }, true).MergeTable().Where(a => a.Status == InvoiceApplicationStatus.AuditPassed || a.Status == InvoiceApplicationStatus.PartialInvoiced).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.Select(x => x.SaleDeptId).Distinct().ToList(); 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; } } return result; } /// /// 获取发票申请费用明细 /// /// /// public async Task>> GetInvoiceDetailsAsync(params long[] ids) { var query1 = TenantDb.Queryable() .InnerJoin((d, f) => d.Category == DetailCategory.InvoiceApplication && d.RecordId == f.Id && (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && f.BusinessType == BusinessType.OceanShippingExport && ((f.Amount > 0 && d.OriginalAmount - d.OriginalSettlementAmount <= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) || (f.Amount < 0 && d.OriginalAmount - d.OriginalSettlementAmount >= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)) ) .LeftJoin((d, f, s) => f.BusinessId == s.Id) .Where((d, f, s) => ids.Contains(d.ApplicationId)) .Select((d, f, s) => new ApplicationDetailDto { ClientName = s.CustomerName, Voyage = s.Voyno, SourceName = s.SourceName, }, true); var list = await TenantDb.UnionAll(query1).ToListAsync(); var result = DataResult>.Success(list); result.Count = list.Count; return result; } protected override async Task> GetSettlementDetails(long id) { var list = await TenantDb.Queryable() .InnerJoin((d, pd) => d.DetailId == pd.Id) .InnerJoin((d, pd, pa) => pd.ApplicationId == pa.Id) .Where(d => d.ApplicationId == id) .Select((d, pd, pa) => new { d.Id, d.ApplicationId, d.ApplyAmount, d.Currency, d.OriginalCurrency, d.OriginalAmount, pa.ApplicationNO, pa.Status, pa.CreateTime, pa.CreateBy, pa.Note }).ToListAsync(); var details = new List(); if (list.Count == 0) return details; var gp = list.GroupBy(d => d.ApplicationId); var uids = list.Select(x => x.CreateBy).Distinct(); var users = await Db.Queryable().Where(x => uids.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync(); foreach (var g in gp) { var firstItem = g.FirstOrDefault(); var dto = new SettlementDetailDto { ApplicationId = g.Key, //Ids = g.Select(x => x.Id), RMBApplyAmount = g.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount), USDApplyAmount = g.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount), ApplicationNO = firstItem.ApplicationNO, Status = (int)firstItem.Status, StatusText = firstItem.Status.GetDescription(), CreateTime = firstItem?.CreateTime, CreateBy = firstItem?.CreateBy, CreateByName = users.Find(x => x.Id == firstItem?.CreateBy)?.UserName, PaymentDate = firstItem?.CreateTime, Note = firstItem?.Note }; //包含多个币别 if (g.GroupBy(x => x.OriginalCurrency).Select(x => x.Key).Count() > 1) { //原始币别=不等于结算单币别的首个币别(参考DS7) dto.OriginalCurrency = g.Select(x => x.OriginalCurrency).FirstOrDefault(); //原始金额=当前结算单的币别合计 dto.OriginalAmount = g.Sum(x => x.ApplyAmount); } else { dto.OriginalCurrency = firstItem?.OriginalCurrency; dto.OriginalAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount); } //结算金额=原申请的原始币别合计 dto.SettlementAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount); details.Add(dto); } return details; } protected override async Task PreSaveAsync(PaymentSettlement settlement) { //settlement.Mode = SettlementMode.InvoiceSettlement; var appIds = settlement.Details.Select(x => x.ApplicationId).Distinct(); var appList = await TenantDb.Queryable().Where(x => appIds.Contains(x.Id)) .Select(x => new { x.Id, x.Status, x.CustomerId, x.CustomerName, }).ToListAsync(); if (appList.Count == 0) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData)); if (appList.Exists(x => x.Status != InvoiceApplicationStatus.AuditPassed)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSelectStatusError)); if (appList.GroupBy(x => x.CustomerId).Select(x => x.Key).Count() > 1) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DetailCustomerOnlyOne)); //获取剩余待结算金额 var ids2 = settlement.Details.Select(x => x.DetailId); var appDetails = await TenantDb.Queryable().Where(x => ids2.Contains(x.Id) && x.Category == DetailCategory.InvoiceApplication) .Select(x => new { x.Id, OriginalRestAmount = x.OriginalAmount - x.OriginalSettlementAmount }).ToListAsync(); StringBuilder sb = new(); foreach (var detail in settlement.Details) { var item = appDetails.Find(x => x.Id == detail.DetailId); if (item == null) { sb.Append(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.EmptyData))); break; } if (detail.OriginalAmount > 0 && detail.OriginalAmount > item.OriginalRestAmount) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName); sb.Append(";"); continue; } else if (detail.OriginalAmount < 0 && detail.OriginalAmount < item.OriginalRestAmount) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName); sb.Append(";"); continue; } detail.Category = DetailCategory.InvoiceSettlement; } return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success; } } }