SET NAMES utf8mb4; USE baiyue_firstleg; CREATE TABLE IF NOT EXISTS fl_loading_pick_assignment ( pick_task_id BIGINT UNSIGNED NOT NULL COMMENT '柜次PDA拣货任务ID;同一任务仅保留一名作业员', assignee_id BIGINT UNSIGNED NOT NULL COMMENT '当前唯一作业员ID', assignee_name VARCHAR(64) NOT NULL COMMENT '当前作业员姓名快照', assigned_by BIGINT UNSIGNED NOT NULL COMMENT '领取任务的作业员或执行分配的平台用户ID', assigned_by_name VARCHAR(64) NULL COMMENT '领取或分配操作人姓名快照', assignment_type VARCHAR(16) NOT NULL COMMENT '分配方式:CLAIMED作业员领取、ASSIGNED平台指派', version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '乐观锁版本号,防止多人并发领取或覆盖', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '任务领取或分配时间', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '作业员分配最后更新时间', PRIMARY KEY (pick_task_id), KEY idx_loading_pick_assignee (assignee_id, updated_at), CONSTRAINT fk_loading_pick_assignment_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), CONSTRAINT chk_loading_pick_assignment_type CHECK (assignment_type IN ('CLAIMED', 'ASSIGNED')) ) ENGINE=InnoDB COMMENT='柜次PDA任务领取与作业员分配'; CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment ( pick_item_id BIGINT UNSIGNED NOT NULL COMMENT 'PDA拣货明细ID,同时作为本表主键', assignee_id BIGINT UNSIGNED NOT NULL COMMENT '当前领取或被分配的作业员ID', assignee_name VARCHAR(64) NOT NULL COMMENT '当前作业员姓名快照', assigned_by BIGINT UNSIGNED NOT NULL COMMENT '执行领取或分配操作的用户ID', assigned_by_name VARCHAR(64) NULL COMMENT '执行领取或分配操作的用户姓名快照', assignment_type VARCHAR(16) NOT NULL COMMENT '分配类型:CLAIMED作业员领取、ASSIGNED管理员分配', version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '乐观锁版本号,每次更新递增', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '明细分配记录创建时间', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '明细分配记录最后更新时间', PRIMARY KEY (pick_item_id), KEY idx_loading_pick_item_assignee (assignee_id, updated_at), CONSTRAINT fk_loading_pick_item_assignment_item FOREIGN KEY (pick_item_id) REFERENCES fl_loading_pick_item (id), CONSTRAINT chk_loading_pick_item_assignment_type CHECK (assignment_type IN ('CLAIMED', 'ASSIGNED')) ) ENGINE=InnoDB COMMENT='PDA拣货明细领取与作业员分配'; CREATE TABLE IF NOT EXISTS fl_loading_pick_review ( pick_task_id BIGINT UNSIGNED NOT NULL COMMENT '已完成的柜次PDA拣货任务ID', review_status VARCHAR(16) NOT NULL DEFAULT 'APPROVED' COMMENT '复核状态:APPROVED已通过;记录创建后不可修改或删除', reviewed_by BIGINT UNSIGNED NOT NULL COMMENT '执行完成复核的平台用户ID', reviewed_by_name VARCHAR(64) NULL COMMENT '复核人姓名快照', remark VARCHAR(500) NULL COMMENT 'PDA任务复核备注', version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '复核记录版本号', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '复核通过时间', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '复核记录最后更新时间;正常业务不允许更新', PRIMARY KEY (pick_task_id), KEY idx_loading_pick_reviewer (reviewed_by, created_at), CONSTRAINT fk_loading_pick_review_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), CONSTRAINT chk_loading_pick_review_status CHECK (review_status = 'APPROVED') ) ENGINE=InnoDB COMMENT='柜次PDA任务完成复核'; CREATE TABLE IF NOT EXISTS fl_loading_pick_operation ( id BIGINT UNSIGNED NOT NULL COMMENT 'PDA任务操作审计记录ID', pick_task_id BIGINT UNSIGNED NOT NULL COMMENT '关联柜次PDA拣货任务ID', operation_id VARCHAR(128) NOT NULL COMMENT '全局唯一操作ID,用于幂等重放', request_hash CHAR(64) NOT NULL COMMENT '完整批量请求或任务操作内容SHA-256摘要', action_type VARCHAR(16) NOT NULL COMMENT '动作类型:CLAIM领取、ASSIGN分配、REVIEW复核、BATCH批量提交', operator_id BIGINT UNSIGNED NOT NULL COMMENT '执行PDA任务操作的用户ID', operator_name VARCHAR(64) NULL COMMENT '操作人姓名快照', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '不可变操作审计创建时间', PRIMARY KEY (id), UNIQUE KEY uk_loading_pick_operation_id (operation_id), KEY idx_loading_pick_operation_task (pick_task_id, created_at), CONSTRAINT fk_loading_pick_operation_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'REVIEW', 'BATCH', 'COMPLETE_LOADING')) ) ENGINE=InnoDB COMMENT='柜次PDA任务级幂等审计'; DROP TRIGGER IF EXISTS trg_loading_pick_review_before_update; DELIMITER $$ CREATE TRIGGER trg_loading_pick_review_before_update BEFORE UPDATE ON fl_loading_pick_review FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA复核记录不可修改'; END$$ DELIMITER ; DROP TRIGGER IF EXISTS trg_loading_pick_review_before_delete; DELIMITER $$ CREATE TRIGGER trg_loading_pick_review_before_delete BEFORE DELETE ON fl_loading_pick_review FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA复核记录不可删除'; END$$ DELIMITER ; DROP TRIGGER IF EXISTS trg_loading_pick_operation_before_update; DELIMITER $$ CREATE TRIGGER trg_loading_pick_operation_before_update BEFORE UPDATE ON fl_loading_pick_operation FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA任务操作历史不可修改'; END$$ DELIMITER ; DROP TRIGGER IF EXISTS trg_loading_pick_operation_before_delete; DELIMITER $$ CREATE TRIGGER trg_loading_pick_operation_before_delete BEFORE DELETE ON fl_loading_pick_operation FOR EACH ROW BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA任务操作历史不可删除'; END$$ DELIMITER ; USE baiyue_iam; DROP PROCEDURE IF EXISTS assert_phase3_pda_permission_ids; DELIMITER $$ CREATE PROCEDURE assert_phase3_pda_permission_ids() BEGIN IF EXISTS ( SELECT 1 FROM iam_permission WHERE id BETWEEN 5102190 AND 5102193 AND permission_code NOT IN ( 'platform:firstleg:pda:view', 'platform:firstleg:pda:assign', 'platform:firstleg:pda:work', 'platform:firstleg:pda:review' ) ) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA权限ID已被其他资源占用'; END IF; END$$ DELIMITER ; CALL assert_phase3_pda_permission_ids(); DROP PROCEDURE assert_phase3_pda_permission_ids; 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) VALUES (5102190, 0, 'PLATFORM', 'MENU', 5102094, 'platform:firstleg:pda:view', 'PDA装柜拣货', '/first-leg/pda-loading', 'GET', 10, 'ACTIVE', 1, 0), (5102191, 0, 'PLATFORM', 'BUTTON', 5102190, 'platform:firstleg:pda:assign', '分配PDA任务', NULL, 'POST', 20, 'ACTIVE', 1, 0), (5102192, 0, 'PLATFORM', 'BUTTON', 5102190, 'platform:firstleg:pda:work', '执行PDA拣货', NULL, 'POST', 30, 'ACTIVE', 1, 0), (5102193, 0, 'PLATFORM', 'BUTTON', 5102190, 'platform:firstleg:pda:review', '复核PDA任务', NULL, 'POST', 40, 'ACTIVE', 1, 0) ON DUPLICATE KEY UPDATE permission_name=VALUES(permission_name), parent_id=VALUES(parent_id), route_path=VALUES(route_path), http_method=VALUES(http_method), sort_no=VALUES(sort_no), status='ACTIVE', built_in=1, deleted=0; INSERT IGNORE INTO iam_role_permission (role_id, permission_id, tenant_id) SELECT role.id, permission.id, 0 FROM iam_role role JOIN iam_permission permission ON permission.id BETWEEN 5102190 AND 5102193 WHERE role.tenant_id=0 AND role.role_code IN ('PLATFORM_ADMIN', 'ORDER_OPERATOR') AND role.deleted=0 AND permission.deleted=0;