优化
This commit is contained in:
+4
@@ -24,6 +24,8 @@ class PlatformMasterDataControllerContractTest {
|
||||
assertMethod(PlatformPartnerController.class, "create", PostMapping.class, "platform:counterparty:create");
|
||||
assertMethod(PlatformPartnerController.class, "update", PutMapping.class, "platform:counterparty:edit");
|
||||
assertMethod(PlatformPartnerController.class, "changeStatus", PatchMapping.class, "platform:counterparty:status");
|
||||
assertMethod(PlatformPartnerController.class, "importTemplate", GetMapping.class, "platform:counterparty:import");
|
||||
assertMethod(PlatformPartnerController.class, "importPartners", PostMapping.class, "platform:counterparty:import");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -34,6 +36,8 @@ class PlatformMasterDataControllerContractTest {
|
||||
assertMethod(PlatformExpressCompanyController.class, "create", PostMapping.class, "platform:express:create");
|
||||
assertMethod(PlatformExpressCompanyController.class, "update", PutMapping.class, "platform:express:edit");
|
||||
assertMethod(PlatformExpressCompanyController.class, "changeStatus", PatchMapping.class, "platform:express:status");
|
||||
assertMethod(PlatformExpressCompanyController.class, "importTemplate", GetMapping.class, "platform:express:import");
|
||||
assertMethod(PlatformExpressCompanyController.class, "importCompanies", PostMapping.class, "platform:express:import");
|
||||
}
|
||||
|
||||
private static void assertContract(Class<?> controller, String authority, String path) throws Exception {
|
||||
|
||||
@@ -26,10 +26,28 @@ class PartnerRepositoryTest {
|
||||
@DisplayName("候选查询强制租户和启用状态")
|
||||
void shouldEnforceTenantAndActiveStatusForCandidateQuery() {
|
||||
PartnerMapper mapper=mock(PartnerMapper.class); when(mapper.selectList(any())).thenReturn(List.of());
|
||||
new PartnerRepository(mapper).activeCandidates(10001,"示例","CUSTOMER");
|
||||
when(mapper.selectPartnerIdsByType(10001,"SHIPPER")).thenReturn(List.of(1L));
|
||||
new PartnerRepository(mapper).activeCandidates(10001,"示例","SHIPPER");
|
||||
@SuppressWarnings("unchecked") ArgumentCaptor<LambdaQueryWrapper<PartnerEntity>> c=ArgumentCaptor.forClass(LambdaQueryWrapper.class);
|
||||
verify(mapper).selectList(c.capture()); c.getValue().getSqlSegment();
|
||||
assertThat(c.getValue().getParamNameValuePairs().values()).contains(10001L,"ACTIVE","CUSTOMER");
|
||||
assertThat(c.getValue().getParamNameValuePairs().values()).contains(10001L,"ACTIVE",1L);
|
||||
verify(mapper).selectPartnerIdsByType(10001L, "SHIPPER");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("默认候选只包含发货单位和收货单位")
|
||||
void shouldLimitDefaultCandidatesToOrderPartyTypes() {
|
||||
PartnerMapper mapper=mock(PartnerMapper.class);
|
||||
when(mapper.selectPartnerIdsByType(10001L,"SHIPPER")).thenReturn(List.of(1L));
|
||||
when(mapper.selectPartnerIdsByType(10001L,"CONSIGNEE")).thenReturn(List.of(2L,1L));
|
||||
when(mapper.selectList(any())).thenReturn(List.of());
|
||||
|
||||
new PartnerRepository(mapper).activeCandidates(10001L,null,null);
|
||||
|
||||
@SuppressWarnings("unchecked") ArgumentCaptor<LambdaQueryWrapper<PartnerEntity>> wrapper=ArgumentCaptor.forClass(LambdaQueryWrapper.class);
|
||||
verify(mapper).selectList(wrapper.capture());
|
||||
wrapper.getValue().getSqlSegment();
|
||||
assertThat(wrapper.getValue().getParamNameValuePairs().values()).contains(10001L,"ACTIVE",1L,2L);
|
||||
}
|
||||
@Test
|
||||
@DisplayName("详情查询强制租户和启用状态")
|
||||
@@ -45,6 +63,7 @@ class PartnerRepositoryTest {
|
||||
@DisplayName("平台分页强制租户并支持筛选")
|
||||
void shouldEnforceTenantAndSupportFilteringForPlatformPage() {
|
||||
PartnerMapper mapper=mock(PartnerMapper.class);
|
||||
when(mapper.selectPartnerIdsByType(10001L, "CUSTOMER")).thenReturn(List.of(9L));
|
||||
when(mapper.selectPage(any(Page.class), any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
new PartnerRepository(mapper).page(10001L,
|
||||
@@ -55,6 +74,6 @@ class PartnerRepositoryTest {
|
||||
verify(mapper).selectPage(any(Page.class), wrapper.capture());
|
||||
wrapper.getValue().getSqlSegment();
|
||||
assertThat(wrapper.getValue().getParamNameValuePairs().values())
|
||||
.contains(10001L, "CUSTOMER", "ACTIVE", "%示例%");
|
||||
.contains(10001L, 9L, "ACTIVE", "%示例%");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -28,9 +28,11 @@ class WarehouseSchemaContractTest {
|
||||
@DisplayName("往来单位表包含实体全部持久化字段")
|
||||
void shouldContainAllPersistentFieldsInPartnerTable() throws IOException {
|
||||
String sql = read("warehouse-partner.sql");
|
||||
assertColumns(sql, "wh_partner", "partner_code", "partner_name", "partner_type", "contact_name",
|
||||
assertColumns(sql, "wh_partner", "data_scope_id", "partner_code", "partner_name", "partner_type", "contact_name",
|
||||
"contact_phone", "contact_email", "country_code", "province", "city", "district", "address_line",
|
||||
"postal_code", "status");
|
||||
"postal_code", "status", "remark");
|
||||
assertThat(sql).contains("CREATE TABLE IF NOT EXISTS wh_partner_type")
|
||||
.contains("idx_wh_partner_type_scope");
|
||||
assertBaseColumns(sql);
|
||||
}
|
||||
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.baiyue.warehouse.service;
|
||||
|
||||
import com.baiyue.warehouse.entity.ExpressCompanyEntity;
|
||||
import com.baiyue.warehouse.repository.ExpressCompanyRepository;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@DisplayName("快递公司批量导入")
|
||||
class ExpressCompanyImportServiceTest {
|
||||
@Test
|
||||
@DisplayName("标准模板通过整批校验后写入全部数据")
|
||||
void shouldImportValidWorkbookAfterFullValidation() throws Exception {
|
||||
ExpressCompanyRepository repository = mock(ExpressCompanyRepository.class);
|
||||
ExpressCompanyImportService service = new ExpressCompanyImportService(repository);
|
||||
byte[] workbook = withRows(service.template(), new String[][] {
|
||||
{"SF", "顺丰速运", "95338", "https://www.sf-express.com", "https://example.com/{trackingNo}", "ACTIVE", "国内件"}
|
||||
});
|
||||
|
||||
var result = service.importFile(10001L, "express.xlsx", workbook);
|
||||
|
||||
assertThat(result.success()).isTrue();
|
||||
assertThat(result.importedRows()).isEqualTo(1);
|
||||
var captor = org.mockito.ArgumentCaptor.forClass(ExpressCompanyEntity.class);
|
||||
verify(repository).insert(captor.capture());
|
||||
assertThat(captor.getValue().getTenantId()).isEqualTo(10001L);
|
||||
assertThat(captor.getValue().getCompanyCode()).isEqualTo("SF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("文件内重复名称时整批拒绝且不写入")
|
||||
void shouldRejectWholeWorkbookWhenAnyRowIsInvalid() throws Exception {
|
||||
ExpressCompanyRepository repository = mock(ExpressCompanyRepository.class);
|
||||
ExpressCompanyImportService service = new ExpressCompanyImportService(repository);
|
||||
byte[] workbook = withRows(service.template(), new String[][] {
|
||||
{"SF", "顺丰速运", "", "", "", "ACTIVE", ""},
|
||||
{"SF2", "顺丰速运", "", "", "", "ACTIVE", ""}
|
||||
});
|
||||
|
||||
var result = service.importFile(10001L, "express.xlsx", workbook);
|
||||
|
||||
assertThat(result.success()).isFalse();
|
||||
assertThat(result.importedRows()).isZero();
|
||||
assertThat(result.errors()).anyMatch(error -> error.row() == 5 && error.field().contains("名称"));
|
||||
verify(repository, never()).insert(any());
|
||||
}
|
||||
|
||||
private static byte[] withRows(byte[] template, String[][] rows) throws Exception {
|
||||
try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(template));
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
var sheet = workbook.getSheetAt(0);
|
||||
for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
||||
var row = sheet.createRow(rowIndex + 3);
|
||||
for (int column = 0; column < rows[rowIndex].length; column++) {
|
||||
row.createCell(column).setCellValue(rows[rowIndex][column]);
|
||||
}
|
||||
}
|
||||
workbook.write(output);
|
||||
return output.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.baiyue.warehouse.service;
|
||||
|
||||
import com.baiyue.warehouse.dto.MasterDataQueries.PartnerImportResult;
|
||||
import com.baiyue.warehouse.entity.PartnerEntity;
|
||||
import com.baiyue.warehouse.repository.PartnerRepository;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@DisplayName("往来单位批量导入")
|
||||
class PartnerImportServiceTest {
|
||||
@Test
|
||||
@DisplayName("标准模板支持多类型并写入服务端数据范围")
|
||||
void shouldImportValidMultiTypeRow() throws Exception {
|
||||
PartnerRepository repository = mock(PartnerRepository.class);
|
||||
PartnerImportService service = new PartnerImportService(repository);
|
||||
byte[] file = withRows(service.template(), new String[][] {
|
||||
{"CUS-100", "测试单位", "CUSTOMER,SHIPPER", "张三", "13800138000", "test@example.com",
|
||||
"CN", "广东省", "深圳市", "南山区", "测试路 1 号", "518000", "ACTIVE", "测试备注"}
|
||||
});
|
||||
|
||||
PartnerImportResult result = service.importFile(10001L, "partners.xlsx", file);
|
||||
|
||||
assertThat(result.success()).isTrue();
|
||||
assertThat(result.importedRows()).isEqualTo(1);
|
||||
var captor = org.mockito.ArgumentCaptor.forClass(PartnerEntity.class);
|
||||
verify(repository).insert(captor.capture());
|
||||
assertThat(captor.getValue().getDataScopeId()).isEqualTo(10001L);
|
||||
assertThat(captor.getValue().getTypes()).containsExactly("CUSTOMER", "SHIPPER");
|
||||
assertThat(captor.getValue().getRemark()).isEqualTo("测试备注");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("文件内任一错误时整批零写入并返回行号")
|
||||
void shouldRejectWholeBatchWhenAnyRowIsInvalid() throws Exception {
|
||||
PartnerRepository repository = mock(PartnerRepository.class);
|
||||
PartnerImportService service = new PartnerImportService(repository);
|
||||
byte[] file = withRows(service.template(), new String[][] {
|
||||
{"CUS-100", "测试单位一", "CUSTOMER", "张三", "13800138000", "", "CN", "", "深圳市", "", "测试路 1 号", "", "ACTIVE", ""},
|
||||
{"CUS-100", "测试单位二", "UNKNOWN", "李四", "13900139000", "bad-email", "C", "", "", "", "", "", "ENABLED", ""}
|
||||
});
|
||||
|
||||
PartnerImportResult result = service.importFile(10001L, "partners.xlsx", file);
|
||||
|
||||
assertThat(result.success()).isFalse();
|
||||
assertThat(result.importedRows()).isZero();
|
||||
assertThat(result.errors()).anyMatch(error -> error.row() == 5 && error.field().equals("单位编码"));
|
||||
assertThat(result.errors()).anyMatch(error -> error.row() == 5 && error.field().equals("单位类型"));
|
||||
verify(repository, never()).insert(any());
|
||||
}
|
||||
|
||||
private static byte[] withRows(byte[] template, String[][] values) throws Exception {
|
||||
try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(template));
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
for (int rowIndex = 0; rowIndex < values.length; rowIndex++) {
|
||||
Row row = workbook.getSheetAt(0).createRow(rowIndex + 3);
|
||||
for (int column = 0; column < values[rowIndex].length; column++) {
|
||||
row.createCell(column).setCellValue(values[rowIndex][column]);
|
||||
}
|
||||
}
|
||||
workbook.write(output);
|
||||
return output.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,11 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class PartnerQueryServiceTest {
|
||||
@Test void unsupportedCandidateTypeReturnsBadRequest() {
|
||||
PartnerRepository repository = mock(PartnerRepository.class);
|
||||
assertThatThrownBy(() -> new PartnerQueryService(repository).candidates(10001L, null, "CUSTOMER"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("SHIPPER");
|
||||
}
|
||||
@Test void missingOrCrossTenantPartnerReturnsNotFound() {
|
||||
PartnerRepository repository = mock(PartnerRepository.class);
|
||||
|
||||
|
||||
+17
-1
@@ -72,8 +72,11 @@ class PlatformMasterDataManagementServiceTest {
|
||||
org.mockito.ArgumentCaptor<PartnerEntity> entity = org.mockito.ArgumentCaptor.forClass(PartnerEntity.class);
|
||||
verify(repository).insert(entity.capture());
|
||||
assertThat(entity.getValue().getTenantId()).isEqualTo(10001L);
|
||||
assertThat(entity.getValue().getDataScopeId()).isEqualTo(10001L);
|
||||
assertThat(entity.getValue().getPartnerCode()).isEqualTo("CUS-001");
|
||||
assertThat(entity.getValue().getPartnerName()).isEqualTo("示例客户");
|
||||
assertThat(entity.getValue().getTypes()).containsExactly("CUSTOMER", "SHIPPER");
|
||||
assertThat(entity.getValue().getRemark()).isEqualTo("测试备注");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -132,6 +135,18 @@ class PlatformMasterDataManagementServiceTest {
|
||||
verify(repository, never()).insert(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("快递公司名称在租户内必须唯一")
|
||||
void shouldRequireUniqueExpressCompanyNameWithinTenant() {
|
||||
ExpressCompanyRepository repository = mock(ExpressCompanyRepository.class);
|
||||
when(repository.existsName(10001L, "顺丰速运", null)).thenReturn(true);
|
||||
ExpressCompanyQueryService service = new ExpressCompanyQueryService(repository);
|
||||
|
||||
assertThatThrownBy(() -> service.create(10001L, expressRequest()))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("名称");
|
||||
verify(repository, never()).insert(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("快递公司并发重复编码统一返回业务冲突")
|
||||
void shouldReturnBusinessConflictForConcurrentDuplicateExpressCompanyCode() {
|
||||
@@ -200,7 +215,8 @@ class PlatformMasterDataManagementServiceTest {
|
||||
|
||||
private static PartnerSaveRequest partnerRequest() {
|
||||
return new PartnerSaveRequest("CUS-001", "示例客户", "CUSTOMER", "张三", "13800138000",
|
||||
"test@example.com", "CN", "广东省", "深圳市", "南山区", "示例地址", "518000", "ACTIVE");
|
||||
"test@example.com", "CN", "广东省", "深圳市", "南山区", "示例地址", "518000", "ACTIVE",
|
||||
java.util.List.of("CUSTOMER", "SHIPPER"), "测试备注");
|
||||
}
|
||||
|
||||
private static ExpressCompanySaveRequest expressRequest() {
|
||||
|
||||
Reference in New Issue
Block a user