This commit is contained in:
wujinliang
2026-09-18 11:41:04 +08:00
parent 263068ac85
commit 1fc3e04723
38 changed files with 378 additions and 61 deletions
@@ -49,7 +49,7 @@ public class DomesticWarehouseOrderExportProviderService {
column("mainStatus", "订单主状态", ExportColumnType.STRING, 16),
column("customerName", "客户", ExportColumnType.STRING, 24),
column("channelName", "渠道", ExportColumnType.STRING, 20),
column("channelChanged", "曾变更渠道", ExportColumnType.BOOLEAN, 12),
column("channelChanged", "曾变更渠道", ExportColumnType.STRING, 12),
column("receivingWarehouseName", "定位仓库", ExportColumnType.STRING, 20),
column("destinationWarehouseName", "交货仓", ExportColumnType.STRING, 20),
column("expectedShipDate", "预计出运日期", ExportColumnType.DATE, 14),
@@ -65,7 +65,7 @@ public class DomesticWarehouseOrderExportProviderService {
column("skuNos", "SKU", ExportColumnType.STRING, 28),
column("taxMode", "报关方式", ExportColumnType.STRING, 16),
column("containerMode", "装柜方式", ExportColumnType.STRING, 14),
column("customsInspection", "是否商检", ExportColumnType.BOOLEAN, 12),
column("customsInspection", "是否商检", ExportColumnType.STRING, 12),
column("containerNo", "集装箱号", ExportColumnType.STRING, 20),
column("cabinetNo", "柜次号", ExportColumnType.STRING, 20),
column("vesselName", "船名", ExportColumnType.STRING, 18),
@@ -126,16 +126,16 @@ public class DomesticWarehouseOrderExportProviderService {
private Map<String, Object> row(UnifiedOrderResponse.Row value) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("inboundCode", value.inboundCode()); row.put("orderNo", value.orderNo());
row.put("mainStatus", value.mainStatus()); row.put("customerName", value.customerName());
row.put("channelName", value.channelName()); row.put("channelChanged", value.channelChanged()); row.put("receivingWarehouseName", value.receivingWarehouseName());
row.put("mainStatus", mainStatusLabel(value.mainStatus())); row.put("customerName", value.customerName());
row.put("channelName", value.channelName()); row.put("channelChanged", yesOrNo(value.channelChanged())); row.put("receivingWarehouseName", value.receivingWarehouseName());
row.put("destinationWarehouseName", value.destinationWarehouseName()); row.put("expectedShipDate", value.expectedShipDate());
row.put("expectedArrivalAt", value.expectedArrivalAt()); row.put("expectedVolumeCbm", value.expectedVolumeCbm());
row.put("totalPackageCount", value.totalPackageCount()); row.put("totalQuantity", value.totalQuantity());
row.put("actualGrossWeightKg", value.actualGrossWeightKg()); row.put("actualVolumeCbm", value.actualVolumeCbm());
row.put("chargeableWeightKg", value.chargeableWeightKg()); row.put("chargeableVolumeCbm", value.chargeableVolumeCbm());
row.put("feeReviewStatus", value.feeReviewStatus()); row.put("skuNos", join(value.skuNos()));
row.put("taxMode", value.taxMode()); row.put("containerMode", value.containerMode());
row.put("customsInspection", value.customsInspection());
row.put("feeReviewStatus", feeReviewStatusLabel(value.feeReviewStatus())); row.put("skuNos", join(value.skuNos()));
row.put("taxMode", taxModeLabel(value.taxMode())); row.put("containerMode", containerModeLabel(value.containerMode()));
row.put("customsInspection", yesOrNo(value.customsInspection()));
var transport = value.transport();
row.put("containerNo", transport == null ? null : transport.containerNo());
row.put("cabinetNo", transport == null ? null : transport.cabinetNo());
@@ -233,6 +233,33 @@ public class DomesticWarehouseOrderExportProviderService {
}
private static String join(List<String> values) { return values == null ? null : String.join(",", values); }
private static String mainStatusLabel(String value) {
return label(value, Map.ofEntries(
Map.entry("DRAFT", "草稿"), Map.entry("SUBMITTED", "待审核"), Map.entry("APPROVED", "已审核"),
Map.entry("ACCEPTED", "已受理"), Map.entry("REJECTED", "已驳回"), Map.entry("PROCESSING", "处理中"),
Map.entry("COMPLETED", "已完成"), Map.entry("CANCELLED", "已取消"),
Map.entry("PENDING_REVIEW", "待审核"), Map.entry("WAIT_MEASURE", "待测量数据"),
Map.entry("WAIT_PALLETIZE", "待一件代发组托"), Map.entry("INBOUNDED", "已入库"),
Map.entry("WAIT_SPLIT", "待分柜"), Map.entry("LOADING", "装柜中"),
Map.entry("LOADED", "装柜完成"), Map.entry("DELIVERED", "派送完成")));
}
private static String feeReviewStatusLabel(String value) {
return label(value, Map.ofEntries(
Map.entry("NOT_SUBMITTED", "未提交"), Map.entry("UNRECORDED", "未录入"),
Map.entry("PENDING", "待审核"), Map.entry("APPROVED", "审核通过"),
Map.entry("REJECTED", "审核驳回"), Map.entry("CONFIRMED", "已确认")));
}
private static String taxModeLabel(String value) {
return label(value, Map.of("BUY_DECLARATION", "买单报关", "TAX_REFUND", "退税报关"));
}
private static String containerModeLabel(String value) {
return label(value, Map.of("FULL_CONTAINER", "整柜", "FCL", "整柜", "LCL", "拼箱"));
}
private static String yesOrNo(Boolean value) { return value == null ? null : value ? "是" : "否"; }
private static String label(String value, Map<String, String> labels) {
if (value == null) return null;
return labels.getOrDefault(value.trim().toUpperCase(), value);
}
private static ExportColumn column(String key, String title, ExportColumnType type, int width) {
return new ExportColumn(key, title, type, width);
}
@@ -527,10 +527,13 @@ public class MerchantBatchImportService {
private static <T> Map<String, T> optionMap(List<T> values, Function<T, String> labeler) {
Map<String, T> result = new LinkedHashMap<>();
for (T value : values) {
String label = labeler.apply(value);
if (result.putIfAbsent(label, value) != null) {
throw new BizException(ResultCode.CONFLICT, "模板选项显示名称重复,请联系平台处理");
String baseLabel = labeler.apply(value);
String label = baseLabel;
int duplicateNumber = 2;
while (result.containsKey(label)) {
label = baseLabel + "(同名选项 " + duplicateNumber++ + ")";
}
result.put(label, value);
}
return result;
}
@@ -4,6 +4,7 @@ import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.common.core.export.ExportContracts.ExportBatchRequest;
import com.baiyue.common.core.export.ExportContracts.ExportBatchResponse;
import com.baiyue.common.core.export.ExportContracts.ExportColumnType;
import com.baiyue.order.dto.UnifiedOrderQuery;
import com.baiyue.order.dto.UnifiedOrderResponse;
import jakarta.annotation.Resource;
@@ -130,6 +131,29 @@ class DomesticWarehouseOrderExportProviderServiceTest {
.hasMessageContaining("does not match");
}
@Test
void exportsChineseDisplayValuesForStatusAndEnumColumns() {
UnifiedOrderResponse.Row row = row("ORD-1", "RK-1", "客户甲");
when(row.mainStatus()).thenReturn("PENDING_REVIEW");
when(row.channelChanged()).thenReturn(false);
when(row.feeReviewStatus()).thenReturn("NOT_SUBMITTED");
when(row.taxMode()).thenReturn("BUY_DECLARATION");
when(row.containerMode()).thenReturn("LCL");
when(row.customsInspection()).thenReturn(false);
when(orders.platformRowsByOrderNos(List.of("ORD-1"))).thenReturn(List.of(row));
ExportBatchResponse response = service.exportBatch(request("1009",
Map.of("selectedOrderNos", List.of("ORD-1")), null, null, 100));
assertThat(response.rows().get(0)).containsEntry("mainStatus", "待审核")
.containsEntry("channelChanged", "否").containsEntry("feeReviewStatus", "未提交")
.containsEntry("taxMode", "买单报关").containsEntry("containerMode", "拼箱")
.containsEntry("customsInspection", "否");
assertThat(response.columns()).filteredOn(column -> column.key().equals("channelChanged")
|| column.key().equals("customsInspection")).extracting(column -> column.type())
.containsOnly(ExportColumnType.STRING);
}
private ExportBatchRequest request(String taskId, Map<String, Object> parameters,
String cursor, String snapshot, int limit) {
return new ExportBatchRequest(taskId, "0", "PLATFORM", "7001", 1,
@@ -229,6 +229,26 @@ class MerchantBatchImportServiceTest {
verify(warehouses).page("Bearer test", 2, 200, "ACTIVE");
}
@Test
void templateKeepsDuplicateDisplayNamesAsDistinctBusinessOptions() throws Exception {
var domestic = new MerchantWarehouseCatalogClient.Warehouse(21L, "CN-YW", "义乌收货仓",
"DOMESTIC", "CN", "ACTIVE");
var firstFba = new MerchantWarehouseCatalogClient.Warehouse(22L, "ATL6", "ATL6",
"FBA", "US", "ACTIVE");
var secondFba = new MerchantWarehouseCatalogClient.Warehouse(24L, "ATL6", "ATL6",
"FBA", "US", "ACTIVE");
when(warehouses.page("Bearer test", 1, 200, "ACTIVE"))
.thenReturn(ApiResponse.success(new PageResult<>(List.of(domestic, firstFba, secondFba), 1, 200, 3, 1)));
byte[] content = service.template(88L, "Bearer test");
try (var workbook = new XSSFWorkbook(new ByteArrayInputStream(content))) {
var options = workbook.getSheet("选项数据");
assertThat(hasCellValue(options, "ATL6")).isTrue();
assertThat(hasCellValue(options, "ATL6(同名选项 2)")).isTrue();
}
}
@Test
void templateFailsClosedWhenLaterWarehousePageCannotBeRead() {
List<MerchantWarehouseCatalogClient.Warehouse> firstPage = new ArrayList<>();