liu
11 小时以前 9d5ff3a521f83d94f9104bda68755449e272a93f
chore(sql): 新增种子质检三类型数据库升级脚本

配合「种子质检支持袋码/托盘码/批次码三种扫码类型」的上线,
把所需库结构一次性对齐,带存在性判断可对同一环境重复执行。

覆盖内容:
- mes_pro_bag_code 新增 qc_status / inbound_event_id / business_code
- mes_pro_pallet、mes_pro_batch 新增 business_code 及唯一索引
- mes_pro_scan_event 新增 scan_type,device_code 改为非必填
- mes_pro_pallet 新增 inbound_event_id / inbound_time
- mes_wm_warehouse 新增 type,并初始化成品合格库、库区、库位
- 新建按袋库存明细表 mes_wm_material_stock_bag
- 新增「质检记录」独立菜单 1065224

脚本不含 DELETE、不做数据搬迁,仅回填 qc_status 与 scan_type 两个
由既有记录可推导的字段,可安全在生产库执行。末尾附自检查询。

Co-Authored-By: Claude <noreply@anthropic.com>
已添加1个文件
235 ■■■■■ 文件已修改
sql/mysql/mes_seed_quality_multitype_upgrade.sql 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/mes_seed_quality_multitype_upgrade.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,235 @@
-- =====================================================================
-- ç§å­è´¨æ£€ã€Œè¢‹ç  / æ‰˜ç›˜ç  / æ‰¹æ¬¡ç ã€ä¸‰ç§æ‰«ç ç±»åž‹ â€”— æ•°æ®åº“升级总脚本
--
-- ç”¨é€”:把「种子质检三类型 + ç”Ÿäº§çº¿æ‰«ç å…¥åº“三类型」所需的库结构一次性对齐。
--       å…¨éƒ¨ DDL å¸¦å­˜åœ¨æ€§åˆ¤æ–­ï¼Œå¯å¯¹åŒä¸€çŽ¯å¢ƒé‡å¤æ‰§è¡Œï¼Œå·²å­˜åœ¨çš„åˆ—/索引/表/
--       èœå•/仓库数据会跳过,不再报 1060 Duplicate column name。
--
-- ç”¨æ³•:必须先选择数据库(use <库名>)再整份执行:
--         mysql -u<user> -p <库名> < mes_seed_quality_multitype_upgrade.sql
--       æˆ–在客户端里先 use <库名>。
--       è‹¥æœªé€‰åº“,第 0 æ­¥ä¼šæ˜Žç¡®æŠ¥å‡ºï¼Œä¸”所有 DDL ä¸€å¾‹è·³è¿‡ï¼ˆä¸ä¼šè¯¯æ”¹ç»“构)。
--
-- å‰ç½®è¡¨ï¼ˆç¼ºå¤±è¯´æ˜ŽçŽ¯å¢ƒè¿‡æ—§ï¼Œéœ€å…ˆè·‘å¯¹åº”åŸºç¡€è„šæœ¬ï¼‰ï¼š
--   mes_pro_bag_code / mes_pro_pallet / mes_pro_batch / mes_pro_scan_event
--   mes_wm_warehouse / mes_wm_warehouse_location / mes_wm_warehouse_area
--   mes_qc_seed_quality / system_menu
--   å…¶ä¸­ mes_pro_scan_event ç”± sql/mes_scan_event_inbound.sql åˆ›å»º
--
-- æœ¬è„šæœ¬ä¸å«ä»»ä½• DELETE,也不做数据搬迁,可安全在生产库执行。
-- æé†’:mes_wm_qualified_warehouse.sql é‡Œçš„「虚拟仓库合格库存搬迁」是破坏性
--       æ•°æ®è¿ç§»ï¼ˆå…ˆåˆå¹¶å†åˆ æºè®°å½•),不在本脚本内,需要时单独评估后执行。
-- æœ¬è„šæœ¬ä¸ä½¿ç”¨å¤šç§Ÿæˆ·ï¼Œæ—  tenant_id å­—段。
-- =====================================================================
-- ---------------------------------------------------------------------
-- 0. ç›®æ ‡åº“确认(未选库时所有 DDL ä¼šè¢«è·³è¿‡ï¼ŒåªæŠ¥æç¤ºï¼‰
-- ---------------------------------------------------------------------
SET @db = DATABASE();
SELECT IF(@db IS NULL OR @db = '',
  '未选择数据库:请先 use <库名> å†æ‰§è¡Œæœ¬è„šæœ¬ï¼Œæœ¬æ¬¡æœªåšä»»ä½•ç»“æž„å˜æ›´',
  CONCAT('目标库:', @db)) AS db_check;
-- ---------------------------------------------------------------------
-- 1. æ¯è¢‹è´¨æ£€çŠ¶æ€ï¼šè´¨æ£€æŒ‰è¢‹ç²’åº¦æµè½¬ã€é”€å”®å‡ºåº“æ ¡éªŒçš„ä¾æ®
-- ---------------------------------------------------------------------
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'qc_status');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_bag_code` ADD COLUMN `qc_status` TINYINT NOT NULL DEFAULT 10 COMMENT ''质检状态(10未质检 20质检合格 30质检不合格)'' AFTER `status`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- å­˜é‡å›žå¡«ï¼šæŒ‰å·²æœ‰ç§å­è´¨æ£€è®°å½•同步袋码质检状态(幂等,仅改不一致的行)
UPDATE `mes_pro_bag_code` b
  JOIN `mes_qc_seed_quality` q ON b.code = q.code AND b.deleted = 0
SET b.qc_status = IF(q.result = 1, 20, 30), b.update_time = NOW()
WHERE b.qc_status <> IF(q.result = 1, 20, 30);
-- ---------------------------------------------------------------------
-- 2. å•袋入库标记:resolve çš„ inbound åˆ¤æ–­ã€submit-group çš„
--    ã€Œæœ‰æ•ˆè¢‹ç å¿…须全部入库」校验都依赖该列
-- ---------------------------------------------------------------------
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'inbound_event_id');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_bag_code` ADD COLUMN `inbound_event_id` BIGINT NULL COMMENT ''入库事件ID''',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ---------------------------------------------------------------------
-- 3. ä¸‰ä¸ªå†…部业务码:托盘码 / æ‰¹æ¬¡ç è¯†åˆ«æ—¶ä¸Žè¿½æº¯ç é”å®šåŒä¸€å¯¹è±¡ï¼Œé˜²æ­¢é‡å¤è´¨æ£€
-- ---------------------------------------------------------------------
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_bag_code` ADD COLUMN `business_code` VARCHAR(16) DEFAULT NULL COMMENT ''内部出入库业务码(16位数字)'' AFTER `code`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_pallet` ADD COLUMN `business_code` VARCHAR(16) DEFAULT NULL COMMENT ''内部出入库业务码(16位数字)'' AFTER `code`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_batch' AND column_name = 'business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_batch` ADD COLUMN `business_code` VARCHAR(16) DEFAULT NULL COMMENT ''内部出入库业务码(16位数字)'' AFTER `code`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.statistics
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND index_name = 'uk_business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_bag_code` ADD UNIQUE KEY `uk_business_code` (`business_code`)', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.statistics
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND index_name = 'uk_business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_pallet` ADD UNIQUE KEY `uk_business_code` (`business_code`)', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.statistics
  WHERE table_schema = @db AND table_name = 'mes_pro_batch' AND index_name = 'uk_business_code');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_batch` ADD UNIQUE KEY `uk_business_code` (`business_code`)', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- åŽ†å²æ•°æ®ä¸ç”±è„šæœ¬å¤åˆ¶è¿½æº¯ç ï¼Œé¿å…ä¸šåŠ¡ç ä¸Žè¿½æº¯ç é‡å¤ï¼›åœ¨ã€Œè¢‹ç åˆ—è¡¨ã€é¡µé¢å‹¾é€‰è¡¥ç”Ÿæˆã€‚
-- ---------------------------------------------------------------------
-- 4. ç”Ÿäº§çº¿æ‰«ç å…¥åº“:三种扫码类型 + è®¾å¤‡ç¼–码非必填 + æ•´æ‰˜å…¥åº“去重标记
-- ---------------------------------------------------------------------
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_scan_event' AND column_name = 'scan_type');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_scan_event` ADD COLUMN `scan_type` VARCHAR(16) NULL COMMENT ''扫码类型(BAG袋码/PALLET托盘码/BATCH批次码)'' AFTER `bag_code`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- è®¾å¤‡ç¼–码改为非必填(前端已去掉该录入项,历史列保持兼容)。
-- MODIFY æœ¬èº«å¯é‡å¤æ‰§è¡Œï¼›è¡¨ä¸å­˜åœ¨æ—¶ä¼šæŠ¥é”™ï¼Œå±žé¢„期(说明未跑基础脚本)。
ALTER TABLE `mes_pro_scan_event`
  MODIFY COLUMN `device_code` VARCHAR(64) NULL DEFAULT NULL COMMENT '设备编码(不再必填)';
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'inbound_event_id');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_pallet` ADD COLUMN `inbound_event_id` BIGINT NULL COMMENT ''最近入库扫码事件编号'' AFTER `bag_count`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'inbound_time');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_pro_pallet` ADD COLUMN `inbound_time` DATETIME NULL COMMENT ''最近入库时间'' AFTER `inbound_event_id`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- åŽ†å²æ‰«ç äº‹ä»¶æŒ‰è¢‹ç å¤„ç†
UPDATE `mes_pro_scan_event` SET `scan_type` = 'BAG' WHERE `scan_type` IS NULL;
-- ---------------------------------------------------------------------
-- 5. ä»“库类型 + åˆæ ¼åº“数据
--    è´¨æ£€é¡µã€Œå…¥åº“合格库」下拉只列 type=20 ä¸”未冻结的仓库,缺了无法提交质检
-- ---------------------------------------------------------------------
SET @exists = (SELECT COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_wm_warehouse' AND column_name = 'type');
SET @sql = IF(@db IS NOT NULL AND @exists = 0,
  'ALTER TABLE `mes_wm_warehouse` ADD COLUMN `type` TINYINT NOT NULL DEFAULT 10 COMMENT ''仓库类型:10暂存库,20合格库'' AFTER `frozen`',
  'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- çŽ°æœ‰ä»“åº“å½’ç±»ï¼šè™šæ‹Ÿçº¿è¾¹ä»“åº“=暂存库;产品库/物料库=合格库
UPDATE `mes_wm_warehouse` SET `type` = 10 WHERE `code` = 'WIP_VIRTUAL_WAREHOUSE' AND `deleted` = 0;
UPDATE `mes_wm_warehouse` SET `type` = 20 WHERE `code` IN ('1212', 'WHS000001') AND `deleted` = 0;
-- æ–°å»ºã€Œæˆå“åˆæ ¼åº“」+ åº“区 + åº“位(幂等)
INSERT INTO `mes_wm_warehouse` (`code`, `name`, `frozen`, `type`, `remark`)
SELECT 'FG_QUALIFIED_WH', '成品合格库', 0, 20, '质检合格直接入库的目标仓库(type=20 åˆæ ¼åº“)'
WHERE NOT EXISTS (SELECT 1 FROM `mes_wm_warehouse` WHERE `code` = 'FG_QUALIFIED_WH' AND `deleted` = 0);
SET @wh_id = (SELECT `id` FROM `mes_wm_warehouse` WHERE `code` = 'FG_QUALIFIED_WH' AND `deleted` = 0 LIMIT 1);
INSERT INTO `mes_wm_warehouse_location` (`code`, `name`, `warehouse_id`, `frozen`, `remark`)
SELECT 'FG_QUALIFIED_WH_LOC', '成品合格库区', @wh_id, 0, '质检合格入库默认库区'
WHERE NOT EXISTS (SELECT 1 FROM `mes_wm_warehouse_location` WHERE `code` = 'FG_QUALIFIED_WH_LOC' AND `deleted` = 0);
SET @loc_id = (SELECT `id` FROM `mes_wm_warehouse_location` WHERE `code` = 'FG_QUALIFIED_WH_LOC' AND `deleted` = 0 LIMIT 1);
INSERT INTO `mes_wm_warehouse_area` (`code`, `name`, `location_id`, `frozen`, `remark`)
SELECT 'FG_QUALIFIED_WH_AREA', '成品合格库位', @loc_id, 0, '质检合格入库默认库位'
WHERE NOT EXISTS (SELECT 1 FROM `mes_wm_warehouse_area` WHERE `code` = 'FG_QUALIFIED_WH_AREA' AND `deleted` = 0);
-- ---------------------------------------------------------------------
-- 6. æŒ‰è¢‹åº“存明细表:质检合格 / ä¸åˆæ ¼æŒ‰è¢‹æ‰£æš‚存、入合格库
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `mes_wm_material_stock_bag` (
    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号',
    `material_stock_id` BIGINT NOT NULL COMMENT '库存汇总记录ID',
    `bag_code_id` BIGINT NOT NULL COMMENT '生产袋码ID',
    `bag_code` VARCHAR(64) NOT NULL COMMENT '袋码',
    `item_id` BIGINT NOT NULL COMMENT '物料ID',
    `batch_id` BIGINT NULL COMMENT '仓库批次ID',
    `batch_code` VARCHAR(64) NULL COMMENT '批次号',
    `vendor_id` BIGINT NULL COMMENT '供应商ID',
    `warehouse_id` BIGINT NOT NULL COMMENT '仓库ID',
    `location_id` BIGINT NULL COMMENT '库区ID',
    `area_id` BIGINT NULL COMMENT '库位ID',
    `stock_state` TINYINT NOT NULL COMMENT '库存状态:10暂存,20合格,30已出库,40报废',
    `status` TINYINT NOT NULL DEFAULT 1 COMMENT '明细状态:1在库,2已出库,3已报废',
    `quantity` DECIMAL(18, 6) NOT NULL DEFAULT 1 COMMENT '袋码库存数量',
    `frozen` BIT NOT NULL DEFAULT 0 COMMENT '是否冻结',
    `last_transaction_id` BIGINT NULL COMMENT '最近库存事务ID',
    `inbound_time` DATETIME NULL COMMENT '入库时间',
    `outbound_time` DATETIME NULL COMMENT '出库时间',
    `creator` VARCHAR(64) DEFAULT '' COMMENT '创建者',
    `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updater` VARCHAR(64) DEFAULT '' COMMENT '更新者',
    `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    `deleted` BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_bag_code` (`bag_code`),
    KEY `idx_material_stock` (`material_stock_id`),
    KEY `idx_batch_state` (`batch_id`, `stock_state`, `status`),
    KEY `idx_location_state` (`warehouse_id`, `location_id`, `area_id`, `stock_state`, `status`),
    KEY `idx_bag_code_id` (`bag_code_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES库存袋码明细';
-- ---------------------------------------------------------------------
-- 7. è´¨æ£€è®°å½•独立菜单(挂在「质量管理」5500 ä¸‹ï¼‰
-- ---------------------------------------------------------------------
INSERT INTO `system_menu`
(`id`, `name`, `parent_id`, `type`, `sort`, `status`, `path`, `icon`, `component`, `component_name`, `permission`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
SELECT 1065224, '质检记录', 5500, 2, 95, 0, 'seed-quality-record', 'ep:list', 'mes/qc/seedQuality/record', 'MesQcSeedQualityRecord', '', b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `id` = 1065224 AND `deleted` = b'0');
-- ---------------------------------------------------------------------
-- 8. æ‰§è¡ŒåŽè‡ªæ£€ï¼šæ¯é¡¹ present=1 ä¸ºå°±ç»ªï¼›æœ€åŽä¸€é¡¹åº” >= 1
--    è‹¥å…¨éƒ¨ä¸º 0,多半是第 0 æ­¥æŠ¥çš„「未选择数据库」
-- ---------------------------------------------------------------------
SELECT 'mes_pro_bag_code.qc_status' AS item, COUNT(*) AS present FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'qc_status'
UNION ALL SELECT 'mes_pro_bag_code.inbound_event_id', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'inbound_event_id'
UNION ALL SELECT 'mes_pro_bag_code.business_code', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_bag_code' AND column_name = 'business_code'
UNION ALL SELECT 'mes_pro_pallet.business_code', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'business_code'
UNION ALL SELECT 'mes_pro_batch.business_code', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_batch' AND column_name = 'business_code'
UNION ALL SELECT 'mes_pro_scan_event.scan_type', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_scan_event' AND column_name = 'scan_type'
UNION ALL SELECT 'mes_pro_pallet.inbound_event_id', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'inbound_event_id'
UNION ALL SELECT 'mes_pro_pallet.inbound_time', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_pro_pallet' AND column_name = 'inbound_time'
UNION ALL SELECT 'mes_wm_warehouse.type', COUNT(*) FROM information_schema.columns
  WHERE table_schema = @db AND table_name = 'mes_wm_warehouse' AND column_name = 'type'
UNION ALL SELECT 'TABLE mes_wm_material_stock_bag', COUNT(*) FROM information_schema.tables
  WHERE table_schema = @db AND table_name = 'mes_wm_material_stock_bag'
UNION ALL SELECT 'MENU è´¨æ£€è®°å½• 1065224', COUNT(*) FROM `system_menu` WHERE `id` = 1065224 AND `deleted` = b'0'
UNION ALL SELECT 'DATA type=20 æœªå†»ç»“仓库', COUNT(*) FROM `mes_wm_warehouse` WHERE `type` = 20 AND `frozen` = 0 AND `deleted` = 0;