fix(firstleg): use short cabinet pallet identities
This commit is contained in:
@@ -1884,7 +1884,7 @@ CREATE TABLE fl_customs_frozen_document_inbound (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='开始报关时冻结的客户资料覆盖范围';
|
||||
|
||||
CREATE TABLE fl_document_sequence (
|
||||
sequence_key varchar(32) NOT NULL COMMENT '单据类型与北京时间日期组合键,例如CAB:20260818',
|
||||
sequence_key varchar(32) NOT NULL COMMENT '单据序列键;日序列如CB:20260818,柜次长期序列固定为CABINET',
|
||||
current_value int unsigned NOT NULL COMMENT '该类型当日已分配的最大序号',
|
||||
PRIMARY KEY (sequence_key),
|
||||
CONSTRAINT chk_fl_document_sequence_value CHECK ((current_value > 0))
|
||||
@@ -3195,7 +3195,7 @@ CREATE TABLE fl_loading_pallet_label (
|
||||
destination_warehouse_code varchar(64) NOT NULL COMMENT 'FBA仓编码快照',
|
||||
destination_warehouse_name varchar(128) DEFAULT NULL COMMENT 'FBA仓名称快照',
|
||||
pallet_index int unsigned NOT NULL COMMENT '当前柜当前FBA仓内从1开始的序号',
|
||||
pallet_code varchar(128) NOT NULL COMMENT '托盘码:集装箱号-FBA仓编码-三位序号',
|
||||
pallet_code varchar(128) NOT NULL COMMENT '托盘码:平台柜次号-FBA仓内部编号-三位序号;不依赖可跨提单复用的真实柜号',
|
||||
created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '生成时间',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_loading_pallet_code (pallet_code),
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
## 模块入口
|
||||
|
||||
散货托盘码:`service/LoadingPalletLabelService.java`、`mapper/LoadingPalletLabelMapper.java`、`controller/PlatformLoadingListController.java`,契约 `src/main/resources/openapi/loading-lists-v1.yaml` 的 `/pallet-labels/prepare` 与 `/pallet-labels/print`。仅在计划 `LOADING/COMPLETED` 且真实柜号有效时,为非一件代发的 FBA 明细按柜号、FBA 地址内部编号、三位序号生成冻结标签;内部编号从 Warehouse 启用主数据读取,缺失或同柜重复时拒绝生成。重复生成须核对已有标签与明细一致,冲突直接拒绝。全部或按仓指定张数打印统一调用 Print `/internal/print/v1/pdfs/fba-pallet-labels`,模板 `FBA_PALLET_A4_LANDSCAPE_V1` 每托一页 297×210 mm,顶部为 SCK8 等 FBA 仓码,条码和底部文字为包含 141 等内部编号的完整托盘号,与海外补打共用版式;装柜完成通过 `LoadingCompletedOutboxService.java` 传递来源托盘。
|
||||
柜次号与散货托盘码:`service/FirstlegDocumentNumberGenerator.java` 为新柜生成全局连续且不按日期重置的 `D0001`、`D0002` 柜次号;`service/LoadingPalletLabelService.java`、`mapper/LoadingPalletLabelMapper.java`、`controller/PlatformLoadingListController.java` 负责散货托盘码,契约为 `src/main/resources/openapi/loading-lists-v1.yaml` 的 `/pallet-labels/prepare` 与 `/pallet-labels/print`。仅在计划 `LOADING/COMPLETED` 且真实柜号有效时,为非一件代发的 FBA 明细按平台柜次号、FBA 地址内部编号、三位序号生成冻结标签;托盘码不依赖可跨提单复用的真实柜号,内部编号从 Warehouse 启用主数据读取,缺失或同柜重复时拒绝生成。重复生成须核对已有标签与明细一致,冲突直接拒绝。全部或按仓指定张数打印统一调用 Print `/internal/print/v1/pdfs/fba-pallet-labels`,模板 `FBA_PALLET_A4_LANDSCAPE_V1` 每托一页 297×210 mm,顶部为 SCK8 等 FBA 仓码,条码和底部文字为完整托盘号,与海外补打共用版式;装柜完成通过 `LoadingCompletedOutboxService.java` 传递来源托盘。
|
||||
|
||||
| 目标 | 入口 |
|
||||
|---|---|
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface LoadingPalletLabelMapper {
|
||||
@Select("""
|
||||
SELECT p.id AS plan_id,p.plan_no,p.plan_status,b.container_no,b.warehouse_id,
|
||||
SELECT p.id AS plan_id,p.plan_no,p.plan_status,b.container_no,b.cabinet_no,b.warehouse_id,
|
||||
i.id AS item_id,i.account_id,i.inbound_id,i.inbound_code,i.destination_warehouse_id,
|
||||
i.destination_warehouse_code,i.destination_warehouse_name,
|
||||
COALESCE(NULLIF(i.pallet_count,0),
|
||||
@@ -55,6 +55,7 @@ public interface LoadingPalletLabelMapper {
|
||||
@Getter @Setter
|
||||
class SourceRow {
|
||||
private Long planId; private String planNo; private String planStatus; private String containerNo;
|
||||
private String cabinetNo;
|
||||
private Long warehouseId; private Long itemId; private Long accountId; private Long inboundId;
|
||||
private Long destinationWarehouseId;
|
||||
private String inboundCode; private String destinationWarehouseCode; private String destinationWarehouseName;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ContainerService {
|
||||
.map(ChannelRow::getChannelCode).anyMatch(channelGroup.channelCodes()::contains);
|
||||
if (!activeGroup) throw conflict("所选物流渠道分组在当前仓库已失效,请重新选择");
|
||||
ContainerBookingEntity value = new ContainerBookingEntity(); value.setId(IdWorker.getId());
|
||||
value.setBookingNo(documentNumbers.next("CB")); value.setCabinetNo(documentNumbers.next("CAB"));
|
||||
value.setBookingNo(documentNumbers.next("CB")); value.setCabinetNo(documentNumbers.nextCabinetNo());
|
||||
value.setSourceType("SIMULATION"); value.setRecordStatus("ACTIVE");
|
||||
value.setChannelGroupCode(channelGroup.code()); value.setChannelCode(null); value.setChannelName(null);
|
||||
value.setWarehouseId(warehouse.id()); value.setWarehouseName(warehouse.warehouseName());
|
||||
|
||||
+19
-5
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
public class FirstlegDocumentNumberGenerator {
|
||||
private static final ZoneId BUSINESS_ZONE = ZoneId.of("Asia/Shanghai");
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyMMdd", Locale.ROOT);
|
||||
private static final Set<String> SUPPORTED_PREFIXES = Set.of("OB", "TA", "CB", "CAB", "LP", "DP");
|
||||
private static final Set<String> SUPPORTED_PREFIXES = Set.of("OB", "TA", "CB", "LP", "DP");
|
||||
private static final long MAX_DAILY_SEQUENCE = 9_999L;
|
||||
|
||||
private final JdbcTemplate jdbc;
|
||||
@@ -42,16 +42,30 @@ public class FirstlegDocumentNumberGenerator {
|
||||
}
|
||||
LocalDate sequenceDate = LocalDate.now(clock);
|
||||
String sequenceKey = prefix + ":" + DateTimeFormatter.BASIC_ISO_DATE.format(sequenceDate);
|
||||
long sequence = nextSequence(sequenceKey);
|
||||
if (sequence > MAX_DAILY_SEQUENCE) {
|
||||
throw new BizException(ResultCode.CONFLICT, "当日" + prefix + "单据编号已用尽");
|
||||
}
|
||||
return prefix + "-" + DATE_FORMAT.format(sequenceDate) + "-" +
|
||||
String.format(Locale.ROOT, "%04d", sequence);
|
||||
}
|
||||
|
||||
/** 平台柜次号是长期业务身份,使用不按日期重置的 D 序号。 */
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public String nextCabinetNo() {
|
||||
return "D" + String.format(Locale.ROOT, "%04d", nextSequence("CABINET"));
|
||||
}
|
||||
|
||||
private long nextSequence(String sequenceKey) {
|
||||
jdbc.update(
|
||||
"INSERT INTO fl_document_sequence(sequence_key,current_value) " +
|
||||
"VALUES(?,LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE " +
|
||||
"current_value=LAST_INSERT_ID(current_value+1)",
|
||||
sequenceKey);
|
||||
Long sequence = jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
||||
if (sequence == null || sequence <= 0 || sequence > MAX_DAILY_SEQUENCE) {
|
||||
throw new BizException(ResultCode.CONFLICT, "当日" + prefix + "单据编号已用尽");
|
||||
if (sequence == null || sequence <= 0) {
|
||||
throw new BizException(ResultCode.CONFLICT, "业务编号生成失败");
|
||||
}
|
||||
return prefix + "-" + DATE_FORMAT.format(sequenceDate) + "-" +
|
||||
String.format(Locale.ROOT, "%04d", sequence);
|
||||
return sequence;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/** 散货托盘码按真实柜号、FBA 地址内部编号和仓内序号组成;一件代发继续使用装箱打托事实。 */
|
||||
/** 散货托盘码按平台柜次号、FBA 地址内部编号和仓内序号组成;一件代发继续使用装箱打托事实。 */
|
||||
@Service
|
||||
public class LoadingPalletLabelService {
|
||||
@Resource private LoadingPalletLabelMapper mapper;
|
||||
@@ -107,7 +107,8 @@ public class LoadingPalletLabelService {
|
||||
row.setItemId(source.getItemId()); row.setAccountId(source.getAccountId()); row.setInboundId(source.getInboundId());
|
||||
row.setInboundCode(source.getInboundCode()); row.setContainerNo(containerNo);
|
||||
row.setDestinationWarehouseCode(warehouseCode); row.setDestinationWarehouseName(source.getDestinationWarehouseName());
|
||||
row.setPalletIndex(index); row.setPalletCode(containerNo + "-" + internalCode + "-" + String.format("%03d", index));
|
||||
row.setPalletIndex(index); row.setPalletCode(plan.getCabinetNo() + "-" + internalCode + "-"
|
||||
+ String.format("%03d", index));
|
||||
if (row.getPalletCode().length() > 128) throw new BizException(ResultCode.CONFLICT, "托盘码长度超过系统限制");
|
||||
result.add(row);
|
||||
}
|
||||
@@ -165,10 +166,14 @@ public class LoadingPalletLabelService {
|
||||
}
|
||||
private PalletLabel label(LabelRow row) { return new PalletLabel(row.getLabelId(), row.getItemId(), row.getAccountId(), row.getInboundId(), row.getInboundCode(), row.getContainerNo(), row.getDestinationWarehouseCode(), internalCode(row), row.getDestinationWarehouseName(), row.getPalletIndex(), row.getPalletCode()); }
|
||||
private String internalCode(LabelRow row) {
|
||||
String prefix = row.getContainerNo() + "-";
|
||||
String suffix = "-" + String.format("%03d", row.getPalletIndex());
|
||||
String palletCode = row.getPalletCode();
|
||||
return palletCode.substring(prefix.length(), palletCode.length() - suffix.length());
|
||||
String body = palletCode.substring(0, palletCode.length() - suffix.length());
|
||||
int separator = body.lastIndexOf('-');
|
||||
if (separator < 0 || separator == body.length() - 1) {
|
||||
throw new BizException(ResultCode.CONFLICT, "托盘码缺少柜次号或 FBA 仓内部编号");
|
||||
}
|
||||
return body.substring(separator + 1);
|
||||
}
|
||||
private static String normalize(String value) { return value == null || value.isBlank() ? null : value.trim(); }
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ CALL phase3_add_allocation_picked_count();
|
||||
DROP PROCEDURE phase3_add_allocation_picked_count;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fl_document_sequence (
|
||||
sequence_key VARCHAR(32) NOT NULL COMMENT '单据类型与北京时间日期组合键,例如CAB:20260818',
|
||||
sequence_key VARCHAR(32) NOT NULL COMMENT '单据序列键;日序列如CB:20260818,柜次长期序列固定为CABINET',
|
||||
current_value INT UNSIGNED NOT NULL COMMENT '该类型当日已分配的最大序号',
|
||||
PRIMARY KEY (sequence_key),
|
||||
CONSTRAINT chk_fl_document_sequence_value CHECK (current_value > 0)
|
||||
@@ -388,7 +388,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pallet_label (
|
||||
destination_warehouse_code VARCHAR(64) NOT NULL COMMENT 'FBA仓编码快照',
|
||||
destination_warehouse_name VARCHAR(128) NULL COMMENT 'FBA仓名称快照',
|
||||
pallet_index INT UNSIGNED NOT NULL COMMENT '当前柜当前FBA仓内从1开始的序号',
|
||||
pallet_code VARCHAR(128) NOT NULL COMMENT '托盘码:集装箱号-FBA仓编码-三位序号',
|
||||
pallet_code VARCHAR(128) NOT NULL COMMENT '托盘码:平台柜次号-FBA仓内部编号-三位序号;不依赖可跨提单复用的真实柜号',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '生成时间',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_loading_pallet_code (pallet_code),
|
||||
|
||||
@@ -2199,7 +2199,7 @@ components:
|
||||
planNo: {type: string, nullable: true, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装与确认装柜清单共用的稳定编号;未创建计划时为空}
|
||||
bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001, description: 平台内部货柜登记号}
|
||||
containerNo: {type: string, maxLength: 64, nullable: true}
|
||||
cabinetNo: {type: string, pattern: '^CAB-[0-9]{6}-[0-9]{4}$', example: CAB-260818-0001, description: 平台稳定柜次号}
|
||||
cabinetNo: {type: string, pattern: '^D[0-9]{4,}$', example: D0001, description: 平台全局连续且不按日期重置的稳定柜次号}
|
||||
sourceType: {type: string, enum: [SIMULATION, OCEAN_BOOKING], description: SIMULATION 为内部模拟柜;OCEAN_BOOKING 为订舱登记直接生成的真实柜}
|
||||
recordStatus: {type: string, enum: [ACTIVE, MERGED], description: 正常列表和详情仅返回 ACTIVE;真实订舱柜被模拟柜消费后变为 MERGED 且不再作为可操作柜返回}
|
||||
mergedIntoContainerBookingId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: MERGED 源真实柜指向保留的模拟柜稳定 containerBookingId;ACTIVE 时为空}
|
||||
|
||||
@@ -301,7 +301,7 @@ components:
|
||||
containerBookingId: {$ref: '#/components/schemas/LongId'}
|
||||
preloadNo: {type: string, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装单号;按北京时间创建日逐日编号,确认后继续作为同一装柜清单号使用}
|
||||
containerNo: {type: string, nullable: true, description: 集装箱号}
|
||||
cabinetNo: {type: string, nullable: true, pattern: '^CAB-[0-9]{6}-[0-9]{4}$', example: CAB-260818-0001, description: 稳定柜次号;不得与真实集装箱号混用}
|
||||
cabinetNo: {type: string, nullable: true, pattern: '^D[0-9]{4,}$', example: D0001, description: 平台全局连续且不按日期重置的稳定柜次号;不得与真实集装箱号混用}
|
||||
customers: {type: array, description: 计划包含的客户, items: {$ref: '#/components/schemas/Customer'}}
|
||||
warehouseId: {$ref: '#/components/schemas/NullableLongId'}
|
||||
warehouseName: {type: string, nullable: true, description: 仓库名称}
|
||||
@@ -359,7 +359,7 @@ components:
|
||||
warehouseId: {$ref: '#/components/schemas/NullableLongId'}
|
||||
warehouseName: {type: string, nullable: true, description: 仓库名称}
|
||||
containerNo: {type: string, nullable: true, description: 集装箱号}
|
||||
cabinetNo: {type: string, nullable: true, pattern: '^CAB-[0-9]{6}-[0-9]{4}$', example: CAB-260818-0001, description: 稳定柜次号}
|
||||
cabinetNo: {type: string, nullable: true, pattern: '^D[0-9]{4,}$', example: D0001, description: 平台全局连续且不按日期重置的稳定柜次号}
|
||||
status: {type: string, enum: [COMPLETED], description: 装柜清单状态}
|
||||
totalPackageCount: {type: string, pattern: '^[0-9]+$', description: 总箱数}
|
||||
totalGrossWeightKg: {type: number, description: 总毛重,单位千克}
|
||||
|
||||
@@ -74,7 +74,7 @@ components:
|
||||
exception: {$ref: '#/components/schemas/ExceptionState'}
|
||||
exceptionHistory: {type: array, items: {$ref: '#/components/schemas/ExceptionHistory'}}
|
||||
timeline: {type: array, items: {$ref: '#/components/schemas/TimelineEntry'}}
|
||||
Container: {type: object, properties: {id: {type: integer, format: int64}, bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001}, cabinetNo: {type: string, pattern: '^CAB-[0-9]{6}-[0-9]{4}$', example: CAB-260818-0001}, containerNo: {type: string}, status: {type: string}, warehouseId: {type: integer, format: int64}, warehouseName: {type: string}, voyageNo: {type: string}, vesselName: {type: string}, pickupCode: {type: string, pattern: '^[0-9]{1,64}$', nullable: true}, pickupCodeUpdatedBy: {type: integer, format: int64, nullable: true}, pickupCodeUpdatedByName: {type: string, nullable: true}, pickupCodeUpdatedAt: {type: string, format: date-time, nullable: true}, version: {type: integer, minimum: 0}}}
|
||||
Container: {type: object, properties: {id: {type: integer, format: int64}, bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001}, cabinetNo: {type: string, pattern: '^D[0-9]{4,}$', example: D0001}, containerNo: {type: string}, status: {type: string}, warehouseId: {type: integer, format: int64}, warehouseName: {type: string}, voyageNo: {type: string}, vesselName: {type: string}, pickupCode: {type: string, pattern: '^[0-9]{1,64}$', nullable: true}, pickupCodeUpdatedBy: {type: integer, format: int64, nullable: true}, pickupCodeUpdatedByName: {type: string, nullable: true}, pickupCodeUpdatedAt: {type: string, format: date-time, nullable: true}, version: {type: integer, minimum: 0}}}
|
||||
PdaSummary: {type: object, properties: {taskId: {type: integer, format: int64}, loadingPlanId: {type: integer, format: int64}, containerBookingId: {type: integer, format: int64}, taskStatus: {type: string, description: '持久化任务态:LOADING/COMPLETED'}, workflowStatus: {type: string, enum: [IN_PROGRESS, AWAITING_REVIEW, COMPLETED], description: 'PDA作业展示态'}, taskVersion: {type: integer}, itemCount: {type: integer}, completedItemCount: {type: integer}, unresolvedItemCount: {type: integer}, photoCounts: {type: array, items: {$ref: '#/components/schemas/PhotoCount'}}, photos: {type: array, items: {$ref: '#/components/schemas/Photo'}}, exceptionReasons: {type: array, items: {type: string}}}}
|
||||
PhotoCount: {type: object, properties: {evidenceType: {type: string}, count: {type: integer}}}
|
||||
Photo: {type: object, properties: {evidenceId: {type: integer, format: int64}, tenantId: {type: integer, format: int64}, inboundId: {type: integer, format: int64}, evidenceType: {type: string}, fileId: {type: integer, format: int64}, fileName: {type: string}, status: {type: string, enum: [ACTIVE, VOID]}, downloadPath: {type: string, nullable: true, description: '仅 ACTIVE 照片提供鉴权下载路径;VOID 历史照片为空'}, uploadedAt: {type: string, format: date-time}}}
|
||||
|
||||
@@ -53,7 +53,7 @@ class ContainerServiceTest {
|
||||
@BeforeEach
|
||||
void setUpWarehouse() {
|
||||
when(documentNumbers.next("CB")).thenReturn("CB-260818-0001");
|
||||
when(documentNumbers.next("CAB")).thenReturn("CAB-260818-0001");
|
||||
when(documentNumbers.nextCabinetNo()).thenReturn("D0001");
|
||||
when(smartLoadingService.createForContainer(anyLong(), anyLong(), anyString())).thenAnswer(invocation ->
|
||||
new com.baiyue.firstleg.dto.SmartLoadingDtos.Plan(501L, "LP-260818-0001", "EDITING",
|
||||
invocation.getArgument(0, Long.class), null, null, 0, true, true, null,
|
||||
@@ -77,7 +77,7 @@ class ContainerServiceTest {
|
||||
ContainerBookingEntity saved = captor.getValue();
|
||||
assertThat(created).isSameAs(saved);
|
||||
assertThat(saved.getBookingNo()).isEqualTo("CB-260818-0001");
|
||||
assertThat(saved.getCabinetNo()).isEqualTo("CAB-260818-0001");
|
||||
assertThat(saved.getCabinetNo()).isEqualTo("D0001");
|
||||
assertThat(saved.getContainerNo()).isNull();
|
||||
assertThat(saved.getOceanBookingId()).isNull();
|
||||
assertThat(saved.getChannelGroupCode()).isEqualTo("MATSON_CLX");
|
||||
|
||||
+14
-2
@@ -42,11 +42,23 @@ class FirstlegDocumentNumberGeneratorTest {
|
||||
assertThat(generator.next("OB")).isEqualTo("OB-260818-0001");
|
||||
assertThat(generator.next("TA")).isEqualTo("TA-260818-0001");
|
||||
assertThat(generator.next("CB")).isEqualTo("CB-260818-0001");
|
||||
assertThat(generator.next("CAB")).isEqualTo("CAB-260818-0001");
|
||||
assertThat(generator.next("LP")).isEqualTo("LP-260818-0001");
|
||||
assertThat(generator.nextCabinetNo()).isEqualTo("D0001");
|
||||
|
||||
verify(jdbc).update(org.mockito.ArgumentMatchers.startsWith("INSERT INTO fl_document_sequence"),
|
||||
eq("OB:20260818"));
|
||||
verify(jdbc).update(org.mockito.ArgumentMatchers.startsWith("INSERT INTO fl_document_sequence"),
|
||||
eq("CABINET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void cabinetSequenceDoesNotResetOrStopAtFourDigits() {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
when(jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class)).thenReturn(9_999L, 10_000L);
|
||||
FirstlegDocumentNumberGenerator generator = new FirstlegDocumentNumberGenerator(jdbc, CLOCK);
|
||||
|
||||
assertThat(generator.nextCabinetNo()).isEqualTo("D9999");
|
||||
assertThat(generator.nextCabinetNo()).isEqualTo("D10000");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,6 +68,6 @@ class FirstlegDocumentNumberGeneratorTest {
|
||||
assertThatThrownBy(() -> generator.next("MSCU")).isInstanceOf(IllegalArgumentException.class);
|
||||
|
||||
when(jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class)).thenReturn(10_000L);
|
||||
assertThatThrownBy(() -> generator.next("CAB")).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> generator.next("LP")).isInstanceOf(BizException.class);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-8
@@ -22,9 +22,11 @@ class LoadingPalletLabelServiceTest {
|
||||
ReflectionTestUtils.setField(service, "printClient", print);
|
||||
ReflectionTestUtils.setField(service, "internalToken", "test-token");
|
||||
var label1 = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabel(1L, 1L, 1L, 1L,
|
||||
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 1, "MSCU6639870-141-001");
|
||||
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 1,
|
||||
"D0002-141-001");
|
||||
var label2 = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabel(2L, 1L, 1L, 1L,
|
||||
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 2, "MSCU6639870-141-002");
|
||||
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 2,
|
||||
"D0002-141-002");
|
||||
var manifest = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelManifest(10L, "LP-1", "MSCU6639870", 2,
|
||||
List.of(new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelGroup("SCK8", "141", "FBA destination", 2, List.of(label1, label2))));
|
||||
org.mockito.Mockito.doReturn(manifest).when(service).prepare(10L, 20L);
|
||||
@@ -39,16 +41,16 @@ class LoadingPalletLabelServiceTest {
|
||||
assertThat(requests.get(0).pageSpec().widthMm()).isEqualByComparingTo("297");
|
||||
assertThat(requests.get(0).pageSpec().heightMm()).isEqualByComparingTo("210");
|
||||
assertThat(requests.get(0).labels()).extracting(com.baiyue.firstleg.client.PrintPdfClient.FbaPalletLabel::palletCode)
|
||||
.containsExactly("MSCU6639870-141-001", "MSCU6639870-141-002");
|
||||
.containsExactly("D0002-141-001", "D0002-141-002");
|
||||
assertThat(requests.get(1).labels()).singleElement().satisfies(label -> {
|
||||
assertThat(label.fbaWarehouseCode()).isEqualTo("SCK8");
|
||||
assertThat(label.palletCode()).isEqualTo("MSCU6639870-141-001");
|
||||
assertThat(label.palletCode()).isEqualTo("D0002-141-001");
|
||||
});
|
||||
org.mockito.Mockito.verify(print, org.mockito.Mockito.never()).generateInboundMarks(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatesStableIndexesPerContainerAndFbaAndSkipsDropship() {
|
||||
void generatesStableIndexesPerCabinetAndFbaAndSkipsDropship() {
|
||||
LoadingPalletLabelMapper mapper = mock(LoadingPalletLabelMapper.class);
|
||||
LoadingPalletLabelService service = new LoadingPalletLabelService();
|
||||
ReflectionTestUtils.setField(service, "mapper", mapper);
|
||||
@@ -72,13 +74,14 @@ class LoadingPalletLabelServiceTest {
|
||||
assertThat(manifest.groups()).extracting(group -> group.destinationWarehouseInternalCode())
|
||||
.containsExactly("154", "CADF");
|
||||
assertThat(saved).extracting(LoadingPalletLabelMapper.LabelRow::getPalletCode)
|
||||
.containsExactly("MSCU6639870-154-001", "MSCU6639870-CADF-001",
|
||||
"MSCU6639870-CADF-002", "MSCU6639870-CADF-003");
|
||||
.containsExactly("D0002-154-001", "D0002-CADF-001",
|
||||
"D0002-CADF-002", "D0002-CADF-003");
|
||||
}
|
||||
|
||||
private LoadingPalletLabelMapper.SourceRow source(long itemId, String destination, int pallets, String fulfillment) {
|
||||
var row = new LoadingPalletLabelMapper.SourceRow(); row.setPlanId(10L); row.setPlanNo("LP-1");
|
||||
row.setPlanStatus("LOADING"); row.setContainerNo("MSCU6639870"); row.setWarehouseId(20L);
|
||||
row.setPlanStatus("LOADING"); row.setContainerNo("MSCU6639870"); row.setCabinetNo("D0002");
|
||||
row.setWarehouseId(20L);
|
||||
row.setItemId(itemId); row.setAccountId(100L); row.setInboundId(itemId + 1000);
|
||||
row.setInboundCode("RK-" + itemId); row.setDestinationWarehouseCode(destination);
|
||||
row.setDestinationWarehouseId("LAX9".equals(destination) ? 101L : 102L);
|
||||
|
||||
Reference in New Issue
Block a user