From 2045a89330bf0d2eb277904ab42591464c6af705 Mon Sep 17 00:00:00 2001 From: yueli Date: Thu, 10 Sep 2026 10:14:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(db):=20=E5=AE=A1=E6=89=B9=E5=8D=95?= =?UTF-8?q?=E6=8D=AE=E6=97=B6=E9=97=B4=E5=8F=A3=E5=BE=84=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=20+=20=E8=A1=A5=E6=B3=A8=E5=86=8C=20scrap=5Fselection=20?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unify_approval_timezone.sql: · scrap_approval 的 4 个时间列由 timestamptz 改为 timestamp without time zone, 与 outbound/borrow 对齐(该表当时无业务数据,转换零损失); · 三张审批表 created_at/updated_at 的 DB 默认值由 UTC 的 now()/CURRENT_TIMESTAMP 统一为 timezone('Asia/Shanghai', now()),杜绝绕过 ORM 的写入偏 8 小时。 add_scrap_selection_perm.sql: GET /scrap/scan 一直声明需要 scrap_selection,但该权限码从未写入 sys_element / sys_role_permission,精确匹配与前缀展开匹配全部落空, 导致除 SUPER_ADMIN 外没有任何角色能调用扫码接口。现补注册, 并授予所有已持有 scrap_execute(按单报废执行)的角色。 --- db_migrations/add_scrap_selection_perm.sql | 34 +++++++++++++++++ db_migrations/unify_approval_timezone.sql | 43 ++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 db_migrations/add_scrap_selection_perm.sql create mode 100644 db_migrations/unify_approval_timezone.sql diff --git a/db_migrations/add_scrap_selection_perm.sql b/db_migrations/add_scrap_selection_perm.sql new file mode 100644 index 0000000..9502883 --- /dev/null +++ b/db_migrations/add_scrap_selection_perm.sql @@ -0,0 +1,34 @@ +-- ============================================================================= +-- 补注册 scrap_selection 权限码 +-- +-- 背景: +-- GET /api/v1/scrap/scan(按单报废执行页的扫码查库存接口)自始就声明需要 +-- scrap_selection,但该权限码从未写入 sys_element / sys_role_permission。 +-- 结果 permission_required('scrap_selection') 的精确匹配与展开匹配(前缀 +-- scrap_selection:)全部落空,导致除 SUPER_ADMIN 外没有任何角色能调用扫码接口。 +-- +-- 处理: +-- 1) 注册 scrap_selection 权限元素(挂在 scrap_create 菜单下,与 scrap_apply / +-- scrap_execute 同级); +-- 2) 授予所有已持有 scrap_execute(按单报废执行)的角色, +-- 保证「执行报废」的人必然可以扫码。 +-- +-- 执行: docker exec -i inventory_db psql -U test -d inventory_system < 本文件 +-- ============================================================================= +BEGIN; + +INSERT INTO sys_element (menu_code, name, code, element_type) +SELECT 'scrap_create', '报废扫码(查询库存)', 'scrap_selection', 'operation' +WHERE NOT EXISTS (SELECT 1 FROM sys_element WHERE code = 'scrap_selection'); + +INSERT INTO sys_role_permission (role_code, target_code, type, company_name) +SELECT DISTINCT sp.role_code, 'scrap_selection', 'element', sp.company_name +FROM sys_role_permission sp +WHERE sp.target_code = 'scrap_execute' AND sp.type = 'element' + AND NOT EXISTS ( + SELECT 1 FROM sys_role_permission r + WHERE r.role_code = sp.role_code AND r.target_code = 'scrap_selection' + AND r.type = 'element' AND COALESCE(r.company_name,'') = COALESCE(sp.company_name,'') + ); + +COMMIT; diff --git a/db_migrations/unify_approval_timezone.sql b/db_migrations/unify_approval_timezone.sql new file mode 100644 index 0000000..af6c295 --- /dev/null +++ b/db_migrations/unify_approval_timezone.sql @@ -0,0 +1,43 @@ +-- ============================================================================= +-- 审批类单据时间口径统一(全部落到 naive 北京时间) +-- +-- 背景: +-- 1) 容器内 PostgreSQL 时区为 Etc/UTC,库级默认 now() / CURRENT_TIMESTAMP 均为 UTC; +-- 2) scrap_approval 原先用 timestamptz 列 + tz-aware Python 值,而 +-- outbound_approval / borrow_approval 用 timestamp without time zone 列; +-- 三张表口径不一致,且 outbound/borrow 的 DB 默认值 CURRENT_TIMESTAMP 是 UTC, +-- 一旦有绕过 ORM 的写入就会产生 8 小时偏差。 +-- +-- 目标: +-- · 三张审批单表的 created_at / updated_at 统一为 timestamp without time zone; +-- · DB 侧默认值统一为 timezone('Asia/Shanghai', now()),即北京时间; +-- · 应用层(SQLAlchemy 模型)始终显式传 beijing_time(),不依赖 DB 默认值。 +-- +-- 执行: docker exec -i inventory_db psql -U test -d inventory_system < 本文件 +-- ============================================================================= +BEGIN; + +-- ----------------------------------------------------------------------------- +-- 1) scrap_approval:timestamptz -> timestamp without time zone +-- (该表此前无业务数据,转换不会造成既有时间语义漂移; +-- ALTER 后原 timestamptz 值会按会话时区 UTC 取钟面值,如需保留请先备份) +-- ----------------------------------------------------------------------------- +ALTER TABLE scrap_approval + ALTER COLUMN created_at TYPE timestamp without time zone, + ALTER COLUMN updated_at TYPE timestamp without time zone, + ALTER COLUMN approved_at TYPE timestamp without time zone, + ALTER COLUMN executed_at TYPE timestamp without time zone; + +ALTER TABLE scrap_approval ALTER COLUMN created_at SET DEFAULT timezone('Asia/Shanghai', now()); +ALTER TABLE scrap_approval ALTER COLUMN updated_at SET DEFAULT timezone('Asia/Shanghai', now()); + +-- ----------------------------------------------------------------------------- +-- 2) outbound_approval / borrow_approval:DB 默认值由 UTC 改为北京时间 +-- 列类型本就是 naive,无需转换 +-- ----------------------------------------------------------------------------- +ALTER TABLE outbound_approval ALTER COLUMN created_at SET DEFAULT timezone('Asia/Shanghai', now()); +ALTER TABLE outbound_approval ALTER COLUMN updated_at SET DEFAULT timezone('Asia/Shanghai', now()); +ALTER TABLE borrow_approval ALTER COLUMN created_at SET DEFAULT timezone('Asia/Shanghai', now()); +ALTER TABLE borrow_approval ALTER COLUMN updated_at SET DEFAULT timezone('Asia/Shanghai', now()); + +COMMIT;