一件代发拣货
This commit is contained in:
@@ -2792,6 +2792,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_carton_label (
|
|||||||
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
||||||
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
||||||
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
||||||
|
sku_code VARCHAR(128) NULL COMMENT '箱唛绑定的SKU快照;二维码内容不变',
|
||||||
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
||||||
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
||||||
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
||||||
@@ -2829,6 +2830,7 @@ BEGIN
|
|||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
CALL unified_carton_label_add_column('label_version', 'INT UNSIGNED NOT NULL DEFAULT 1 COMMENT ''内部兼容批次字段,固定为1且不进入箱码'' AFTER carton_index');
|
CALL unified_carton_label_add_column('label_version', 'INT UNSIGNED NOT NULL DEFAULT 1 COMMENT ''内部兼容批次字段,固定为1且不进入箱码'' AFTER carton_index');
|
||||||
|
CALL unified_carton_label_add_column('sku_code', 'VARCHAR(128) NULL COMMENT ''箱唛绑定的SKU快照;二维码内容不变'' AFTER cargo_name');
|
||||||
CALL unified_carton_label_add_column('batch_status', 'VARCHAR(16) NOT NULL DEFAULT ''ACTIVE'' COMMENT ''批次状态:ACTIVE有效、VOID已作废'' AFTER label_version');
|
CALL unified_carton_label_add_column('batch_status', 'VARCHAR(16) NOT NULL DEFAULT ''ACTIVE'' COMMENT ''批次状态:ACTIVE有效、VOID已作废'' AFTER label_version');
|
||||||
CALL unified_carton_label_add_column('cargo_fingerprint', 'CHAR(64) NULL COMMENT ''影响标签字段的SHA-256指纹'' AFTER batch_status');
|
CALL unified_carton_label_add_column('cargo_fingerprint', 'CHAR(64) NULL COMMENT ''影响标签字段的SHA-256指纹'' AFTER batch_status');
|
||||||
CALL unified_carton_label_add_column('voided_at', 'DATETIME(3) NULL COMMENT ''批次作废时间'' AFTER cargo_fingerprint');
|
CALL unified_carton_label_add_column('voided_at', 'DATETIME(3) NULL COMMENT ''批次作废时间'' AFTER cargo_fingerprint');
|
||||||
|
|||||||
@@ -63,7 +63,12 @@ public interface OrderCargoClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
record CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
record CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
||||||
Integer packageCount, BigDecimal lengthCm, BigDecimal widthCm,
|
String skuNo, Integer packageCount, BigDecimal lengthCm, BigDecimal widthCm,
|
||||||
BigDecimal heightCm) {
|
BigDecimal heightCm) {
|
||||||
|
public CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
||||||
|
Integer packageCount, BigDecimal lengthCm, BigDecimal widthCm,
|
||||||
|
BigDecimal heightCm) {
|
||||||
|
this(cargoId, orderId, itemNo, cargoName, null, packageCount, lengthCm, widthCm, heightCm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class InboundCartonLabelEntity {
|
|||||||
private Long inboundDetailId;
|
private Long inboundDetailId;
|
||||||
private Integer cargoItemNo;
|
private Integer cargoItemNo;
|
||||||
private String cargoName;
|
private String cargoName;
|
||||||
|
private String skuCode;
|
||||||
private Integer detailPackageCount;
|
private Integer detailPackageCount;
|
||||||
private String inboundCode;
|
private String inboundCode;
|
||||||
private String boxCode;
|
private String boxCode;
|
||||||
|
|||||||
+10
@@ -62,6 +62,16 @@ public class InboundCartonLabelRepository {
|
|||||||
.set(InboundCartonLabelEntity::getCargoFingerprint, fingerprint));
|
.set(InboundCartonLabelEntity::getCargoFingerprint, fingerprint));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initializeLegacySku(long tenantId, long inboundId, long inboundDetailId, String skuCode) {
|
||||||
|
if (skuCode == null || skuCode.isBlank()) return;
|
||||||
|
labels.update(null, new LambdaUpdateWrapper<InboundCartonLabelEntity>()
|
||||||
|
.eq(InboundCartonLabelEntity::getTenantId, tenantId)
|
||||||
|
.eq(InboundCartonLabelEntity::getInboundId, inboundId)
|
||||||
|
.eq(InboundCartonLabelEntity::getInboundDetailId, inboundDetailId)
|
||||||
|
.isNull(InboundCartonLabelEntity::getSkuCode)
|
||||||
|
.set(InboundCartonLabelEntity::getSkuCode, skuCode.trim()));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean initializeOriginalPackageCount(long tenantId, long inboundId, int packageCount) {
|
public boolean initializeOriginalPackageCount(long tenantId, long inboundId, int packageCount) {
|
||||||
return inbounds.update(null, new LambdaUpdateWrapper<InboundOrderEntity>()
|
return inbounds.update(null, new LambdaUpdateWrapper<InboundOrderEntity>()
|
||||||
.eq(InboundOrderEntity::getTenantId, tenantId)
|
.eq(InboundOrderEntity::getTenantId, tenantId)
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ public class InboundCartonLabelService implements CartonLabelBindingResolver {
|
|||||||
throw new BizException(ResultCode.CONFLICT, "当前入库单状态不允许首次生成箱号");
|
throw new BizException(ResultCode.CONFLICT, "当前入库单状态不允许首次生成箱号");
|
||||||
}
|
}
|
||||||
List<OrderCargoClient.CargoLabelBinding> cargoes = loadCargoes(inbound);
|
List<OrderCargoClient.CargoLabelBinding> cargoes = loadCargoes(inbound);
|
||||||
|
if ("ONE_CLICK_DROPSHIP".equals(inbound.getFulfillmentType())
|
||||||
|
&& cargoes.stream().anyMatch(cargo -> cargo.skuNo() == null || cargo.skuNo().isBlank())) {
|
||||||
|
throw new BizException(ResultCode.VALIDATION_FAILED, "一件代发货物明细缺少SKU,不能生成箱唛");
|
||||||
|
}
|
||||||
|
existing.forEach(label -> cargoes.stream()
|
||||||
|
.filter(cargo -> java.util.Objects.equals(cargo.cargoId(), label.getInboundDetailId()))
|
||||||
|
.findFirst().ifPresent(cargo -> repository.initializeLegacySku(tenantId, inboundId,
|
||||||
|
label.getInboundDetailId(), cargo.skuNo())));
|
||||||
String fingerprint = fingerprint(cargoes);
|
String fingerprint = fingerprint(cargoes);
|
||||||
if (!existing.isEmpty()) {
|
if (!existing.isEmpty()) {
|
||||||
String existingFingerprint = consistent.get(0).getCargoFingerprint();
|
String existingFingerprint = consistent.get(0).getCargoFingerprint();
|
||||||
@@ -202,6 +210,7 @@ public class InboundCartonLabelService implements CartonLabelBindingResolver {
|
|||||||
label.setInboundDetailId(cargo.cargoId());
|
label.setInboundDetailId(cargo.cargoId());
|
||||||
label.setCargoItemNo(cargo.itemNo());
|
label.setCargoItemNo(cargo.itemNo());
|
||||||
label.setCargoName(cargo.cargoName());
|
label.setCargoName(cargo.cargoName());
|
||||||
|
label.setSkuCode(cargo.skuNo());
|
||||||
label.setDetailPackageCount(cargo.packageCount());
|
label.setDetailPackageCount(cargo.packageCount());
|
||||||
label.setInboundCode(inbound.getInboundCode());
|
label.setInboundCode(inbound.getInboundCode());
|
||||||
label.setBoxCode(inbound.getInboundCode() + "#" + total + "-" + index);
|
label.setBoxCode(inbound.getInboundCode() + "#" + total + "-" + index);
|
||||||
@@ -256,7 +265,8 @@ public class InboundCartonLabelService implements CartonLabelBindingResolver {
|
|||||||
|
|
||||||
private String fingerprint(List<OrderCargoClient.CargoLabelBinding> cargoes) {
|
private String fingerprint(List<OrderCargoClient.CargoLabelBinding> cargoes) {
|
||||||
String source = cargoes.stream().map(cargo -> String.join("|", String.valueOf(cargo.itemNo()),
|
String source = cargoes.stream().map(cargo -> String.join("|", String.valueOf(cargo.itemNo()),
|
||||||
cargo.cargoName() == null ? "" : cargo.cargoName().trim(), String.valueOf(cargo.packageCount()),
|
cargo.cargoName() == null ? "" : cargo.cargoName().trim(),
|
||||||
|
cargo.skuNo() == null ? "" : cargo.skuNo().trim(), String.valueOf(cargo.packageCount()),
|
||||||
decimalOrEmpty(cargo.lengthCm()), decimalOrEmpty(cargo.widthCm()), decimalOrEmpty(cargo.heightCm())))
|
decimalOrEmpty(cargo.lengthCm()), decimalOrEmpty(cargo.widthCm()), decimalOrEmpty(cargo.heightCm())))
|
||||||
.collect(java.util.stream.Collectors.joining("\n"));
|
.collect(java.util.stream.Collectors.joining("\n"));
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ DELIMITER ;
|
|||||||
CALL phase2_carton_label_add_column('label_version', 'INT UNSIGNED NOT NULL DEFAULT 1 COMMENT ''内部兼容批次字段,固定为1且不进入箱码'' AFTER carton_index');
|
CALL phase2_carton_label_add_column('label_version', 'INT UNSIGNED NOT NULL DEFAULT 1 COMMENT ''内部兼容批次字段,固定为1且不进入箱码'' AFTER carton_index');
|
||||||
CALL phase2_carton_label_add_column('batch_status', 'VARCHAR(16) NOT NULL DEFAULT ''ACTIVE'' COMMENT ''批次状态:ACTIVE有效、VOID已作废'' AFTER label_version');
|
CALL phase2_carton_label_add_column('batch_status', 'VARCHAR(16) NOT NULL DEFAULT ''ACTIVE'' COMMENT ''批次状态:ACTIVE有效、VOID已作废'' AFTER label_version');
|
||||||
CALL phase2_carton_label_add_column('cargo_fingerprint', 'CHAR(64) NULL COMMENT ''影响标签字段的SHA-256指纹'' AFTER batch_status');
|
CALL phase2_carton_label_add_column('cargo_fingerprint', 'CHAR(64) NULL COMMENT ''影响标签字段的SHA-256指纹'' AFTER batch_status');
|
||||||
|
CALL phase2_carton_label_add_column('sku_code', 'VARCHAR(128) NULL COMMENT ''箱唛绑定的SKU快照;二维码内容不变'' AFTER cargo_name');
|
||||||
CALL phase2_carton_label_add_column('voided_at', 'DATETIME(3) NULL COMMENT ''批次作废时间'' AFTER cargo_fingerprint');
|
CALL phase2_carton_label_add_column('voided_at', 'DATETIME(3) NULL COMMENT ''批次作废时间'' AFTER cargo_fingerprint');
|
||||||
DROP PROCEDURE phase2_carton_label_add_column;
|
DROP PROCEDURE phase2_carton_label_add_column;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_carton_label (
|
|||||||
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
||||||
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
||||||
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
||||||
|
sku_code VARCHAR(128) NULL COMMENT '箱唛绑定的SKU快照;二维码内容不变',
|
||||||
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
||||||
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
||||||
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_carton_label (
|
|||||||
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键',
|
||||||
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照',
|
||||||
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
cargo_name VARCHAR(255) NULL COMMENT '货物名称快照',
|
||||||
|
sku_code VARCHAR(128) NULL COMMENT '箱唛绑定的SKU快照;二维码内容不变',
|
||||||
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照',
|
||||||
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照',
|
||||||
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标',
|
||||||
|
|||||||
+8
@@ -154,6 +154,14 @@ public class DispatchPdaWorkflowService {
|
|||||||
if (replay != null) return read(replay, DispatchPdaResponses.PickingCompleted.class).withReplay();
|
if (replay != null) return read(replay, DispatchPdaResponses.PickingCompleted.class).withReplay();
|
||||||
requireVehicle(order);
|
requireVehicle(order);
|
||||||
DispatchPdaTask task = tasks.lockByDispatch(customerId, order.getId());
|
DispatchPdaTask task = tasks.lockByDispatch(customerId, order.getId());
|
||||||
|
if (task != null && "COMPLETED".equals(task.getStatus())) {
|
||||||
|
List<DispatchItem> completedItems = items.findByDispatchOrder(customerId, order.getId());
|
||||||
|
long planned = completedItems.stream().map(DispatchItem::getPackageCount).filter(Objects::nonNull)
|
||||||
|
.mapToLong(Integer::longValue).sum();
|
||||||
|
long picked = picks.listTask(customerId, task.getId()).stream().mapToLong(p -> n(p.getPackages())).sum();
|
||||||
|
return new DispatchPdaResponses.PickingCompleted(order.getDispatchNo(), order.getStatus(), planned,
|
||||||
|
picked, Math.max(0, planned - picked), picked < planned, true);
|
||||||
|
}
|
||||||
if (task == null || !("PDA_PENDING".equals(task.getStatus()) || "PICKING".equals(task.getStatus()))) {
|
if (task == null || !("PDA_PENDING".equals(task.getStatus()) || "PICKING".equals(task.getStatus()))) {
|
||||||
throw conflict("Dispatch PDA task is not available for completion");
|
throw conflict("Dispatch PDA task is not available for completion");
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -243,6 +243,18 @@ public class InboundPlanService {
|
|||||||
if (trimToNull(request.warehouseName()) != null) line.setDestinationWarehouseName(request.warehouseName().trim());
|
if (trimToNull(request.warehouseName()) != null) line.setDestinationWarehouseName(request.warehouseName().trim());
|
||||||
lineMapper.updateById(line);
|
lineMapper.updateById(line);
|
||||||
}
|
}
|
||||||
|
// Pallets carry the same destination snapshot and are consumed by PDA/resource assignment.
|
||||||
|
// Update them in this transaction so a plan edit cannot leave lines and pallets pointing at
|
||||||
|
// different warehouses.
|
||||||
|
List<InboundPlanPallet> pallets = palletMapper.selectList(new LambdaQueryWrapper<InboundPlanPallet>()
|
||||||
|
.eq(InboundPlanPallet::getPlanId, plan.getId())
|
||||||
|
.eq(InboundPlanPallet::getCustomerId, plan.getCustomerId()));
|
||||||
|
for (InboundPlanPallet pallet : pallets) {
|
||||||
|
pallet.setDestinationWarehouseId(String.valueOf(request.overseasWarehouseId()));
|
||||||
|
if (trimToNull(request.warehouseCode()) != null) pallet.setDestinationWarehouseCode(request.warehouseCode().trim());
|
||||||
|
if (trimToNull(request.warehouseName()) != null) pallet.setDestinationWarehouseName(request.warehouseName().trim());
|
||||||
|
palletMapper.updateById(pallet);
|
||||||
|
}
|
||||||
return detail(customerId, plan);
|
return detail(customerId, plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class LastlegOrderControllerTest {
|
|||||||
private final LastlegOrderService service = mock(LastlegOrderService.class);
|
private final LastlegOrderService service = mock(LastlegOrderService.class);
|
||||||
private final LastlegOrderController controller = controller();
|
private final LastlegOrderController controller = controller();
|
||||||
private final LastlegOrderRequests.Query query = new LastlegOrderRequests.Query(
|
private final LastlegOrderRequests.Query query = new LastlegOrderRequests.Query(
|
||||||
1, 20, null, null, null, null, null, null, null, null, null, null, null, null, null);
|
1L, 20L, null, null, null, null, null, null, null, null, null, null, null, null, null);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void platformEndpointRejectsMerchantIdentity() {
|
void platformEndpointRejectsMerchantIdentity() {
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ class MerchantLastlegOrderControllerTest {
|
|||||||
private final LastlegOrderService service = mock(LastlegOrderService.class);
|
private final LastlegOrderService service = mock(LastlegOrderService.class);
|
||||||
private final MerchantLastlegOrderController controller = controller();
|
private final MerchantLastlegOrderController controller = controller();
|
||||||
private final LastlegOrderRequests.Query query = new LastlegOrderRequests.Query(
|
private final LastlegOrderRequests.Query query = new LastlegOrderRequests.Query(
|
||||||
1, 20, null, null, null, null, null, null, null, null, null, null, null, null, null);
|
1L, 20L, null, null, null, null, null, null, null, null, null, null, null, null, null);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void merchantListUsesOnlyAuthenticatedTenant() {
|
void merchantListUsesOnlyAuthenticatedTenant() {
|
||||||
|
|||||||
+41
@@ -2,11 +2,17 @@ package com.baiyue.lastleg.dispatch.pda.service;
|
|||||||
|
|
||||||
import com.baiyue.lastleg.delivery.mapper.OutboundOrderMapper;
|
import com.baiyue.lastleg.delivery.mapper.OutboundOrderMapper;
|
||||||
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
|
import com.baiyue.lastleg.dispatch.entity.DispatchOrder;
|
||||||
|
import com.baiyue.lastleg.dispatch.entity.DispatchItem;
|
||||||
|
import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper;
|
||||||
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
|
import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper;
|
||||||
import com.baiyue.lastleg.dispatch.pda.dto.DispatchPdaRequests;
|
import com.baiyue.lastleg.dispatch.pda.dto.DispatchPdaRequests;
|
||||||
import com.baiyue.lastleg.dispatch.pda.dto.DispatchPdaResponses;
|
import com.baiyue.lastleg.dispatch.pda.dto.DispatchPdaResponses;
|
||||||
import com.baiyue.lastleg.dispatch.pda.entity.DispatchPdaOperation;
|
import com.baiyue.lastleg.dispatch.pda.entity.DispatchPdaOperation;
|
||||||
|
import com.baiyue.lastleg.dispatch.pda.entity.DispatchPdaPick;
|
||||||
|
import com.baiyue.lastleg.dispatch.pda.entity.DispatchPdaTask;
|
||||||
import com.baiyue.lastleg.dispatch.pda.mapper.DispatchPdaOperationMapper;
|
import com.baiyue.lastleg.dispatch.pda.mapper.DispatchPdaOperationMapper;
|
||||||
|
import com.baiyue.lastleg.dispatch.pda.mapper.DispatchPdaPickMapper;
|
||||||
|
import com.baiyue.lastleg.dispatch.pda.mapper.DispatchPdaTaskMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -15,6 +21,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
@@ -25,6 +33,9 @@ class DispatchPdaWorkflowServiceTest {
|
|||||||
@Mock private DispatchOrderMapper orders;
|
@Mock private DispatchOrderMapper orders;
|
||||||
@Mock private DispatchPdaOperationMapper operations;
|
@Mock private DispatchPdaOperationMapper operations;
|
||||||
@Mock private OutboundOrderMapper outboundOrders;
|
@Mock private OutboundOrderMapper outboundOrders;
|
||||||
|
@Mock private DispatchItemMapper items;
|
||||||
|
@Mock private DispatchPdaTaskMapper tasks;
|
||||||
|
@Mock private DispatchPdaPickMapper picks;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void labelsTransferredPalletsWithOriginalAndCurrentFbaWarehouses() {
|
void labelsTransferredPalletsWithOriginalAndCurrentFbaWarehouses() {
|
||||||
@@ -126,4 +137,34 @@ class DispatchPdaWorkflowServiceTest {
|
|||||||
assertEquals("DEPARTED", result.status());
|
assertEquals("DEPARTED", result.status());
|
||||||
assertEquals(true, result.replayed());
|
assertEquals(true, result.replayed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void completingAnAutomaticallyCompletedTaskReturnsIdempotentSuccess() {
|
||||||
|
DispatchPdaWorkflowService service = new DispatchPdaWorkflowService();
|
||||||
|
ReflectionTestUtils.setField(service, "orders", orders);
|
||||||
|
ReflectionTestUtils.setField(service, "operations", operations);
|
||||||
|
ReflectionTestUtils.setField(service, "items", items);
|
||||||
|
ReflectionTestUtils.setField(service, "tasks", tasks);
|
||||||
|
ReflectionTestUtils.setField(service, "picks", picks);
|
||||||
|
DispatchOrder order = new DispatchOrder();
|
||||||
|
order.setId(1L); order.setCustomerId("100"); order.setDispatchNo("PC1");
|
||||||
|
order.setStatus("READY_TO_DEPART"); order.setVehiclePlate("CA-100");
|
||||||
|
DispatchPdaTask task = new DispatchPdaTask();
|
||||||
|
task.setId(2L); task.setStatus("COMPLETED");
|
||||||
|
DispatchItem item = new DispatchItem(); item.setPackageCount(6);
|
||||||
|
DispatchPdaPick pick = new DispatchPdaPick(); pick.setPackages(6L);
|
||||||
|
DispatchPdaRequests.CompletePicking request = new DispatchPdaRequests.CompletePicking("complete-1", "normal");
|
||||||
|
when(orders.findByDispatchNo("100", "PC1")).thenReturn(order);
|
||||||
|
when(orders.lockById("100", 1L)).thenReturn(order);
|
||||||
|
when(operations.findKey("100", "complete-1")).thenReturn(null);
|
||||||
|
when(tasks.lockByDispatch("100", 1L)).thenReturn(task);
|
||||||
|
when(items.findByDispatchOrder("100", 1L)).thenReturn(List.of(item));
|
||||||
|
when(picks.listTask("100", 2L)).thenReturn(List.of(pick));
|
||||||
|
|
||||||
|
DispatchPdaResponses.PickingCompleted result = service.completePicking("100", "PC1", request);
|
||||||
|
|
||||||
|
assertEquals("READY_TO_DEPART", result.status());
|
||||||
|
assertEquals(6, result.pickedPackages());
|
||||||
|
assertEquals(true, result.replayed());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -2,6 +2,7 @@ package com.baiyue.lastleg.inboundplan.service;
|
|||||||
|
|
||||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlan;
|
import com.baiyue.lastleg.inboundplan.entity.InboundPlan;
|
||||||
import com.baiyue.lastleg.inboundplan.dto.InboundPlanRequests;
|
import com.baiyue.lastleg.inboundplan.dto.InboundPlanRequests;
|
||||||
|
import com.baiyue.lastleg.inboundplan.dto.UpdateInboundPlanRequest;
|
||||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlanLine;
|
import com.baiyue.lastleg.inboundplan.entity.InboundPlanLine;
|
||||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPallet;
|
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPallet;
|
||||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPalletAllocation;
|
import com.baiyue.lastleg.inboundplan.entity.InboundPlanPalletAllocation;
|
||||||
@@ -199,6 +200,53 @@ class InboundPlanServiceTest {
|
|||||||
.map(InboundPlanPalletAllocation::getPlannedPackageCount).toList());
|
.map(InboundPlanPalletAllocation::getPlannedPackageCount).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateSynchronizesDestinationSnapshotToLinesAndPallets() {
|
||||||
|
InboundPlan plan = new InboundPlan();
|
||||||
|
plan.setId(20L);
|
||||||
|
plan.setPlanNo("IP-20");
|
||||||
|
plan.setCustomerId("100");
|
||||||
|
plan.setStatus("PENDING_ASSIGNMENT");
|
||||||
|
plan.setVersion(3);
|
||||||
|
|
||||||
|
InboundPlanLine line = new InboundPlanLine();
|
||||||
|
line.setId(21L);
|
||||||
|
line.setCustomerId("100");
|
||||||
|
line.setPlanId(20L);
|
||||||
|
line.setDestinationWarehouseId("OLD-WH");
|
||||||
|
line.setDestinationWarehouseCode("OLD-CODE");
|
||||||
|
line.setDestinationWarehouseName("Old warehouse");
|
||||||
|
|
||||||
|
InboundPlanPallet pallet = new InboundPlanPallet();
|
||||||
|
pallet.setId(22L);
|
||||||
|
pallet.setCustomerId("100");
|
||||||
|
pallet.setPlanId(20L);
|
||||||
|
pallet.setDestinationWarehouseId("OLD-WH");
|
||||||
|
pallet.setDestinationWarehouseCode("OLD-CODE");
|
||||||
|
pallet.setDestinationWarehouseName("Old warehouse");
|
||||||
|
|
||||||
|
when(planMapper.selectOne(any())).thenReturn(plan);
|
||||||
|
when(lineMapper.selectList(any())).thenReturn(List.of(line), List.of(line));
|
||||||
|
when(palletMapper.selectList(any())).thenReturn(List.of(pallet), List.of(pallet));
|
||||||
|
when(allocationMapper.selectList(any())).thenReturn(List.of());
|
||||||
|
|
||||||
|
service.update("100", "IP-20",
|
||||||
|
new UpdateInboundPlanRequest("100", 193000000000200003L,
|
||||||
|
" US-LAX-01 ", " Los Angeles Warehouse ", 3));
|
||||||
|
|
||||||
|
ArgumentCaptor<InboundPlanLine> updatedLine = ArgumentCaptor.forClass(InboundPlanLine.class);
|
||||||
|
verify(lineMapper).updateById(updatedLine.capture());
|
||||||
|
assertEquals("193000000000200003", updatedLine.getValue().getDestinationWarehouseId());
|
||||||
|
assertEquals("US-LAX-01", updatedLine.getValue().getDestinationWarehouseCode());
|
||||||
|
assertEquals("Los Angeles Warehouse", updatedLine.getValue().getDestinationWarehouseName());
|
||||||
|
|
||||||
|
ArgumentCaptor<InboundPlanPallet> updatedPallet = ArgumentCaptor.forClass(InboundPlanPallet.class);
|
||||||
|
verify(palletMapper).updateById(updatedPallet.capture());
|
||||||
|
assertEquals("193000000000200003", updatedPallet.getValue().getDestinationWarehouseId());
|
||||||
|
assertEquals("US-LAX-01", updatedPallet.getValue().getDestinationWarehouseCode());
|
||||||
|
assertEquals("Los Angeles Warehouse", updatedPallet.getValue().getDestinationWarehouseName());
|
||||||
|
}
|
||||||
|
|
||||||
private SourceOrderSnapshot order(Long id, String inboundCode, String volume, String warehouse) {
|
private SourceOrderSnapshot order(Long id, String inboundCode, String volume, String warehouse) {
|
||||||
return new SourceOrderSnapshot(id, "100", "CONT-1", inboundCode, "PENDING_ASSIGNMENT", null,
|
return new SourceOrderSnapshot(id, "100", "CONT-1", inboundCode, "PENDING_ASSIGNMENT", null,
|
||||||
new BigDecimal(volume), new BigDecimal(volume).multiply(BigDecimal.TEN).intValue(),
|
new BigDecimal(volume), new BigDecimal(volume).multiply(BigDecimal.TEN).intValue(),
|
||||||
|
|||||||
+2
-2
@@ -182,7 +182,7 @@ class LastlegOrderServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pageUsesPaginationAndPlatformFiltersWithoutCustomerScope() {
|
void pageUsesPaginationAndPlatformFiltersWithoutCustomerScope() {
|
||||||
var query = new LastlegOrderRequests.Query(3, 25, "LL-", "FIRST_LEG", "IN-", null,
|
var query = new LastlegOrderRequests.Query(3L, 25L, "LL-", "FIRST_LEG", "IN-", null,
|
||||||
"", "PENDING_ASSIGNMENT", null, "LAX", null, null, null, null, null);
|
"", "PENDING_ASSIGNMENT", null, "LAX", null, null, null, null, null);
|
||||||
var resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<LastlegOrder>(3, 25);
|
var resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<LastlegOrder>(3, 25);
|
||||||
resultPage.setTotal(0);
|
resultPage.setTotal(0);
|
||||||
@@ -208,7 +208,7 @@ class LastlegOrderServiceTest {
|
|||||||
when(orders.findPalletMergeRelations(List.of(11L))).thenReturn(List.of(
|
when(orders.findPalletMergeRelations(List.of(11L))).thenReturn(List.of(
|
||||||
new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-2", "PMG-1"),
|
new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-2", "PMG-1"),
|
||||||
new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-3", "PMG-1")));
|
new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-3", "PMG-1")));
|
||||||
var query = new LastlegOrderRequests.Query(1, 10, null, null, null, null,
|
var query = new LastlegOrderRequests.Query(1L, 10L, null, null, null, null,
|
||||||
null, null, null, null, null, null, null, null, null);
|
null, null, null, null, null, null, null, null, null);
|
||||||
|
|
||||||
var result = service.page(null, query);
|
var result = service.page(null, query);
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ public class InternalOrderCargoController {
|
|||||||
}
|
}
|
||||||
return ApiResponse.success(orders.findCargoInheritedByOrder(tenantId, orderId).stream()
|
return ApiResponse.success(orders.findCargoInheritedByOrder(tenantId, orderId).stream()
|
||||||
.map(cargo -> new CargoLabelBinding(cargo.getId(), orderId, cargo.getItemNo(),
|
.map(cargo -> new CargoLabelBinding(cargo.getId(), orderId, cargo.getItemNo(),
|
||||||
cargo.getCargoName(), cargo.getPackageCount(), cargo.getLengthCm(), cargo.getWidthCm(),
|
cargo.getCargoName(), cargo.getSkuNo(), cargo.getPackageCount(), cargo.getLengthCm(),
|
||||||
cargo.getHeightCm()))
|
cargo.getWidthCm(), cargo.getHeightCm()))
|
||||||
.toList());
|
.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +155,13 @@ public class InternalOrderCargoController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public record CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
public record CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
||||||
Integer packageCount, java.math.BigDecimal lengthCm,
|
String skuNo, Integer packageCount, java.math.BigDecimal lengthCm,
|
||||||
java.math.BigDecimal widthCm, java.math.BigDecimal heightCm) {
|
java.math.BigDecimal widthCm, java.math.BigDecimal heightCm) {
|
||||||
|
public CargoLabelBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
||||||
|
Integer packageCount, java.math.BigDecimal lengthCm,
|
||||||
|
java.math.BigDecimal widthCm, java.math.BigDecimal heightCm) {
|
||||||
|
this(cargoId, orderId, itemNo, cargoName, null, packageCount, lengthCm, widthCm, heightCm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record MeasurementDeclarationSnapshot(
|
public record MeasurementDeclarationSnapshot(
|
||||||
|
|||||||
Reference in New Issue
Block a user