fix(lastleg): preserve dropship source pallets
This commit is contained in:
@@ -1842,3 +1842,21 @@ CALL assert_receiving_warehouse_assignment_ready();
|
||||
DROP PROCEDURE assert_receiving_warehouse_assignment_ready;
|
||||
|
||||
SELECT 'PASS' AS migration_status, '海外接柜仓预分配与柜级修改结构已就绪' AS message;
|
||||
|
||||
-- 一件代发来源托盘与海外仓实物托盘分离,实物绑定不得覆盖来源身份。
|
||||
USE baiyue_lastleg;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_plan_pallet' AND column_name='source_pallet_no'),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN source_pallet_no VARCHAR(128) NULL COMMENT ''一件代发不可变来源托盘号快照'' AFTER pallet_no'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
ALTER TABLE ll_inbound_plan_pallet
|
||||
MODIFY COLUMN pallet_no VARCHAR(64) NOT NULL COMMENT '当前托盘编号:分配前为计划占位码,分配后为海外仓实物托盘码';
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_inbound_stock_receipt' AND column_name='source_pallet_no'),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE ll_inbound_stock_receipt ADD COLUMN source_pallet_no VARCHAR(128) NULL COMMENT ''一件代发不可变来源托盘号快照'' AFTER pallet_no'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
ALTER TABLE ll_inbound_stock_receipt
|
||||
MODIFY COLUMN pallet_no VARCHAR(64) NOT NULL COMMENT '海外仓实物托盘码';
|
||||
|
||||
+2
-2
@@ -135,8 +135,8 @@ public class DropshipOrderService {
|
||||
throw conflict("Dropship pallet activation is incomplete; repair profiles before retrying");
|
||||
}
|
||||
Map<String, List<InboundStockReceipt>> receiptsByPallet = receipts.stream()
|
||||
.filter(receipt -> receipt.getPalletNo() != null)
|
||||
.collect(Collectors.groupingBy(InboundStockReceipt::getPalletNo));
|
||||
.filter(receipt -> receipt.getSourcePalletNo() != null)
|
||||
.collect(Collectors.groupingBy(InboundStockReceipt::getSourcePalletNo));
|
||||
if (receiptsByPallet.size() != profilesForOrder.size()) {
|
||||
throw conflict("PDA pallet count does not match dropship source pallet count");
|
||||
}
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ public class InboundPlanPallet {
|
||||
private String customerId;
|
||||
private Long planId;
|
||||
private String palletNo;
|
||||
private String sourcePalletNo;
|
||||
private String destinationWarehouseId;
|
||||
private String destinationWarehouseCode;
|
||||
private String destinationWarehouseName;
|
||||
|
||||
+1
@@ -25,6 +25,7 @@ public class InboundStockReceipt {
|
||||
private String productNameEn;
|
||||
private Long warehousePalletId;
|
||||
private String palletNo;
|
||||
private String sourcePalletNo;
|
||||
private Long warehouseLocationId;
|
||||
private String warehouseLocationCode;
|
||||
private String batchNo;
|
||||
|
||||
+1
-1
@@ -945,7 +945,7 @@ public class InboundPdaWorkflowService {
|
||||
boolean wholePalletInbound = "ONE_CLICK_DROPSHIP".equals(orderType);
|
||||
Map<String, InboundPlanPallet> palletsByNo = wholePalletInbound
|
||||
? repository.pallets(plan.getId()).stream().collect(java.util.stream.Collectors.toMap(
|
||||
InboundPlanPallet::getPalletNo, value -> value)) : Map.of();
|
||||
InboundPlanPallet::getSourcePalletNo, value -> value)) : Map.of();
|
||||
Map<Long, InboundPlanPalletAllocation> allocationsByPallet = wholePalletInbound
|
||||
? allocations.stream().collect(java.util.stream.Collectors.toMap(
|
||||
InboundPlanPalletAllocation::getPalletId, value -> value)) : Map.of();
|
||||
|
||||
+2
-1
@@ -116,7 +116,7 @@ public class InboundStockReceiptService {
|
||||
if (value(allocation.getPickedPackageCount()) != value(allocation.getPlannedPackageCount())) {
|
||||
throw conflict("One-click dropship inbound must receive a complete source pallet");
|
||||
}
|
||||
DropshipPalletSnapshot sourcePallet = dropshipPallets.get(pallet.getPalletNo());
|
||||
DropshipPalletSnapshot sourcePallet = dropshipPallets.get(pallet.getSourcePalletNo());
|
||||
if (sourcePallet == null || sourcePallet.packageCount() != value(allocation.getPickedPackageCount())) {
|
||||
throw conflict("One-click dropship source pallet SKU package total does not match PDA receipt");
|
||||
}
|
||||
@@ -261,6 +261,7 @@ public class InboundStockReceiptService {
|
||||
receipt.setProductNameEn(sku.productNameEn());
|
||||
receipt.setWarehousePalletId(pallet.getWarehousePalletId());
|
||||
receipt.setPalletNo(pallet.getPalletNo());
|
||||
receipt.setSourcePalletNo(pallet.getSourcePalletNo());
|
||||
receipt.setWarehouseLocationId(pallet.getWarehouseLocationId());
|
||||
receipt.setBatchNo(plan.getPlanNo());
|
||||
receipt.setReceivedPackages(packages);
|
||||
|
||||
+3
-1
@@ -297,7 +297,8 @@ public class InboundPlanService {
|
||||
if (palletVolume.compareTo(remainingVolume) > 0) palletVolume = remainingVolume;
|
||||
InboundPlanPallet pallet = new InboundPlanPallet();
|
||||
pallet.setId(IdWorker.getId()); pallet.setCustomerId(plan.getCustomerId()); pallet.setPlanId(plan.getId());
|
||||
pallet.setPalletNo(source.palletNo().trim()); pallet.setDestinationWarehouseId(order.destinationWarehouseId());
|
||||
pallet.setPalletNo(source.palletNo().trim()); pallet.setSourcePalletNo(source.palletNo().trim());
|
||||
pallet.setDestinationWarehouseId(order.destinationWarehouseId());
|
||||
pallet.setDestinationWarehouseCode(order.destinationWarehouseCode());
|
||||
pallet.setDestinationWarehouseName(order.destinationWarehouseName());
|
||||
pallet.setCapacityCbm(PalletAllocator.PALLET_CAPACITY_CBM); pallet.setAllocatedVolumeCbm(palletVolume);
|
||||
@@ -437,6 +438,7 @@ public class InboundPlanService {
|
||||
String sourcePalletNo = palletIndex < sourcePalletNos.size() ? sourcePalletNos.get(palletIndex) : null;
|
||||
pallet.setPalletNo(sourcePalletNo == null || sourcePalletNo.isBlank()
|
||||
? plan.getPlanNo() + "-P" + String.format("%03d", palletIndex + 1) : sourcePalletNo.trim());
|
||||
pallet.setSourcePalletNo(sourcePalletNo == null || sourcePalletNo.isBlank() ? null : sourcePalletNo.trim());
|
||||
pallet.setDestinationWarehouseId(sample.destinationWarehouseId());
|
||||
pallet.setDestinationWarehouseCode(sample.destinationWarehouseCode());
|
||||
pallet.setDestinationWarehouseName(sample.destinationWarehouseName());
|
||||
|
||||
@@ -555,7 +555,8 @@ CREATE TABLE IF NOT EXISTS ll_inbound_plan_pallet (
|
||||
id BIGINT NOT NULL COMMENT '计划托盘ID(雪花ID)',
|
||||
customer_id VARCHAR(128) NOT NULL COMMENT '客户账号标识',
|
||||
plan_id BIGINT NOT NULL COMMENT '入库计划ID',
|
||||
pallet_no VARCHAR(64) NOT NULL COMMENT '计划托盘编号',
|
||||
pallet_no VARCHAR(64) NOT NULL COMMENT '当前托盘编号:分配前为计划占位码,分配后为海外仓实物托盘码',
|
||||
source_pallet_no VARCHAR(128) NULL COMMENT '一件代发不可变来源托盘号快照',
|
||||
destination_warehouse_id VARCHAR(128) NULL COMMENT '目的仓ID快照',
|
||||
destination_warehouse_code VARCHAR(128) NULL COMMENT '目的仓编码快照',
|
||||
destination_warehouse_name VARCHAR(255) NULL COMMENT '目的仓名称快照',
|
||||
@@ -617,7 +618,7 @@ ALTER TABLE ll_inbound_plan_pallet COMMENT='尾程入库计划托盘表:按目
|
||||
ALTER TABLE ll_inbound_plan_pallet
|
||||
MODIFY COLUMN id BIGINT NOT NULL COMMENT '计划托盘ID(雪花ID)',
|
||||
MODIFY COLUMN plan_id BIGINT NOT NULL COMMENT '入库计划ID',
|
||||
MODIFY COLUMN pallet_no VARCHAR(64) NOT NULL COMMENT '计划托盘编号',
|
||||
MODIFY COLUMN pallet_no VARCHAR(64) NOT NULL COMMENT '当前托盘编号:分配前为计划占位码,分配后为海外仓实物托盘码',
|
||||
MODIFY COLUMN destination_warehouse_id VARCHAR(128) NULL COMMENT '目的仓ID快照',
|
||||
MODIFY COLUMN destination_warehouse_code VARCHAR(128) NULL COMMENT '目的仓编码快照',
|
||||
MODIFY COLUMN destination_warehouse_name VARCHAR(255) NULL COMMENT '目的仓名称快照',
|
||||
@@ -1105,7 +1106,8 @@ CREATE TABLE IF NOT EXISTS ll_inbound_stock_receipt (
|
||||
line_id BIGINT NOT NULL COMMENT '入仓计划明细ID', order_id BIGINT NOT NULL COMMENT '订单ID', inbound_code VARCHAR(128) NOT NULL COMMENT '入仓单号快照',
|
||||
sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码快照', product_name_zh VARCHAR(255) NULL COMMENT '中文品名快照',
|
||||
product_name_en VARCHAR(255) NULL COMMENT '英文品名快照',
|
||||
warehouse_pallet_id BIGINT NOT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(64) NOT NULL COMMENT '托盘号',
|
||||
warehouse_pallet_id BIGINT NOT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(64) NOT NULL COMMENT '海外仓实物托盘码',
|
||||
source_pallet_no VARCHAR(128) NULL COMMENT '一件代发不可变来源托盘号快照',
|
||||
warehouse_location_id BIGINT NULL COMMENT '仓库库位ID', warehouse_location_code VARCHAR(128) NULL COMMENT '仓库库位编码',
|
||||
batch_no VARCHAR(128) NOT NULL COMMENT '库存批次号', received_packages BIGINT NOT NULL COMMENT '实收箱数',
|
||||
inventory_balance_id BIGINT NOT NULL COMMENT '库存余额记录ID', inventory_position_id BIGINT NOT NULL COMMENT '库存仓位记录ID',
|
||||
|
||||
+2
-1
@@ -141,7 +141,8 @@ class DropshipOrderServiceTest {
|
||||
|
||||
private static InboundStockReceipt receipt(long palletId, String palletNo, long positionId, long packages) {
|
||||
InboundStockReceipt receipt = new InboundStockReceipt();
|
||||
receipt.setOrderId(10L); receipt.setWarehousePalletId(palletId); receipt.setPalletNo(palletNo);
|
||||
receipt.setOrderId(10L); receipt.setWarehousePalletId(palletId);
|
||||
receipt.setPalletNo("WH-" + palletId); receipt.setSourcePalletNo(palletNo);
|
||||
receipt.setInventoryPositionId(positionId); receipt.setReceivedPackages(packages);
|
||||
return receipt;
|
||||
}
|
||||
|
||||
+2
@@ -557,6 +557,8 @@ class InboundPdaWorkflowServiceTest {
|
||||
@Test
|
||||
void dropshipTaskIsMarkedAndWholePalletPickReceivesThePlannedPalletAtOnce() {
|
||||
plan.setSourceOrderId(101L);
|
||||
targetPallet.setPalletNo("WH-PALLET-21");
|
||||
targetPallet.setSourcePalletNo("PLT-21");
|
||||
LastlegOrder order = new LastlegOrder();
|
||||
order.setId(101L); order.setOrderType("ONE_CLICK_DROPSHIP");
|
||||
when(repository.order(101L)).thenReturn(order);
|
||||
|
||||
+5
-1
@@ -218,6 +218,7 @@ class InboundStockReceiptServiceTest {
|
||||
void activatesDropshipAfterGenericStockInReceiptIsCreated() {
|
||||
Fixture fixture = fixture(5, 5, 5, 10);
|
||||
fixture.order.setOrderType("ONE_CLICK_DROPSHIP");
|
||||
fixture.pallet.setPalletNo("WH-PALLET-21");
|
||||
when(dropshipOrders.palletSnapshots("100", 101L)).thenReturn(List.of(dropshipPallet("PLT-21", 5)));
|
||||
when(orders.selectBatchIds(any())).thenReturn(List.of(fixture.order));
|
||||
when(inventory.stockIn(eq("100"), eq("operator"), any(InventoryCommandRequests.StockIn.class)))
|
||||
@@ -230,6 +231,8 @@ class InboundStockReceiptServiceTest {
|
||||
verify(dropshipOrders).activateAfterStockIn(eq("100"), eq(101L), eq(2L), activationReceipts.capture());
|
||||
assertEquals(1, activationReceipts.getValue().size());
|
||||
assertEquals(10L, activationReceipts.getValue().get(0).getInventoryPositionId());
|
||||
assertEquals("PLT-21", activationReceipts.getValue().get(0).getSourcePalletNo());
|
||||
assertEquals("WH-PALLET-21", activationReceipts.getValue().get(0).getPalletNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -311,7 +314,8 @@ class InboundStockReceiptServiceTest {
|
||||
|
||||
private InboundPlanPallet pallet(long id, long warehousePalletId) {
|
||||
InboundPlanPallet pallet = new InboundPlanPallet(); pallet.setId(id); pallet.setPlanId(1L);
|
||||
pallet.setPalletNo("PLT-" + id); pallet.setWarehousePalletId(warehousePalletId);
|
||||
pallet.setPalletNo("PLT-" + id); pallet.setSourcePalletNo("PLT-" + id);
|
||||
pallet.setWarehousePalletId(warehousePalletId);
|
||||
pallet.setWarehouseLocationId(3001L); return pallet;
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -253,6 +253,8 @@ class InboundPlanServiceTest {
|
||||
verify(palletMapper, times(2)).insert(pallets.capture());
|
||||
assertEquals(List.of("SOURCE-P-1", "SOURCE-P-2"),
|
||||
pallets.getAllValues().stream().map(InboundPlanPallet::getPalletNo).toList());
|
||||
assertEquals(List.of("SOURCE-P-1", "SOURCE-P-2"),
|
||||
pallets.getAllValues().stream().map(InboundPlanPallet::getSourcePalletNo).toList());
|
||||
ArgumentCaptor<InboundPlanPalletAllocation> allocations =
|
||||
ArgumentCaptor.forClass(InboundPlanPalletAllocation.class);
|
||||
verify(allocationMapper, times(2)).insert(allocations.capture());
|
||||
@@ -354,6 +356,8 @@ class InboundPlanServiceTest {
|
||||
verify(palletMapper, times(2)).insert(pallets.capture());
|
||||
assertEquals(List.of("SOURCE-P-1", "SOURCE-P-2"),
|
||||
pallets.getAllValues().stream().map(InboundPlanPallet::getPalletNo).toList());
|
||||
assertEquals(List.of("SOURCE-P-1", "SOURCE-P-2"),
|
||||
pallets.getAllValues().stream().map(InboundPlanPallet::getSourcePalletNo).toList());
|
||||
ArgumentCaptor<InboundPlanPalletAllocation> allocations =
|
||||
ArgumentCaptor.forClass(InboundPlanPalletAllocation.class);
|
||||
verify(allocationMapper, times(2)).insert(allocations.capture());
|
||||
|
||||
Reference in New Issue
Block a user