This commit is contained in:
2026-08-20 18:02:38 +08:00
parent b55b049e77
commit 1cd8b6a473
210 changed files with 6974 additions and 825 deletions
@@ -13,10 +13,18 @@ CREATE TABLE IF NOT EXISTS fl_carrier_schedule_query (
tracking_no VARCHAR(128) NOT NULL COMMENT '提交至船公司官网的跟踪号码',
official_url VARCHAR(500) NOT NULL COMMENT '船公司官网查询入口地址快照',
access_mode VARCHAR(32) NOT NULL COMMENT '官网访问方式:PUBLIC_FORM公开表单、HCAPTCHA人机校验、DYNAMIC_IFRAME动态页面',
status VARCHAR(24) NOT NULL COMMENT '任务状态:READY可查询、MANUAL_REQUIRED需人工处理、SUCCESS已取得有效结果',
status VARCHAR(24) NOT NULL COMMENT '任务状态:READY、MANUAL_REQUIRED、ARRIVED、PICKUP_READY、STOPPED',
trigger_source VARCHAR(32) NOT NULL DEFAULT 'MANUAL' COMMENT '任务触发来源:OUTBOUND_CONFIRM或MANUAL',
latest_standard_node VARCHAR(32) NULL COMMENT '最近标准船节点',
latest_node_observed_at DATETIME(3) NULL COMMENT '最近标准节点观测时间',
stopped_at DATETIME(3) NULL COMMENT '任务停止时间',
stop_reason VARCHAR(500) NULL COMMENT '任务停止原因',
lease_owner VARCHAR(64) NULL COMMENT '当前调度租约持有者',
lease_until DATETIME(3) NULL COMMENT '当前调度租约过期时间',
consecutive_failures INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '连续失败次数,用于指数退避',
window_started_at DATETIME(3) NOT NULL COMMENT '当前三天查询窗口起始时间',
attempt_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '当前查询窗口已执行次数;最多3次',
next_allowed_at DATETIME(3) NOT NULL COMMENT '频控规则允许的下次查询时间',
next_allowed_at DATETIME(3) NULL COMMENT '频控规则允许的下次查询时间;停止后为空',
last_attempt_at DATETIME(3) NULL COMMENT '最近一次查询尝试时间',
last_success_at DATETIME(3) NULL COMMENT '最近一次取得有效结果时间',
source_updated_at DATETIME(3) NULL COMMENT '船公司官网展示的结果更新时间',
@@ -37,7 +45,7 @@ CREATE TABLE IF NOT EXISTS fl_carrier_schedule_query (
PRIMARY KEY (id),
UNIQUE KEY uk_carrier_schedule_query_no (query_no),
UNIQUE KEY uk_carrier_schedule_query_scope
(customer_id,ocean_booking_id,container_scope_id,carrier_code,tracking_type,tracking_no),
(customer_id,ocean_booking_id,container_scope_id),
KEY idx_carrier_schedule_query_due (status,next_allowed_at,id),
KEY idx_carrier_schedule_query_customer (customer_id,updated_at,id),
KEY idx_carrier_schedule_query_expiry (expires_at,id),
@@ -52,7 +60,10 @@ CREATE TABLE IF NOT EXISTS fl_carrier_schedule_query (
CONSTRAINT chk_carrier_schedule_query_access CHECK
(access_mode IN ('PUBLIC_FORM','HCAPTCHA','DYNAMIC_IFRAME')),
CONSTRAINT chk_carrier_schedule_query_status CHECK
(status IN ('READY','MANUAL_REQUIRED','SUCCESS')),
(status IN ('READY','MANUAL_REQUIRED','ARRIVED','PICKUP_READY','STOPPED')),
CONSTRAINT chk_carrier_schedule_query_node CHECK
(latest_standard_node IS NULL OR latest_standard_node IN
('DEPARTED_WAREHOUSE','AT_ORIGIN_PORT','DEPARTED_ORIGIN_PORT','IN_TRANSIT','ARRIVED','PICKUP_READY')),
CONSTRAINT chk_carrier_schedule_query_attempt CHECK (attempt_count BETWEEN 0 AND 3)
) ENGINE=InnoDB COMMENT='六家船公司官网查询任务与三天窗口频控';
@@ -95,9 +106,35 @@ CREATE TABLE IF NOT EXISTS fl_carrier_schedule_query_history (
PRIMARY KEY (id),
KEY idx_carrier_schedule_history_query (query_id,created_at,id),
CONSTRAINT fk_carrier_schedule_history_query FOREIGN KEY (query_id) REFERENCES fl_carrier_schedule_query(id),
CONSTRAINT chk_carrier_schedule_history_action CHECK (action IN ('CREATE','ATTEMPT','MANUAL_RESULT'))
CONSTRAINT chk_carrier_schedule_history_action CHECK
(action IN ('CREATE','AUTO_CREATE','MANUAL_RESULT','NODE_OBSERVED','PROVIDER_QUERY','STOP'))
) ENGINE=InnoDB COMMENT='船司查询任务不可变历史';
CREATE TABLE IF NOT EXISTS fl_carrier_schedule_node_fact (
id BIGINT UNSIGNED NOT NULL COMMENT '标准船节点事实ID',
query_id BIGINT UNSIGNED NOT NULL COMMENT '所属查询任务ID',
event_key VARCHAR(192) NOT NULL COMMENT '供应商编码与供应商事件ID组成的幂等键',
provider_code VARCHAR(32) NOT NULL COMMENT '轨迹供应商编码',
provider_node_code VARCHAR(64) NOT NULL COMMENT '供应商原始节点编码',
standard_node VARCHAR(32) NOT NULL COMMENT '标准船节点',
node_sequence INT UNSIGNED NOT NULL COMMENT '标准节点单调序号',
observed_at DATETIME(3) NOT NULL COMMENT '供应商观测时间',
estimated_at DATETIME(3) NULL COMMENT '供应商预计发生时间',
actual_at DATETIME(3) NULL COMMENT '供应商确认实际发生时间',
location_code VARCHAR(32) NULL COMMENT '节点地点编码',
location_name VARCHAR(128) NULL COMMENT '节点地点名称',
source_reference VARCHAR(500) NULL COMMENT '可审计来源引用',
raw_payload_hash CHAR(64) NOT NULL COMMENT '原始响应SHA-256;不保存敏感原文',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '事实入库时间',
PRIMARY KEY (id),
UNIQUE KEY uk_carrier_schedule_node_event (query_id,event_key),
KEY idx_carrier_schedule_node_timeline (query_id,node_sequence,observed_at,id),
CONSTRAINT fk_carrier_schedule_node_query FOREIGN KEY (query_id) REFERENCES fl_carrier_schedule_query(id),
CONSTRAINT chk_carrier_schedule_node_standard CHECK
(standard_node IN ('DEPARTED_WAREHOUSE','AT_ORIGIN_PORT','DEPARTED_ORIGIN_PORT','IN_TRANSIT','ARRIVED','PICKUP_READY')),
CONSTRAINT chk_carrier_schedule_node_sequence CHECK (node_sequence IN (10,20,30,40,50,60))
) ENGINE=InnoDB COMMENT='供应商标准船节点不可变事实';
CREATE TABLE IF NOT EXISTS fl_carrier_schedule_query_operation (
id BIGINT UNSIGNED NOT NULL COMMENT '船司查询写操作幂等记录ID',
query_id BIGINT UNSIGNED NULL COMMENT '关联查询任务ID;创建任务落库前允许为空',
@@ -138,6 +175,8 @@ DROP TRIGGER IF EXISTS trg_carrier_schedule_attempt_before_update;
DROP TRIGGER IF EXISTS trg_carrier_schedule_attempt_before_delete;
DROP TRIGGER IF EXISTS trg_carrier_schedule_history_before_update;
DROP TRIGGER IF EXISTS trg_carrier_schedule_history_before_delete;
DROP TRIGGER IF EXISTS trg_carrier_schedule_node_before_update;
DROP TRIGGER IF EXISTS trg_carrier_schedule_node_before_delete;
DELIMITER $$
CREATE TRIGGER trg_carrier_schedule_attempt_before_update BEFORE UPDATE ON fl_carrier_schedule_query_attempt
FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询尝试不可修改'; END$$
@@ -147,15 +186,21 @@ CREATE TRIGGER trg_carrier_schedule_history_before_update BEFORE UPDATE ON fl_ca
FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询历史不可修改'; END$$
CREATE TRIGGER trg_carrier_schedule_history_before_delete BEFORE DELETE ON fl_carrier_schedule_query_history
FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询历史不可删除'; END$$
CREATE TRIGGER trg_carrier_schedule_node_before_update BEFORE UPDATE ON fl_carrier_schedule_node_fact
FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='标准船节点事实不可修改'; END$$
CREATE TRIGGER trg_carrier_schedule_node_before_delete BEFORE DELETE ON fl_carrier_schedule_node_fact
FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='标准船节点事实不可删除'; END$$
DELIMITER ;
USE baiyue_iam;
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='platform:firstleg:port-schedule-query:view';
AND permission.permission_code IN ('platform:firstleg:port-schedule-query:view',
'platform:firstleg:port-schedule-query:attempt');
DELETE FROM iam_permission
WHERE tenant_id=0 AND permission_code='platform:firstleg:port-schedule-query:view';
WHERE tenant_id=0 AND permission_code IN ('platform:firstleg:port-schedule-query:view',
'platform:firstleg:port-schedule-query:attempt');
DROP PROCEDURE IF EXISTS assert_carrier_schedule_query_permission_ids;
DELIMITER $$
@@ -163,16 +208,15 @@ CREATE PROCEDURE assert_carrier_schedule_query_permission_ids()
BEGIN
IF EXISTS (
SELECT 1 FROM iam_permission
WHERE (id IN (5102184,5102186,5102187,5102188)
WHERE (id IN (5102184,5102186,5102188)
AND permission_code <> CASE id
WHEN 5102184 THEN 'platform:firstleg:port-schedule-query:list'
WHEN 5102186 THEN 'platform:firstleg:port-schedule-query:create'
WHEN 5102187 THEN 'platform:firstleg:port-schedule-query:attempt'
WHEN 5102188 THEN 'platform:firstleg:port-schedule-query:manual'
END)
OR id=5102185
OR id IN (5102185,5102187)
OR (permission_code LIKE 'platform:firstleg:port-schedule-query:%'
AND (tenant_id<>0 OR app_code<>'PLATFORM' OR id NOT IN (5102184,5102186,5102187,5102188)))
AND (tenant_id<>0 OR app_code<>'PLATFORM' OR id NOT IN (5102184,5102186,5102188)))
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT='三期船司查询权限迁移失败:5102184-5102188 ID或权限码被占用';
@@ -188,7 +232,6 @@ INSERT INTO iam_permission
VALUES
(5102184,0,'PLATFORM','BUTTON',5102180,'platform:firstleg:port-schedule-query:list','查询船司任务',NULL,'GET',40,'ACTIVE',1,0),
(5102186,0,'PLATFORM','BUTTON',5102180,'platform:firstleg:port-schedule-query:create','创建船司任务',NULL,'POST',60,'ACTIVE',1,0),
(5102187,0,'PLATFORM','BUTTON',5102180,'platform:firstleg:port-schedule-query:attempt','执行船司查询',NULL,'POST',70,'ACTIVE',1,0),
(5102188,0,'PLATFORM','BUTTON',5102180,'platform:firstleg:port-schedule-query:manual','录入人工结果',NULL,'POST',80,'ACTIVE',1,0)
ON DUPLICATE KEY UPDATE tenant_id=0,app_code='PLATFORM',permission_type=VALUES(permission_type),
permission_code=VALUES(permission_code),permission_name=VALUES(permission_name),parent_id=VALUES(parent_id),
@@ -209,12 +252,13 @@ BEGIN
IF (SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema='baiyue_firstleg' AND table_name IN
('fl_carrier_schedule_query','fl_carrier_schedule_query_attempt',
'fl_carrier_schedule_query_history','fl_carrier_schedule_query_operation')) <> 4 THEN
'fl_carrier_schedule_query_history','fl_carrier_schedule_query_operation',
'fl_carrier_schedule_node_fact')) <> 5 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询任务表未完整创建';
END IF;
IF (SELECT COUNT(*) FROM baiyue_iam.iam_permission
WHERE tenant_id=0 AND id BETWEEN 5102184 AND 5102188
AND permission_code LIKE 'platform:firstleg:port-schedule-query:%') <> 4 THEN
WHERE tenant_id=0 AND id IN (5102184,5102186,5102188)
AND permission_code LIKE 'platform:firstleg:port-schedule-query:%') <> 3 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询任务权限未完整创建';
END IF;
IF (SELECT COUNT(*)
@@ -223,7 +267,7 @@ BEGIN
JOIN baiyue_iam.iam_permission permission ON permission.id=role_permission.permission_id
WHERE role.tenant_id=0 AND role.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR')
AND permission.tenant_id=0
AND permission.permission_code LIKE 'platform:firstleg:port-schedule-query:%') <> 8 THEN
AND permission.permission_code LIKE 'platform:firstleg:port-schedule-query:%') <> 6 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='船司查询任务角色授权未完整创建';
END IF;
END$$