From e7193d427385bee732dc5d8e77b3230435b1da5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B5=87=E6=96=87=E9=BE=99?= Date: Tue, 9 Jul 2024 17:59:09 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=BB=98=E8=B4=B9=E8=87=AA?= =?UTF-8?q?=E7=94=B1=E7=BB=93=E7=AE=97=E5=8F=8A=E5=85=B6=E6=98=8E=E7=BB=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DS.WMS.Core/Settlement/Dtos/FeeDto.cs | 6 +- .../DS.WMS.Core/Settlement/Dtos/FeeItem.cs | 146 +++++ .../Settlement/Dtos/PaymentSettlementDto.cs | 37 +- .../Settlement/Dtos/SettlementDetailDto.cs | 150 ++++- .../Settlement/Dtos/SettlementDto.cs | 5 +- .../Interface/IFreeSettlementService.cs | 16 - .../IPaymentFreeSettlementService.cs | 21 + .../Method/FreeSettlementService.cs | 135 ----- .../Method/PaymentFreeSettlementService.cs | 518 ++++++++++++++++++ .../PaymentFreeSettlementController.cs | 77 +++ .../DS.WMS.FeeApi/Logs/internal-nlog.txt | 14 + 11 files changed, 958 insertions(+), 167 deletions(-) create mode 100644 ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeItem.cs delete mode 100644 ds-wms-service/DS.WMS.Core/Settlement/Interface/IFreeSettlementService.cs create mode 100644 ds-wms-service/DS.WMS.Core/Settlement/Interface/IPaymentFreeSettlementService.cs delete mode 100644 ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs create mode 100644 ds-wms-service/DS.WMS.Core/Settlement/Method/PaymentFreeSettlementService.cs create mode 100644 ds-wms-service/DS.WMS.FeeApi/Controllers/PaymentFreeSettlementController.cs diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeDto.cs b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeDto.cs index c6b67c0c..33be6dd5 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeDto.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeDto.cs @@ -5,9 +5,9 @@ using DS.WMS.Core.Op.Entity; namespace DS.WMS.Core.Settlement.Dtos { /// - /// 费用记录返回实体 + /// 用于结算的按业务展示的费用组 /// - public class FeeBizDto + public class SettlementBiz { /// /// 业务Id @@ -205,7 +205,7 @@ namespace DS.WMS.Core.Settlement.Dtos /// /// 按业务分组的费用 /// - public class FeeDto : FeeBizDto + public class FeeDto : SettlementBiz { public long Id { get; set; } diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeItem.cs b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeItem.cs new file mode 100644 index 00000000..31a57406 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/FeeItem.cs @@ -0,0 +1,146 @@ +using DS.Module.Core; +using DS.WMS.Core.Fee.Method; +using DS.WMS.Core.Op.Entity; + +namespace DS.WMS.Core.Settlement.Dtos +{ + /// + /// 费用表单 + /// + public class FeeForm + { + readonly List _items; + + /// + /// 费用记录项 + /// + public List Items => _items; + + /// + /// 使用指定的数据源初始化统计。 + /// + /// 数据源 + public FeeForm(List source) + { + _items = source; + + UnchargedRMB = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.RestAmount); + UnchargedUSD = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.RestAmount); + UnchargedOther = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.RestAmount); + UnpaidRMB = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.RestAmount); + UnpaidUSD = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.RestAmount); + UnpaidOther = Items.FindAll(x => x.Currency == FeeServiceBase.RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.RestAmount); + } + + /// + /// 人民币未收 + /// + public decimal UnchargedRMB { get; private set; } + + /// + /// 人民币未付 + /// + public decimal UnpaidRMB { get; private set; } + + /// + /// 美元未收 + /// + public decimal UnchargedUSD { get; private set; } + + /// + /// 美元未付 + /// + public decimal UnpaidUSD { get; private set; } + + /// + /// 其他未收 + /// + public decimal UnchargedOther { get; private set; } + + /// + /// 其他未付 + /// + public decimal UnpaidOther { get; private set; } + } + + /// + /// 费用项 + /// + public class FeeItem + { + /// + /// 费用记录ID + /// + public long Id { get; set; } + + /// + /// 业务ID + /// + public long BusinessId { get; set; } + + /// + /// 业务类型 + /// + public BusinessType BusinessType { get; set; } + + /// + /// 客户名称 + /// + public string? CustomerName { get; set; } + + /// + /// 费用名称 + /// + public string? FeeName { get; set; } + + /// + /// 费用类型 + /// + public FeeType FeeType { get; set; } + + /// + /// 金额 + /// + public decimal Amount { get; set; } + + /// + /// 币别 + /// + public string Currency { get; set; } + + /// + /// 未结金额 + /// + public decimal RestAmount { get; set; } + + /// + /// 本次结算金额 + /// + public decimal SettlementAmount { get; set; } + + /// + /// 原始汇率 + /// + public decimal? OriginalRate { get; set; } + + /// + /// 开票金额 + /// + public decimal? InvoiceAmount { get; set; } + + /// + /// 财务税率 + /// + public decimal AccTaxRate { get; set; } + + /// + /// 录入方式 + /// + public string? InputMethod { get; set; } + + /// + /// 备注 + /// + public string? Remark { get; set; } + } +} diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/PaymentSettlementDto.cs b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/PaymentSettlementDto.cs index cb72eea0..b04a7139 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/PaymentSettlementDto.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/PaymentSettlementDto.cs @@ -122,14 +122,6 @@ namespace DS.WMS.Core.Settlement.Dtos /// public decimal? AdvanceAmount { get; set; } - [IgnoreDataMember] - public List UnInvoiceList { get; set; } - - /// - /// 未开票金额 - /// - public string UnInvoiceAmount => string.Join(" ", UnInvoiceList ?? []); - /// /// 是否导出凭证 /// @@ -149,5 +141,34 @@ namespace DS.WMS.Core.Settlement.Dtos /// 是否生成支票 /// public bool IsGenerateCheck { get; set; } + + [IgnoreDataMember] + public List UnInvoiceList { get; set; } + + /// + /// 未开票金额 + /// + public string UnInvoiceAmount => string.Join(" ", UnInvoiceList ?? []); + + /// + /// 结算明细 + /// + public List? Details { get; set; } + } + + /// + /// 付费自由结算 + /// + public class FreePaymentSettlementDto : PaymentSettlementDto + { + /// + /// 结算明细 + /// + public new List? Details { get; set; } + + /// + /// 结算金额合计 + /// + public List? SummaryItems { get; set; } } } diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDetailDto.cs b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDetailDto.cs index 67b8b8fe..ac933e37 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDetailDto.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDetailDto.cs @@ -1,9 +1,11 @@ using System.Runtime.Serialization; +using DS.Module.Core; +using DS.WMS.Core.Op.Entity; namespace DS.WMS.Core.Settlement.Dtos { /// - /// 结算明细DTO + /// 付费申请结算明细DTO /// public class SettlementDetailDto { @@ -70,4 +72,150 @@ namespace DS.WMS.Core.Settlement.Dtos /// public string? Note { get; set; } } + + /// + /// 付费自由结算明细DTO + /// + public class FreeSettlementDetailDto + { + /// + /// ID + /// + public long Id { get; set; } + + /// + /// 费用记录ID + /// + public long RecordId { get; set; } + + /// + /// 业务ID + /// + public long BusinessId { get; set; } + + /// + /// 业务类型 + /// + public BusinessType BusinessType { get; set; } + + /// + /// 主提单号 + /// + public string? MBLNO { get; set; } + + /// + /// 分提单号 + /// + public string? HBLNO { get; set; } + + /// + /// 委托编号 + /// + public string? CustomerNo { get; set; } + + /// + /// 委托单位 + /// + public string? ClientName { get; set; } + + /// + /// 开船日期 + /// + public DateTime? ETD { get; set; } + + /// + /// 业务来源 + /// + public string? SourceName { get; set; } + + /// + /// 揽货人 + /// + public string? Sale { get; set; } + + /// + /// 会计期间 + /// + public string? AccountDate { get; set; } + + /// + /// 船名 + /// + public string? Vessel { get; set; } + + /// + /// 航次 + /// + public string? Voyage { get; set; } + + /// + /// 船公司 + /// + public string? Carrier { get; set; } + + /// + /// 经营单位 + /// + public string? Enterprise { get; set; } + + /// + /// 报关单号 + /// + public string? CustomNo { get; set; } + + /// + /// 客户/费用对象名称 + /// + public string? CustomerName { get; set; } + + /// + /// 费用名称 + /// + public string? FeeName { get; set; } + + /// + /// 费用类型 + /// + public FeeType FeeType { get; set; } + + /// + /// 结算金额 + /// + public decimal ApplyAmount { get; set; } + + /// + /// 币别 + /// + public string Currency { get; set; } + + /// + /// 折算汇率 + /// + public decimal? ExchangeRate { get; set; } + + /// + /// 原始汇率 + /// + public decimal? OriginalRate { get; set; } + + /// + /// 原始币别 + /// + public string OriginalCurrency { get; set; } + + /// + /// 原始金额 + /// + public decimal OriginalAmount { get; set; } + + /// + /// 更改单 + /// + public string? ChangeOrder { get; set; } + + /// + /// 备注 + /// + public string? Note { get; set; } + } } diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDto.cs b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDto.cs index 877200df..7d0d9e37 100644 --- a/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDto.cs +++ b/ds-wms-service/DS.WMS.Core/Settlement/Dtos/SettlementDto.cs @@ -182,9 +182,6 @@ namespace DS.WMS.Core.Settlement.Dtos /// public DateTime CreateTime { get; set; } - /// - /// 结算明细 - /// - public List Details { get; set; } + } } diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Interface/IFreeSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Interface/IFreeSettlementService.cs deleted file mode 100644 index 9bce9e03..00000000 --- a/ds-wms-service/DS.WMS.Core/Settlement/Interface/IFreeSettlementService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using DS.Module.Core; -using DS.WMS.Core.Application.Dtos; -using DS.WMS.Core.Application.Interface; -using DS.WMS.Core.Settlement.Dtos; -using DS.WMS.Core.Settlement.Entity; - -namespace DS.WMS.Core.Settlement.Interface -{ - /// - /// 付费自由结算 - /// - public interface IFreeSettlementService : ISettlementService - { - - } -} diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Interface/IPaymentFreeSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Interface/IPaymentFreeSettlementService.cs new file mode 100644 index 00000000..bacc386b --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Settlement/Interface/IPaymentFreeSettlementService.cs @@ -0,0 +1,21 @@ +using DS.Module.Core; +using DS.WMS.Core.Application.Interface; +using DS.WMS.Core.Settlement.Dtos; +using DS.WMS.Core.Settlement.Entity; + +namespace DS.WMS.Core.Settlement.Interface +{ + /// + /// 付费自由结算 + /// + public interface IPaymentFreeSettlementService : ISettlementService + { + /// + /// 获取待结算费用分页列表 + /// + /// + /// + /// 查询条件请参考中定义的字段 + Task>> GetBizListAsync(PageRequest request); + } +} diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs deleted file mode 100644 index 0b855503..00000000 --- a/ds-wms-service/DS.WMS.Core/Settlement/Method/FreeSettlementService.cs +++ /dev/null @@ -1,135 +0,0 @@ -using DS.Module.Core; -using DS.Module.Core.Extensions; -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 FreeSettlementService : SettlementService, IFreeSettlementService - { - /// - /// 初始化 - /// - /// - public FreeSettlementService(IServiceProvider provider) : base(provider) - { - } - - /// - /// 获取待结算费用分页列表 - /// - /// - /// - /// 查询条件请参考中定义的字段 - public async Task>> GeFeeListAsync(PageRequest request) - { - var whereList = request.GetConditionalModels(Db); - var result = await CreateQuery().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.Currency, - x.FeeType, - //x.Amount, - //x.OrderAmount, - //x.SettlementAmount, - //x.OrderSettlementAmount, - x.InvoiceAmount, - UnSettlementAmount = 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.Currency == RMB_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettlementAmount); - item.UnpaidUSD = fees.FindAll(x => x.Currency == USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettlementAmount); - item.UnpaidOther = fees.FindAll(x => x.Currency != RMB_CODE && x.Currency != USD_CODE && x.FeeType == FeeType.Payable).Sum(x => x.UnSettlementAmount); - item.UnchargedRMB = fees.FindAll(x => x.Currency == RMB_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettlementAmount); - item.UnchargedUSD = fees.FindAll(x => x.Currency == USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettlementAmount); - item.UnchargedOther = fees.FindAll(x => x.Currency != RMB_CODE && x.Currency != USD_CODE && x.FeeType == FeeType.Receivable).Sum(x => x.UnSettlementAmount); - item.UnpaidInvoiceRMB = fees.FindAll(x => x.Currency == RMB_CODE && x.FeeType == FeeType.Payable && x.UnSettlementAmount == 0).Sum(x => x.InvoiceAmount); - item.UnpaidInvoiceUSD = fees.FindAll(x => x.Currency == USD_CODE && x.FeeType == FeeType.Payable && x.UnSettlementAmount == 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 CreateQuery() - { - 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.BusinessDate,//业务日期 - 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 }); - } - } -} diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/PaymentFreeSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/PaymentFreeSettlementService.cs new file mode 100644 index 00000000..063bbd05 --- /dev/null +++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/PaymentFreeSettlementService.cs @@ -0,0 +1,518 @@ +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.Dtos; +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 == 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 == 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 != RMB_CODE && x.Currency != 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 == 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 == 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 != RMB_CODE && x.Currency != 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 == 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 == 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.BusinessDate,//业务日期 + 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 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 && + (f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) != 0) + .Select(f => new FeeItem + { + Id = f.Id, + BusinessId = f.BusinessId, + BusinessType = f.BusinessType, + CustomerName = f.CustomerName, + FeeName = f.FeeName, + FeeType = f.FeeType, + Amount = f.Amount, + Currency = f.Currency, + OriginalRate = f.ExchangeRate, + RestAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, + SettlementAmount = f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount, + InvoiceAmount = f.InvoiceAmount, + AccTaxRate = f.AccTaxRate, + Remark = f.Remark + }).ToListAsync(); + + return DataResult.Success(new FeeForm(list)); + } + + /// + /// 获取付费自由结算及其明细 + /// + /// 结算单ID + /// + public async Task> GetAsync(long id) + { + var model = await TenantDb.Queryable().Select(x => new FreePaymentSettlementDto + { + 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(); + + if (model != null) + { + model.Details = await TenantDb.Queryable().Where(x => x.ApplicationId == id && x.Category == FeeCategory.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, + Note = d.Note + }).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); + } + + /// + /// 提交结算单 + /// + /// + /// + public override async Task> SaveAsync(SettlementRequest request) + { + var settlement = request.Settlement; + if (settlement.SettlementDate == default) + settlement.SettlementDate = DateTime.Now; + + settlement.Mode = SettlementMode.Payment; + settlement.BillType = SettlementBillType.Payment; + + if (request.Details?.Count > 0) + { + var appIds = request.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 != PaymentApplicationStatus.AuditPassed && x.Status != PaymentApplicationStatus.PartialSettlement)) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSelectStatusError)); + + if (appList.GroupBy(x => x.CustomerId).Select(x => x.Key).Count() > 1) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DetailCustomerOnlyOne)); + + //金额禁止为0 + if (request.Details.Any(x => x.Amount == 0 || x.OriginalAmount == 0)) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero)); + + if (settlement.Id == 0) + { + var app = appList[0]; + settlement.CustomerId = app.CustomerId; + settlement.CustomerName = app.CustomerName; + } + + settlement.Details = request.Details.Select(x => new ApplicationDetail + { + ApplicationId = x.ApplicationId, + DetailId = x.Id, + RecordId = x.RecordId, + BusinessId = x.BusinessId, + BusinessType = x.BusinessType, + CustomerName = x.CustomerName ?? settlement.CustomerName, + FeeId = x.FeeId, + FeeName = x.FeeName, + FeeType = x.FeeType, + Category = FeeCategory.PaidFreeSettlement, + ApplyAmount = x.Amount, + Currency = x.Currency, + ExchangeRate = x.ExchangeRate, + OriginalAmount = x.OriginalAmount, + OriginalCurrency = x.OriginalCurrency ?? (settlement.Currency.IsNullOrEmpty() ? x.Currency : settlement.Currency), + }).ToList(); + + if (settlement.Details.Any(x => x.OriginalCurrency.IsNullOrEmpty())) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.OriginalCurrencyCanNotNull)); + + //获取剩余待结算金额 + var ids2 = settlement.Details.Select(x => x.DetailId); + var appDetails = await TenantDb.Queryable().Where(x => ids2.Contains(x.Id) && x.Category == FeeCategory.PaidApplication) + .Select(x => new + { + x.Id, + //RestAmount = x.ApplyAmount - x.ProcessedAmount, + OriginalRestAmount = x.OriginalAmount - x.OriginalProcessedAmount + }).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; + } + } + if (sb.Length > 0) + return DataResult.Failed(sb.ToString()); + + settlement.Amount = settlement.Details.Sum(x => x.ApplyAmount); + } + + await TenantDb.Ado.BeginTranAsync(); + try + { + //关联导航属性插入 + if (settlement.Id == 0) + { + //创建时需要生成申请单编号 + var sequence = CommonService.Value.GetSequenceNext(); + if (!sequence.Succeeded) + { + return DataResult.Failed(sequence.Message, MultiLanguageConst.SequenceSetNotExist); + } + settlement.ApplicationNO = "CP" + SnowFlakeSingle.Instance.NextId(); //申请编号 + settlement.SettlementNO = sequence.Data; //结算单号 + + await TenantDb.InsertNav(settlement).Include(x => x.Details).ExecuteCommandAsync(); + } + else + { + if (settlement.Details.Count > 0) + await TenantDb.Insertable(settlement.Details).ExecuteCommandAsync(); + + await TenantDb.Updateable(settlement).IgnoreColumns(x => new + { + x.ApplicationNO, + x.SettlementNO, + x.IsLocked, + x.CreateBy, + x.CreateTime, + x.Deleted, + x.DeleteBy, + x.DeleteTime + }).ExecuteCommandAsync(); + } + + if (request.Details?.Count > 0) + { + //更新申请明细的已处理金额 + var list = request.Details.Select(x => new ApplicationDetail + { + Id = x.Id, + ProcessedAmount = x.Amount, + OriginalProcessedAmount = x.OriginalAmount + }).ToList(); + await TenantDb.Updateable(list) + .PublicSetColumns(x => x.ProcessedAmount, "+") + .PublicSetColumns(x => x.OriginalProcessedAmount, "+") + .UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount }) + .ExecuteCommandAsync(); + + //更新费用记录的已结算金额 + var fees = request.Details.Select(x => new FeeRecord + { + Id = x.RecordId, + SettlementAmount = x.OriginalAmount + }).ToList(); + await TenantDb.Updateable(fees) + .PublicSetColumns(x => x.SettlementAmount, "+") + .UpdateColumns(x => new { x.SettlementAmount }) + .ExecuteCommandAsync(); + } + + await TenantDb.Ado.CommitTranAsync(); + return DataResult.Success(settlement); + } + catch (Exception ex) + { + await TenantDb.Ado.RollbackTranAsync(); + await ex.LogAsync(Db); + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); + } + //finally + //{ + // if (request.Details?.Count > 0) + // await WriteBackStatusAsync(settlement); + //} + } + + protected override DataResult PreDelete(List settlements) + { + if (settlements.Any(x => x.IsLocked)) + return DataResult.FailedWithDesc(nameof(MultiLanguageConst.SettlementIsLocked)); + + return DataResult.Success; + } + + protected override async Task OnDeleteDetailAsync(List settlements) + { + await base.OnDeleteDetailAsync(settlements); + + var detailList = settlements.SelectMany(x => x.Details); + //还原费用表的已结算金额 + var fees = detailList.Select(x => new FeeRecord { Id = x.RecordId, SettlementAmount = x.OriginalAmount }).ToList(); + await TenantDb.Updateable(fees) + .PublicSetColumns(it => it.SettlementAmount, "-") + .UpdateColumns(x => new { x.SettlementAmount }) + .ExecuteCommandAsync(); + } + } +} diff --git a/ds-wms-service/DS.WMS.FeeApi/Controllers/PaymentFreeSettlementController.cs b/ds-wms-service/DS.WMS.FeeApi/Controllers/PaymentFreeSettlementController.cs new file mode 100644 index 00000000..7e1ac60c --- /dev/null +++ b/ds-wms-service/DS.WMS.FeeApi/Controllers/PaymentFreeSettlementController.cs @@ -0,0 +1,77 @@ +using DS.Module.Core; +using DS.Module.Core.Data; +using DS.WMS.Core.Settlement.Dtos; +using DS.WMS.Core.Settlement.Entity; +using DS.WMS.Core.Settlement.Interface; +using Microsoft.AspNetCore.Mvc; + +namespace DS.WMS.FeeApi.Controllers +{ + /// + /// 付费自由结算API + /// + public class PaymentFreeSettlementController : ApiController + { + readonly IPaymentFreeSettlementService _service; + + /// + /// 初始化 + /// + /// + public PaymentFreeSettlementController(IPaymentFreeSettlementService service) + { + _service = service; + } + + /// + /// 获取待结算费用分页列表 + /// + /// + /// + [HttpPost, Route("GetFeeList")] + public async Task>> GetFeeListAsync([FromBody] PageRequest request) + { + return await _service.GetBizListAsync(request); + } + + + /// + /// 根据付费申请创建结算单 + /// + /// + /// + [HttpPost, Route("Save")] + public async Task> SaveAsync([FromBody] SettlementRequest request) + { + return await _service.SaveAsync(request); + } + + /// + /// 删除申请单明细 + /// + /// 申请单明细ID + /// + [HttpPost, Route("DeleteDetail")] + public async Task DeleteDetailAsync([FromBody] IdModel model) + { + if (!ModelState.IsValid) + return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest); + + return await _service.DeleteDetailAsync(model.Ids); + } + + /// + /// 删除申请单 + /// + /// 申请单ID + /// + [HttpPost, Route("Delete")] + public async Task DeleteAsync([FromBody] IdModel model) + { + if (!ModelState.IsValid) + return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest); + + return await _service.DeleteAsync(model.Ids); + } + } +} diff --git a/ds-wms-service/DS.WMS.FeeApi/Logs/internal-nlog.txt b/ds-wms-service/DS.WMS.FeeApi/Logs/internal-nlog.txt index b070bd53..3c53e5e4 100644 --- a/ds-wms-service/DS.WMS.FeeApi/Logs/internal-nlog.txt +++ b/ds-wms-service/DS.WMS.FeeApi/Logs/internal-nlog.txt @@ -2252,3 +2252,17 @@ 2024-07-08 17:48:22.1047 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config 2024-07-08 17:48:22.1047 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile 2024-07-08 17:48:22.1047 Info Configuration initialized. +2024-07-09 11:49:51.2234 Info Registered target NLog.Targets.FileTarget(Name=allfile) +2024-07-09 11:49:51.2600 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) +2024-07-09 11:49:51.2600 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) +2024-07-09 11:49:51.2824 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False +2024-07-09 11:49:51.2824 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config +2024-07-09 11:49:51.2824 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile +2024-07-09 11:49:51.3056 Info Configuration initialized. +2024-07-09 11:54:05.4348 Info Registered target NLog.Targets.FileTarget(Name=allfile) +2024-07-09 11:54:05.4650 Info Registered target NLog.Targets.FileTarget(Name=ownFile-web) +2024-07-09 11:54:05.4650 Info Registered target NLog.Targets.ColoredConsoleTarget(Name=console) +2024-07-09 11:54:05.4790 Info NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 5.2.8.2366. Product version: 5.2.8+f586f1341c46fa38aaaff4c641e7f0fa7e813943. GlobalAssemblyCache: False +2024-07-09 11:54:05.4790 Info Validating config: TargetNames=console, ownFile-web, ConfigItems=54, FilePath=D:\Source\Repos\DS8\ds-wms-service\DS.WMS.FeeApi\bin\Debug\net8.0\nlog.config +2024-07-09 11:54:05.4790 Warn Unused target detected. Add a rule for this target to the configuration. TargetName: allfile +2024-07-09 11:54:05.4954 Info Configuration initialized.