Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
2026-09-04 12:03:17 +08:00
6 changed files with 23 additions and 28 deletions
@@ -169,7 +169,7 @@ public class FbaPricingRepository {
public List<CustomerChargeRuleEntity> matchRules(InboundPricingEntity inbound, LocalDateTime at) { public List<CustomerChargeRuleEntity> matchRules(InboundPricingEntity inbound, LocalDateTime at) {
return rules.selectList(new LambdaQueryWrapper<CustomerChargeRuleEntity>() return rules.selectList(new LambdaQueryWrapper<CustomerChargeRuleEntity>()
.eq(CustomerChargeRuleEntity::getTenantId, inbound.getTenantId()) .eq(CustomerChargeRuleEntity::getTenantId, inbound.getTenantId())
.eq(CustomerChargeRuleEntity::getCustomerId, inbound.getCustomerId()) .eq(CustomerChargeRuleEntity::getCustomerId, inbound.getTenantId())
.eq(CustomerChargeRuleEntity::getBusinessType, inbound.getBusinessType()) .eq(CustomerChargeRuleEntity::getBusinessType, inbound.getBusinessType())
.eq(CustomerChargeRuleEntity::getTaxMode, inbound.getTaxMode()) .eq(CustomerChargeRuleEntity::getTaxMode, inbound.getTaxMode())
.eq(CustomerChargeRuleEntity::getStatus, "ACTIVE") .eq(CustomerChargeRuleEntity::getStatus, "ACTIVE")
@@ -348,9 +348,6 @@ public class FbaPricingService {
if (!"FBA".equals(inbound.getDestinationType()) && !"OVERSEAS".equals(inbound.getDestinationType())) { if (!"FBA".equals(inbound.getDestinationType()) && !"OVERSEAS".equals(inbound.getDestinationType())) {
throw conflict("当前目的地类型不支持自动计费"); throw conflict("当前目的地类型不支持自动计费");
} }
if (inbound.getCustomerId() == null || inbound.getCustomerId() <= 0) {
throw conflict("入库单缺少订单客户归属,不能生成对客费用");
}
if (inbound.getWarehouseId() == null || !StringUtils.hasText(inbound.getChannelCode())) { if (inbound.getWarehouseId() == null || !StringUtils.hasText(inbound.getChannelCode())) {
throw conflict("入库单缺少起运仓或渠道匹配维度"); throw conflict("入库单缺少起运仓或渠道匹配维度");
} }
@@ -428,7 +425,7 @@ public class FbaPricingService {
fee.setChargeRuleId(null); fee.setChargeRuleVersion(null); fee.setChargeRuleId(null); fee.setChargeRuleVersion(null);
fee.setCarrierRateId(rate.getId()); fee.setCarrierRateVersion(rate.getRateVersion()); fee.setCarrierRateId(rate.getId()); fee.setCarrierRateVersion(rate.getRateVersion());
fee.setPriceBookVersionId(estimate.priceBookVersionId()); fee.setPriceBookVersionId(estimate.priceBookVersionId());
fee.setRuleCode(null); fee.setCustomerId(inbound.getCustomerId()); fee.setRuleCode(null); fee.setCustomerId(tenantId);
fee.setCustomerName(inbound.getCustomerName()); fee.setBusinessType(inbound.getBusinessType()); fee.setCustomerName(inbound.getCustomerName()); fee.setBusinessType(inbound.getBusinessType());
fee.setTaxMode(inbound.getTaxMode()); fee.setPricingTaxMode(inbound.getPricingTaxMode()); fee.setTaxMode(inbound.getTaxMode()); fee.setPricingTaxMode(inbound.getPricingTaxMode());
fee.setRoundingScale(estimate.roundingScale()); fee.setRoundingMode(estimate.roundingMode()); fee.setRoundingScale(estimate.roundingScale()); fee.setRoundingMode(estimate.roundingMode());
@@ -100,7 +100,7 @@ public class InboundFeeDetailService {
detail.setInboundCode(inbound.getInboundCode()); detail.setInboundCode(inbound.getInboundCode());
detail.setDirection("RECEIVABLE"); detail.setDirection("RECEIVABLE");
detail.setBusinessDate(now.toLocalDate()); detail.setBusinessDate(now.toLocalDate());
detail.setCustomerId(inbound.getCustomerId()); detail.setCustomerId(tenantId);
detail.setCustomerName(inbound.getCustomerName()); detail.setCustomerName(inbound.getCustomerName());
detail.setInvoiceTitle(inbound.getCompanyName()); detail.setInvoiceTitle(inbound.getCompanyName());
detail.setFeeCategorySnapshot(feeItem.getCategory()); detail.setFeeCategorySnapshot(feeItem.getCategory());
@@ -186,7 +186,7 @@ public class InboundFeeDetailService {
detail.setSourceType("FBA_PRICING"); detail.setSourceFeeId(fee.getId()); detail.setSourceType("FBA_PRICING"); detail.setSourceFeeId(fee.getId());
detail.setSourceFeeVersion(fee.getFeeVersion()); detail.setSourceFeeNo(fee.getFeeNo()); detail.setSourceFeeVersion(fee.getFeeVersion()); detail.setSourceFeeNo(fee.getFeeNo());
detail.setInboundCode(inbound.getInboundCode()); detail.setDirection("RECEIVABLE"); detail.setInboundCode(inbound.getInboundCode()); detail.setDirection("RECEIVABLE");
detail.setBusinessDate(now.toLocalDate()); detail.setCustomerId(inbound.getCustomerId()); detail.setBusinessDate(now.toLocalDate()); detail.setCustomerId(tenantId);
detail.setCustomerName(inbound.getCustomerName()); detail.setInvoiceTitle(inbound.getCompanyName()); detail.setCustomerName(inbound.getCustomerName()); detail.setInvoiceTitle(inbound.getCompanyName());
detail.setFeeCategorySnapshot(feeItem.getCategory()); detail.setTradeScopeSnapshot(feeItem.getTradeScope()); detail.setFeeCategorySnapshot(feeItem.getCategory()); detail.setTradeScopeSnapshot(feeItem.getTradeScope());
detail.setFeeTypeNameSnapshot(feeItem.getFeeTypeName()); detail.setChannelCode(inbound.getChannelCode()); detail.setFeeTypeNameSnapshot(feeItem.getFeeTypeName()); detail.setChannelCode(inbound.getChannelCode());
@@ -60,7 +60,7 @@ public class MeasurementBatchService {
} }
validateSource(command); validateSource(command);
List<InboundMeasurementItemEntity> calculatedItems = calculateItems( List<InboundMeasurementItemEntity> calculatedItems = calculateItems(
command, dimensionWeighting.load(command.tenantId()), inbound.getCustomerId()); command, dimensionWeighting.load(command.tenantId()));
InboundMeasurementEntity measurement; InboundMeasurementEntity measurement;
if (command.measurementId() == null) { if (command.measurementId() == null) {
@@ -140,8 +140,7 @@ public class MeasurementBatchService {
} }
private List<InboundMeasurementItemEntity> calculateItems( private List<InboundMeasurementItemEntity> calculateItems(
MeasurementBatchCommand command, CustomerDimensionWeightingService.RuleSet dimensionRules, MeasurementBatchCommand command, CustomerDimensionWeightingService.RuleSet dimensionRules) {
Long customerId) {
Set<String> itemNumbers = new HashSet<>(); Set<String> itemNumbers = new HashSet<>();
return command.items().stream().map(source -> { return command.items().stream().map(source -> {
if (!itemNumbers.add(source.itemNo())) { if (!itemNumbers.add(source.itemNo())) {
@@ -163,8 +162,8 @@ public class MeasurementBatchService {
baseLength, baseWidth, baseHeight); baseLength, baseWidth, baseHeight);
String requestedMode = normalizeMode(source.coefficientMode()); String requestedMode = normalizeMode(source.coefficientMode());
CustomerChargeRuleEntity coefficientRule = "MULTIPLY".equals(requestedMode) CustomerChargeRuleEntity coefficientRule = "MULTIPLY".equals(requestedMode)
? requireCoefficientRule(command.tenantId(), customerId, source.chargeRuleId()) ? requireCoefficientRule(command.tenantId(), source.chargeRuleId())
: requestedMode == null ? findDefaultCoefficientRule(command.tenantId(), customerId) : null; : requestedMode == null ? findDefaultCoefficientRule(command.tenantId()) : null;
String coefficientMode = coefficientRule != null ? "MULTIPLY" : requestedMode; String coefficientMode = coefficientRule != null ? "MULTIPLY" : requestedMode;
boolean useDimensionRule = "ADD".equals(coefficientMode); boolean useDimensionRule = "ADD".equals(coefficientMode);
BigDecimal addition = weighted.edgeAdditionCm() == null BigDecimal addition = weighted.edgeAdditionCm() == null
@@ -257,15 +256,13 @@ public class MeasurementBatchService {
return normalized; return normalized;
} }
private CustomerChargeRuleEntity findDefaultCoefficientRule(long tenantId, Long customerId) { private CustomerChargeRuleEntity findDefaultCoefficientRule(long tenantId) {
if (customerId == null || customerId <= 0) return null; return pricingRepository.findDefaultRule(tenantId, tenantId);
return pricingRepository.findDefaultRule(tenantId, customerId);
} }
private CustomerChargeRuleEntity requireCoefficientRule(long tenantId, Long customerId, Long ruleId) { private CustomerChargeRuleEntity requireCoefficientRule(long tenantId, Long ruleId) {
Long effectiveCustomerId = tenantId;
CustomerChargeRuleEntity rule = ruleId == null CustomerChargeRuleEntity rule = ruleId == null
? pricingRepository.findDefaultRule(tenantId, effectiveCustomerId) ? pricingRepository.findDefaultRule(tenantId, tenantId)
: pricingRepository.findRule(tenantId, ruleId); : pricingRepository.findRule(tenantId, ruleId);
if (rule == null || !"ACTIVE".equals(rule.getStatus()) if (rule == null || !"ACTIVE".equals(rule.getStatus())
|| !java.util.Objects.equals(rule.getTenantId(), tenantId)) { || !java.util.Objects.equals(rule.getTenantId(), tenantId)) {
@@ -98,7 +98,7 @@ class FbaPricingServiceTest {
assertThat(fee.getValue().getPricingTaxMode()).isEqualTo("TAX_INCLUDED"); assertThat(fee.getValue().getPricingTaxMode()).isEqualTo("TAX_INCLUDED");
assertThat(fee.getValue().getChargeRuleId()).isNull(); assertThat(fee.getValue().getChargeRuleId()).isNull();
assertThat(fee.getValue().getCarrierId()).isNull(); assertThat(fee.getValue().getCarrierId()).isNull();
assertThat(fee.getValue().getCustomerId()).isEqualTo(11L); assertThat(fee.getValue().getCustomerId()).isEqualTo(TENANT);
assertThat(fee.getValue().getConversionFactor()).isEqualByComparingTo("167"); assertThat(fee.getValue().getConversionFactor()).isEqualByComparingTo("167");
assertThat(fee.getValue().getRoundingScale()).isEqualTo(6); assertThat(fee.getValue().getRoundingScale()).isEqualTo(6);
assertThat(fee.getValue().getRoundingMode()).isEqualTo("HALF_UP"); assertThat(fee.getValue().getRoundingMode()).isEqualTo("HALF_UP");
@@ -151,19 +151,20 @@ class FbaPricingServiceTest {
} }
@Test @Test
@DisplayName("缺少订单客户归属时拒绝生成对客费用") @DisplayName("订单客户字段为空时使用租户归属生成对客费用")
void rejectsMissingOrderCustomerOwnership() { void usesTenantOwnershipWhenOrderCustomerIsMissing() {
readyRepository(); readyRepository();
InboundPricingEntity inbound = inbound("200.000", "0.2000"); InboundPricingEntity inbound = inbound("200.000", "0.2000");
inbound.setCustomerId(null); inbound.setCustomerId(null);
when(repository.findInbound(TENANT, INBOUND)).thenReturn(inbound); when(repository.findInbound(TENANT, INBOUND)).thenReturn(inbound);
when(priceBookEstimator.estimate(any())).thenReturn(
estimate("KG", "200.000", "2.000000", "400.00", "0.00"));
assertThatThrownBy(() -> service.calculate( assertThat(service.calculate(TENANT, OPERATOR, INBOUND, NOW, "calc-no-customer"))
TENANT, OPERATOR, INBOUND, NOW, "calc-no-customer")) .isNotNull();
.isInstanceOf(BizException.class) ArgumentCaptor<InboundFeeEntity> fee = ArgumentCaptor.forClass(InboundFeeEntity.class);
.hasMessageContaining("缺少订单客户归属"); verify(repository).insertFee(fee.capture());
verify(priceBookEstimator, never()).estimate(any()); assertThat(fee.getValue().getCustomerId()).isEqualTo(TENANT);
verify(repository, never()).insertFee(any());
} }
@Test @Test
@@ -427,7 +427,7 @@ class MeasurementBatchServiceTest {
InboundOrderEntity inbound = new InboundOrderEntity(); InboundOrderEntity inbound = new InboundOrderEntity();
inbound.setId(10L); inbound.setId(10L);
inbound.setTenantId(1L); inbound.setTenantId(1L);
inbound.setCustomerId(1L); inbound.setCustomerId(null);
inbound.setProcessStatus("WAIT_MEASURE"); inbound.setProcessStatus("WAIT_MEASURE");
inbound.setVersion(0); inbound.setVersion(0);
return inbound; return inbound;