This commit is contained in:
2026-08-05 09:30:08 +08:00
parent 3791fee285
commit 81c9c92f5d
10 changed files with 112 additions and 14 deletions
@@ -13,13 +13,15 @@ import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("FBA计费OpenAPI契约")
class FbaPricingContractTest {
@Test
@DisplayName("只有客户规则列表允许省略企业参数")
void onlyCustomerRuleListAllowsOptionalTenant() {
Method rules = method("rules");
assertThat(rules.getParameterTypes()[1]).isEqualTo(Long.class);
assertThat(rules.getParameters()[1].getAnnotation(RequestParam.class).required()).isFalse();
@DisplayName("只有基础资料列表允许省略企业参数")
void onlyMasterDataListsAllowOptionalTenant() {
for (String listMethod : new String[] {"rules", "rates"}) {
Method method = method(listMethod);
assertThat(method.getParameterTypes()[1]).isEqualTo(Long.class);
assertThat(method.getParameters()[1].getAnnotation(RequestParam.class).required()).isFalse();
}
for (String scopedMethod : new String[] {"rule", "createRule", "retireRule", "rates",
for (String scopedMethod : new String[] {"rule", "createRule", "retireRule",
"rate", "createRate", "retireRate"}) {
Method method = method(scopedMethod);
assertThat(method.getParameterTypes()[1]).isEqualTo(long.class);
@@ -56,6 +58,12 @@ class FbaPricingContractTest {
.doesNotContain("name: customerName")
.doesNotContain("name: chargeMode")
.doesNotContain("name: status");
String carrierRates = openapi.substring(
openapi.indexOf("/api/platform/v1/fba-pricing/carrier-rates:"),
openapi.indexOf("/api/platform/v1/fba-pricing/carrier-rates/versions:"));
assertThat(carrierRates)
.contains("OptionalTenantId")
.contains("name: rateCode");
assertThat(openapi)
.contains("OptionalTenantId: {name: tenantId, in: query, required: false")
.contains("schema: {type: string, pattern: '^[1-9][0-9]*$'}")
@@ -3,6 +3,7 @@ package com.baiyue.firstleg.repository;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baiyue.firstleg.entity.CustomerChargeRuleEntity;
import com.baiyue.firstleg.entity.CarrierFbaRateEntity;
import com.baiyue.firstleg.mapper.CarrierFbaRateMapper;
import com.baiyue.firstleg.mapper.CustomerChargeRuleMapper;
import com.baiyue.firstleg.mapper.InboundFeeItemMapper;
@@ -29,6 +30,8 @@ class FbaPricingRepositoryRuleListTest {
static void initializeEntityMetadata() {
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), "test"),
CustomerChargeRuleEntity.class);
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), "test"),
CarrierFbaRateEntity.class);
}
@Test
@@ -41,6 +44,17 @@ class FbaPricingRepositoryRuleListTest {
assertThat(queryValues(10001L, "CR-1")).containsExactlyInAnyOrder(10001L, "CR-1");
}
@Test
void platformRateListOmitsTenantConditionWhenTenantIsAbsent() {
assertThat(rateQueryValues(null, null)).isEmpty();
}
@Test
void platformRateListKeepsTenantAndRateCodeFiltersWhenProvided() {
assertThat(rateQueryValues(10001L, "RATE-1"))
.containsExactlyInAnyOrder(10001L, "RATE-1");
}
@Test
void internalVersionCalculationKeepsTenantAndRuleCodeFilters() {
CustomerChargeRuleMapper rules = mock(CustomerChargeRuleMapper.class);
@@ -76,8 +90,28 @@ class FbaPricingRepositoryRuleListTest {
return wrapper.getValue().getParamNameValuePairs().values();
}
private static Collection<Object> rateQueryValues(Long tenantId, String rateCode) {
CarrierFbaRateMapper rates = mock(CarrierFbaRateMapper.class);
when(rates.selectList(org.mockito.ArgumentMatchers.any())).thenReturn(List.of());
FbaPricingRepository repository = repository(mock(CustomerChargeRuleMapper.class), rates);
repository.listRates(tenantId, rateCode);
@SuppressWarnings("unchecked")
ArgumentCaptor<LambdaQueryWrapper<CarrierFbaRateEntity>> wrapper =
ArgumentCaptor.forClass(LambdaQueryWrapper.class);
verify(rates).selectList(wrapper.capture());
wrapper.getValue().getSqlSegment();
return wrapper.getValue().getParamNameValuePairs().values();
}
private static FbaPricingRepository repository(CustomerChargeRuleMapper rules) {
return new FbaPricingRepository(rules, mock(CarrierFbaRateMapper.class),
return repository(rules, mock(CarrierFbaRateMapper.class));
}
private static FbaPricingRepository repository(
CustomerChargeRuleMapper rules, CarrierFbaRateMapper rates) {
return new FbaPricingRepository(rules, rates,
mock(InboundPricingMapper.class), mock(InboundFeeMapper.class), mock(InboundFeeItemMapper.class),
mock(InboundPricingIdempotencyMapper.class), mock(InboundOutboxMapper.class));
}
@@ -26,4 +26,16 @@ class InboundWorkflowSqlContractTest {
.contains("information_schema.statistics")
.contains("idx_review_exception_release");
}
@Test
@DisplayName("存量托盘分配表会补齐仓储资源租户")
void shouldMigrateWarehouseResourceTenantForExistingAllocationTable() throws Exception {
String migration = new ClassPathResource("db/phase2-fba-pricing-migration.sql")
.getContentAsString(StandardCharsets.UTF_8);
assertThat(migration)
.contains("phase2_fba_add_column('fl_inbound_pallet_allocation', 'warehouse_resource_tenant_id'")
.contains("SET warehouse_resource_tenant_id = tenant_id")
.contains("MODIFY COLUMN warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL");
}
}