优化
This commit is contained in:
@@ -223,10 +223,6 @@ CREATE TABLE IF NOT EXISTS fl_loading_plan (
|
||||
plan_no VARCHAR(40) NOT NULL COMMENT '平台唯一装柜计划号',
|
||||
container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '货柜预订ID',
|
||||
plan_status VARCHAR(24) NOT NULL DEFAULT 'EDITING' COMMENT '装柜计划状态:EDITING编辑中、LOADING装柜中、COMPLETED装柜完成;建议须经人工确认',
|
||||
push_idempotency_key VARCHAR(128) NULL COMMENT '推送预装幂等键',
|
||||
preload_pushed_by BIGINT UNSIGNED NULL COMMENT '推送预装操作人ID',
|
||||
preload_pushed_by_name VARCHAR(64) NULL COMMENT '推送预装操作人名称快照',
|
||||
preload_pushed_at DATETIME(3) NULL COMMENT '开始装柜并进入LOADING的时间',
|
||||
preload_completed_by BIGINT UNSIGNED NULL COMMENT '预装完成操作人ID',
|
||||
preload_completed_by_name VARCHAR(64) NULL COMMENT '预装完成操作人名称快照',
|
||||
preload_completed_at DATETIME(3) NULL COMMENT '预装完成时间',
|
||||
@@ -244,7 +240,6 @@ CREATE TABLE IF NOT EXISTS fl_loading_plan (
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_loading_plan_no (plan_no),
|
||||
UNIQUE KEY uk_loading_plan_booking (container_booking_id),
|
||||
UNIQUE KEY uk_loading_plan_push_key (push_idempotency_key),
|
||||
KEY idx_loading_plan_status (plan_status, updated_at, id),
|
||||
CONSTRAINT fk_loading_plan_booking FOREIGN KEY (container_booking_id)
|
||||
REFERENCES fl_container_booking (id),
|
||||
@@ -833,10 +828,6 @@ BEGIN
|
||||
IF OLD.plan_status = 'LOADING' AND (
|
||||
NOT (OLD.id <=> NEW.id) OR NOT (OLD.plan_no <=> NEW.plan_no)
|
||||
OR NOT (OLD.container_booking_id <=> NEW.container_booking_id)
|
||||
OR NOT (OLD.push_idempotency_key <=> NEW.push_idempotency_key)
|
||||
OR NOT (OLD.preload_pushed_by <=> NEW.preload_pushed_by)
|
||||
OR NOT (OLD.preload_pushed_by_name <=> NEW.preload_pushed_by_name)
|
||||
OR NOT (OLD.preload_pushed_at <=> NEW.preload_pushed_at)
|
||||
OR NOT (OLD.remark <=> NEW.remark)
|
||||
OR NOT (OLD.created_by <=> NEW.created_by)
|
||||
OR NOT (OLD.created_by_name <=> NEW.created_by_name)
|
||||
@@ -856,12 +847,7 @@ BEGIN
|
||||
) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '同状态乐观锁触碰不得修改阶段审计字段';
|
||||
END IF;
|
||||
IF OLD.plan_status = 'EDITING' AND NEW.plan_status = 'LOADING' THEN
|
||||
IF NEW.push_idempotency_key IS NULL OR CHAR_LENGTH(TRIM(NEW.push_idempotency_key)) = 0 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '开始装柜必须提供幂等键';
|
||||
END IF;
|
||||
SET NEW.preload_pushed_at = COALESCE(NEW.preload_pushed_at, CURRENT_TIMESTAMP(3));
|
||||
ELSEIF OLD.plan_status = 'LOADING' AND NEW.plan_status = 'COMPLETED' THEN
|
||||
IF OLD.plan_status = 'LOADING' AND NEW.plan_status = 'COMPLETED' THEN
|
||||
IF EXISTS (SELECT 1 FROM fl_loading_plan_item item
|
||||
WHERE item.loading_plan_id = OLD.id AND item.deleted = 0
|
||||
AND NOT EXISTS (
|
||||
@@ -1324,6 +1310,13 @@ DELIMITER ;
|
||||
CALL relocate_legacy_inbound_loading_permissions();
|
||||
DROP PROCEDURE relocate_legacy_inbound_loading_permissions;
|
||||
|
||||
DELETE role_permission FROM iam_role_permission role_permission
|
||||
JOIN iam_permission permission ON permission.id = role_permission.permission_id
|
||||
WHERE permission.tenant_id = 0 AND permission.permission_code IN (
|
||||
'platform:firstleg:smart-loading:create', 'platform:firstleg:smart-loading:push');
|
||||
DELETE FROM iam_permission WHERE tenant_id = 0 AND permission_code IN (
|
||||
'platform:firstleg:smart-loading:create', 'platform:firstleg:smart-loading:push');
|
||||
|
||||
INSERT INTO iam_permission
|
||||
(id, tenant_id, app_code, permission_type, parent_id, permission_code,
|
||||
permission_name, route_path, http_method, sort_no, status, built_in, deleted)
|
||||
@@ -1338,14 +1331,10 @@ VALUES
|
||||
'编辑货柜', NULL, 'PUT', 30, 'ACTIVE', 1, 0),
|
||||
(5102094, 0, 'PLATFORM', 'MENU', 5102000, 'platform:firstleg:smart-loading:list',
|
||||
'智能装柜', '/first-leg/smart-loading', 'GET', 50, 'ACTIVE', 1, 0),
|
||||
(5102096, 0, 'PLATFORM', 'BUTTON', 5102094, 'platform:firstleg:smart-loading:create',
|
||||
'创建智能装柜计划', NULL, 'POST', 20, 'ACTIVE', 1, 0),
|
||||
(5102097, 0, 'PLATFORM', 'BUTTON', 5102094, 'platform:firstleg:smart-loading:assign',
|
||||
'分配装柜明细', NULL, 'POST', 30, 'ACTIVE', 1, 0),
|
||||
(5102098, 0, 'PLATFORM', 'BUTTON', 5102094, 'platform:firstleg:smart-loading:delete',
|
||||
'删除装柜明细', NULL, 'DELETE', 40, 'ACTIVE', 1, 0),
|
||||
(5102099, 0, 'PLATFORM', 'BUTTON', 5102094, 'platform:firstleg:smart-loading:push',
|
||||
'推送预装', NULL, 'POST', 50, 'ACTIVE', 1, 0),
|
||||
(5102100, 0, 'PLATFORM', 'MENU', 5102000, 'platform:firstleg:preload:list',
|
||||
'预装清单', '/first-leg/preload-list', 'GET', 60, 'ACTIVE', 1, 0),
|
||||
(5102102, 0, 'PLATFORM', 'BUTTON', 5102100, 'platform:firstleg:preload:view',
|
||||
@@ -1375,8 +1364,7 @@ FROM iam_role role
|
||||
'platform:firstleg:container:list', 'platform:firstleg:container:view',
|
||||
'platform:firstleg:container:create',
|
||||
'platform:firstleg:container:edit', 'platform:firstleg:smart-loading:list',
|
||||
'platform:firstleg:smart-loading:create', 'platform:firstleg:smart-loading:assign',
|
||||
'platform:firstleg:smart-loading:delete', 'platform:firstleg:smart-loading:push',
|
||||
'platform:firstleg:smart-loading:assign', 'platform:firstleg:smart-loading:delete',
|
||||
'platform:firstleg:preload:list', 'platform:firstleg:preload:view',
|
||||
'platform:firstleg:preload:edit', 'platform:firstleg:preload:complete',
|
||||
'platform:firstleg:preload:confirm', 'platform:firstleg:loading-list:list',
|
||||
@@ -1506,12 +1494,11 @@ BEGIN
|
||||
AND permission_code IN (
|
||||
'platform:firstleg:container:list', 'platform:firstleg:container:view',
|
||||
'platform:firstleg:container:create', 'platform:firstleg:container:edit',
|
||||
'platform:firstleg:smart-loading:list', 'platform:firstleg:smart-loading:create',
|
||||
'platform:firstleg:smart-loading:assign', 'platform:firstleg:smart-loading:delete',
|
||||
'platform:firstleg:smart-loading:push', 'platform:firstleg:preload:list',
|
||||
'platform:firstleg:smart-loading:list', 'platform:firstleg:smart-loading:assign',
|
||||
'platform:firstleg:smart-loading:delete', 'platform:firstleg:preload:list',
|
||||
'platform:firstleg:preload:view', 'platform:firstleg:preload:edit',
|
||||
'platform:firstleg:preload:complete', 'platform:firstleg:preload:confirm',
|
||||
'platform:firstleg:loading-list:list', 'platform:firstleg:loading-list:view')) <> 16 THEN
|
||||
'platform:firstleg:loading-list:list', 'platform:firstleg:loading-list:view')) <> 14 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '智能装柜迁移失败:平台权限资源未完整创建';
|
||||
END IF;
|
||||
IF (SELECT COUNT(DISTINCT CONCAT(role.role_code, ':', permission.permission_code))
|
||||
@@ -1524,12 +1511,11 @@ BEGIN
|
||||
'platform:firstleg:container:list', 'platform:firstleg:container:view',
|
||||
'platform:firstleg:container:create',
|
||||
'platform:firstleg:container:edit', 'platform:firstleg:smart-loading:list',
|
||||
'platform:firstleg:smart-loading:create', 'platform:firstleg:smart-loading:assign',
|
||||
'platform:firstleg:smart-loading:delete', 'platform:firstleg:smart-loading:push',
|
||||
'platform:firstleg:smart-loading:assign', 'platform:firstleg:smart-loading:delete',
|
||||
'platform:firstleg:preload:list', 'platform:firstleg:preload:view',
|
||||
'platform:firstleg:preload:edit', 'platform:firstleg:preload:complete',
|
||||
'platform:firstleg:preload:confirm', 'platform:firstleg:loading-list:list',
|
||||
'platform:firstleg:loading-list:view')) <> 32 THEN
|
||||
'platform:firstleg:loading-list:view')) <> 28 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '智能装柜迁移失败:平台角色授权未完整写入';
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
@@ -523,26 +523,6 @@ paths:
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingWarehouseRemarkRequest'}}}
|
||||
responses:
|
||||
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
|
||||
/api/platform/v1/first-leg/smart-loading/plans/{planId}/push-preload:
|
||||
post:
|
||||
summary: 推送智能装柜计划到预装清单
|
||||
description: >-
|
||||
需要 platform:firstleg:smart-loading:push 权限。push-preload 不要求真实柜号,
|
||||
只冻结 EDITING 柜次计划的明细并建立稳定预装关联,不创建 PDA 作业任务;计划必须处于 EDITING 且版本匹配。
|
||||
预装页面随后补录真实柜号;只有预装 CONFIRMED、真实柜号存在、已关联 RELEASED 订舱时才创建待领取 PDA 任务,领取后才进入 LOADING。
|
||||
智能装柜首次分配会创建入库单级 PENDING 预装聚合;push 会在同一事务内对全部实际分配再次确保该聚合存在且仍为 PENDING,
|
||||
但不会覆盖 CONFIRMING/CONFIRMED 记录,也不会在 LOADING 后补建。
|
||||
推送事务会先为所有已分配入库单建立 PENDING 预装计划与 EDITING 柜次计划的正式关联,
|
||||
任一关联缺失、版本冲突或分配数量为零都会整体失败并禁止 PDA/LOADING;不得在 LOADING 后补关联。
|
||||
parameters:
|
||||
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
- {$ref: '#/components/parameters/IdempotencyKey'}
|
||||
requestBody:
|
||||
required: true
|
||||
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingPushRequest'}}}
|
||||
responses:
|
||||
'200': {description: 推送成功或业务失败,按响应体 code 判断}
|
||||
'403': {description: 无智能装柜推送权限}
|
||||
/openapi/v1/inbound-measurements:
|
||||
post:
|
||||
summary: 提交一条第三方箱规测量结果和一张图片
|
||||
@@ -1651,11 +1631,6 @@ components:
|
||||
properties:
|
||||
version: {type: integer, minimum: 0}
|
||||
data: {$ref: '#/components/schemas/ContainerSaveRequest'}
|
||||
SmartLoadingPushRequest:
|
||||
type: object
|
||||
required: [expectedVersion]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
SmartLoadingAssignRequest:
|
||||
type: object
|
||||
required: [inboundId, inboundDetailId, packageCount, expectedVersion, operationId]
|
||||
|
||||
@@ -49,7 +49,7 @@ paths:
|
||||
patch:
|
||||
summary: 修改预装运输信息
|
||||
description: >-
|
||||
已推送后可在 EDITING 或 LOADING 阶段首次补录真实集装箱号;已有柜号的纠正仅限仍为 EDITING、PDA任务尚未领取且无任何物理作业事实时,并必须提供原因和当前版本;
|
||||
可在 EDITING 或 LOADING 阶段首次补录真实集装箱号;已有柜号的纠正仅限仍为 EDITING、PDA任务尚未领取且无任何物理作业事实时,并必须提供原因和当前版本;
|
||||
containerNo 为 null 表示保持当前值,非空时服务端移除格式空白、转大写并校验ISO 6346结构、设备类别和校验位,空白字符串非法且禁止清空。
|
||||
x-permission: platform:firstleg:preload:edit
|
||||
parameters:
|
||||
@@ -301,9 +301,8 @@ components:
|
||||
readiness: {$ref: '#/components/schemas/PreloadReadiness'}
|
||||
PreloadReadiness:
|
||||
type: object
|
||||
required: [preloadPushed, containerNoReady, preloadLinkCount, confirmedPreloadCount, confirmationStatus, canConfirm, readyForPda, blockingReasons]
|
||||
required: [containerNoReady, preloadLinkCount, confirmedPreloadCount, confirmationStatus, canConfirm, readyForPda, blockingReasons]
|
||||
properties:
|
||||
preloadPushed: {type: boolean, description: 是否已完成 push-preload}
|
||||
containerNoReady: {type: boolean, description: 是否已录入真实集装箱号 containerNo}
|
||||
preloadLinkCount: {type: integer, format: int32, minimum: 0, description: 计划关联的入库预装票据数}
|
||||
confirmedPreloadCount: {type: integer, format: int32, minimum: 0, description: 已确认预装票据数}
|
||||
@@ -317,7 +316,7 @@ components:
|
||||
blockingReasons:
|
||||
type: array
|
||||
description: 阻止计划确认的稳定原因码
|
||||
items: {type: string, enum: [PRELOAD_NOT_PUSHED, LOADING_PLAN_NOT_EDITING, PRELOAD_LINK_MISSING, OCEAN_BOOKING_NOT_LINKED, OCEAN_BOOKING_NOT_RELEASED, PDA_TASK_ALREADY_CREATED, PRELOAD_ALREADY_CONFIRMED]}
|
||||
items: {type: string, enum: [LOADING_PLAN_NOT_EDITING, PRELOAD_LINK_MISSING, OCEAN_BOOKING_NOT_LINKED, OCEAN_BOOKING_NOT_RELEASED, PDA_TASK_ALREADY_CREATED, PRELOAD_ALREADY_CONFIRMED]}
|
||||
ConfirmPreloadRequest:
|
||||
type: object
|
||||
required: [expectedVersion, operationReason]
|
||||
|
||||
@@ -2,7 +2,7 @@ openapi: 3.0.3
|
||||
info:
|
||||
title: Phase 3 Preload and Container Loading Bridge API
|
||||
version: 1.0.0
|
||||
description: Links must be created while preload=PENDING and loadingPlan=EDITING. Smart-loading push creates all allocated links atomically before any PDA task creation; push-preload never requires containerNo and never advances LOADING. LOADING plans cannot be repaired through post-hoc binding.
|
||||
description: The container loading plan is created atomically with the container. Adding an inbound allocation creates its preload aggregate and link in the same transaction while loadingPlan=EDITING or LOADING; plan confirmation remains the gate before PDA task creation.
|
||||
paths:
|
||||
/api/platform/v1/inbounds/{inboundId}/preload/loading-plans:
|
||||
get:
|
||||
|
||||
Reference in New Issue
Block a user