优化
This commit is contained in:
@@ -11,10 +11,67 @@ public interface LoadingInboundMapper {
|
||||
+ "FROM fl_inbound_order WHERE tenant_id=#{tenantId} AND id=#{inboundId} AND deleted=0")
|
||||
Snapshot find(@Param("tenantId") long tenantId, @Param("inboundId") long inboundId);
|
||||
|
||||
@Select("""
|
||||
SELECT batch.source_inbound_id AS sourceInboundId,
|
||||
batch.loaded_child_inbound_id AS loadedChildInboundId,
|
||||
batch.parent_inbound_id AS rootInboundId,
|
||||
source.process_status AS sourceStatus, source.version AS sourceVersion,
|
||||
child.process_status AS loadedChildStatus, child.version AS loadedChildVersion
|
||||
FROM fl_inbound_split_batch batch
|
||||
JOIN fl_inbound_order source ON source.id=batch.source_inbound_id
|
||||
AND source.tenant_id=batch.tenant_id AND source.deleted=0
|
||||
JOIN fl_inbound_order child ON child.id=batch.loaded_child_inbound_id
|
||||
AND child.tenant_id=batch.tenant_id AND child.deleted=0
|
||||
WHERE batch.tenant_id=#{tenantId} AND batch.status='APPLIED'
|
||||
AND (batch.source_inbound_id=#{inboundId} OR batch.loaded_child_inbound_id=#{inboundId})
|
||||
ORDER BY batch.id DESC LIMIT 1
|
||||
""")
|
||||
CompletionTarget completionTarget(@Param("tenantId") long tenantId,
|
||||
@Param("inboundId") long inboundId);
|
||||
|
||||
@Update("UPDATE fl_inbound_order SET process_status='LOADED', updated_by=#{operatorId}, version=version+1 "
|
||||
+ "WHERE tenant_id=#{tenantId} AND id=#{inboundId} AND deleted=0 AND process_status='LOADING' AND version=#{expectedVersion}")
|
||||
int completeLoading(@Param("tenantId") long tenantId, @Param("inboundId") long inboundId,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_order child
|
||||
JOIN fl_inbound_split_batch batch ON batch.loaded_child_inbound_id=child.id
|
||||
AND batch.tenant_id=child.tenant_id AND batch.status='APPLIED'
|
||||
JOIN fl_inbound_order source ON source.id=batch.source_inbound_id
|
||||
AND source.tenant_id=batch.tenant_id AND source.deleted=0
|
||||
SET child.process_status='LOADED', child.updated_by=#{operatorId}, child.version=child.version+1
|
||||
WHERE child.tenant_id=#{tenantId} AND batch.source_inbound_id=#{sourceInboundId}
|
||||
AND child.deleted=0 AND child.process_status='LOADING'
|
||||
AND source.version=#{expectedSourceVersion}
|
||||
""")
|
||||
int completeLoadedChild(@Param("tenantId") long tenantId,
|
||||
@Param("sourceInboundId") long sourceInboundId,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("expectedSourceVersion") int expectedSourceVersion);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_inbound_order root
|
||||
SET root.process_status='LOADED', root.updated_by=#{operatorId}, root.version=root.version+1
|
||||
WHERE root.tenant_id=#{tenantId} AND root.id=#{rootInboundId} AND root.deleted=0
|
||||
AND root.inbound_role='MASTER' AND root.process_status IN ('INBOUNDED','LOADING')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM fl_inbound_order remainder
|
||||
WHERE remainder.tenant_id=root.tenant_id AND remainder.parent_inbound_id=root.id
|
||||
AND remainder.inbound_role='CHILD' AND remainder.split_purpose='REMAINDER'
|
||||
AND remainder.split_status='NOT_SPLIT' AND remainder.deleted=0)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM fl_inbound_order loaded
|
||||
WHERE loaded.tenant_id=root.tenant_id AND loaded.parent_inbound_id=root.id
|
||||
AND loaded.inbound_role='CHILD' AND loaded.split_purpose='LOADED'
|
||||
AND loaded.process_status<>'LOADED' AND loaded.deleted=0)
|
||||
""")
|
||||
int aggregateRootLoaded(@Param("tenantId") long tenantId,
|
||||
@Param("rootInboundId") long rootInboundId,
|
||||
@Param("operatorId") long operatorId);
|
||||
|
||||
record Snapshot(Long id, Long tenantId, String processStatus, Integer version) {}
|
||||
record CompletionTarget(Long sourceInboundId, Long loadedChildInboundId, Long rootInboundId,
|
||||
String sourceStatus, Integer sourceVersion,
|
||||
String loadedChildStatus, Integer loadedChildVersion) {}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,19 @@ public class LoadingRepository {
|
||||
return inbounds.completeLoading(tenantId, inboundId, operatorId, expectedVersion);
|
||||
}
|
||||
|
||||
public LoadingInboundMapper.CompletionTarget completionTarget(long tenantId, long inboundId) {
|
||||
return inbounds.completionTarget(tenantId, inboundId);
|
||||
}
|
||||
|
||||
public int completeLoadedChild(long tenantId, long sourceInboundId, long operatorId,
|
||||
int expectedSourceVersion) {
|
||||
return inbounds.completeLoadedChild(tenantId, sourceInboundId, operatorId, expectedSourceVersion);
|
||||
}
|
||||
|
||||
public int aggregateRootLoaded(long tenantId, long rootInboundId, long operatorId) {
|
||||
return inbounds.aggregateRootLoaded(tenantId, rootInboundId, operatorId);
|
||||
}
|
||||
|
||||
public List<LoadingEvidenceEntity> listEvidence(long tenantId, long inboundId) {
|
||||
return evidences.selectList(new LambdaQueryWrapper<LoadingEvidenceEntity>()
|
||||
.eq(LoadingEvidenceEntity::getTenantId, tenantId)
|
||||
|
||||
+38
@@ -14,6 +14,7 @@ import com.baiyue.firstleg.loading.entity.InboundLoadingPickTaskEntity;
|
||||
import com.baiyue.firstleg.loading.domain.PickingStatus;
|
||||
import com.baiyue.firstleg.loading.dto.LoadingResponses.PickingResponse;
|
||||
import com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.Snapshot;
|
||||
import com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.CompletionTarget;
|
||||
import com.baiyue.firstleg.loading.bridge.service.LoadingModelBridgeService;
|
||||
import com.baiyue.firstleg.loading.repository.LoadingRepository;
|
||||
import com.baiyue.firstleg.repository.LoadingPickRepository;
|
||||
@@ -98,6 +99,10 @@ public class LoadingDeliveryService {
|
||||
LoadingActionResponse replay = claimOrReplay(tenantId, inboundId, operatorId, COMPLETE_LOADING, key, hash);
|
||||
if (replay != null) return replay;
|
||||
Snapshot inbound = requireInbound(tenantId, inboundId);
|
||||
CompletionTarget target = repository.completionTarget(tenantId, inboundId);
|
||||
if (target != null) {
|
||||
return completeFulfillmentSlice(tenantId, inboundId, operatorId, operatorName, key, request, target);
|
||||
}
|
||||
if ("LOADED".equals(inbound.processStatus()) || "DELIVERED".equals(inbound.processStatus())) {
|
||||
loadingModelBridge.requireCompleted(tenantId, inboundId);
|
||||
return complete(tenantId, inboundId, operatorId, COMPLETE_LOADING, key,
|
||||
@@ -114,6 +119,30 @@ public class LoadingDeliveryService {
|
||||
new LoadingActionResponse("LOADED", evidenceResponse(tenantId, inboundId)));
|
||||
}
|
||||
|
||||
private LoadingActionResponse completeFulfillmentSlice(long tenantId, long evidenceInboundId,
|
||||
long operatorId, String operatorName, String key,
|
||||
CompleteLoadingRequest request,
|
||||
CompletionTarget target) {
|
||||
if ("LOADED".equals(target.loadedChildStatus())) {
|
||||
return complete(tenantId, evidenceInboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED", evidenceResponse(tenantId, evidenceInboundId)));
|
||||
}
|
||||
if (!"LOADING".equals(target.loadedChildStatus())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "实装履约分片不在装柜中");
|
||||
}
|
||||
loadingModelBridge.requireCompleted(tenantId, target.sourceInboundId());
|
||||
completionGate.requireBookingTransportAndCustoms(tenantId, target.sourceInboundId());
|
||||
requireCompletedPicking(tenantId, target.sourceInboundId());
|
||||
requireCompletionEvidence(tenantId, target.sourceInboundId());
|
||||
if (repository.completeLoadedChild(tenantId, target.sourceInboundId(), operatorId,
|
||||
request.expectedVersion()) != 1) throw concurrent();
|
||||
repository.aggregateRootLoaded(tenantId, target.rootInboundId(), operatorId);
|
||||
addHistory(tenantId, target.loadedChildInboundId(), "LOADING", "LOADED", COMPLETE_LOADING,
|
||||
request.remark(), operatorId, operatorName);
|
||||
return complete(tenantId, evidenceInboundId, operatorId, COMPLETE_LOADING, key,
|
||||
new LoadingActionResponse("LOADED", evidenceResponse(tenantId, evidenceInboundId)));
|
||||
}
|
||||
|
||||
public EvidenceListResponse evidence(long tenantId, long inboundId) {
|
||||
requireLoadingStage(tenantId, inboundId);
|
||||
return evidenceResponse(tenantId, inboundId);
|
||||
@@ -274,6 +303,8 @@ public class LoadingDeliveryService {
|
||||
|
||||
private Snapshot requireLoadingStage(long tenantId, long inboundId) {
|
||||
Snapshot value = requireInbound(tenantId, inboundId);
|
||||
CompletionTarget target = repository.completionTarget(tenantId, inboundId);
|
||||
if (target != null && Set.of("LOADING", "LOADED").contains(target.loadedChildStatus())) return value;
|
||||
if (!("LOADING".equals(value.processStatus()) || "LOADED".equals(value.processStatus())
|
||||
|| "DELIVERED".equals(value.processStatus()))) {
|
||||
throw new BizException(ResultCode.CONFLICT, "订单尚未进入装柜阶段");
|
||||
@@ -285,6 +316,13 @@ public class LoadingDeliveryService {
|
||||
* corrections are handled by the offline/manual process defined for phase three. */
|
||||
private Snapshot requireMutableLoadingStage(long tenantId, long inboundId) {
|
||||
Snapshot value = requireInbound(tenantId, inboundId);
|
||||
CompletionTarget target = repository.completionTarget(tenantId, inboundId);
|
||||
if (target != null) {
|
||||
if (!"LOADING".equals(target.loadedChildStatus())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "装柜完成后不允许在线修改证据");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (!"LOADING".equals(value.processStatus())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "装柜完成后不允许在线修改证据");
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ public interface InboundSplitSettlementMapper {
|
||||
actual_net_weight_kg,measure_completed_at,inbounded_at,express_company_code,express_company_name,
|
||||
express_tracking_no,public_remark,created_by,created_by_name,created_at,updated_by,updated_at,deleted,version,
|
||||
inbound_role,parent_inbound_id,root_inbound_id,split_sequence,split_status,split_purpose)
|
||||
SELECT #{childId},tenant_id,task_id,order_id,order_no,#{childInboundCode},'INBOUNDED',order_status_snapshot,
|
||||
SELECT #{childId},tenant_id,task_id,order_id,order_no,#{childInboundCode},
|
||||
CASE WHEN #{splitPurpose}='LOADED' THEN 'LOADING' ELSE 'INBOUNDED' END,order_status_snapshot,
|
||||
'APPROVED',fee_status,fee_review_status,notification_status,expected_arrival_at,customer_id,customer_name,
|
||||
company_id,company_name,warehouse_id,warehouse_name,delivery_warehouse_id,delivery_warehouse_name,business_type,
|
||||
channel_code,channel_name,carrier_id,carrier_name,tax_mode,pricing_tax_mode,container_mode,customs_inspection,
|
||||
|
||||
@@ -153,7 +153,7 @@ public class UnifiedInboundQueryService {
|
||||
: "CONFIRMED".equals(preloadStatus) ? null
|
||||
: preloadStatus == null ? "SMART_SPLIT" : "CONFIRM_PRELOAD";
|
||||
case "LOADING" -> "COMPLETE_LOADING";
|
||||
case "LOADED" -> "COMPLETE_DELIVERY";
|
||||
case "LOADED" -> null;
|
||||
case "DELIVERED" -> null;
|
||||
default -> null;
|
||||
};
|
||||
|
||||
@@ -160,13 +160,13 @@ CREATE TABLE IF NOT EXISTS fl_inbound_split_item (
|
||||
child_inbound_id BIGINT UNSIGNED NOT NULL COMMENT '子入仓单ID',
|
||||
line_no INT UNSIGNED NOT NULL COMMENT '同一拆分批次内的行号',
|
||||
source_inbound_detail_id BIGINT UNSIGNED NULL COMMENT '订单货物明细逻辑ID',
|
||||
source_measurement_id BIGINT UNSIGNED NULL COMMENT '来源测量批次ID',
|
||||
source_measurement_item_id BIGINT UNSIGNED NULL COMMENT '来源测量箱规明细ID',
|
||||
source_measurement_id BIGINT UNSIGNED NOT NULL COMMENT '来源测量批次ID',
|
||||
source_measurement_item_id BIGINT UNSIGNED NOT NULL COMMENT '来源测量箱规明细ID',
|
||||
package_count INT UNSIGNED NOT NULL COMMENT '分配给子单的箱数',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_inbound_split_batch_line (tenant_id, split_batch_id, line_no),
|
||||
UNIQUE KEY uk_inbound_split_batch_source_item (tenant_id, split_batch_id, source_measurement_item_id),
|
||||
UNIQUE KEY uk_inbound_split_batch_source_child (tenant_id, split_batch_id, source_measurement_item_id, child_inbound_id),
|
||||
KEY idx_inbound_split_detail (tenant_id, source_inbound_detail_id, created_at),
|
||||
CONSTRAINT chk_inbound_split_item_package CHECK (package_count > 0),
|
||||
CONSTRAINT fk_inbound_split_item_batch FOREIGN KEY (split_batch_id) REFERENCES fl_inbound_split_batch (id),
|
||||
@@ -232,6 +232,9 @@ CALL phase3_inbound_add_column(
|
||||
CALL phase3_inbound_add_column(
|
||||
'fl_inbound_split_item', 'line_no',
|
||||
"INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '同一拆分批次内的行号' AFTER child_inbound_id");
|
||||
ALTER TABLE fl_inbound_split_item
|
||||
MODIFY source_measurement_id BIGINT UNSIGNED NOT NULL COMMENT '来源测量批次ID',
|
||||
MODIFY source_measurement_item_id BIGINT UNSIGNED NOT NULL COMMENT '来源测量箱规明细ID';
|
||||
CALL phase3_inbound_add_column(
|
||||
'fl_inbound_split_batch', 'loaded_child_inbound_id',
|
||||
"BIGINT UNSIGNED NULL COMMENT '本批次实装子单ID' AFTER package_count");
|
||||
@@ -339,6 +342,9 @@ CALL phase3_inbound_add_index(
|
||||
CALL phase3_inbound_add_index(
|
||||
'fl_inbound_split_batch', 'idx_inbound_split_loading_plan',
|
||||
'KEY `idx_inbound_split_loading_plan` (`tenant_id`, `loading_plan_id`, `container_booking_id`, `status`, `id`)');
|
||||
CALL phase3_inbound_add_index(
|
||||
'fl_inbound_split_batch', 'uk_inbound_split_source_once',
|
||||
'UNIQUE KEY `uk_inbound_split_source_once` (`tenant_id`, `source_inbound_id`)');
|
||||
|
||||
DROP PROCEDURE IF EXISTS phase3_inbound_drop_split_legacy_index;
|
||||
DELIMITER $$
|
||||
@@ -395,6 +401,9 @@ BEGIN
|
||||
IF NEW.inbound_role = 'MASTER' AND NEW.parent_inbound_id IS NOT NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '主入仓单不能绑定父单';
|
||||
END IF;
|
||||
IF NEW.inbound_role = 'MASTER' AND NEW.split_purpose <> 'MASTER' THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '主入仓单用途必须为MASTER';
|
||||
END IF;
|
||||
IF NEW.inbound_role = 'CHILD' THEN
|
||||
IF NEW.parent_inbound_id IS NULL OR NEW.root_inbound_id IS NULL
|
||||
OR NEW.split_sequence IS NULL OR NEW.package_count IS NULL THEN
|
||||
@@ -419,7 +428,8 @@ CREATE TRIGGER trg_inbound_order_parent_before_update
|
||||
BEFORE UPDATE ON fl_inbound_order
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NOT (OLD.inbound_role <=> NEW.inbound_role)
|
||||
IF NOT (OLD.tenant_id <=> NEW.tenant_id)
|
||||
OR NOT (OLD.inbound_role <=> NEW.inbound_role)
|
||||
OR NOT (OLD.parent_inbound_id <=> NEW.parent_inbound_id)
|
||||
OR NOT (OLD.root_inbound_id <=> NEW.root_inbound_id)
|
||||
OR NOT (OLD.split_sequence <=> NEW.split_sequence)
|
||||
@@ -436,8 +446,9 @@ BEGIN
|
||||
IF NEW.split_status NOT IN ('NOT_SPLIT', 'PARTIALLY_SPLIT', 'FULLY_SPLIT') THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '入仓单拆分状态非法';
|
||||
END IF;
|
||||
IF NEW.inbound_role = 'CHILD' AND NEW.split_purpose = 'MASTER' THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '子入仓单用途非法';
|
||||
IF (NEW.inbound_role = 'CHILD' AND NEW.split_purpose = 'MASTER')
|
||||
OR (NEW.inbound_role = 'MASTER' AND NEW.split_purpose <> 'MASTER') THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '入仓单层级与用途不一致';
|
||||
END IF;
|
||||
IF NEW.inbound_role = 'MASTER'
|
||||
AND ((NEW.package_count = 0 AND NEW.split_status <> 'FULLY_SPLIT')
|
||||
@@ -450,6 +461,9 @@ CREATE TRIGGER trg_inbound_split_item_before_insert
|
||||
BEFORE INSERT ON fl_inbound_split_item
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.source_measurement_id IS NULL OR NEW.source_measurement_item_id IS NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '拆分明细必须绑定真实测量来源';
|
||||
END IF;
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM fl_inbound_split_batch batch
|
||||
@@ -467,7 +481,7 @@ BEGIN
|
||||
AND child_order.parent_inbound_id = NEW.parent_inbound_id
|
||||
AND child_order.package_count >= NEW.package_count
|
||||
AND child_order.deleted = 0
|
||||
AND (NEW.source_measurement_item_id IS NULL OR EXISTS (
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM fl_inbound_measurement_item source_item
|
||||
JOIN fl_inbound_measurement source_batch ON source_batch.id = source_item.measurement_id
|
||||
@@ -475,7 +489,7 @@ BEGIN
|
||||
AND source_item.tenant_id = NEW.tenant_id
|
||||
AND source_item.measurement_id = NEW.source_measurement_id
|
||||
AND source_batch.inbound_id = COALESCE(batch.source_inbound_id, batch.parent_inbound_id)
|
||||
))
|
||||
)
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '拆分明细与批次、主单或子单不一致';
|
||||
END IF;
|
||||
@@ -497,23 +511,32 @@ BEGIN
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '拆分批次主单不存在或客户归属不一致';
|
||||
END IF;
|
||||
IF NEW.source_inbound_id IS NOT NULL AND NOT EXISTS (
|
||||
IF NEW.source_inbound_id IS NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM fl_inbound_order source_order
|
||||
WHERE source_order.id = NEW.source_inbound_id
|
||||
AND source_order.tenant_id = NEW.tenant_id
|
||||
AND source_order.deleted = 0
|
||||
AND (source_order.id = NEW.parent_inbound_id OR
|
||||
AND source_order.package_count = NEW.package_count
|
||||
AND ((source_order.id = NEW.parent_inbound_id
|
||||
AND source_order.inbound_role = 'MASTER'
|
||||
AND source_order.split_status = 'NOT_SPLIT') OR
|
||||
(source_order.inbound_role = 'CHILD'
|
||||
AND source_order.parent_inbound_id = NEW.parent_inbound_id
|
||||
AND source_order.split_purpose = 'REMAINDER'))
|
||||
AND source_order.split_purpose = 'REMAINDER'
|
||||
AND source_order.split_status = 'NOT_SPLIT'))
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '拆分批次来源必须是根主单或其余量子单';
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '拆分批次来源必须是箱数匹配且未消费的根主单或余量子单';
|
||||
END IF;
|
||||
IF NEW.loaded_package_count > 0 AND (
|
||||
NEW.loading_plan_id IS NULL OR NEW.container_booking_id IS NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM fl_loading_plan plan
|
||||
WHERE plan.id = NEW.loading_plan_id
|
||||
AND plan.container_booking_id = NEW.container_booking_id
|
||||
AND EXISTS (SELECT 1 FROM fl_loading_plan_item plan_item
|
||||
WHERE plan_item.loading_plan_id = plan.id
|
||||
AND plan_item.account_id = NEW.tenant_id
|
||||
AND plan_item.inbound_id = NEW.source_inbound_id
|
||||
AND plan_item.deleted = 0)
|
||||
)
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '实装拆分批次必须绑定匹配的装柜计划和柜次';
|
||||
@@ -544,13 +567,23 @@ BEGIN
|
||||
NEW.loading_plan_id IS NULL OR NEW.container_booking_id IS NULL OR NOT EXISTS (
|
||||
SELECT 1 FROM fl_loading_plan plan
|
||||
WHERE plan.id = NEW.loading_plan_id
|
||||
AND plan.container_booking_id = NEW.container_booking_id)))
|
||||
AND plan.container_booking_id = NEW.container_booking_id
|
||||
AND EXISTS (SELECT 1 FROM fl_loading_plan_item plan_item
|
||||
WHERE plan_item.loading_plan_id = plan.id
|
||||
AND plan_item.account_id = NEW.tenant_id
|
||||
AND plan_item.inbound_id = NEW.source_inbound_id
|
||||
AND plan_item.deleted = 0)))
|
||||
OR NOT EXISTS (
|
||||
SELECT 1 FROM fl_inbound_order parent_order
|
||||
WHERE parent_order.id = NEW.parent_inbound_id
|
||||
AND parent_order.tenant_id = NEW.tenant_id
|
||||
AND parent_order.inbound_role = 'MASTER'
|
||||
AND parent_order.version > NEW.expected_parent_version
|
||||
) OR NOT EXISTS (
|
||||
SELECT 1 FROM fl_inbound_order source_order
|
||||
WHERE source_order.id = NEW.source_inbound_id
|
||||
AND source_order.tenant_id = NEW.tenant_id
|
||||
AND source_order.split_status = 'FULLY_SPLIT'
|
||||
) OR
|
||||
(SELECT COALESCE(SUM(item.package_count), 0)
|
||||
FROM fl_inbound_split_item item
|
||||
|
||||
@@ -126,7 +126,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_split_detail (
|
||||
source_package_count > 1 AND locked_package_count > 0
|
||||
AND locked_package_count < source_package_count
|
||||
),
|
||||
CONSTRAINT chk_inbound_split_status CHECK (status IN ('LOCKED', 'COMPLETED')),
|
||||
CONSTRAINT chk_legacy_inbound_split_status CHECK (status IN ('LOCKED', 'COMPLETED')),
|
||||
CONSTRAINT chk_inbound_split_completion CHECK (
|
||||
(status = 'LOCKED' AND child_inbound_id IS NULL AND completed_at IS NULL)
|
||||
OR (status = 'COMPLETED' AND child_inbound_id IS NOT NULL AND completed_at IS NOT NULL)
|
||||
@@ -143,39 +143,14 @@ CREATE TRIGGER trg_inbound_split_detail_before_insert
|
||||
BEFORE INSERT ON fl_inbound_split_detail
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE v_parent_tenant BIGINT UNSIGNED;
|
||||
DECLARE v_parent_parent BIGINT UNSIGNED;
|
||||
SELECT tenant_id, parent_inbound_id INTO v_parent_tenant, v_parent_parent
|
||||
FROM fl_inbound_order WHERE id = NEW.parent_inbound_id AND deleted = 0;
|
||||
IF v_parent_tenant <> NEW.tenant_id OR v_parent_parent IS NOT NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '部分锁定只能发生在客户所属主入库单';
|
||||
END IF;
|
||||
IF NEW.status <> 'LOCKED' OR NEW.child_inbound_id IS NOT NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '部分锁定创建时不能提前绑定二级子入库单';
|
||||
END IF;
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '旧部分锁定台账已退役,请使用主子分片批次';
|
||||
END$$
|
||||
|
||||
CREATE TRIGGER trg_inbound_split_detail_before_update
|
||||
BEFORE UPDATE ON fl_inbound_split_detail
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE v_child_tenant BIGINT UNSIGNED;
|
||||
DECLARE v_child_parent BIGINT UNSIGNED;
|
||||
IF NEW.tenant_id <> OLD.tenant_id OR NEW.parent_inbound_id <> OLD.parent_inbound_id
|
||||
OR NEW.inbound_detail_id <> OLD.inbound_detail_id
|
||||
OR NEW.source_package_count <> OLD.source_package_count
|
||||
OR NEW.locked_package_count <> OLD.locked_package_count
|
||||
OR NEW.operation_id <> OLD.operation_id THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '部分锁定的归属和箱数创建后不可修改';
|
||||
END IF;
|
||||
IF OLD.status <> 'LOCKED' OR NEW.status <> 'COMPLETED' OR NEW.child_inbound_id IS NULL THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '部分锁定只允许完成并绑定二级子入库单';
|
||||
END IF;
|
||||
SELECT tenant_id, parent_inbound_id INTO v_child_tenant, v_child_parent
|
||||
FROM fl_inbound_order WHERE id = NEW.child_inbound_id AND deleted = 0;
|
||||
IF v_child_tenant <> NEW.tenant_id OR v_child_parent <> NEW.parent_inbound_id THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '剩余箱数必须绑定主单唯一二级子入库单';
|
||||
END IF;
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '旧部分锁定台账只读,不允许更新';
|
||||
END$$
|
||||
|
||||
CREATE TRIGGER trg_inbound_split_detail_before_delete
|
||||
|
||||
+1
-2
@@ -52,8 +52,7 @@ class UnifiedInboundQueryServiceTest {
|
||||
assertThat(UnifiedInboundQueryService.nextAction("INBOUNDED", "INBOUNDED", "CONFIRMED")).isNull();
|
||||
assertThat(UnifiedInboundQueryService.nextAction("INBOUNDED", "WAIT_SPLIT", null))
|
||||
.isEqualTo("SMART_SPLIT");
|
||||
assertThat(UnifiedInboundQueryService.nextAction("LOADED", "LOADED", null))
|
||||
.isEqualTo("COMPLETE_DELIVERY");
|
||||
assertThat(UnifiedInboundQueryService.nextAction("LOADED", "LOADED", null)).isNull();
|
||||
assertThat(UnifiedInboundQueryService.nextAction("DELIVERED", "DELIVERED", null)).isNull();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user