This commit is contained in:
2026-08-17 20:21:44 +08:00
parent b8c7f9fea2
commit 092c003e3a
6 changed files with 44 additions and 10 deletions
@@ -2528,14 +2528,38 @@ CREATE TABLE IF NOT EXISTS fl_inbound_order (
) ENGINE=InnoDB COMMENT='二期头程入库单聚合根和列表查询快照';
UPDATE baiyue_order.ord_order o
LEFT JOIN baiyue_firstleg.fl_inbound_order i
JOIN baiyue_firstleg.fl_inbound_order i
ON i.tenant_id = o.tenant_id AND i.order_id = o.id AND i.deleted = 0
SET o.inbound_code = COALESCE(i.inbound_code, CONCAT('RK-', o.id))
SET o.inbound_code = i.inbound_code
WHERE o.deleted = 0
AND o.status <> 'DRAFT'
AND (o.submitted_at IS NOT NULL
OR o.status IN ('SUBMITTED', 'APPROVED', 'ACCEPTED', 'PROCESSING', 'COMPLETED'))
AND o.inbound_code IS NULL;
AND o.inbound_code IS NULL
AND i.inbound_code IS NOT NULL
AND TRIM(i.inbound_code) <> '';
-- 非草稿订单若既无订单入仓码也无 Firstleg 权威入仓码,禁止用内部 ID 伪造业务键。
DROP PROCEDURE IF EXISTS assert_submitted_order_inbound_code;
DELIMITER $$
CREATE PROCEDURE assert_submitted_order_inbound_code()
BEGIN
IF EXISTS (
SELECT 1
FROM baiyue_order.ord_order o
WHERE o.deleted = 0
AND o.status <> 'DRAFT'
AND (o.submitted_at IS NOT NULL
OR o.status IN ('SUBMITTED', 'APPROVED', 'ACCEPTED', 'PROCESSING', 'COMPLETED'))
AND (o.inbound_code IS NULL OR TRIM(o.inbound_code) = '')
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '存在已提交订单缺少权威入仓码,请先修复订单/Firstleg业务事实后重跑';
END IF;
END$$
DELIMITER ;
CALL assert_submitted_order_inbound_code();
DROP PROCEDURE IF EXISTS assert_submitted_order_inbound_code;
-- 从未提交的草稿或由草稿直接取消的订单不应拥有入仓码。
UPDATE baiyue_order.ord_order
@@ -9,6 +9,7 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
import com.baiyue.firstleg.dto.InboundOrderReference;
import com.baiyue.firstleg.service.InboundOrderCreationService;
import com.baiyue.firstleg.service.InboundCartonLabelService;
import com.baiyue.firstleg.service.UnifiedInboundQueryService;
import com.baiyue.firstleg.dto.UnifiedInboundDetail;
import com.baiyue.firstleg.dto.UnifiedInboundQuery;
@@ -35,6 +36,8 @@ public class InternalInboundOrderController {
@Resource
private InboundOrderCreationService service;
@Resource
private InboundCartonLabelService cartonLabels;
@Resource
private UnifiedInboundQueryService unifiedQueryService;
@Value("${baiyue.security.internal-service-token}")
private String internalToken;
@@ -59,7 +62,9 @@ public class InternalInboundOrderController {
|| command.totalPackageCount() != null && command.totalPackageCount() < 1) {
throw new BizException(ResultCode.BAD_REQUEST, "订单入库快照不完整");
}
return ApiResponse.success(service.createFromApprovedOrder(command));
long inboundId = service.createFromApprovedOrder(command);
cartonLabels.getOrCreate(command.tenantId(), inboundId);
return ApiResponse.success(inboundId);
}
@PostMapping("/order-preparing")
@@ -4,6 +4,7 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.dto.InboundOrderReference;
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
import com.baiyue.firstleg.service.InboundOrderCreationService;
import com.baiyue.firstleg.service.InboundCartonLabelService;
import com.baiyue.firstleg.service.UnifiedInboundQueryService;
import com.baiyue.firstleg.dto.UnifiedInboundQuery;
import com.baiyue.common.core.api.PageResult;
@@ -27,6 +28,8 @@ class InternalInboundOrderReferenceControllerTest {
@MockBean
private InboundOrderCreationService service;
@MockBean
private InboundCartonLabelService cartonLabels;
@MockBean
private UnifiedInboundQueryService unifiedQueryService;
@Resource
private InternalInboundOrderController controller;
@@ -79,6 +82,7 @@ class InternalInboundOrderReferenceControllerTest {
assertThat(controller.createFromApprovedOrder("internal-token", command).data()).isEqualTo(88L);
verify(service).createFromApprovedOrder(command);
verify(cartonLabels).getOrCreate(10001L, 88L);
}
private static OrderApprovedInboundCommand approvedCommand(String inboundCode, Long carrierId) {
@@ -64,19 +64,17 @@ public class OrderApplicationService {
private Long createDraftInternal(long tenantId, long userId, OrderRequests.SaveRequest request) {
productImageGuard.requireOwned(tenantId, request.cargoes());
var snapshots = masterDataGuard.validate(tenantId, request);
String inboundCodePrefix = pricingChannelGuard.requireAvailable(tenantId, request.receivingWarehouseId(),
pricingChannelGuard.requireAvailable(tenantId, request.receivingWarehouseId(),
request.channelCode(), request.destinationType());
OrderEntity order = new OrderEntity();
long orderId = IdWorker.getId();
order.setId(orderId); order.setTenantId(tenantId); order.setOrderNo(nextNo(orderId));
order.setStatus(OrderStatus.DRAFT);
apply(order, tenantId, request, snapshots);
order.setInboundCode(nextInboundCode(inboundCodePrefix));
order.setCreatedBy(userId); order.setUpdatedBy(userId);
repository.insertOrder(order);
saveChildren(tenantId, userId, order.getId(), request);
record(tenantId, order.getId(), null, OrderStatus.DRAFT, "CREATE", null, userId, null);
prepareDraftInbound(order, request);
return order.getId();
}
@@ -116,7 +114,7 @@ public class OrderApplicationService {
repository.replaceDraftChildren(tenantId, id);
saveChildren(tenantId, userId, id, request);
record(tenantId, id, before, order.getStatus(), "UPDATE", null, userId, null);
prepareDraftInbound(order, request);
if (before == OrderStatus.SUBMITTED) prepareDraftInbound(order, request);
}
@Transactional
@@ -29,6 +29,9 @@ class OrderPickupSqlContractTest {
assertThat(relax).isGreaterThanOrEqualTo(0).isLessThan(clearDraft);
assertThat(sql).contains(
"column_name = 'requested_pickup_at'",
"ALTER TABLE baiyue_order.ord_order ADD COLUMN requested_pickup_at DATETIME(3) NULL");
"ALTER TABLE baiyue_order.ord_order ADD COLUMN requested_pickup_at DATETIME(3) NULL",
"CREATE PROCEDURE assert_submitted_order_inbound_code()",
"SIGNAL SQLSTATE '45000'");
assertThat(sql).doesNotContain("CONCAT('RK-', o.id)");
}
}
@@ -58,7 +58,7 @@ class OrderApplicationServiceStateTest {
assertThat(orderId).isNotNull();
verify(eligibility, never()).requireApproved(anyLong());
verify(repository).insertOrder(argThat(order -> order.getStatus() == OrderStatus.DRAFT
&& order.getInboundCode().matches("PCHWK\\d{6}0001")));
&& order.getInboundCode() == null));
}
@Test