后台去重数据新增国家

This commit is contained in:
2026-08-23 22:50:58 +08:00
parent 5a750be066
commit 8712df2645
12 changed files with 294 additions and 37 deletions
@@ -56,6 +56,7 @@ class DedupeTotalDataControllerTest {
eq(LocalDate.of(2026, 7, 1)),
eq(LocalDate.of(2026, 7, 31)),
eq(3L),
isNull(),
eq(8L));
ResponseEntity<StreamingResponseBody> response = controller.export(
@@ -63,6 +64,7 @@ class DedupeTotalDataControllerTest {
LocalDate.of(2026, 7, 1),
LocalDate.of(2026, 7, 31),
3L,
null,
request);
assertNotNull(response.getBody());
@@ -84,9 +86,10 @@ class DedupeTotalDataControllerTest {
eq(LocalDate.of(2026, 7, 1)),
eq(LocalDate.of(2026, 7, 31)),
eq(3L),
isNull(),
eq(8L));
verify(service, never()).writeMonthlyZipExport(
any(OutputStream.class), any(), any(), any(), any(), any());
any(OutputStream.class), any(), any(), any(), any(), any(), any());
verifyNoInteractions(permissionMenuService);
}
@@ -109,6 +112,7 @@ class DedupeTotalDataControllerTest {
null,
LocalDate.of(2026, 8, 2),
3L,
null,
request);
assertEquals(MediaType.parseMediaType(
@@ -125,9 +129,10 @@ class DedupeTotalDataControllerTest {
isNull(),
eq(LocalDate.of(2026, 8, 2)),
eq(3L),
isNull(),
eq(8L));
verify(service, never()).writeMonthlyZipExport(
any(OutputStream.class), any(), any(), any(), any(), any());
any(OutputStream.class), any(), any(), any(), any(), any(), any());
}
@Test
@@ -153,6 +158,7 @@ class DedupeTotalDataControllerTest {
eq(LocalDate.of(2026, 7, 15)),
eq(LocalDate.of(2026, 8, 2)),
eq(3L),
isNull(),
eq(8L));
ResponseEntity<StreamingResponseBody> response = controller.export(
@@ -160,6 +166,7 @@ class DedupeTotalDataControllerTest {
LocalDate.of(2026, 7, 15),
LocalDate.of(2026, 8, 2),
3L,
null,
request);
assertEquals(MediaType.parseMediaType("application/zip"), response.getHeaders().getContentType());
@@ -176,8 +183,9 @@ class DedupeTotalDataControllerTest {
eq(LocalDate.of(2026, 7, 15)),
eq(LocalDate.of(2026, 8, 2)),
eq(3L),
isNull(),
eq(8L));
verify(service, never()).writeExport(any(OutputStream.class), any(), any(), any(), any(), any());
verify(service, never()).writeExport(any(OutputStream.class), any(), any(), any(), any(), any(), any());
}
@Test
@@ -194,6 +202,7 @@ class DedupeTotalDataControllerTest {
LocalDate.of(2026, 8, 2),
LocalDate.of(2026, 7, 15),
3L,
null,
request));
assertEquals(400, exception.getCode());
@@ -21,6 +21,7 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.test.util.ReflectionTestUtils;
@@ -188,6 +189,58 @@ class DedupeTotalDataServiceTest {
verify(dedupeTotalDataMapper, never()).insert(any(DedupeTotalDataEntity.class));
}
@Test
void importReadsAndNormalizesCountryColumn() throws Exception {
when(adminUserMapper.selectById(23L)).thenReturn(user(23L, "normal", "member-a"));
stubWritableGroup(23L, 7L);
when(dedupeTotalDataMapper.selectExistingDataValues(List.of("B012345678"))).thenReturn(List.of());
when(dedupeTotalDataMapper.insertBatchIgnore(any())).thenReturn(1);
MockMultipartFile file = asinCountryWorkbook("B012345678", "德国, US,United Kingdom");
var result = service.importFromExcel(file, 7L, 23L);
assertEquals(1, result.getInsertedCount());
ArgumentCaptor<List<DedupeTotalDataEntity>> captor = ArgumentCaptor.forClass(List.class);
verify(dedupeTotalDataMapper).insertBatchIgnore(captor.capture());
assertEquals("DE,US,UK", captor.getValue().getFirst().getCountry());
}
@Test
void importKeepsCountryBlankWhenHeaderMissing() throws Exception {
when(adminUserMapper.selectById(23L)).thenReturn(user(23L, "normal", "member-a"));
stubWritableGroup(23L, 7L);
when(dedupeTotalDataMapper.selectExistingDataValues(List.of("B012345678"))).thenReturn(List.of());
when(dedupeTotalDataMapper.insertBatchIgnore(any())).thenReturn(1);
var result = service.importFromExcel(asinWorkbook("B012345678"), 7L, 23L);
assertEquals(1, result.getInsertedCount());
ArgumentCaptor<List<DedupeTotalDataEntity>> captor = ArgumentCaptor.forClass(List.class);
verify(dedupeTotalDataMapper).insertBatchIgnore(captor.capture());
assertEquals(null, captor.getValue().getFirst().getCountry());
}
@Test
@SuppressWarnings({"rawtypes", "unchecked"})
void pageFiltersByCountryWithFindInSet() {
TableInfoHelper.initTableInfo(
new MapperBuilderAssistant(new MybatisConfiguration(), ""),
DedupeTotalDataEntity.class);
when(adminUserMapper.selectById(1L)).thenReturn(user(1L, "super_admin", "root"));
when(dedupeTotalDataMapper.selectCount(any())).thenReturn(0L);
when(dedupeTotalDataMapper.selectList(any())).thenReturn(List.of());
service.page(1, 15, "", "", null, null, null, "UK", 1L);
ArgumentCaptor<LambdaQueryWrapper<DedupeTotalDataEntity>> queryCaptor =
ArgumentCaptor.forClass((Class) LambdaQueryWrapper.class);
verify(dedupeTotalDataMapper).selectCount(queryCaptor.capture());
LambdaQueryWrapper<DedupeTotalDataEntity> query = queryCaptor.getValue();
query.getSqlSegment();
assertTrue(query.getParamNameValuePairs().containsValue("UK"));
assertTrue(query.getCustomSqlSegment().contains("FIND_IN_SET"));
}
@Test
void concurrentDuplicateDuringImportIsSkipped() throws Exception {
when(adminUserMapper.selectById(23L)).thenReturn(user(23L, "normal", "member-a"));
@@ -294,6 +347,7 @@ class DedupeTotalDataServiceTest {
when(shopManageGroupMapper.selectManagedMemberUserIds(10L)).thenReturn(List.of(23L));
DedupeTotalDataEntity entity = data(91L, 23L);
entity.setUploaderUsername("member-a");
entity.setCountry("DE,UK");
entity.setCreatedAt(LocalDateTime.of(2026, 7, 20, 12, 30));
when(dedupeTotalDataMapper.selectList(any())).thenReturn(List.of(entity));
@@ -305,11 +359,13 @@ class DedupeTotalDataServiceTest {
try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(bytes))) {
var sheet = workbook.getSheetAt(0);
assertEquals("国家", sheet.getRow(0).getCell(2).getStringCellValue());
assertEquals("ASIN值", sheet.getRow(0).getCell(1).getStringCellValue());
assertEquals("B012345678", sheet.getRow(1).getCell(1).getStringCellValue());
assertEquals("member-a", sheet.getRow(1).getCell(2).getStringCellValue());
assertEquals("", sheet.getRow(1).getCell(3).getStringCellValue());
assertEquals("2026-07-20 12:30:00", sheet.getRow(1).getCell(4).getStringCellValue());
assertEquals("DE,UK", sheet.getRow(1).getCell(2).getStringCellValue());
assertEquals("member-a", sheet.getRow(1).getCell(3).getStringCellValue());
assertEquals("", sheet.getRow(1).getCell(4).getStringCellValue());
assertEquals("2026-07-20 12:30:00", sheet.getRow(1).getCell(5).getStringCellValue());
}
verify(shopManageGroupMapper).selectManagedMemberUserIds(10L);
@@ -548,4 +604,23 @@ class DedupeTotalDataServiceTest {
output.toByteArray());
}
}
private MockMultipartFile asinCountryWorkbook(String asin, String country) throws Exception {
try (XSSFWorkbook workbook = new XSSFWorkbook();
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
var sheet = workbook.createSheet("data");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ASIN");
header.createCell(1).setCellValue("国家");
Row row = sheet.createRow(1);
row.createCell(0).setCellValue(asin);
row.createCell(1).setCellValue(country);
workbook.write(output);
return new MockMultipartFile(
"file",
"data.xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
output.toByteArray());
}
}
}