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.Code.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 SqlSugar; namespace DS.WMS.Core.Settlement.Method { /// /// 付费自由结算 /// public class PaymentFreeSettlementService : SettlementService, IPaymentFreeSettlementService { /// /// 初始化 /// /// public PaymentFreeSettlementService(IServiceProvider provider) : base(provider) { } /// /// 获取待结算业务分页列表 /// /// /// /// 查询条件请参考中定义的字段 public async Task>> GetBizListAsync(PageRequest request) { var whereList = request.GetConditionalModels(Db); var result = await CreateBizQuery().Where(whereList).GroupBy(x => new { x.BusinessId, x.BusinessType }) .Select().ToQueryPageAsync(request.PageCondition); if (result.Data.Count > 0) { //获取统计信息 var ids = result.Data.Select(x => x.BusinessId); var types = result.Data.Select(x => x.BusinessType).Distinct(); var fees = await TenantDb.Queryable().Where(x => ids.Contains(x.BusinessId) && types.Contains(x.BusinessType)) .Select(x => new { x.BusinessId, x.BusinessType, x.Currency, x.FeeType, //x.Amount, //x.OrderAmount, //x.SettlementAmount, //x.OrderSettlementAmount, x.InvoiceAmount, UnSettledAmount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount //剩余待结算 }).ToListAsync(); //关联用户名称 var userIds = result.Data.Select(x => x.CreateBy) .Union(result.Data.Select(x => x.OperatorId)) .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(); 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.UnpaidRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount); item.UnpaidUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount); item.UnpaidOther = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettledAmount); item.UnchargedRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount); item.UnchargedUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount); item.UnchargedOther = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettledAmount); item.UnpaidInvoiceRMB = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.RMB_CODE && x.FeeType == FeeType.Payable && x.UnSettledAmount == 0).Sum(x => x.InvoiceAmount); item.UnpaidInvoiceUSD = fees.FindAll(x => x.BusinessId == item.BusinessId && x.BusinessType == item.BusinessType && x.Currency == FeeCurrency.USD_CODE && x.FeeType == FeeType.Payable && x.UnSettledAmount == 0).Sum(x => x.InvoiceAmount); item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName; item.Operator = users.Find(x => x.Id == item.OperatorId)?.UserName; item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName; } } return result; } //创建各项费用数据的查询并集 internal ISugarQueryable CreateBizQuery() { var query1 = TenantDb.Queryable((f, s) => new JoinQueryInfos( JoinType.Inner, s.Id == f.BusinessId && f.BusinessType == BusinessType.OceanShippingExport && f.FeeStatus == FeeStatus.AuditPassed && (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0)) .Select((f, s) => new FeeDto { Id = f.Id, FeeId = f.FeeId, FeeCode = f.FeeCode, FeeName = f.FeeName, FeeType = f.FeeType, CustomerId = f.CustomerId, CustomerName = f.CustomerName, BusinessId = f.BusinessId, BusinessType = BusinessType.OceanShippingExport, Currency = f.Currency, DebitNo = f.DebitNo, SaleOrgId = f.SaleOrgId, SaleOrg = f.SaleOrg, CreateBy = f.CreateBy, AccountDate = s.AccountDate, BusinessDate = s.CreateTime,//业务日期 ClientName = s.CustomerName,//委托单位 CustomerNo = s.CustomerNo, CustomNo = s.CustomNo, DischargePort = s.DischargePort, ETD = s.ETD, HBLNO = s.HBLNO, LoadPort = s.LoadPort, MBLNO = s.MBLNO, OperatorId = s.OperatorId, SaleDeptId = s.SaleDeptId, Sale = s.Sale,//揽货人 Vessel = s.Vessel,//船名 Voyage = s.Voyno,//航次 BookingNo = s.BookingNo, Enterprise = s.Enterprise, }); //海运进口 return TenantDb.UnionAll(new List> { query1 }); } /// /// 根据业务编号及类型获取关联费用记录 /// /// 业务ID与业务类型 /// public async Task> GetFeesAsync(params FeeClient[] items) { var bizIds = items.Select(x => x.Id).Distinct(); var types = items.Select(x => x.BusinessType).Distinct(); var cIds = items.Select(x => x.CustomerId).Distinct(); var list = await TenantDb.Queryable() .Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && cIds.Contains(f.CustomerId) && f.FeeStatus == FeeStatus.AuditPassed && (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0) .Select(f => new FeeItem { RecordId = f.Id, BusinessId = f.BusinessId, BusinessType = f.BusinessType, CustomerId = f.CustomerId, CustomerName = f.CustomerName, FeeId = f.FeeId, FeeName = f.FeeName, FeeType = f.FeeType, TotalAmount = f.Amount, Currency = f.Currency, OriginalRate = f.ExchangeRate, RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, InvoiceAmount = f.InvoiceAmount, AccTaxRate = f.AccTaxRate, Remark = f.Remark }).ToListAsync(); foreach (var item in list) { //本次结算金额默认等于剩余金额 item.Amount = item.RestAmount; item.OriginalAmount = item.RestAmount; } return DataResult.Success(new FeeForm(list)); } /// /// 获取付费自由结算单 /// /// 结算单ID /// public async Task> GetAsync(long id) { var model = await TenantDb.Queryable().Select(x => new PaymentSettlementDto { Id = x.Id, ApplicationNO = x.ApplicationNO, //申请编号 SettlementNO = x.SettlementNO, //结算单号 CustomerId = x.CustomerId, //结算单位 CustomerName = x.CustomerName, Mode = x.Mode, //结算类型 SettlementDate = x.SettlementDate, //结算日期 SettlementTypeId = x.SettlementTypeId, //结算方式 CustomerBankId = x.CustomerBankId, //客户银行 Account = x.Account, //客户账户 Currency = x.Currency, //币别 Amount = x.Amount, //金额 ExchangeRate = x.ExchangeRate, //汇率 IsLocked = x.IsLocked, //锁定状态 SaleDeptId = x.SaleDeptId, //所属分部 BillType = x.BillType, //单据类型 Category = x.Category, //业务类别 LedgerVoucherNO = x.LedgerVoucherNO, //总账凭证号 RelativeNO = x.RelativeNO, //相关号码 InvoiceAmount = x.InvoiceAmount, InvoiceDate = x.InvoiceDate, InvoiceNO = x.InvoiceNO, Note = x.Note, //备注 AccountAmount = x.AccountAmount, //记账资料 AccountCurrency = x.AccountCurrency, AccountRate = x.AccountRate, PrePayAmount = x.PrePayAmount, //预付支资料 PrePayCurrency = x.PrePayCurrency, PrePayRate = x.PrePayRate, AHSRAmount = x.AHSRAmount, //实收支资料 AHSRCurrency = x.AHSRCurrency, AHSRRate = x.AHSRRate, FinancialAmount = x.FinancialAmount,//财务费用 FinancialCurrency = x.FinancialCurrency, FinancialRate = x.FinancialRate, AdvanceAmount = x.AdvanceAmount, //预收支资料 AdvanceCurrency = x.AdvanceCurrency, AdvanceRate = x.AdvanceRate, }).FirstAsync(x => x.Id == id && x.Mode == SettlementMode.FreeSettlement); return DataResult.Success(model); } /// /// 获取付费自由结算明细 /// /// /// public async Task> GetDetailsAsync(PageRequest request) { var model = new FreeSettlement(); model.Details = await TenantDb.Queryable().Where(x => x.ApplicationId == request.OtherQueryCondition && x.Category == DetailCategory.PaidFreeSettlement) .InnerJoin((d, f) => d.RecordId == f.Id) .Select((d, f) => new FreeSettlementDetailDto { Id = d.Id, RecordId = f.Id, BusinessId = f.BusinessId, BusinessType = f.BusinessType, CustomerName = d.CustomerName, FeeName = d.FeeName, FeeType = d.FeeType, ExchangeRate = d.ExchangeRate, OriginalAmount = d.OriginalAmount, OriginalCurrency = d.OriginalCurrency, OriginalRate = f.ExchangeRate, ApplyAmount = d.ApplyAmount, Currency = d.Currency }).ToListAsync(); var gList = model.Details.GroupBy(x => x.BusinessType); foreach (var g in gList) { var ids = g.Select(x => x.BusinessId); switch (g.Key) { case BusinessType.OceanShippingExport: var list1 = await TenantDb.Queryable().Where(x => ids.Contains(x.Id)) .LeftJoin((s, cs) => s.SourceId == cs.Id) .Select((s, cs) => new { s.Id, s.MBLNO, s.HBLNO, s.CustomerNo, ClientName = s.CustomerName, s.ETD, cs.SourceName, s.Sale, s.AccountDate, s.Vessel, Voyage = s.Voyno, s.Carrier, s.Enterprise, s.CustomNo }).ToListAsync(); foreach (var item in g) { var biz = list1.Find(x => x.Id == item.BusinessId); if (biz != null) { item.MBLNO = biz.MBLNO; item.HBLNO = biz.HBLNO; item.CustomerNo = biz.CustomerNo; item.ClientName = biz.ClientName; item.ETD = biz.ETD; item.SourceName = biz.SourceName; item.Sale = biz.Sale; item.AccountDate = biz.AccountDate; item.Vessel = biz.Vessel; item.Voyage = biz.Voyage; item.Carrier = biz.Carrier; item.Enterprise = biz.Enterprise; item.CustomNo = biz.CustomNo; } } break; case BusinessType.OceanShippingImport: break; } } model.SummaryItems = model.Details.GroupBy(x => new { x.FeeType, x.Currency }).Select(x => new SummaryItem { FeeType = x.Key.FeeType, Currency = x.Key.Currency, Amount = x.Sum(y => y.ApplyAmount) }).ToList(); return DataResult.Success(model); } protected override async Task PreSaveAsync(PaymentSettlement settlement) { settlement.Mode = SettlementMode.FreeSettlement; settlement.BillType = SettlementBillType.Payment; //获取剩余待结算金额 var ids = settlement.Details.Select(x => x.RecordId); var fees = await TenantDb.Queryable().Where(x => ids.Contains(x.Id) && x.FeeStatus == FeeStatus.AuditPassed) .Select(x => new { x.Id, OriginalRestAmount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount }).ToListAsync(); StringBuilder sb = new(); foreach (var detail in settlement.Details) { var item = fees.Find(x => x.Id == detail.RecordId); 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.PaidApplicationSettlement; } return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success; } protected override DataResult PreDelete(List settlements) { if (settlements.Any(x => x.IsLocked)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked)); return DataResult.Success; } } }