新增海外仓阶梯费用

This commit is contained in:
2026-08-05 11:20:28 +08:00
parent 9678ee0f1f
commit cac377de96
20 changed files with 801 additions and 10 deletions
@@ -0,0 +1,36 @@
package com.baiyue.warehouse.controller;
import org.junit.jupiter.api.Test;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
class PlatformOverseasStorageFeeControllerContractTest {
@Test
void exposesCrud() {
assertThat(PlatformOverseasStorageFeeController.class.getAnnotation(RequestMapping.class).value())
.containsExactly("/api/platform/v1/overseas-storage-fees");
assertMethod("page", GetMapping.class, "platform:overseas-storage-fee:list");
assertMethod("detail", GetMapping.class, "platform:overseas-storage-fee:list");
assertMethod("create", PostMapping.class, "platform:overseas-storage-fee:create");
assertMethod("update", PutMapping.class, "platform:overseas-storage-fee:edit");
assertMethod("delete", DeleteMapping.class, "platform:overseas-storage-fee:delete");
}
private static void assertMethod(String name, Class<? extends Annotation> mapping, String authority) {
Method method = Arrays.stream(PlatformOverseasStorageFeeController.class.getDeclaredMethods())
.filter(candidate -> candidate.getName().equals(name)).findFirst().orElseThrow();
assertThat(method.getAnnotation(mapping)).isNotNull();
assertThat(method.getAnnotation(PreAuthorize.class).value())
.isEqualTo("hasAuthority('" + authority + "')");
}
}
@@ -0,0 +1,31 @@
package com.baiyue.warehouse.repository;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class OverseasStorageFeeSqlContractTest {
@Test
void containsSchemaAndPermissions() throws IOException {
String sql = Files.readString(Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"));
assertThat(sql)
.contains("CREATE TABLE IF NOT EXISTS wh_overseas_storage_fee_rule")
.contains("CREATE TABLE IF NOT EXISTS wh_overseas_storage_fee_tier")
.contains("uk_overseas_fee_active_customer")
.contains("idx_overseas_fee_page")
.contains("idx_overseas_fee_customer_name")
.contains("uk_overseas_fee_tier_start")
.contains("idx_overseas_fee_tier_rule")
.contains("platform:overseas-storage-fee:list")
.contains("platform:overseas-storage-fee:create")
.contains("platform:overseas-storage-fee:edit")
.contains("platform:overseas-storage-fee:delete")
.contains("CALL unified_assert_overseas_storage_fee()")
.contains("海外仓阶梯费用表、索引和权限校验通过");
}
}
@@ -0,0 +1,110 @@
package com.baiyue.warehouse.service;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.dto.OverseasStorageFeeDtos;
import com.baiyue.warehouse.entity.OverseasStorageFeeRuleEntity;
import com.baiyue.warehouse.entity.OverseasStorageFeeTierEntity;
import com.baiyue.warehouse.repository.OverseasStorageFeeRepository;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.math.BigDecimal;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SpringJUnitConfig(OverseasStorageFeeService.class)
class OverseasStorageFeeServiceTest {
@MockBean
private OverseasStorageFeeRepository repository;
@Resource
private OverseasStorageFeeService service;
@Test
void createsRule() {
doAnswer(invocation -> {
OverseasStorageFeeRuleEntity rule = invocation.getArgument(0);
rule.setId(10L);
return null;
}).when(repository).insertRule(any());
Long id = service.create(new OverseasStorageFeeDtos.CreateRequest(
10001L, "示例客户", "USD", List.of(tier(8, 30, "0.8"), tier(1, 7, "0.5"))));
assertThat(id).isEqualTo(10L);
verify(repository).insertTiers(any());
}
@Test
void rejectsTierGap() {
OverseasStorageFeeDtos.CreateRequest request = new OverseasStorageFeeDtos.CreateRequest(
10001L, "示例客户", "USD", List.of(tier(1, 7, "0.5"), tier(9, 30, "0.8")));
assertThatThrownBy(() -> service.create(request)).isInstanceOf(BizException.class);
verify(repository, never()).insertRule(any());
}
@Test
void rejectsDuplicateCustomer() {
when(repository.existsCustomer(10001L, null)).thenReturn(true);
OverseasStorageFeeDtos.CreateRequest request = new OverseasStorageFeeDtos.CreateRequest(
10001L, "示例客户", "USD", List.of(tier(1, 30, "0.8")));
assertThatThrownBy(() -> service.create(request)).isInstanceOf(BizException.class);
}
@Test
void pagesWithTiers() {
OverseasStorageFeeRuleEntity rule = rule();
OverseasStorageFeeTierEntity tier = new OverseasStorageFeeTierEntity();
tier.setId(20L);
tier.setRuleId(10L);
tier.setStartDay(1);
tier.setEndDay(30);
tier.setUnitPrice(new BigDecimal("0.8"));
tier.setSortNo(1);
OverseasStorageFeeDtos.PageQuery query = new OverseasStorageFeeDtos.PageQuery(1, 20, null, null);
when(repository.page(query)).thenReturn(new PageResult<>(List.of(rule), 1, 20, 1, 1));
when(repository.findTiers(List.of(10L))).thenReturn(List.of(tier));
OverseasStorageFeeDtos.View result = service.page(query).records().get(0);
assertThat(result.customerId()).isEqualTo(10001L);
assertThat(result.tiers()).singleElement().extracting(OverseasStorageFeeDtos.TierView::unitPrice)
.isEqualTo(new BigDecimal("0.8"));
}
@Test
void detectsStaleUpdate() {
OverseasStorageFeeRuleEntity rule = rule();
when(repository.find(10L)).thenReturn(rule);
OverseasStorageFeeDtos.UpdateRequest request = new OverseasStorageFeeDtos.UpdateRequest(
10001L, "示例客户", "USD", List.of(tier(1, 30, "0.8")), 2);
assertThatThrownBy(() -> service.update(10L, request)).isInstanceOf(BizException.class);
verify(repository, never()).updateRule(any());
}
private static OverseasStorageFeeDtos.TierRequest tier(int start, int end, String price) {
return new OverseasStorageFeeDtos.TierRequest(start, end, new BigDecimal(price));
}
private static OverseasStorageFeeRuleEntity rule() {
OverseasStorageFeeRuleEntity rule = new OverseasStorageFeeRuleEntity();
rule.setId(10L);
rule.setTenantId(10001L);
rule.setCustomerName("示例客户");
rule.setCurrency("USD");
rule.setVersion(1);
return rule;
}
}