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.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>> 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 FeeApplicationBiz { Id = s.Id, AccountDate = s.AccountDate, BusinessType = BusinessType.OceanShippingExport, CntrTotal = s.CntrTotal, CreateBy = s.CreateBy, CustomerId = s.CustomerId, CustomerName = s.CustomerName,//委托单位 DischargePort = s.DischargePort, ETD = s.ETD, HBLNO = s.HBLNO, LoadPort = s.LoadPort, MBLNO = s.MBLNO, OperatorId = s.OperatorId, SaleDeptId = s.SaleDeptId, //SaleDeptName //所属部门 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)); } /// /// 获取分页列表 /// /// /// public async Task>> GetListAsync(PageRequest request) { var query = TenantDb.Queryable(); List whereList = []; if (!request.QueryCondition.IsNullOrEmpty()) whereList = Db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition); int? index = null; foreach (var item in whereList) { ConditionalModel? model = item as ConditionalModel; //设置了状态筛选 if (model != null && string.Equals(model.FieldName, nameof(ApplicationDto.AuditStatus)) && int.TryParse(model.FieldValue, out int statusValue)) { AuditStatusForQuery status = (AuditStatusForQuery)statusValue; switch (status) { case AuditStatusForQuery.Pending: query = query.Where(x => x.AuditerId == null); break; case AuditStatusForQuery.Audited: query = query.Where(x => x.AuditerId != null); break; case AuditStatusForQuery.MarkerOnly: var ids = await GetCurrentFlowsQuery(PaymentApplicationAuditService.AuditTypes).Select(x => x.BusinessId).ToListAsync(); if (ids.Count == 0) ids.Add(0L); query = query.Where(x => ids.Contains(x.Id)); break; } index = whereList.IndexOf(item); break; } } if (index.HasValue) whereList.RemoveAt(index.Value); return await query.Where(whereList).Select().ToQueryPageAsync(request.PageCondition); } /// /// 获取申请单详情 /// /// 申请单ID /// public async Task> GetAsync(long id) { var dto = await TenantDb.Queryable().Where(x => x.Id == id).Select().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 FeeApplicationDetailDto { 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, 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; } } } return DataResult.Success(dto); } protected override DataResult PreSave(PaymentApplication application, PaymentApplication dbValue) { if (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; } } }