This commit is contained in:
2026-09-16 19:32:52 +08:00
parent dfcd280dd7
commit 8797c0bef9
5 changed files with 88 additions and 18 deletions
@@ -5,6 +5,7 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.domain.PriceModel;
import com.baiyue.firstleg.domain.PricingTaxMode;
import com.baiyue.firstleg.dto.FbaPricingDtos.FeeSnapshotResponse;
import com.baiyue.firstleg.entity.CarrierFbaRateEntity;
import com.baiyue.firstleg.entity.InboundFeeEntity;
import com.baiyue.firstleg.entity.InboundFeeItemEntity;
import com.baiyue.firstleg.entity.InboundPricingEntity;
@@ -770,6 +771,7 @@ class FbaPricingServiceTest {
when(repository.findInbound(TENANT, 30002L)).thenReturn(secondInbound);
when(repository.findLatestFeeForUpdate(TENANT, INBOUND)).thenReturn(first);
when(repository.findLatestFeeForUpdate(TENANT, 30002L)).thenReturn(second);
when(repository.findRate(201L)).thenReturn(storedRate(201L, PriceModel.REGION_WEIGHT_TIER));
when(repository.nextFeeVersion(TENANT, INBOUND)).thenReturn(2);
when(repository.nextFeeVersion(TENANT, 30002L)).thenReturn(2);
when(repository.completeIdempotency(any(), eq(901L), eq(NOW))).thenReturn(1);
@@ -824,6 +826,7 @@ class FbaPricingServiceTest {
when(repository.findInbound(TENANT, 30002L)).thenReturn(unlockedInbound);
when(repository.findLatestFeeForUpdate(TENANT, INBOUND)).thenReturn(sent);
when(repository.findLatestFeeForUpdate(TENANT, 30002L)).thenReturn(calculated);
when(repository.findRate(201L)).thenReturn(storedRate(201L, PriceModel.REGION_WEIGHT_TIER));
when(repository.nextFeeVersion(TENANT, 30002L)).thenReturn(2);
when(repository.completeIdempotency(any(), eq(901L), eq(NOW))).thenReturn(1);
when(repository.supersedeCurrent(TENANT, 502L, "CALCULATED")).thenReturn(1);
@@ -847,6 +850,50 @@ class FbaPricingServiceTest {
verify(priceBookEstimator).estimate(eq(TENANT), any());
}
@Test
@DisplayName("同柜混合固定仓价和区域阶梯时仅重算区域阶梯成员")
void recalculatesOnlyRegionalMembersWhenContainerUsesMixedPriceModels() {
readyRepository();
InboundPricingEntity regionalInbound = inbound("90", "0.1");
InboundPricingEntity fixedInbound = inbound("110", "0.1");
fixedInbound.setId(30002L); fixedInbound.setInboundCode("RK-FIXED");
InboundFeeEntity regional = savedFee("CALCULATED");
regional.setActualWeightKg(new BigDecimal("90")); regional.setActualVolumeCbm(new BigDecimal("0.1"));
InboundFeeEntity fixed = savedFee("CALCULATED");
fixed.setId(502L); fixed.setInboundId(30002L); fixed.setCarrierRateId(203L);
fixed.setActualWeightKg(new BigDecimal("110")); fixed.setActualVolumeCbm(new BigDecimal("0.1"));
when(repository.containerTierMembersForUpdate(901L, TENANT)).thenReturn(List.of(
memberRow(901L, INBOUND, "90", "0.1"), memberRow(901L, 30002L, "110", "0.1")
));
when(repository.findInbound(TENANT, INBOUND)).thenReturn(regionalInbound);
when(repository.findInbound(TENANT, 30002L)).thenReturn(fixedInbound);
when(repository.findLatestFeeForUpdate(TENANT, INBOUND)).thenReturn(regional);
when(repository.findLatestFeeForUpdate(TENANT, 30002L)).thenReturn(fixed);
when(repository.findRate(201L)).thenReturn(storedRate(201L, PriceModel.REGION_WEIGHT_TIER));
when(repository.findRate(203L)).thenReturn(storedRate(203L, PriceModel.FBA_WAREHOUSE_RATE));
when(repository.nextFeeVersion(TENANT, INBOUND)).thenReturn(2);
when(repository.completeIdempotency(any(), eq(901L), eq(NOW))).thenReturn(1);
when(repository.supersedeCurrent(TENANT, 501L, "CALCULATED")).thenReturn(1);
when(repository.markInboundContainerFeeRecalculated(eq(TENANT), eq(INBOUND), anyString(),
any(), any(), anyString(), any()))
.thenReturn(1);
when(priceBookEstimator.estimate(eq(TENANT), any())).thenReturn(regionEstimate("90", "8", "720"));
when(containerTierAllocator.allocate(any(), eq(new BigDecimal("8")))).thenReturn(
new ContainerTierAmountAllocator.Allocation(new BigDecimal("90"), new BigDecimal("720"),
Map.of(INBOUND, new BigDecimal("720.00"))));
var result = service.recalculateUnlockedContainerCustomerFees(901L, TENANT, "mixed-models");
assertThat(result.status()).isEqualTo(FbaPricingService.ContainerFeeRecalculationStatus.RECALCULATED);
assertThat(result.recalculatedCount()).isEqualTo(1);
verify(repository).supersedeCurrent(TENANT, 501L, "CALCULATED");
verify(repository, never()).supersedeCurrent(TENANT, 502L, "CALCULATED");
ArgumentCaptor<List<ContainerTierAmountAllocator.Member>> members = ArgumentCaptor.forClass(List.class);
verify(containerTierAllocator).allocate(members.capture(), eq(new BigDecimal("8")));
assertThat(members.getValue()).extracting(ContainerTierAmountAllocator.Member::inboundId)
.containsExactly(INBOUND);
}
@Test
@DisplayName("柜内费用全部锁定时关系变更无需重算且不报错")
void skipsContainerRecalculationWhenEveryFeeIsImmutable() {
@@ -973,6 +1020,12 @@ class FbaPricingServiceTest {
new BigDecimal(amount), "USD", new BigDecimal("167"), 6, "HALF_UP");
}
private CarrierFbaRateEntity storedRate(long id, PriceModel model) {
CarrierFbaRateEntity rate = new CarrierFbaRateEntity();
rate.setId(id); rate.setPriceModel(model.name());
return rate;
}
private InboundPricingIdempotencyEntity completed(String operation, long feeId) {
InboundPricingIdempotencyEntity value = new InboundPricingIdempotencyEntity();
value.setId(900L); value.setOperation(operation); value.setStatus("COMPLETED");