85 lines
4.3 KiB
MySQL
85 lines
4.3 KiB
MySQL
|
|
-- =============================================================================
|
|||
|
|
-- 三期迁移:坏件处置量跟踪(配合三期的「坏件报废」闭环)
|
|||
|
|
--
|
|||
|
|
-- 背景
|
|||
|
|
-- 二期只支持坏件的「回库」一种出口,故用 `quantity - remaining_qty` 就能
|
|||
|
|
-- 反推已回库量。三期补上「报废」出口后,这个反推就不再成立 ——
|
|||
|
|
-- 它会把报废掉的数量误算成已回库量。
|
|||
|
|
--
|
|||
|
|
-- 因此拆出两个独立累计列:restocked_qty(累计回库)与 scrapped_qty(累计报废)。
|
|||
|
|
--
|
|||
|
|
-- ★ 不变式(全表恒成立,测试中逐行校验):
|
|||
|
|
-- restocked_qty + scrapped_qty + remaining_qty = quantity
|
|||
|
|
-- 暂不加 DB 层 CHECK 约束:本系统库存数量普遍以 Python float 累加后再
|
|||
|
|
-- 落 numeric(19,4),极端小数下可能出现 4 位以外的舍入抖动,硬约束会把
|
|||
|
|
-- 一次合法操作变成 500。改为在接口层维护并由测试守住不变式。
|
|||
|
|
--
|
|||
|
|
-- 状态值归一
|
|||
|
|
-- 二期把「部分处置」命名为 '部分回库'。三期报废也会产生部分状态,旧名不再
|
|||
|
|
-- 准确,统一改为 '处理中'。新状态机(取值见 app/models/transaction.py):
|
|||
|
|
-- 待处理 → 处理中 → ┬ 已回库(全部回库)
|
|||
|
|
-- ├ 已报废(全部报废)
|
|||
|
|
-- └ 已闭环(回库与报废混合)
|
|||
|
|
--
|
|||
|
|
-- 安全性:纯追加式 DDL;新列带 DEFAULT 0,既有行自动补 0。
|
|||
|
|
-- 幂等:全部 IF NOT EXISTS / 带条件的 UPDATE,可重复执行。
|
|||
|
|
--
|
|||
|
|
-- 执行
|
|||
|
|
-- docker exec -i inventory_db psql -U test -d inventory_system < 本文件
|
|||
|
|
-- =============================================================================
|
|||
|
|
|
|||
|
|
BEGIN;
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- 1) 处置量跟踪列
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
ALTER TABLE trans_defective_goods
|
|||
|
|
ADD COLUMN IF NOT EXISTS restocked_qty numeric(19,4) NOT NULL DEFAULT 0,
|
|||
|
|
ADD COLUMN IF NOT EXISTS scrapped_qty numeric(19,4) NOT NULL DEFAULT 0;
|
|||
|
|
|
|||
|
|
COMMENT ON COLUMN trans_defective_goods.restocked_qty IS '累计已回库数量';
|
|||
|
|
COMMENT ON COLUMN trans_defective_goods.scrapped_qty IS '累计已报废数量';
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- 2) 存量回填
|
|||
|
|
-- 迁移前只有「回库」一种出口,故「已减少的在管量」全部归入 restocked_qty。
|
|||
|
|
-- 本表在写此迁移时为空,此段为幂等防御,防止在其它环境(已有数据)执行时
|
|||
|
|
-- 出现 restocked/scrapped 全 0 而 remaining 已减少的不一致状态。
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
UPDATE trans_defective_goods
|
|||
|
|
SET restocked_qty = GREATEST(COALESCE(quantity, 0) - COALESCE(remaining_qty, 0), 0)
|
|||
|
|
WHERE restocked_qty = 0
|
|||
|
|
AND scrapped_qty = 0
|
|||
|
|
AND COALESCE(quantity, 0) > COALESCE(remaining_qty, 0);
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- 3) 状态值归一:'部分回库' → '处理中'
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
UPDATE trans_defective_goods SET status = '处理中' WHERE status = '部分回库';
|
|||
|
|
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
-- 4) 执行后核对:不一致行数必须为 0
|
|||
|
|
-- ---------------------------------------------------------------------------
|
|||
|
|
\echo '--- 处置量不变式核对(inconsistent 应为 0)---'
|
|||
|
|
SELECT count(*) AS total,
|
|||
|
|
count(*) FILTER (
|
|||
|
|
WHERE COALESCE(restocked_qty,0) + COALESCE(scrapped_qty,0)
|
|||
|
|
+ COALESCE(remaining_qty,0) <> COALESCE(quantity,0)
|
|||
|
|
) AS inconsistent
|
|||
|
|
FROM trans_defective_goods;
|
|||
|
|
|
|||
|
|
\echo '--- 状态取值分布 ---'
|
|||
|
|
SELECT COALESCE(status, '<NULL>') AS status, count(*) FROM trans_defective_goods GROUP BY 1;
|
|||
|
|
|
|||
|
|
COMMIT;
|
|||
|
|
|
|||
|
|
|
|||
|
|
-- =============================================================================
|
|||
|
|
-- 回滚段(仅撤销三期变更;不动二期表结构)
|
|||
|
|
-- =============================================================================
|
|||
|
|
-- BEGIN;
|
|||
|
|
-- ALTER TABLE trans_defective_goods DROP COLUMN IF EXISTS restocked_qty;
|
|||
|
|
-- ALTER TABLE trans_defective_goods DROP COLUMN IF EXISTS scrapped_qty;
|
|||
|
|
-- UPDATE trans_defective_goods SET status = '部分回库' WHERE status = '处理中';
|
|||
|
|
-- COMMIT;
|