using System.Text; using DS.Module.Core; using DS.Module.Core.Enums; using DS.Module.Core.Extensions; 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 queryList = CreateListQuery(); if (!request.QueryCondition.IsNullOrEmpty()) { var whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition); queryList = queryList.Where(whereList); } return await queryList.GroupBy(x => x.Id).ToQueryPageAsync(request.PageCondition); } internal ISugarQueryable CreateListQuery() { var query1 = TenantDb.Queryable() .InnerJoin((a, d) => a.Id == d.ApplicationId) .LeftJoin((a, d, s) => d.BusinessId == s.Id) .LeftJoin((a, d, s, b) => a.CustomerBankId == b.Id) .Select((a, d, s, b) => new PaymentApplicationDto { Id = a.Id, ApplicationNO = a.ApplicationNO, CustomerId = a.CustomerId, CustomerName = a.CustomerName, AmountOther = a.AmountOther, AmountRMB = a.AmountRMB, AmountUSD = a.AmountUSD, SaleDeptId = a.SaleDeptId, CreateBy = a.CreateBy, CreateTime = a.CreateTime, Currency = a.Currency, ExchangeRate = a.ExchangeRate, Reason = a.Reason, Status = a.Status, AuditerId = a.AuditerId, AuditerName = a.AuditerName, AuditTime = a.AuditTime, IsInvoiceReceived = a.IsInvoiceReceived, Client = s.CustomerName, IsPrinted = a.IsPrinted, PrintTimes = a.PrintTimes, InvoiceAmount = a.InvoiceAmount, InvoiceDate = a.InvoiceDate, InvoiceNO = a.InvoiceNO, SettlementType = a.SettlementType, PaymentDate = a.PaymentDate, Note = a.Note, BillNO = s.CustomerNo, //业务编号=委托编号 CustomerBankId = a.CustomerBankId, CustomerBank = b.BankName + "-" + b.Account, //汇总项 RestAmountRMB = SqlFunc.Subqueryable().Where(f => f.Id == d.RecordId && f.FeeStatus == FeeStatus.AuditPassed && f.Currency == 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 == 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 != RMB_CODE && f.Currency != 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(); 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; } } 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 BizApplication { Id = s.Id, AccountDate = s.AccountDate, BusinessType = BusinessType.OceanShippingExport, CntrTotal = s.CntrTotal, CreateBy = s.CreateBy, CustomerId = s.CustomerId,//费用对象 CustomerName = s.CustomerName, CustomerNO = s.CustomerNo, DischargePort = s.DischargePort, ETD = s.ETD, HBLNO = s.HBLNO, LoadPort = s.LoadPort, MBLNO = s.MBLNO, OperatorId = s.OperatorId, SaleDeptId = s.SaleDeptId, SaleId = s.SaleId, SaleName = s.Sale,//揽货人 Vessel = s.Vessel,//船名 Voyage = s.Voyno,//航次 BookingNO = s.BookingNo, StlName = s.StlName, FeeType = f.FeeType, FeeId = f.FeeId, Currency = f.Currency, IsAdvancedPay = f.IsAdvancedPay, IsInvoice = f.IsInvoice, //统计项 UnpaidRMB = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), UnpaidUSD = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency == "USD").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), UnpaidOther = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Payable && f.Currency != "USD" && f.Currency != "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), UnreceivedRMB = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency == "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), UnreceivedUSD = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency == "USD").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), UnreceivedOther = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && f.FeeType == FeeType.Receivable && f.Currency != "USD" && f.Currency != "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.Amount.Value)), //UnpaidRMBInv = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && // f.FeeType == FeeType.Payable && f.Currency == "CNY").Select(f => SqlFunc.AggregateSumNoNull(f.InvoiceAmount.Value)), //UnpaidUSDInv = SqlFunc.Subqueryable().Where(f => f.BusinessId == s.Id && f.FeeStatus == FeeStatus.AuditPassed && // f.FeeType == FeeType.Payable && f.Currency == "USD").Select(f => SqlFunc.AggregateSumNoNull(f.InvoiceAmount.Value)) }); //海运进口 return TenantDb.UnionAll(new List> { query1 }); } /// /// 根据业务编号及类型获取关联费用记录 /// /// 业务ID /// 业务类型 /// public async Task> GetFeesAsync(long id, BusinessType businessType) { var list = await TenantDb.Queryable() .Where(f => f.BusinessId == id && f.BusinessType == businessType && f.FeeStatus == FeeStatus.AuditPassed) .Select(f => new FeeRecordDto { RecordId = f.Id, BusinessId = id, BusinessType = 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 }).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; } } return DataResult.Success(new FeeDto(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, SettlementType = a.SettlementType, 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() .LeftJoin((d, f) => d.RecordId == f.Id) .LeftJoin((d, f, b) => f.BusinessId == b.BusinessId && f.BusinessType == b.BusinessType) .Where(d => d.ApplicationId == id) .Select((d, f, b) => new PaymentApplicationDetailDto { AccTaxRate = f.AccTaxRate, Amount = d.Amount, FeeName = d.FeeName, FeeType = f.FeeType, FeeObject = f.CustomerName, OriginalCurrency = d.OriginalCurrency, OriginalRate = f.ExchangeRate, ExchangeRate = d.ExchangeRate, OriginalAmount = d.OriginalAmount, //未申请金额=(金额-结算金额-申请金额+申请金额已结算) RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, BusinessId = b.BusinessId, BusinessType = b.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 == RMB_CODE).Sum(x => x.RestAmount); dto.RestAmountUSD = dto.Details.FindAll(x => x.OriginalCurrency == USD_CODE).Sum(x => x.RestAmount); dto.AmountOther = dto.Details.FindAll(x => x.OriginalCurrency != RMB_CODE && x.OriginalCurrency != USD_CODE).Sum(x => x.RestAmount); } return DataResult.Success(dto); } protected override DataResult PreSave(PaymentApplication application, PaymentApplication dbValue) { if (dbValue != null && (dbValue.Status == PaymentApplicationStatus.AuditSubmittd || dbValue.Status == PaymentApplicationStatus.AuditPassed)) return DataResult.Failed("只能修改状态为:未提交/审核驳回的申请单"); if (application.Details.Count > 0 && !string.Equals(dbValue.Currency, application.Currency, StringComparison.OrdinalIgnoreCase)) return DataResult.Failed("提交申请单币别需与原申请单币别一致"); if (application.Details.Count > 0) { if (!application.Currency.IsNullOrEmpty() && application.Details.Any(x => x.Currency != application.Currency)) return DataResult.Failed($"申请单不是原币申请,所有明细币别必须为 {application.Currency}"); } return DataResult.Success; } protected override DataResult CalculateAmount(PaymentApplication application, List fees) { StringBuilder sb = new(); foreach (var detail in application.Details) { var fee = fees.Find(x => x.Id == detail.RecordId); if (fee == null) { sb.Append($"未能关联明细【{detail.FeeName}】的费用信息;"); continue; } detail.Record = fee; //未申请金额=总金额-结算金额-申请金额+申请金额已结算 var restAmount = fee.Amount.GetValueOrDefault() - fee.SettlementAmount.GetValueOrDefault() - fee.OrderAmount.GetValueOrDefault() + fee.OrderSettlementAmount; if (detail.OriginalAmount > 0 && detail.OriginalAmount > restAmount) { sb.Append($"申请单明细【{detail.FeeName}】的申请金额不能超出原费用的金额;"); continue; } if (detail.OriginalAmount < 0 && detail.OriginalAmount < restAmount) { sb.Append($"申请单明细【{detail.FeeName}】的申请金额不能超出原费用的金额;"); continue; } //更新费用记录的已申请金额 fee.OrderAmount += detail.OriginalAmount; //类别固定为付费申请 detail.Category = FeeCategory.PaidApplication; } if (sb.Length > 0) return DataResult.Failed(sb.ToString()); application.AmountRMB = application.Details.Where(x => x.Currency == "CNY").Sum(x => x.Amount); application.AmountUSD = application.Details.Where(x => x.Currency == "USD").Sum(x => x.Amount); application.AmountOther = application.Details.Where(x => x.Currency != "CNY" && x.Currency != "USD").Sum(x => x.Amount); return DataResult.Success; } protected override async Task UpdateFeesAsync(List fees) { await TenantDb.Updateable(fees).UpdateColumns(x => new { x.OrderAmount }).ExecuteCommandAsync(); } protected override DataResult PreDelete(List applications) { if (applications.Any(x => x.Status != PaymentApplicationStatus.Pending && x.Status != PaymentApplicationStatus.AuditRejected)) return DataResult.Failed("只能删除状态为‘未提交’或‘驳回’的申请单", MultiLanguageConst.FeeRecordDelete); return DataResult.Success; } protected override async Task OnDeleteDetailAsync(List details) { //还原费用表的已申请金额 var fees = details.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(); } protected override DataResult PreSubmitApproval(List applications) { if (applications.Exists(x => x.Status == PaymentApplicationStatus.AuditSubmittd || x.Status == PaymentApplicationStatus.AuditPassed)) return DataResult.Failed("提交内容包含正在审批中/已审批的申请单"); return DataResult.Success; } protected override void OnSubmitApproval(PaymentApplication application) { application.Status = PaymentApplicationStatus.AuditSubmittd; } /// /// 设置是否收到发票 /// /// /// /// 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.Failed("设置失败"); } } }