diff --git a/db.sql b/db.sql
index 3931b2b..1a2694e 100644
--- a/db.sql
+++ b/db.sql
@@ -336,7 +336,6 @@ CREATE TABLE `t_sales_product_price` (
`CostItem` VARCHAR(64) NOT NULL COMMENT '费用项',
`CostUnit` VARCHAR(16) NOT NULL COMMENT '费用单位:kg/票/件',
`Currency` VARCHAR(16) NOT NULL COMMENT '币种:RMB/USD/EUR',
- `ChargingTime` VARCHAR(32) NULL COMMENT '收费时机:预报/出库/签收',
`ChargingCondition` VARCHAR(64) NULL COMMENT '收费条件',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
@@ -466,7 +465,6 @@ CREATE TABLE `t_service_channel_price` (
`CostItem` VARCHAR(64) NOT NULL COMMENT '费用项',
`CostUnit` VARCHAR(16) NOT NULL COMMENT '费用单位:kg/票/件',
`Currency` VARCHAR(16) NOT NULL COMMENT '币种:RMB/USD/EUR',
- `ChargingTime` VARCHAR(32) NULL COMMENT '收费时机:预报/出库/签收',
`ChargingCondition` VARCHAR(64) NULL COMMENT '收费条件',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人',
diff --git a/sql/migrate_drop_charging_time.sql b/sql/migrate_drop_charging_time.sql
new file mode 100644
index 0000000..6be5730
--- /dev/null
+++ b/sql/migrate_drop_charging_time.sql
@@ -0,0 +1,3 @@
+-- 移除卖价/买价主表「收费时机」字段(已由件重尺阶段触发算价,不再配置 ChargingTime)
+ALTER TABLE `t_sales_product_price` DROP COLUMN IF EXISTS `ChargingTime`;
+ALTER TABLE `t_service_channel_price` DROP COLUMN IF EXISTS `ChargingTime`;
diff --git a/src/Oms.Application/Dtos/Channels/SalesProductPriceListOutput.cs b/src/Oms.Application/Dtos/Channels/SalesProductPriceListOutput.cs
index d12d01d..4c843f9 100644
--- a/src/Oms.Application/Dtos/Channels/SalesProductPriceListOutput.cs
+++ b/src/Oms.Application/Dtos/Channels/SalesProductPriceListOutput.cs
@@ -45,11 +45,6 @@ public class SalesProductPriceListOutput
///
public string Currency { get; set; } = string.Empty;
- ///
- /// 计费时机。
- ///
- public string? ChargingTime { get; set; }
-
///
/// 计费条件。
///
diff --git a/src/Oms.Application/Dtos/Channels/SalesProductPriceSaveInput.cs b/src/Oms.Application/Dtos/Channels/SalesProductPriceSaveInput.cs
index 91ce695..49cc0dc 100644
--- a/src/Oms.Application/Dtos/Channels/SalesProductPriceSaveInput.cs
+++ b/src/Oms.Application/Dtos/Channels/SalesProductPriceSaveInput.cs
@@ -47,11 +47,6 @@ public class SalesProductPriceSaveInput
///
public string Currency { get; set; } = string.Empty;
- ///
- /// 计费时机。
- ///
- public string? ChargingTime { get; set; }
-
///
/// 计费条件。
///
diff --git a/src/Oms.Application/Dtos/Channels/ServiceChannelPriceListOutput.cs b/src/Oms.Application/Dtos/Channels/ServiceChannelPriceListOutput.cs
index a00582a..bf32e9d 100644
--- a/src/Oms.Application/Dtos/Channels/ServiceChannelPriceListOutput.cs
+++ b/src/Oms.Application/Dtos/Channels/ServiceChannelPriceListOutput.cs
@@ -45,11 +45,6 @@ public class ServiceChannelPriceListOutput
///
public string Currency { get; set; } = string.Empty;
- ///
- /// 计费时机。
- ///
- public string? ChargingTime { get; set; }
-
///
/// 计费条件。
///
diff --git a/src/Oms.Application/Dtos/Channels/ServiceChannelPriceSaveInput.cs b/src/Oms.Application/Dtos/Channels/ServiceChannelPriceSaveInput.cs
index 85266b7..8346e22 100644
--- a/src/Oms.Application/Dtos/Channels/ServiceChannelPriceSaveInput.cs
+++ b/src/Oms.Application/Dtos/Channels/ServiceChannelPriceSaveInput.cs
@@ -47,11 +47,6 @@ public class ServiceChannelPriceSaveInput
///
public string Currency { get; set; } = string.Empty;
- ///
- /// 计费时机。
- ///
- public string? ChargingTime { get; set; }
-
///
/// 计费条件。
///
diff --git a/src/Oms.Application/Dtos/Orders/OrderExportInput.cs b/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
index bbd95e8..1b757f4 100644
--- a/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
+++ b/src/Oms.Application/Dtos/Orders/OrderExportInput.cs
@@ -6,22 +6,26 @@ namespace Oms.Application.Dtos.Orders;
public class OrderExportInput
{
///
- /// 状态。
+ /// 状态:all 或 OrderStatusCodes 枚举值。
///
+ [Newtonsoft.Json.JsonProperty("status")]
public string? Status { get; set; }
///
/// 关键词。
///
+ [Newtonsoft.Json.JsonProperty("keyword")]
public string? Keyword { get; set; }
///
/// 创建TimeStart。
///
+ [Newtonsoft.Json.JsonProperty("createTimeStart")]
public DateTime? CreateTimeStart { get; set; }
///
/// 创建TimeEnd。
///
+ [Newtonsoft.Json.JsonProperty("createTimeEnd")]
public DateTime? CreateTimeEnd { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs b/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
index 45f6c35..642ffb8 100644
--- a/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
+++ b/src/Oms.Application/Dtos/Orders/OrderPaginatedInput.cs
@@ -8,30 +8,36 @@ public class OrderPaginatedInput
///
/// 页码,从 1 开始。
///
+ [Newtonsoft.Json.JsonProperty("page")]
public int Page { get; set; } = 1;
///
/// 每页条数。
///
+ [Newtonsoft.Json.JsonProperty("pageSize")]
public int PageSize { get; set; } = 20;
///
- /// 状态。
+ /// 状态:all 或 OrderStatusCodes 枚举值。
///
+ [Newtonsoft.Json.JsonProperty("status")]
public string? Status { get; set; }
///
/// 关键词。
///
+ [Newtonsoft.Json.JsonProperty("keyword")]
public string? Keyword { get; set; }
///
/// 创建TimeStart。
///
+ [Newtonsoft.Json.JsonProperty("createTimeStart")]
public DateTime? CreateTimeStart { get; set; }
///
/// 创建TimeEnd。
///
+ [Newtonsoft.Json.JsonProperty("createTimeEnd")]
public DateTime? CreateTimeEnd { get; set; }
}
diff --git a/src/Oms.Application/Dtos/Orders/PublishSnapshotRuleDtos.cs b/src/Oms.Application/Dtos/Orders/PublishSnapshotRuleDtos.cs
index c28a384..e61ac43 100644
--- a/src/Oms.Application/Dtos/Orders/PublishSnapshotRuleDtos.cs
+++ b/src/Oms.Application/Dtos/Orders/PublishSnapshotRuleDtos.cs
@@ -84,8 +84,6 @@ public class SalesProductPriceSnapshotItemDto
public string Currency { get; set; } = string.Empty;
- public string? ChargingTime { get; set; }
-
public string? ChargingCondition { get; set; }
public List Factors { get; set; } = [];
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
index 9306171..c2b4372 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.Helpers.cs
@@ -84,7 +84,6 @@ public partial class SalesProductService
CostItem = price.CostItem,
CostUnit = price.CostUnit,
Currency = price.Currency,
- ChargingTime = price.ChargingTime,
ChargingCondition = price.ChargingCondition,
Factors = factorMap.TryGetValue(price.Id, out var factors) ? factors.Select(MapPriceFactorOutput).ToList() : [],
Details = detailMap.TryGetValue(price.Id, out var details) ? details.Select(MapPriceDetailOutput).ToList() : [],
@@ -423,7 +422,6 @@ public partial class SalesProductService
CostItem = output.CostItem,
CostUnit = output.CostUnit,
Currency = output.Currency,
- ChargingTime = output.ChargingTime,
ChargingCondition = output.ChargingCondition,
Factors = output.Factors.Select(item => new ChannelPriceFactorInput
{
@@ -455,7 +453,6 @@ public partial class SalesProductService
CostItem = output.CostItem,
CostUnit = output.CostUnit,
Currency = output.Currency,
- ChargingTime = output.ChargingTime,
ChargingCondition = output.ChargingCondition,
Factors = output.Factors.Select(item => new ChannelPriceFactorInput
{
diff --git a/src/Oms.Application/Services/Channels/SalesProductService.cs b/src/Oms.Application/Services/Channels/SalesProductService.cs
index c61690b..0efc684 100644
--- a/src/Oms.Application/Services/Channels/SalesProductService.cs
+++ b/src/Oms.Application/Services/Channels/SalesProductService.cs
@@ -197,7 +197,6 @@ public partial class SalesProductService : ApplicationService
CostItem = input.CostItem,
CostUnit = input.CostUnit,
Currency = input.Currency,
- ChargingTime = input.ChargingTime,
ChargingCondition = input.ChargingCondition
},
BuildSalesProductPriceFactors(input.Factors),
@@ -230,7 +229,6 @@ public partial class SalesProductService : ApplicationService
price.CostItem = input.CostItem;
price.CostUnit = input.CostUnit;
price.Currency = input.Currency;
- price.ChargingTime = input.ChargingTime;
price.ChargingCondition = input.ChargingCondition;
await SalesProductRepository.UpdatePriceAsync(
price,
@@ -308,7 +306,6 @@ public partial class SalesProductService : ApplicationService
CostItem = priceInput.CostItem,
CostUnit = priceInput.CostUnit,
Currency = priceInput.Currency,
- ChargingTime = priceInput.ChargingTime,
ChargingCondition = priceInput.ChargingCondition
});
factors.AddRange(BuildSalesProductPriceFactors(priceInput.Factors, currentTempId));
diff --git a/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs b/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
index c97ff16..ccfa5ca 100644
--- a/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
+++ b/src/Oms.Application/Services/Channels/ServiceChannelService.Helpers.cs
@@ -136,7 +136,6 @@ public partial class ServiceChannelService
CostItem = price.CostItem,
CostUnit = price.CostUnit,
Currency = price.Currency,
- ChargingTime = price.ChargingTime,
ChargingCondition = price.ChargingCondition,
Factors = factorMap.TryGetValue(price.Id, out var factors) ? factors.Select(MapPriceFactorOutput).ToList() : [],
Details = detailMap.TryGetValue(price.Id, out var details) ? details.Select(MapPriceDetailOutput).ToList() : [],
@@ -392,7 +391,6 @@ public partial class ServiceChannelService
CostItem = output.CostItem,
CostUnit = output.CostUnit,
Currency = output.Currency,
- ChargingTime = output.ChargingTime,
ChargingCondition = output.ChargingCondition,
Factors = output.Factors.Select(item => new ChannelPriceFactorInput
{
diff --git a/src/Oms.Application/Services/Channels/ServiceChannelService.cs b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
index 9a97747..e41f7f6 100644
--- a/src/Oms.Application/Services/Channels/ServiceChannelService.cs
+++ b/src/Oms.Application/Services/Channels/ServiceChannelService.cs
@@ -284,7 +284,6 @@ public partial class ServiceChannelService : ApplicationService
CostItem = input.CostItem,
CostUnit = input.CostUnit,
Currency = input.Currency,
- ChargingTime = input.ChargingTime,
ChargingCondition = input.ChargingCondition
},
BuildPriceFactors(input.Factors),
@@ -317,7 +316,6 @@ public partial class ServiceChannelService : ApplicationService
price.CostItem = input.CostItem;
price.CostUnit = input.CostUnit;
price.Currency = input.Currency;
- price.ChargingTime = input.ChargingTime;
price.ChargingCondition = input.ChargingCondition;
await ServiceChannelRepository.UpdatePriceAsync(
price,
@@ -395,7 +393,6 @@ public partial class ServiceChannelService : ApplicationService
CostItem = priceInput.CostItem,
CostUnit = priceInput.CostUnit,
Currency = priceInput.Currency,
- ChargingTime = priceInput.ChargingTime,
ChargingCondition = priceInput.ChargingCondition
});
factors.AddRange(BuildPriceFactors(priceInput.Factors, currentTempId));
diff --git a/src/Oms.Application/Services/Operations/InboundRecordService.cs b/src/Oms.Application/Services/Operations/InboundRecordService.cs
index ca15f83..524958f 100644
--- a/src/Oms.Application/Services/Operations/InboundRecordService.cs
+++ b/src/Oms.Application/Services/Operations/InboundRecordService.cs
@@ -2,6 +2,7 @@ using Fake.Application;
using Microsoft.AspNetCore.Mvc;
using Oms.Application.Dtos.Operations;
using Oms.Application.Dtos.Shared;
+using Oms.Application.Services.Orders;
using Oms.Domain.ChannelsAggregate.Repositories;
using Oms.Domain.OperationsAggregate.Entities;
using Oms.Domain.OperationsAggregate.Repositories;
@@ -18,6 +19,7 @@ public class InboundRecordService : ApplicationService
private IInboundRecordRepository InboundRecordRepository => LazyServiceProvider.GetRequiredService();
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService();
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService();
+ private OrderService OrderService => LazyServiceProvider.GetRequiredService();
///
/// 新增入库记录。
@@ -50,6 +52,12 @@ public class InboundRecordService : ApplicationService
};
var savedEntity = await InboundRecordRepository.InsertAsync(entity);
+ await OrderService.ApplyReceiveBillingByWaybillAsync(
+ input.WaybillNo,
+ input.Length,
+ input.Width,
+ input.Height,
+ input.Weight);
return ObjectMapper.Map(savedEntity);
}
diff --git a/src/Oms.Application/Services/Orders/OrderService.ParcelBilling.cs b/src/Oms.Application/Services/Orders/OrderService.ParcelBilling.cs
index 4ee7d7e..7577f5e 100644
--- a/src/Oms.Application/Services/Orders/OrderService.ParcelBilling.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.ParcelBilling.cs
@@ -102,24 +102,14 @@ public partial class OrderService
}
var customer = await CustomerRepository.FirstOrDefaultAsync(x => x.Id == order.CustomerId);
- var fees = ParcelBillingCalculator.CalculateForecastReceivableFees(
- snapshotBinding.Price,
- snapshotBinding.PriceVersion,
- snapshotBinding.PriceEffectiveTime,
+ await UpsertReceivableFeesAsync(
+ order,
+ snapshotBinding,
forecast.ChargeableWeight ?? 0,
zoneKeys,
order.CargoAttribute ?? CargoAttributeCodes.General,
- customer?.CustomerGroup);
-
- if (fees.Count == 0 && ParcelBillingCalculator.HasEnabledForecastPriceItems(snapshotBinding.Price))
- {
- throw new BusinessException("产品卖价快照未配置或未匹配到有效价格");
- }
-
- if (fees.Count > 0)
- {
- await OrderRepository.UpsertFeesAsync(order.Id, fees);
- }
+ customer?.CustomerGroup,
+ OrderFeeChargingStageCodes.Forecast);
order.OrderStatus = OrderStatusCodes.Predeclared;
order.PredeclareFailReason = string.Empty;
@@ -289,6 +279,116 @@ public partial class OrderService
};
}
+ private async Task ResolveSnapshotBindingFromOrderAsync(SalesProduct product, Order order)
+ {
+ var bindTime = order.CreateTime == default ? DateTime.Now : order.CreateTime;
+ SalesProductRulesPublishSnapshotDto rulesSnapshot;
+ string rulesVersion;
+ DateTime rulesEffectiveTime;
+
+ if (string.IsNullOrWhiteSpace(order.SalesProductRulesVersion)
+ || order.SalesProductRulesVersion.StartsWith("LIVE-", StringComparison.OrdinalIgnoreCase))
+ {
+ rulesSnapshot = await BuildLiveRulesSnapshotAsync(product);
+ rulesVersion = order.SalesProductRulesVersion ?? $"LIVE-{product.Id}";
+ rulesEffectiveTime = bindTime;
+ }
+ else
+ {
+ var rulesRecord = await SalesProductRepository.GetPublishRecordByVersionAsync(
+ product.Id,
+ RulesOperatorType,
+ order.SalesProductRulesVersion);
+ if (rulesRecord?.Content == null)
+ {
+ throw new BusinessException("未命中订单绑定的规则快照版本");
+ }
+
+ rulesSnapshot = OmsDocHelper.DeserializeRulesSnapshot(rulesRecord.Content)
+ ?? throw new BusinessException("未命中订单绑定的规则快照版本");
+ rulesVersion = rulesRecord.Version;
+ rulesEffectiveTime = rulesRecord.PublishTime;
+ }
+
+ SalesProductPricePublishSnapshotDto priceSnapshot;
+ string priceVersion;
+ DateTime priceEffectiveTime;
+
+ if (string.IsNullOrWhiteSpace(order.SalesProductPriceVersion)
+ || order.SalesProductPriceVersion.StartsWith("LIVE-", StringComparison.OrdinalIgnoreCase))
+ {
+ priceSnapshot = await BuildLivePriceSnapshotAsync(product);
+ if (priceSnapshot.Prices.Count == 0)
+ {
+ throw new BusinessException("未命中订单绑定的价格快照版本");
+ }
+
+ priceVersion = order.SalesProductPriceVersion ?? $"LIVE-{product.Id}";
+ priceEffectiveTime = bindTime;
+ }
+ else
+ {
+ var priceRecord = await SalesProductRepository.GetPublishRecordByVersionAsync(
+ product.Id,
+ PriceOperatorType,
+ order.SalesProductPriceVersion);
+ if (priceRecord?.Content == null)
+ {
+ throw new BusinessException("未命中订单绑定的价格快照版本");
+ }
+
+ priceSnapshot = OmsDocHelper.DeserializePriceSnapshot(priceRecord.Content)
+ ?? throw new BusinessException("未命中订单绑定的价格快照版本");
+ if (priceSnapshot.Prices.Count == 0)
+ {
+ throw new BusinessException("未命中订单绑定的价格快照版本");
+ }
+
+ priceVersion = priceRecord.Version;
+ priceEffectiveTime = priceRecord.PublishTime;
+ }
+
+ return new ProductSnapshotBinding
+ {
+ RulesVersion = rulesVersion,
+ PriceVersion = priceVersion,
+ RulesEffectiveTime = rulesEffectiveTime,
+ PriceEffectiveTime = priceEffectiveTime,
+ Rules = rulesSnapshot,
+ Price = priceSnapshot
+ };
+ }
+
+ private async Task UpsertReceivableFeesAsync(
+ Order order,
+ ProductSnapshotBinding snapshotBinding,
+ decimal chargeableWeight,
+ IReadOnlyList zoneKeys,
+ string cargoAttribute,
+ CustomerGroup? customerGroup,
+ string chargingStage)
+ {
+ var fees = ParcelBillingCalculator.CalculateReceivableFees(
+ snapshotBinding.Price,
+ snapshotBinding.PriceVersion,
+ snapshotBinding.PriceEffectiveTime,
+ chargeableWeight,
+ zoneKeys,
+ cargoAttribute,
+ customerGroup,
+ chargingStage);
+
+ if (fees.Count == 0 && ParcelBillingCalculator.HasEnabledReceivablePriceItems(snapshotBinding.Price))
+ {
+ throw new BusinessException("产品卖价快照未配置或未匹配到有效价格");
+ }
+
+ if (fees.Count > 0)
+ {
+ await OrderRepository.UpsertFeesAsync(order.Id, fees);
+ }
+ }
+
private async Task BuildLiveRulesSnapshotAsync(SalesProduct product)
{
var snapshot = new SalesProductRulesPublishSnapshotDto
@@ -340,7 +440,6 @@ public partial class OrderService
CostItem = price.CostItem,
CostUnit = price.CostUnit,
Currency = price.Currency,
- ChargingTime = price.ChargingTime,
ChargingCondition = price.ChargingCondition,
Factors = factorMap.TryGetValue(price.Id, out var factors)
? factors.Select(MapPriceFactorOutput).ToList()
@@ -738,6 +837,26 @@ public partial class OrderService
}
}
+ private static void SyncReceiveToShipAndDownstream(List weights, OrderWeight receive)
+ {
+ foreach (var type in new[] { OrderWeightTypeCodes.Ship, OrderWeightTypeCodes.Downstream })
+ {
+ var row = weights.FirstOrDefault(x => x.Type == type);
+ if (row == null)
+ {
+ continue;
+ }
+
+ row.Length = receive.Length;
+ row.Width = receive.Width;
+ row.Height = receive.Height;
+ row.ActualWeight = receive.ActualWeight;
+ row.VolumetricWeight = receive.VolumetricWeight;
+ row.ChargeableWeight = receive.ChargeableWeight;
+ row.Cubic = receive.Cubic;
+ }
+ }
+
private static Order BuildDraftOrderEntity(
OrderParcelCreateInput input,
SalesProduct product,
@@ -908,6 +1027,122 @@ public partial class OrderService
await OrderRepository.UpdateAsync(order);
}
+ ///
+ /// 入库收货后:覆盖 receive 件重尺、重算计费重,写入 inbound 阶段应收,并同步 ship/downstream 重量行。
+ ///
+ internal async Task ApplyReceiveBillingByWaybillAsync(
+ string waybillNo,
+ decimal? length,
+ decimal? width,
+ decimal? height,
+ decimal? actualWeight)
+ {
+ if (string.IsNullOrWhiteSpace(waybillNo))
+ {
+ return;
+ }
+
+ if (!length.HasValue || !width.HasValue || !height.HasValue || !actualWeight.HasValue
+ || length <= 0 || width <= 0 || height <= 0 || actualWeight <= 0)
+ {
+ return;
+ }
+
+ var order = await OrderRepository.GetByServiceNoAsync(waybillNo.Trim());
+ if (order == null || string.IsNullOrWhiteSpace(order.ProductCode))
+ {
+ return;
+ }
+
+ if (order.OrderStatus is not (OrderStatusCodes.Predeclared or OrderStatusCodes.Received))
+ {
+ return;
+ }
+
+ var product = await SalesProductRepository.GetByProductCodeAsync(order.ProductCode.Trim());
+ if (product == null)
+ {
+ return;
+ }
+
+ var weights = (await OrderRepository.GetWeightsByOrderIdsAsync([order.Id]))
+ .OrderBy(x => x.Id)
+ .ToList();
+ var receive = weights.FirstOrDefault(x => x.Type == OrderWeightTypeCodes.Receive);
+ if (receive == null)
+ {
+ return;
+ }
+
+ receive.Length = length;
+ receive.Width = width;
+ receive.Height = height;
+ receive.ActualWeight = actualWeight;
+ receive.Cubic = ParcelBillingCalculator.CalculateCubic(length.Value, width.Value, height.Value);
+
+ ProductSnapshotBinding snapshotBinding;
+ try
+ {
+ snapshotBinding = await ResolveSnapshotBindingFromOrderAsync(product, order);
+ }
+ catch (BusinessException)
+ {
+ return;
+ }
+
+ try
+ {
+ await ApplyChargeableWeightAsync(product, snapshotBinding.Rules, receive);
+ }
+ catch (BusinessException)
+ {
+ return;
+ }
+
+ SyncReceiveToShipAndDownstream(weights, receive);
+ await OrderRepository.ReplaceWeightsAsync(order.Id, weights);
+
+ var recipients = await OrderRepository.GetRecipientsByOrderIdsAsync([order.Id]);
+ var recipient = recipients.FirstOrDefault();
+ var zoneKeys = await ResolvePriceZoneKeysAsync(
+ product,
+ snapshotBinding.Rules,
+ snapshotBinding.Price,
+ order.ConsigneeCountry ?? string.Empty,
+ recipient?.Province,
+ recipient?.City,
+ recipient?.ZipCode);
+ if (zoneKeys == null || zoneKeys.Count == 0)
+ {
+ return;
+ }
+
+ var customer = order.CustomerId.HasValue
+ ? await CustomerRepository.FirstOrDefaultAsync(x => x.Id == order.CustomerId.Value)
+ : null;
+
+ try
+ {
+ await UpsertReceivableFeesAsync(
+ order,
+ snapshotBinding,
+ receive.ChargeableWeight ?? 0,
+ zoneKeys,
+ order.CargoAttribute ?? CargoAttributeCodes.General,
+ customer?.CustomerGroup,
+ OrderFeeChargingStageCodes.Inbound);
+ }
+ catch (BusinessException)
+ {
+ return;
+ }
+
+ order.OrderStatus = OrderStatusCodes.Received;
+ order.ReceiveTime = DateTime.Now;
+ order.UpdateTime = DateTime.Now;
+ await OrderRepository.UpdateAsync(order);
+ }
+
private async Task BuildParcelCreateOutputAsync(Order order)
{
var mapped = (await MapOrderOutputsAsync([order])).First();
diff --git a/src/Oms.Application/Services/Orders/OrderService.ParcelQuote.cs b/src/Oms.Application/Services/Orders/OrderService.ParcelQuote.cs
index 125e0d8..460637b 100644
--- a/src/Oms.Application/Services/Orders/OrderService.ParcelQuote.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.ParcelQuote.cs
@@ -171,7 +171,7 @@ public partial class OrderService
}
///
- /// 查价试算:按国家+邮编匹配分区,在卖价快照中匹配明细(忽略收费时机)。
+ /// 查价试算:按国家+邮编匹配分区,在卖价快照中匹配明细。
///
private async Task TryComputePriceCheckQuoteAsync(
SalesProduct product,
diff --git a/src/Oms.Application/Services/Orders/OrderService.cs b/src/Oms.Application/Services/Orders/OrderService.cs
index 5fc0b31..d582717 100644
--- a/src/Oms.Application/Services/Orders/OrderService.cs
+++ b/src/Oms.Application/Services/Orders/OrderService.cs
@@ -40,7 +40,7 @@ public partial class OrderService : ApplicationService
/// 3. 按接口约定返回列表结果。
///
[HttpPost("/order/list")]
- public async Task> GetPaginatedListAsync(OrderPaginatedInput input)
+ public async Task> GetPaginatedListAsync([FromBody] OrderPaginatedInput input)
{
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
CustomerRepository,
@@ -204,7 +204,7 @@ public partial class OrderService : ApplicationService
/// 3. 以文件形式返回结果。
///
[HttpPost("/order/export")]
- public async Task ExportAsync(OrderExportInput input)
+ public async Task ExportAsync([FromBody] OrderExportInput input)
{
await CleanupExpiredFilesAsync(GetOrderExportDirectory());
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
@@ -473,7 +473,9 @@ public partial class OrderService : ApplicationService
{
status = status?.Trim();
keyword = keyword?.Trim();
- var hasStatusFilter = !string.IsNullOrWhiteSpace(status) && status != "all";
+ var statusValue = !string.IsNullOrWhiteSpace(status) && !string.Equals(status, "all", StringComparison.OrdinalIgnoreCase)
+ ? status
+ : null;
var hasKeywordFilter = !string.IsNullOrWhiteSpace(keyword);
var hasCustomerFilter = customerId.HasValue;
var customerIdValue = customerId.GetValueOrDefault();
@@ -485,7 +487,7 @@ public partial class OrderService : ApplicationService
var end = createTimeEnd.Value;
return order =>
(!hasCustomerFilter || order.CustomerId == customerIdValue) &&
- (!hasStatusFilter || order.OrderStatus == status) &&
+ (statusValue == null || order.OrderStatus == statusValue) &&
(!hasKeywordFilter ||
order.ServiceNo.Contains(keyword!) ||
(order.ClientNo ?? string.Empty).Contains(keyword!) ||
@@ -499,7 +501,7 @@ public partial class OrderService : ApplicationService
var start = createTimeStart.Value;
return order =>
(!hasCustomerFilter || order.CustomerId == customerIdValue) &&
- (!hasStatusFilter || order.OrderStatus == status) &&
+ (statusValue == null || order.OrderStatus == statusValue) &&
(!hasKeywordFilter ||
order.ServiceNo.Contains(keyword!) ||
(order.ClientNo ?? string.Empty).Contains(keyword!) ||
@@ -512,7 +514,7 @@ public partial class OrderService : ApplicationService
var end = createTimeEnd.Value;
return order =>
(!hasCustomerFilter || order.CustomerId == customerIdValue) &&
- (!hasStatusFilter || order.OrderStatus == status) &&
+ (statusValue == null || order.OrderStatus == statusValue) &&
(!hasKeywordFilter ||
order.ServiceNo.Contains(keyword!) ||
(order.ClientNo ?? string.Empty).Contains(keyword!) ||
@@ -522,7 +524,7 @@ public partial class OrderService : ApplicationService
return order =>
(!hasCustomerFilter || order.CustomerId == customerIdValue) &&
- (!hasStatusFilter || order.OrderStatus == status) &&
+ (statusValue == null || order.OrderStatus == statusValue) &&
(!hasKeywordFilter ||
order.ServiceNo.Contains(keyword!) ||
(order.ClientNo ?? string.Empty).Contains(keyword!) ||
diff --git a/src/Oms.Application/Services/Orders/ParcelBillingCalculator.cs b/src/Oms.Application/Services/Orders/ParcelBillingCalculator.cs
index 29ca860..a81786d 100644
--- a/src/Oms.Application/Services/Orders/ParcelBillingCalculator.cs
+++ b/src/Oms.Application/Services/Orders/ParcelBillingCalculator.cs
@@ -353,23 +353,21 @@ internal static class ParcelBillingCalculator
decimal chargeableWeight,
IReadOnlyList zoneKeys,
string cargoAttribute,
- CustomerGroup? customerGroup)
- {
- var items = priceSnapshot.Prices.Select(p => new BillingPriceItem(
- p.Status, p.ChargingTime, p.CostItem, p.Currency, p.Details));
- return CalculateForecastFees(
- items,
- OrderFeeTypeCodes.Receivable,
+ CustomerGroup? customerGroup) =>
+ CalculateReceivableFees(
+ priceSnapshot,
priceVersion,
priceEffectiveTime,
chargeableWeight,
zoneKeys,
cargoAttribute,
customerGroup,
- onlyForecastChargingTime: false);
- }
+ OrderFeeChargingStageCodes.Forecast);
public static bool HasEnabledQuotePriceItems(SalesProductPricePublishSnapshotDto priceSnapshot) =>
+ HasEnabledReceivablePriceItems(priceSnapshot);
+
+ public static bool HasEnabledReceivablePriceItems(SalesProductPricePublishSnapshotDto priceSnapshot) =>
priceSnapshot.Prices.Any(x => x.Status == 1);
///
@@ -510,14 +508,15 @@ internal static class ParcelBillingCalculator
string zoneName,
string cargoAttribute,
CustomerGroup? customerGroup) =>
- CalculateForecastReceivableFees(
+ CalculateReceivableFees(
priceSnapshot,
priceVersion,
priceEffectiveTime,
chargeableWeight,
new[] { zoneName },
cargoAttribute,
- customerGroup);
+ customerGroup,
+ OrderFeeChargingStageCodes.Forecast);
public static List CalculateForecastReceivableFees(
SalesProductPricePublishSnapshotDto priceSnapshot,
@@ -526,20 +525,67 @@ internal static class ParcelBillingCalculator
decimal chargeableWeight,
IReadOnlyList zoneKeys,
string cargoAttribute,
- CustomerGroup? customerGroup)
- {
- var items = priceSnapshot.Prices.Select(p => new BillingPriceItem(
- p.Status, p.ChargingTime, p.CostItem, p.Currency, p.Details));
- return CalculateForecastFees(
- items,
- OrderFeeTypeCodes.Receivable,
+ CustomerGroup? customerGroup) =>
+ CalculateReceivableFees(
+ priceSnapshot,
priceVersion,
priceEffectiveTime,
chargeableWeight,
zoneKeys,
cargoAttribute,
customerGroup,
- onlyForecastChargingTime: true);
+ OrderFeeChargingStageCodes.Forecast);
+
+ ///
+ /// 应收费用:卖价全部启用项参与;ChargingStage 由件重尺阶段决定。
+ ///
+ public static List CalculateReceivableFees(
+ SalesProductPricePublishSnapshotDto priceSnapshot,
+ string priceVersion,
+ DateTime priceEffectiveTime,
+ decimal chargeableWeight,
+ IReadOnlyList zoneKeys,
+ string cargoAttribute,
+ CustomerGroup? customerGroup,
+ string chargingStage)
+ {
+ var items = priceSnapshot.Prices.Select(p => new ReceivableBillingPriceItem(
+ p.Status, p.CostItem, p.Currency, p.Details));
+ return CalculateReceivableFeesFromItems(
+ items,
+ priceVersion,
+ priceEffectiveTime,
+ chargeableWeight,
+ zoneKeys,
+ cargoAttribute,
+ customerGroup,
+ chargingStage);
+ }
+
+ ///
+ /// 应付费用:买价全部启用项参与;ChargingStage 由件重尺阶段决定。
+ ///
+ public static List CalculatePayableFees(
+ IReadOnlyList prices,
+ string priceVersion,
+ DateTime priceEffectiveTime,
+ decimal chargeableWeight,
+ IReadOnlyList zoneKeys,
+ string cargoAttribute,
+ CustomerGroup? customerGroup,
+ string chargingStage)
+ {
+ var items = prices.Select(p => new PayableBillingPriceItem(
+ p.Status, p.CostItem, p.Currency, p.Details));
+ return CalculatePayableFeesFromItems(
+ items,
+ priceVersion,
+ priceEffectiveTime,
+ chargeableWeight,
+ zoneKeys,
+ cargoAttribute,
+ customerGroup,
+ chargingStage);
}
///
@@ -552,44 +598,25 @@ internal static class ParcelBillingCalculator
decimal chargeableWeight,
string zoneName,
string cargoAttribute,
- CustomerGroup? customerGroup)
- {
- var items = prices.Select(p => new BillingPriceItem(
- p.Status, p.ChargingTime, p.CostItem, p.Currency, p.Details));
- return CalculateForecastFees(
- items,
- OrderFeeTypeCodes.Payable,
+ CustomerGroup? customerGroup) =>
+ CalculatePayableFees(
+ prices,
priceVersion,
priceEffectiveTime,
chargeableWeight,
new[] { zoneName },
cargoAttribute,
customerGroup,
- onlyForecastChargingTime: true);
- }
+ OrderFeeChargingStageCodes.Forecast);
public static bool HasEnabledForecastPriceItems(SalesProductPricePublishSnapshotDto priceSnapshot) =>
- priceSnapshot.Prices.Any(x => x.Status == 1 && IsForecastChargingTime(x.ChargingTime));
+ HasEnabledReceivablePriceItems(priceSnapshot);
+
+ public static bool HasEnabledPayablePriceItems(IReadOnlyList prices) =>
+ prices.Any(x => x.Status == 1);
public static bool HasEnabledForecastPayablePriceItems(IReadOnlyList prices) =>
- prices.Any(x => x.Status == 1 && IsForecastChargingTime(x.ChargingTime));
-
- public static string NormalizeChargingTime(string? chargingTime)
- {
- var value = chargingTime?.Trim();
- if (string.IsNullOrWhiteSpace(value))
- {
- return OrderFeeChargingStageCodes.Forecast;
- }
-
- return value switch
- {
- "预报" => OrderFeeChargingStageCodes.Forecast,
- "入库" => OrderFeeChargingStageCodes.Inbound,
- "出库" => OrderFeeChargingStageCodes.Outbound,
- _ => value.ToLowerInvariant()
- };
- }
+ HasEnabledPayablePriceItems(prices);
public static string GetCargoAttributeLabel(string? cargoAttribute) => cargoAttribute switch
{
@@ -662,25 +689,19 @@ internal static class ParcelBillingCalculator
Cubic = CalculateCubic(context.Length, context.Width, context.Height)
};
- private static List CalculateForecastFees(
- IEnumerable priceItems,
- string feeType,
+ private static List CalculateReceivableFeesFromItems(
+ IEnumerable priceItems,
string priceVersion,
DateTime priceEffectiveTime,
decimal chargeableWeight,
IReadOnlyList zoneKeys,
string cargoAttribute,
CustomerGroup? customerGroup,
- bool onlyForecastChargingTime)
+ string chargingStage)
{
var fees = new List();
foreach (var priceItem in priceItems.Where(x => x.Status == 1))
{
- if (onlyForecastChargingTime && !IsForecastChargingTime(priceItem.ChargingTime))
- {
- continue;
- }
-
var detail = MatchPriceDetail(priceItem.Details, zoneKeys, cargoAttribute, chargeableWeight);
if (detail == null)
{
@@ -696,31 +717,71 @@ internal static class ParcelBillingCalculator
customerGroup);
fees.Add(new OrderFee
{
- Type = feeType,
+ Type = OrderFeeTypeCodes.Receivable,
CostItem = priceItem.CostItem,
Amount = amount,
Currency = priceItem.Currency,
PriceNo = priceVersion,
PriceEffectiveTime = priceEffectiveTime,
- ChargingStage = OrderFeeChargingStageCodes.Forecast
+ ChargingStage = chargingStage
});
}
return fees;
}
- private readonly record struct BillingPriceItem(
+ private static List CalculatePayableFeesFromItems(
+ IEnumerable priceItems,
+ string priceVersion,
+ DateTime priceEffectiveTime,
+ decimal chargeableWeight,
+ IReadOnlyList zoneKeys,
+ string cargoAttribute,
+ CustomerGroup? customerGroup,
+ string chargingStage)
+ {
+ var fees = new List();
+ foreach (var priceItem in priceItems.Where(x => x.Status == 1))
+ {
+ var detail = MatchPriceDetail(priceItem.Details, zoneKeys, cargoAttribute, chargeableWeight);
+ if (detail == null)
+ {
+ continue;
+ }
+
+ var amount = CalculateDetailAmount(
+ priceItem.Details,
+ detail,
+ zoneKeys,
+ cargoAttribute,
+ chargeableWeight,
+ customerGroup);
+ fees.Add(new OrderFee
+ {
+ Type = OrderFeeTypeCodes.Payable,
+ CostItem = priceItem.CostItem,
+ Amount = amount,
+ Currency = priceItem.Currency,
+ PriceNo = priceVersion,
+ PriceEffectiveTime = priceEffectiveTime,
+ ChargingStage = chargingStage
+ });
+ }
+
+ return fees;
+ }
+
+ private readonly record struct ReceivableBillingPriceItem(
byte Status,
- string? ChargingTime,
string CostItem,
string Currency,
List Details);
- private static bool IsForecastChargingTime(string? chargingTime)
- {
- var normalized = NormalizeChargingTime(chargingTime);
- return normalized is OrderFeeChargingStageCodes.Forecast or "";
- }
+ private readonly record struct PayableBillingPriceItem(
+ byte Status,
+ string CostItem,
+ string Currency,
+ List Details);
private static ChannelPriceDetailOutput? MatchPriceDetail(
IReadOnlyList details,
diff --git a/src/Oms.Application/Shared/PublishSnapshotSlimmer.cs b/src/Oms.Application/Shared/PublishSnapshotSlimmer.cs
index 99e01fe..f622062 100644
--- a/src/Oms.Application/Shared/PublishSnapshotSlimmer.cs
+++ b/src/Oms.Application/Shared/PublishSnapshotSlimmer.cs
@@ -19,7 +19,6 @@ public static class PublishSnapshotSlimmer
CostItem = price.CostItem,
CostUnit = price.CostUnit,
Currency = price.Currency,
- ChargingTime = price.ChargingTime,
ChargingCondition = price.ChargingCondition,
Factors = price.Factors,
Details = price.Details
diff --git a/src/Oms.Domain/ChannelsAggregate/Entities/SalesProductPrice.cs b/src/Oms.Domain/ChannelsAggregate/Entities/SalesProductPrice.cs
index 00cb835..ee55ea9 100644
--- a/src/Oms.Domain/ChannelsAggregate/Entities/SalesProductPrice.cs
+++ b/src/Oms.Domain/ChannelsAggregate/Entities/SalesProductPrice.cs
@@ -21,7 +21,5 @@ public class SalesProductPrice : OmsAuditedEntity
public string Currency { get; set; } = string.Empty;
- public string? ChargingTime { get; set; }
-
public string? ChargingCondition { get; set; }
}
diff --git a/src/Oms.Domain/ChannelsAggregate/Entities/ServiceChannelPrice.cs b/src/Oms.Domain/ChannelsAggregate/Entities/ServiceChannelPrice.cs
index f23aa88..665759b 100644
--- a/src/Oms.Domain/ChannelsAggregate/Entities/ServiceChannelPrice.cs
+++ b/src/Oms.Domain/ChannelsAggregate/Entities/ServiceChannelPrice.cs
@@ -21,7 +21,5 @@ public class ServiceChannelPrice : OmsAuditedEntity
public string Currency { get; set; } = string.Empty;
- public string? ChargingTime { get; set; }
-
public string? ChargingCondition { get; set; }
}
diff --git a/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs b/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
index b8906e5..ea41dad 100644
--- a/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
+++ b/src/Oms.Domain/ChannelsAggregate/Repositories/ISalesProductRepository.cs
@@ -52,6 +52,12 @@ public interface ISalesProductRepository : IRepository
Task GetPublishRecordByIdAsync(int id, CancellationToken cancellationToken = default);
+ Task GetPublishRecordByVersionAsync(
+ int salesProductId,
+ string operatorType,
+ string version,
+ CancellationToken cancellationToken = default);
+
Task GetEffectivePublishRecordAsync(
int salesProductId,
string operatorType,
diff --git a/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs b/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
index 7526450..06ec59c 100644
--- a/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
+++ b/src/Oms.SqlSugarCore/Channels/SalesProductRepository.cs
@@ -195,6 +195,28 @@ public class SalesProductRepository : OmsSqlSugarRepository, ISale
return await db.Queryable().FirstAsync(x => x.Id == id, cancellationToken);
}
+ public async Task GetPublishRecordByVersionAsync(
+ int salesProductId,
+ string operatorType,
+ string version,
+ CancellationToken cancellationToken = default)
+ {
+ if (string.IsNullOrWhiteSpace(version))
+ {
+ return null;
+ }
+
+ var db = await GetDbContextAsync(cancellationToken);
+ var records = await db.Queryable()
+ .Where(x => x.SalesProductId == salesProductId
+ && x.OperatorType == operatorType
+ && x.Version == version)
+ .OrderBy(x => x.PublishTime, SqlSugar.OrderByType.Desc)
+ .Take(1)
+ .ToListAsync(cancellationToken);
+ return records.FirstOrDefault();
+ }
+
public async Task GetEffectivePublishRecordAsync(
int salesProductId,
string operatorType,
diff --git a/src/Oms.Tests/ParcelBillingCalculatorDemoTests.cs b/src/Oms.Tests/ParcelBillingCalculatorDemoTests.cs
index 8bc1660..792adcf 100644
--- a/src/Oms.Tests/ParcelBillingCalculatorDemoTests.cs
+++ b/src/Oms.Tests/ParcelBillingCalculatorDemoTests.cs
@@ -89,10 +89,10 @@ public class ParcelBillingCalculatorDemoTests
var (priceVersion, effectiveTime) = ParcelBillingTestData.SnapshotMeta();
var receivableSnapshot = ParcelBillingTestData.BuildReceivableSnapshot(
ParcelBillingTestData.ReceivablePriceItem(
- "预报", 1, "freight",
+ 1, "freight",
ParcelBillingTestData.ContinueFreightDetail()),
ParcelBillingTestData.ReceivablePriceItem(
- "预报", 1, "操作费",
+ 1, "操作费",
ParcelBillingTestData.FixedPriceDetail(5M)));
var receivableFees = ParcelBillingCalculator.CalculateForecastReceivableFees(
@@ -119,7 +119,7 @@ public class ParcelBillingCalculatorDemoTests
// —— 5. 应付(买价)——
var payablePrices = ParcelBillingTestData.BuildPayablePrices(
ParcelBillingTestData.PayablePriceItem(
- "预报", 1, "freight",
+ 1, "freight",
ParcelBillingTestData.ContinueFreightDetail(
firstWeight: 1M, firstPrice: 12M, continueUnit: 0.5M, continuePrice: 4M)));
diff --git a/src/Oms.Tests/ParcelBillingCalculatorTests.cs b/src/Oms.Tests/ParcelBillingCalculatorTests.cs
index f9721e2..d40a06f 100644
--- a/src/Oms.Tests/ParcelBillingCalculatorTests.cs
+++ b/src/Oms.Tests/ParcelBillingCalculatorTests.cs
@@ -61,7 +61,6 @@ public class ParcelBillingCalculatorTests
{
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
ParcelBillingTestData.ReceivablePriceItem(
- "预报",
1,
"freight",
ParcelBillingTestData.ContinueFreightDetail()));
@@ -83,30 +82,50 @@ public class ParcelBillingCalculatorTests
fees[0].PriceNo.Should().Be(_meta.PriceVersion);
}
- [Theory]
- [InlineData("入库")]
- [InlineData("出库")]
- [InlineData("inbound")]
- [InlineData("outbound")]
- public void CalculateForecastReceivableFees_ShouldSkipNonForecastChargingTime(string chargingTime)
+ [Fact]
+ public void CalculateReceivableFees_ShouldIncludeAllEnabledPriceItems()
{
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
ParcelBillingTestData.ReceivablePriceItem(
- chargingTime,
1,
"freight",
ParcelBillingTestData.ContinueFreightDetail()));
- var fees = ParcelBillingCalculator.CalculateForecastReceivableFees(
+ var fees = ParcelBillingCalculator.CalculateReceivableFees(
snapshot,
_meta.PriceVersion,
_meta.EffectiveTime,
1.2M,
- Zone,
+ new[] { Zone },
"general",
- null);
+ null,
+ OrderFeeChargingStageCodes.Forecast);
- fees.Should().BeEmpty();
+ fees.Should().ContainSingle();
+ fees[0].ChargingStage.Should().Be(OrderFeeChargingStageCodes.Forecast);
+ }
+
+ [Fact]
+ public void CalculateReceivableFees_InboundStage_ShouldSetChargingStage()
+ {
+ var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
+ ParcelBillingTestData.ReceivablePriceItem(
+ 1,
+ "freight",
+ ParcelBillingTestData.ContinueFreightDetail()));
+
+ var fees = ParcelBillingCalculator.CalculateReceivableFees(
+ snapshot,
+ _meta.PriceVersion,
+ _meta.EffectiveTime,
+ 1.2M,
+ new[] { Zone },
+ "general",
+ null,
+ OrderFeeChargingStageCodes.Inbound);
+
+ fees.Should().ContainSingle();
+ fees[0].ChargingStage.Should().Be(OrderFeeChargingStageCodes.Inbound);
}
[Fact]
@@ -114,12 +133,10 @@ public class ParcelBillingCalculatorTests
{
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
ParcelBillingTestData.ReceivablePriceItem(
- "预报",
1,
"freight",
ParcelBillingTestData.ContinueFreightDetail()),
ParcelBillingTestData.ReceivablePriceItem(
- "预报",
1,
"操作费",
ParcelBillingTestData.FixedPriceDetail(5M)));
@@ -150,7 +167,7 @@ public class ParcelBillingCalculatorTests
detail.CustomerGroupValues = new Dictionary { ["客户组1"] = 15M };
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
- ParcelBillingTestData.ReceivablePriceItem("预报", 1, "freight", detail));
+ ParcelBillingTestData.ReceivablePriceItem(1, "freight", detail));
var fees = ParcelBillingCalculator.CalculateForecastReceivableFees(
snapshot,
@@ -170,7 +187,6 @@ public class ParcelBillingCalculatorTests
{
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
ParcelBillingTestData.ReceivablePriceItem(
- "outbound",
1,
"freight",
ParcelBillingTestData.TotalTierDetail("3", 0.5M, 10M, weightInterval: "(0-0.5]"),
@@ -200,7 +216,7 @@ public class ParcelBillingCalculatorTests
}
[Fact]
- public void CalculateQuoteReceivableFees_ShouldSupportOutboundTotalPriceTiers()
+ public void CalculateQuoteReceivableFees_ShouldSupportTotalPriceTiers()
{
var details = new[]
{
@@ -210,7 +226,7 @@ public class ParcelBillingCalculatorTests
ParcelBillingTestData.TotalTierDetail("3", 2M, 14M),
};
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
- ParcelBillingTestData.ReceivablePriceItem("outbound", 1, "freight", details));
+ ParcelBillingTestData.ReceivablePriceItem(1, "freight", details));
var fees = ParcelBillingCalculator.CalculateQuoteReceivableFees(
snapshot,
@@ -232,7 +248,7 @@ public class ParcelBillingCalculatorTests
detail.CustomerGroupValues = new Dictionary { ["普通客户"] = 12M };
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
- ParcelBillingTestData.ReceivablePriceItem("预报", 1, "freight", detail));
+ ParcelBillingTestData.ReceivablePriceItem(1, "freight", detail));
var fees = ParcelBillingCalculator.CalculateForecastReceivableFees(
snapshot,
@@ -248,12 +264,13 @@ public class ParcelBillingCalculatorTests
}
[Fact]
- public void HasEnabledForecastPriceItems_ShouldDetectForecastEnabledItems()
+ public void HasEnabledReceivablePriceItems_ShouldDetectAnyEnabledItems()
{
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
- ParcelBillingTestData.ReceivablePriceItem("入库", 1, "freight", ParcelBillingTestData.ContinueFreightDetail()),
- ParcelBillingTestData.ReceivablePriceItem("预报", 1, "freight", ParcelBillingTestData.ContinueFreightDetail()));
+ ParcelBillingTestData.ReceivablePriceItem(1, "freight", ParcelBillingTestData.ContinueFreightDetail()),
+ ParcelBillingTestData.ReceivablePriceItem(0, "freight", ParcelBillingTestData.ContinueFreightDetail()));
+ ParcelBillingCalculator.HasEnabledReceivablePriceItems(snapshot).Should().BeTrue();
ParcelBillingCalculator.HasEnabledForecastPriceItems(snapshot).Should().BeTrue();
}
@@ -271,7 +288,6 @@ public class ParcelBillingCalculatorTests
{
var prices = ParcelBillingTestData.BuildPayablePrices(
ParcelBillingTestData.PayablePriceItem(
- "预报",
1,
"freight",
ParcelBillingTestData.ContinueFreightDetail(
@@ -300,7 +316,6 @@ public class ParcelBillingCalculatorTests
{
var prices = ParcelBillingTestData.BuildPayablePrices(
ParcelBillingTestData.PayablePriceItem(
- "预报",
0,
"freight",
ParcelBillingTestData.ContinueFreightDetail()));
@@ -315,7 +330,7 @@ public class ParcelBillingCalculatorTests
null);
fees.Should().BeEmpty();
- ParcelBillingCalculator.HasEnabledForecastPayablePriceItems(prices).Should().BeFalse();
+ ParcelBillingCalculator.HasEnabledPayablePriceItems(prices).Should().BeFalse();
}
[Fact]
@@ -323,9 +338,9 @@ public class ParcelBillingCalculatorTests
{
var detail = ParcelBillingTestData.ContinueFreightDetail();
var snapshot = ParcelBillingTestData.BuildReceivableSnapshot(
- ParcelBillingTestData.ReceivablePriceItem("预报", 1, "freight", detail));
+ ParcelBillingTestData.ReceivablePriceItem(1, "freight", detail));
var payablePrices = ParcelBillingTestData.BuildPayablePrices(
- ParcelBillingTestData.PayablePriceItem("预报", 1, "freight", detail));
+ ParcelBillingTestData.PayablePriceItem(1, "freight", detail));
var receivable = ParcelBillingCalculator.CalculateForecastReceivableFees(
snapshot, _meta.PriceVersion, _meta.EffectiveTime, 1.2M, Zone, "general", null);
diff --git a/src/Oms.Tests/PriceCheckSnapshotVerificationTests.cs b/src/Oms.Tests/PriceCheckSnapshotVerificationTests.cs
index cdf68e6..ff24576 100644
--- a/src/Oms.Tests/PriceCheckSnapshotVerificationTests.cs
+++ b/src/Oms.Tests/PriceCheckSnapshotVerificationTests.cs
@@ -9,7 +9,7 @@ using Oms.Domain.OrdersAggregate.Consts;
namespace Oms.Tests;
///
-/// 验证查价卖价快照匹配:忽略收费时机、unit 公式、重量左开右闭区间。
+/// 验证查价卖价快照匹配:unit 公式、重量左开右闭区间。
///
public class PriceCheckSnapshotVerificationTests
{
@@ -23,7 +23,6 @@ public class PriceCheckSnapshotVerificationTests
Id = 1,
Status = 1,
CostItem = "freight",
- ChargingTime = "outbound",
Details =
[
Detail(24, 1, "total", "3", "0,0.5", 11),
@@ -37,7 +36,6 @@ public class PriceCheckSnapshotVerificationTests
Id = 2,
Status = 1,
CostItem = "handling",
- ChargingTime = "outbound",
Details = [Detail(28, 2, "total", "3", "0,10", 20)]
})
]
diff --git a/src/Oms.Tests/Support/ParcelBillingTestData.cs b/src/Oms.Tests/Support/ParcelBillingTestData.cs
index dbb6595..b7755dc 100644
--- a/src/Oms.Tests/Support/ParcelBillingTestData.cs
+++ b/src/Oms.Tests/Support/ParcelBillingTestData.cs
@@ -24,7 +24,6 @@ internal static class ParcelBillingTestData
params ServiceChannelPriceListOutput[] prices) => prices.ToList();
public static SalesProductPriceListOutput ReceivablePriceItem(
- string chargingTime,
byte status,
string costItem,
params ChannelPriceDetailOutput[] details) =>
@@ -33,12 +32,10 @@ internal static class ParcelBillingTestData
Status = status,
CostItem = costItem,
Currency = "CNY",
- ChargingTime = chargingTime,
Details = details.ToList()
};
public static ServiceChannelPriceListOutput PayablePriceItem(
- string chargingTime,
byte status,
string costItem,
params ChannelPriceDetailOutput[] details) =>
@@ -47,7 +44,6 @@ internal static class ParcelBillingTestData
Status = status,
CostItem = costItem,
Currency = "CNY",
- ChargingTime = chargingTime,
Details = details.ToList()
};