From 2f658407c37bd80bc044a2ffd0a261d71b15d1b6 Mon Sep 17 00:00:00 2001 From: yueli Date: Thu, 17 Sep 2026 11:26:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(db):=20=E5=9F=BA=E7=A1=80=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=96=B0=E5=A2=9E=E3=80=8C=E9=87=87=E8=B4=AD=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=E3=80=8D=E5=AD=97=E6=AE=B5=E5=B9=B6=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 需求:物料主数据增加一个可直接跳转的补货地址(淘宝/1688 等),纳入字段权限管控。 ★ 设计取舍:读写**共用同一个权限码** material_list:purchaseLink 上一轮刚修完「写用 A 码、读用 B 码」造成的读写错位(附件备注),新字段刻意 沿用 referencePrice 的既有模式 —— 一个码同时进 field_permissions.py(读过滤) 与 base.py 的 field_to_perm(写过滤)。单码最大的好处是**结构上不可能错位**: 能读必然能写、反之亦然,不会再有「填了看不到」或「看得到改不了」。 若将来要求「能看不能改」,需拆两个码并同步改三处,届时一并回归验证。 ★ 列类型用 text 而非 varchar(N):外链常带很长的查询串,截断后是打不开的地址, 且截断是静默的 —— 用户只会觉得「链接坏了」。 默认授予 SUPER_ADMIN / SUPERVISOR / WAREHOUSE_MGR / INBOUND(覆盖实际补货的人 与管理物料的人)。⚠ 这是本次取的默认值,业务可按需增删 —— 改 VALUES 再执行一次即可。 幂等;不含 psql 元命令,DataGrip 可直接整段执行;含核对段与回滚段。 --- .../phase6_material_purchase_link.sql | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 db_migrations/phase6_material_purchase_link.sql diff --git a/db_migrations/phase6_material_purchase_link.sql b/db_migrations/phase6_material_purchase_link.sql new file mode 100644 index 0000000..cad1808 --- /dev/null +++ b/db_migrations/phase6_material_purchase_link.sql @@ -0,0 +1,94 @@ +-- ============================================================================= +-- 基础信息 · 新增「采购链接」字段 + 权限注册 +-- +-- 需求 +-- 物料主数据上增加一个可直接跳转的补货地址(淘宝 / 1688 等), +-- 并纳入字段级权限管控。 +-- +-- --------------------------------------------------------------------------- +-- ★ 设计取舍:读写**共用同一个权限码** material_list:purchaseLink +-- 上一轮刚修完「写用了 A 码、读用了 B 码」造成的读写错位(附件备注), +-- 新字段刻意沿用 referencePrice 的既有模式 —— 一个码同时进 +-- field_permissions.py(读过滤)与 base.py 的 field_to_perm(写过滤)。 +-- 单码最大的好处是**结构上不可能出现口径错位**:能读必然能写、反之亦然, +-- 不会再有「填了看不到」或「看得到改不了」。 +-- +-- 若业务后续要求「能看不能改」,再拆成两个码并同步改三处 +-- (field_permissions.py / base.py 的 POST 与 PUT),届时请一并回归验证。 +-- +-- ★ 为什么列类型用 text 而不是 varchar(N) +-- 外链(尤其是电商)常带很长的查询串,varchar 截断后得到的是打不开的地址, +-- 而且截断是静默的 —— 用户只会觉得"链接坏了"。 +-- +-- 默认授予:SUPER_ADMIN / SUPERVISOR / WAREHOUSE_MGR / INBOUND +-- —— 覆盖「实际补货的人」与「管理物料的人」。 +-- ⚠ 这是本次取的默认值,业务可按需增删;增删只需改下面的 VALUES 再执行一次。 +-- +-- 幂等:带 IF NOT EXISTS / WHERE NOT EXISTS,可重复执行。 +-- 脚本文本不含 psql 元命令,DataGrip / DBeaver 可直接整段执行。 +-- 执行:docker exec -i inventory_db psql -U test -d inventory_system < 本文件 +-- ============================================================================= + +BEGIN; + +-- --------------------------------------------------------------------------- +-- 一、加列 +-- --------------------------------------------------------------------------- +ALTER TABLE material_base + ADD COLUMN IF NOT EXISTS purchase_link text DEFAULT ''; + +COMMENT ON COLUMN material_base.purchase_link IS + '采购链接:补货时直接跳转的购买地址。受 material_list:purchaseLink 字段权限管控(读写同码)'; + +-- --------------------------------------------------------------------------- +-- 二、注册字段权限元素 +-- --------------------------------------------------------------------------- +INSERT INTO sys_element (menu_code, name, code, element_type) +SELECT 'material_list', '采购链接', 'material_list:purchaseLink', 'element' +WHERE NOT EXISTS (SELECT 1 FROM sys_element WHERE code = 'material_list:purchaseLink'); + +-- --------------------------------------------------------------------------- +-- 三、默认授予 +-- --------------------------------------------------------------------------- +INSERT INTO sys_role_permission (role_code, target_code, type, company_name) +SELECT v.role_code, 'material_list:purchaseLink', 'element', NULL +FROM (VALUES ('SUPER_ADMIN'), ('SUPERVISOR'), ('WAREHOUSE_MGR'), ('INBOUND')) AS v(role_code) +WHERE NOT EXISTS ( + SELECT 1 FROM sys_role_permission r + WHERE r.role_code = v.role_code + AND r.target_code = 'material_list:purchaseLink' + AND r.type = 'element' +); + +COMMIT; + + +-- ============================================================================= +-- 执行后核对 +-- ============================================================================= +SELECT '=== 1) 新列已就位 ===' AS "核对项"; +SELECT column_name, data_type, column_default FROM information_schema.columns + WHERE table_name = 'material_base' AND column_name = 'purchase_link'; + +SELECT '=== 2) 权限元素已注册 ===' AS "核对项"; +SELECT code, name, menu_code, element_type FROM sys_element + WHERE code = 'material_list:purchaseLink'; + +SELECT '=== 3) 已授予角色(默认应为 4 个)===' AS "核对项"; +SELECT role_code FROM sys_role_permission + WHERE target_code = 'material_list:purchaseLink' AND type = 'element' ORDER BY role_code; + +SELECT '=== 4) 存量数据回填为空的应占多数 ===' AS "核对项"; +SELECT count(*) AS 物料总数, + count(*) FILTER (WHERE coalesce(purchase_link,'') = '') AS 未填链接 + FROM material_base; + + +-- ============================================================================= +-- 回滚段 +-- ============================================================================= +-- BEGIN; +-- DELETE FROM sys_role_permission WHERE target_code = 'material_list:purchaseLink'; +-- DELETE FROM sys_element WHERE code = 'material_list:purchaseLink'; +-- ALTER TABLE material_base DROP COLUMN IF EXISTS purchase_link; +-- COMMIT;