diff --git a/db_migrations/add_stocktake_draft_company_name.sql b/db_migrations/add_stocktake_draft_company_name.sql new file mode 100644 index 0000000..da1f450 --- /dev/null +++ b/db_migrations/add_stocktake_draft_company_name.sql @@ -0,0 +1,32 @@ +-- ============================================================================= +-- 一次性迁移:盘点草稿表增加公司隔离键 +-- stocktake_draft.company_name varchar(255) +-- +-- 背景 +-- 改造前 stocktake_draft 没有任何公司维度,导致三个跨公司污染问题: +-- 1. /draft/start-new 调用 StocktakeDraft.query.all() 清空**整张表**, +-- 任一库管开启新盘点会删掉其他公司所有人的盘点进度; +-- 2. get_stock_info() 全局按 barcode/sku 匹配三张库存表,不同公司同码 +-- 物料会互相串货; +-- 3. 去重键 (session_id, uuid) 不含公司,跨公司同码记录互相覆盖。 +-- +-- 取值来源 +-- material_base.company_name(公司的真实载体是字符串,不是 id)。 +-- 普通用户由 get_current_company_filter() 从 JWT 强制取本公司; +-- 超管/跨域用户未显式指定公司时为 NULL —— NULL 表示「不过滤公司」。 +-- +-- 存量数据 +-- 保留不动(本脚本不做 DELETE)。存量行 company_name 为 NULL, +-- 普通用户按公司过滤后看不到,超管仍可见。 +-- +-- 执行: docker exec -i inventory_db psql -U test -d inventory_system < 本文件 +-- ============================================================================= +BEGIN; + +ALTER TABLE stocktake_draft ADD COLUMN IF NOT EXISTS company_name varchar(255); + +-- 盘点会话的所有查询都会带上 company_name 过滤,故建复合索引而非单列索引 +CREATE INDEX IF NOT EXISTS ix_stocktake_draft_company_session + ON stocktake_draft(company_name, session_id); + +COMMIT; diff --git a/inventory-backend/app/models/inbound/stocktake.py b/inventory-backend/app/models/inbound/stocktake.py index b7148fe..54c62fa 100644 --- a/inventory-backend/app/models/inbound/stocktake.py +++ b/inventory-backend/app/models/inbound/stocktake.py @@ -28,6 +28,9 @@ class StocktakeDraft(db.Model): diff_qty = db.Column(db.Numeric(19, 4), default=0) # 盘点备注(可选) remark = db.Column(db.String(255), comment='盘点备注(可选)') + # 所属公司(多租户隔离键)。取自 material_base.company_name; + # 超管/跨域用户在未指定公司时为 NULL,表示不做公司过滤。 + company_name = db.Column(db.String(255), index=True, comment='所属公司') def to_dict(self): return { @@ -41,5 +44,6 @@ class StocktakeDraft(db.Model): 'stock_id': self.stock_id, 'stock_qty': float(self.stock_qty or 0), 'diff_qty': float(self.diff_qty or 0), - 'remark': self.remark + 'remark': self.remark, + 'company_name': self.company_name }