From dd5c82e5236ba727bda79d9d077918c214518d12 Mon Sep 17 00:00:00 2001 From: zzh <1368735060@qq.com> Date: Tue, 7 Jul 2026 12:36:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(order):=20=E6=94=AF=E6=8C=81=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E8=AF=A6=E6=83=85=E6=89=8B=E5=8A=A8=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=B4=B9=E7=94=A8=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 OrderFeeAddInput 并在 OrderEdit 服务中实现费用追加逻辑,配合前端订单详情抽屉添加费用能力。 Co-authored-by: Cursor --- .../Dtos/Orders/OrderFeeAddInput.cs | 66 +++++++++++++++++++ .../Services/Orders/OrderService.OrderEdit.cs | 63 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/Oms.Application/Dtos/Orders/OrderFeeAddInput.cs diff --git a/src/Oms.Application/Dtos/Orders/OrderFeeAddInput.cs b/src/Oms.Application/Dtos/Orders/OrderFeeAddInput.cs new file mode 100644 index 0000000..dd7e173 --- /dev/null +++ b/src/Oms.Application/Dtos/Orders/OrderFeeAddInput.cs @@ -0,0 +1,66 @@ +using System.ComponentModel.DataAnnotations; + +namespace Oms.Application.Dtos.Orders; + +/// +/// 手动添加订单费用入参。 +/// +public class OrderFeeAddInput +{ + /// + /// 订单主键。 + /// + [Required] + public int Id { get; set; } + + /// + /// 费用类型:receivable / payable。 + /// + [Required] + [StringLength(16)] + public string Type { get; set; } = string.Empty; + + /// + /// 费用项编码。 + /// + [Required] + [StringLength(64)] + public string CostItem { get; set; } = string.Empty; + + /// + /// 金额。 + /// + [Required] + public decimal Amount { get; set; } + + /// + /// 币种。 + /// + [Required] + [StringLength(16)] + public string Currency { get; set; } = string.Empty; + + /// + /// 计费阶段:forecast / inbound / outbound。 + /// + [Required] + [StringLength(16)] + public string ChargingStage { get; set; } = string.Empty; + + /// + /// 下游服务商(应付可选)。 + /// + [StringLength(128)] + public string? DownstreamProvider { get; set; } + + /// + /// 价格编号(可选)。 + /// + [StringLength(64)] + public string? PriceNo { get; set; } + + /// + /// 价格生效时间(可选)。 + /// + public DateTime? PriceEffectiveTime { get; set; } +} diff --git a/src/Oms.Application/Services/Orders/OrderService.OrderEdit.cs b/src/Oms.Application/Services/Orders/OrderService.OrderEdit.cs index 1474bbb..deeacca 100644 --- a/src/Oms.Application/Services/Orders/OrderService.OrderEdit.cs +++ b/src/Oms.Application/Services/Orders/OrderService.OrderEdit.cs @@ -233,6 +233,69 @@ public partial class OrderService return (await MapOrderOutputsAsync([order])).First(); } + /// + /// 手动添加订单费用(应收或应付)。 + /// + [HttpPost("/order/fee/add")] + public async Task AddOrderFeeAsync(OrderFeeAddInput input) + { + var order = await GetOrderOrThrowAsync(input.Id); + + var type = input.Type?.Trim().ToLowerInvariant() ?? string.Empty; + if (type is not (OrderFeeTypeCodes.Receivable or OrderFeeTypeCodes.Payable)) + { + throw new BusinessException("费用类型无效"); + } + + var costItem = input.CostItem?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(costItem)) + { + throw new BusinessException("费用项不能为空"); + } + + if (input.Amount <= 0) + { + throw new BusinessException("金额必须大于0"); + } + + var currency = input.Currency?.Trim() ?? string.Empty; + if (string.IsNullOrWhiteSpace(currency)) + { + throw new BusinessException("币种不能为空"); + } + + var chargingStage = input.ChargingStage?.Trim() ?? string.Empty; + if (chargingStage is not ( + OrderFeeChargingStageCodes.Forecast + or OrderFeeChargingStageCodes.Inbound + or OrderFeeChargingStageCodes.Outbound)) + { + throw new BusinessException("计费阶段无效"); + } + + var fee = new OrderFee + { + Type = type, + CostItem = costItem, + Amount = input.Amount, + Currency = currency, + ChargingStage = chargingStage, + DownstreamProvider = string.IsNullOrWhiteSpace(input.DownstreamProvider) + ? null + : input.DownstreamProvider.Trim(), + PriceNo = string.IsNullOrWhiteSpace(input.PriceNo) ? null : input.PriceNo.Trim(), + PriceEffectiveTime = input.PriceEffectiveTime, + CreateTime = DateTime.Now, + UpdateTime = DateTime.Now, + }; + + await OrderRepository.UpsertFeesAsync(order.Id, [fee]); + order.UpdateTime = DateTime.Now; + await OrderRepository.UpdateAsync(order); + + return (await MapOrderOutputsAsync([order])).First(); + } + private async Task RecalculateReceivableCoreAsync(Order order) { if (string.IsNullOrWhiteSpace(order.ProductCode))