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.Application.Interface; using DS.WMS.Core.Fee.Dtos; using DS.WMS.Core.Fee.Entity; using DS.WMS.Core.Info.Entity; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Sys.Entity; using SqlSugar; namespace DS.WMS.Core.Application.Method { /// /// 付费申请实现 /// public class PaymentApplicationService : ApplicationService, IPaymentApplicationService { /// /// 初始化 /// /// public PaymentApplicationService(IServiceProvider serviceProvider) : base(serviceProvider) { } /// /// 获取分页列表 /// /// /// public async Task>> GetListAsync(PageRequest request) { var query = CreateListQuery(); if (!request.QueryCondition.IsNullOrEmpty()) { var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition); query = query.Where(whereList); } var result = await query.GroupBy(x => x.Id).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; } internal ISugarQueryable CreateListQuery() { var query1 = TenantDb.Queryable() .LeftJoin((a, d) => a.Id == d.ApplicationId) .LeftJoin((a, d, f) => d.RecordId == f.Id) .LeftJoin((a, d, f, s) => f.BusinessId == s.Id) .Select((a, d, f, s) => new PaymentApplicationDto { Id = a.Id, ApplicationNO = a.ApplicationNO, Status = a.Status, CustomerId = a.CustomerId, CustomerName = a.CustomerName, //结算单位 ClientName = s.CustomerName, //委托单位 AmountOther = a.AmountOther, AmountRMB = a.AmountRMB, AmountUSD = a.AmountUSD, SaleDeptId = a.SaleDeptId, SettlementTypeId = a.SettlementTypeId, SettlementTypeName = a.SettlementType.StlName, //结算方式 CreateBy = a.CreateBy, //申请人 CreateTime = a.CreateTime, //申请日期 PaymentDate = a.PaymentDate, //申请支付日期 Currency = a.Currency, Reason = a.Reason, AuditerId = a.AuditerId, AuditerName = a.AuditerName, //审核人 AuditTime = a.AuditTime, //审核时间 IsInvoiceReceived = a.IsInvoiceReceived, IsPrinted = a.IsPrinted, PrintTimes = a.PrintTimes, InvoiceAmount = a.InvoiceAmount, InvoiceDate = a.InvoiceDate, InvoiceNO = a.InvoiceNO, Note = a.Note, BillNO = s.CustomerNo, //业务编号=委托编号 CustomerBankId = a.CustomerBankId, CustomerBank = a.CustomerBank.BankName, //结算对象银行 CustomerAccount = a.CustomerBank.Account, //结算对象账号 //汇总项 RestAmountRMB = SqlFunc.Subqueryable().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)), RestAmountUSD = SqlFunc.Subqueryable().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)), RestAmountOther = SqlFunc.Subqueryable().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency != FeeCurrency.RMB_CODE && f.Currency != FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount)) }); return TenantDb.UnionAll(new List> { query1 }); } /// /// 获取待付费的业务列表(编辑用) /// /// /// public async Task>> GetBizListAsync(PageRequest request) { var queryList = CreateBizQuery(); if (!request.QueryCondition.IsNullOrEmpty()) { var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition); queryList = queryList.Where(whereList); } var result = await queryList.ToQueryPageAsync(request.PageCondition); if (result.Data.Count > 0) { //关联用户名称 var userIds = result.Data.Where(x => x.OperatorId.HasValue).Select(x => x.OperatorId.Value) .Union(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(); var orgs = await Db.Queryable().Where(x => userIds.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; if (item.OperatorId.HasValue) item.Operator = users.Find(x => x.Id == item.OperatorId.Value)?.UserName; item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName; } } return result; } //创建各项业务数据的查询并集 internal ISugarQueryable CreateBizQuery() { //海运出口 var query1 = TenantDb.Queryable() .InnerJoin((s, f) => s.Id == f.BusinessId && f.BusinessType == BusinessType.OceanShippingExport) .Where((s, f) => f.FeeStatus == FeeStatus.AuditPassed) .GroupBy((s, f) => s.Id) .Select((s, f) => new BizPaymentApplication { Id = s.Id, BusinessType = BusinessType.OceanShippingExport, CustomerNo = s.CustomerNo, //委托编号 MBLNO = s.MBLNO, HBLNO = s.HBLNO, CustomerId = s.CustomerId, CustomerName = s.CustomerName,//结费单位 ClientName = s.CustomerName, //委托单位 AccountDate = s.AccountDate, BookingNO = s.BookingNo, //订舱编号 CntrTotal = s.CntrTotal, CreateBy = s.CreateBy, ETD = s.ETD, DischargePort = s.DischargePort, LoadPort = s.LoadPort, OperatorId = s.OperatorId, SaleDeptId = s.SaleDeptId, //所属分部 SaleId = s.SaleId, SaleName = s.Sale, //揽货人 Vessel = s.Vessel, //船名 Voyage = s.Voyno, //航次 StlName = s.StlName, //结算方式 //统计项 UnpaidRMB = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnpaidUSD = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnpaidOther = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency != FeeCurrency.USD_CODE && f.Currency != FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnreceivedRMB = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnreceivedUSD = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnreceivedOther = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency != FeeCurrency.USD_CODE && f.Currency != FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount)), UnpaidRMBInv = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == FeeCurrency.RMB_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount)), UnpaidUSDInv = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == FeeCurrency.USD_CODE).Select(f => SqlFunc.AggregateSum(f.Amount - f.InvoiceAmount - f.OrderInvoiceAmount + f.OrderInvSettlementAmount)) }); //海运进口 return TenantDb.UnionAll(new List> { query1 }); } /// /// 根据业务编号及类型获取关联费用记录 /// /// 业务ID与业务类型 /// public async Task> GetFeesAsync(params BizItem[] items) { var bizIds = items.Select(x => x.Id).ToList(); var types = items.Select(x => x.BusinessType).ToList(); var list = await TenantDb.Queryable() .Where(f => bizIds.Contains(f.BusinessId) && types.Contains(f.BusinessType) && f.FeeStatus == FeeStatus.AuditPassed) .Select(f => new FeePaymentDto { RecordId = f.Id, BusinessId = f.BusinessId, BusinessType = f.BusinessType, CustomerName = f.CustomerName, FeeId = f.FeeId, FeeName = f.FeeName, FeeType = f.FeeType, Amount = f.Amount, Currency = f.Currency, OriginalCurrency = f.Currency, OriginalRate = f.ExchangeRate, RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, InvoiceAmount = f.InvoiceAmount, Remark = f.Remark, CreateBy = f.CreateBy, TaxRate = f.TaxRate }).ToListAsync(); //移除未接金额为0的项 list.RemoveAll(f => f.RestAmount == 0); if (list.Count > 0) { //关联用户名称 var userIds = list.Select(x => x.CreateBy).Distinct(); var users = await Db.Queryable().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync(); foreach (var item in list) { item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName; item.ApplyAmount = item.RestAmount; //申请金额默认=剩余金额 } } return DataResult.Success(new PaymentApplicaitonBiz(list)); } /// /// 获取申请单详情 /// /// 申请单ID /// public async Task> GetAsync(long id) { var dto = await TenantDb.Queryable().LeftJoin((a, b) => a.CustomerBankId == b.Id) .Where((a, b) => a.Id == id).Select((a, b) => new PaymentApplicationDto { Id = a.Id, ApplicationNO = a.ApplicationNO, Currency = a.Currency, CustomerId = a.CustomerId, CustomerName = a.CustomerName, CustomerBankId = a.CustomerBankId, CustomerBank = b.BankAccountNo, Status = a.Status, CreateTime = a.CreateTime, CreateBy = a.CreateBy, AmountRMB = a.AmountRMB, AmountUSD = a.AmountUSD, AmountOther = a.AmountOther, SettlementTypeId = a.SettlementTypeId, PaymentDate = a.PaymentDate, ChequeRemarks = a.ChequeRemarks, InvoiceDate = a.InvoiceDate, InvoiceAmount = a.InvoiceAmount, SaleDeptId = a.SaleDeptId, Note = a.Note }).FirstAsync(); if (dto != null) { dto.Details = await TenantDb.Queryable().Where(d => d.ApplicationId == id) .InnerJoin((d, f) => d.RecordId == f.Id) .InnerJoin((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType) .Select((d, f, b) => new ApplicationDetailDto { Id = d.Id, RecordId = f.Id, AccTaxRate = f.AccTaxRate, Amount = d.ApplyAmount, FeeId = d.FeeId, FeeName = d.FeeName, FeeType = d.FeeType, CustomerId = f.CustomerId, CustomerName = d.CustomerName, OriginalCurrency = d.OriginalCurrency, OriginalRate = f.ExchangeRate, ExchangeRate = d.ExchangeRate, OriginalAmount = d.OriginalAmount, //未申请金额=(金额-结算金额-申请金额+申请金额已结算) RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, BusinessId = f.BusinessId, BusinessType = f.BusinessType, IsBusinessLocking = b.IsBusinessLocking, IsFeeLocking = b.IsFeeLocking }).ToListAsync(); var gList = dto.Details.GroupBy(x => x.BusinessType).ToList(); foreach (var g in gList) { var ids = g.Select(x => x.BusinessId).ToList(); switch (g.Key) { case BusinessType.OceanShippingExport: var list1 = await TenantDb.Queryable().Where(x => ids.Contains(x.Id)).Select(x => new { x.Id, x.MBLNO, x.CustomerNo, x.CustomerName, x.ETD, x.CntrTotal, x.AccountDate, x.OperatorCode, x.Vessel, x.Voyno, x.Carrier, x.Forwarder }).ToListAsync(); foreach (var item in g) { var biz = list1.Find(x => x.Id == item.BusinessId); if (biz != null) { item.MBLNO = biz.MBLNO; item.CustomerName = biz.CustomerName; item.CustomerNo = biz.CustomerNo; item.ETD = biz.ETD; item.CntrTotal = biz.CntrTotal; item.AccountDate = biz.AccountDate; item.Operator = biz.OperatorCode; item.Vessel = biz.Vessel; item.Voyage = biz.Voyno; item.Carrier = biz.Carrier; item.Forwarder = biz.Forwarder; } } break; case BusinessType.OceanShippingImport: break; } } dto.RestAmountRMB = dto.Details.FindAll(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).Sum(x => x.RestAmount); dto.RestAmountUSD = dto.Details.FindAll(x => x.OriginalCurrency == FeeCurrency.USD_CODE).Sum(x => x.RestAmount); dto.AmountOther = dto.Details.FindAll(x => x.OriginalCurrency != FeeCurrency.RMB_CODE && x.OriginalCurrency != FeeCurrency.USD_CODE).Sum(x => x.RestAmount); } return DataResult.Success(dto); } protected override async Task> GetDetailsAsync(IEnumerable items) { var ids1 = items.Select(x => x.Id); var ids2 = items.Select(x => x.BusinessType); var list = await TenantDb.Queryable().Where(x => ids1.Contains(x.BusinessId) && ids2.Contains(x.BusinessType) && x.FeeStatus == FeeStatus.AuditPassed) .Select(x => new ApplicationDetail { RecordId = x.Id, ApplyAmount = x.Amount - x.SettlementAmount - x.OrderAmount + x.OrderSettlementAmount, Currency = x.Currency, ExchangeRate = x.ExchangeRate, OriginalCurrency = x.Currency }).ToListAsync(); list.RemoveAll(x => x.ApplyAmount == 0); foreach (var item in list) item.OriginalAmount = item.ApplyAmount; return list; } protected override DataResult EnsureApplication(PaymentApplication application, PaymentApplication dbValue) { if (dbValue != null) { if (dbValue.Status == PaymentApplicationStatus.AuditSubmittd || dbValue.Status == PaymentApplicationStatus.AuditPassed) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSaveStatusError)); if (application.Id > 0 && !string.Equals(dbValue.Currency, application.Currency, StringComparison.OrdinalIgnoreCase)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSaveCurrencyError)); } return DataResult.Success; } protected override DataResult CalculateAmount(PaymentApplication application, List fees) { if (fees == null) return DataResult.Success; //非原币申请且原始金额为0,则禁止提交 if (application.Details.Any(x => x.OriginalAmount == 0 && !application.Currency.IsNullOrEmpty())) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalAmountCannotBeZero)); StringBuilder sb = new(); foreach (var detail in application.Details) { var fee = fees.Find(x => x.Id == detail.RecordId); if (fee == null) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.ApplicationCannotRelateFee)), detail.FeeName); sb.Append(";"); continue; } detail.Record = fee; //未申请金额=总金额-结算金额-申请金额+申请金额已结算 var restAmount = fee.Amount - fee.SettlementAmount - fee.OrderAmount + fee.OrderSettlementAmount; if (restAmount == 0) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.FeeNobalance)), fee.FeeName); sb.Append(";"); continue; } if (detail.OriginalAmount > 0 && detail.OriginalAmount > restAmount) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), fee.FeeName); sb.Append(";"); continue; } else if (detail.OriginalAmount < 0 && detail.OriginalAmount < restAmount) { sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), fee.FeeName); sb.Append(";"); continue; } //更新费用记录的已申请金额 fee.OrderAmount += detail.OriginalAmount; //类别固定为付费申请 detail.Category = DetailCategory.PaidApplication; } return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success; } protected override Task PreSaveAsync(PaymentApplication application) { application.AmountRMB = application.Details.Where(x => x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount); application.AmountUSD = application.Details.Where(x => x.Currency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount); application.AmountOther = application.Details.Where(x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount); return Task.CompletedTask; } protected override async Task OnSaveAsync(PaymentApplication application, List? fees) { if (application.Id > 0) { await TenantDb.Updateable(application).IgnoreColumns(x => new { x.ApplicationNO, x.AmountRMB, x.AmountUSD, x.AmountOther, x.CreateBy, x.CreateTime, x.Deleted, x.DeleteBy, x.DeleteTime }).ExecuteCommandAsync(); } if (fees != null && fees.Count > 0) await TenantDb.Updateable(fees) .PublicSetColumns(x => x.OrderAmount, "+") .UpdateColumns(x => new { x.OrderAmount }) .ExecuteCommandAsync(); } protected override async Task> PostSaveAsync(PaymentApplication application) { var app = await TenantDb.Queryable().Includes(x => x.Details).FirstAsync(x => x.Id == application.Id); return DataResult.Success(app); } protected override DataResult PreDelete(List applications) { if (applications.Any(x => x.Status != PaymentApplicationStatus.Pending && x.Status != PaymentApplicationStatus.AuditRejected)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationDeleteStatusError)); return DataResult.Success; } protected override async Task OnDeleteDetailAsync(List applications, DeleteOption deleteOption) { var detailList = applications.SelectMany(x => x.Details); //还原费用表的已申请金额 var fees = detailList.Select(x => new FeeRecord { Id = x.RecordId, OrderAmount = x.OriginalAmount }).ToList(); await TenantDb.Updateable(fees) .PublicSetColumns(it => it.OrderAmount, "-") .UpdateColumns(x => new { x.OrderAmount }) .ExecuteCommandAsync(); if (deleteOption == DeleteOption.DetailOnly) { //更新总申请金额 var appIds = applications.Select(x => x.Id); var dIds = detailList.Select(x => x.Id); var details = await TenantDb.Queryable().Where(x => appIds.Contains(x.ApplicationId) && !dIds.Contains(x.Id)) .Select(x => new { x.ApplicationId, x.ApplyAmount, x.Currency }).ToListAsync(); var gList = details.GroupBy(x => x.ApplicationId).ToList(); foreach (var item in applications) { var gItems = gList.Find(x => x.Key == item.Id); if (gItems == null) { item.AmountRMB = item.AmountUSD = item.AmountOther = 0m; item.CustomerId = 0; item.CustomerName = null; item.CustomerBankId = null; await TenantDb.Updateable(item) .UpdateColumns(x => new { x.AmountRMB, x.AmountUSD, x.AmountOther, x.CustomerId, x.CustomerName, x.CustomerBankId }) .ExecuteCommandAsync(); } else { item.AmountRMB = gItems.Where(x => x.Currency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount); item.AmountUSD = gItems.Where(x => x.Currency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount); item.AmountOther = gItems.Where(x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount); await TenantDb.Updateable(item) .UpdateColumns(x => new { x.AmountRMB, x.AmountUSD, x.AmountOther }) .ExecuteCommandAsync(); } } } } protected override DataResult PreSubmitApproval(List applications) { if (applications.Exists(x => x.Status == PaymentApplicationStatus.AuditSubmittd || x.Status == PaymentApplicationStatus.AuditPassed)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationIsAuditing)); return DataResult.Success; } protected override void OnSubmitApproval(PaymentApplication application) { application.Status = PaymentApplicationStatus.AuditSubmittd; } protected override void OnWithdraw(PaymentApplication application) { application.Status = PaymentApplicationStatus.Pending; } /// /// 设置是否收到发票 /// /// /// /// public async Task SetInvoiceReceivedAsync(bool isInvoiceReceived, params long[] ids) { var list = ids.Select(x => new PaymentApplication { Id = x, IsInvoiceReceived = isInvoiceReceived }).ToList(); int rows = await TenantDb.Updateable(list) .UpdateColumns(x => new { x.IsInvoiceReceived }) .ExecuteCommandAsync(); return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } }