fix(export): 公司隔离移出 if filters 判定,确保无条件执行
export_excel 的行级公司隔离原本嵌套在 `if filters:` 内部:
只要调用方不传或传空筛选条件,整段隔离会被跳过且不抛错 —— 静默失效。
(实测: 修复前 export_excel({}, None) 会导出跨公司全部 1816 行。)
现把 get_current_company_filter() 及其 filter_conditions.append 提到
if filters: 之前,无论有无筛选条件都绝对执行。
同时清理路由里 filters 字典的 'company' 死键 —— export_excel 从不消费它,
真正生效的是 get_current_company_filter() 直接读 request.args 上的公司标识。
注意:前端 handleExport 的 company 参数必须保留(已在代码中加注说明)。
实测 WAREHOUSE_MGR 带 ?company=IRIS 导出 1126 行仅 IRIS,不带则 1816 行
涵盖 IRIS+LICA —— 跨域角色按公司收窄范围完全依赖这个 query 参数。
实测(修复后):
SALES/IRIS filters={} → 1126 行, 仅 IRIS
SALES/IRIS filters={keyword:''}→ 1126 行, 仅 IRIS
WAREHOUSE_MGR ?company=IRIS → 1126 行, 仅 IRIS
WAREHOUSE_MGR (无参数) → 1816 行, IRIS+LICA
This commit is contained in:
@ -202,9 +202,12 @@ def get_options():
|
||||
def export_data():
|
||||
try:
|
||||
# 获取筛选条件
|
||||
# ★ 此处刻意不放 company:export_excel 从不消费该键,放进来是死参数、易误导。
|
||||
# 真正生效的公司隔离由 export_excel 内的 get_current_company_filter() 直接读
|
||||
# request.args 里的 company / company_name —— 所以前端仍需把它带在 query
|
||||
# string 上,跨域角色(超管 / WAREHOUSE_MGR)按公司出报表就靠这个参数。
|
||||
filters = {
|
||||
'keyword': request.args.get('keyword', ''),
|
||||
'company': request.args.get('company', ''),
|
||||
'category': request.args.get('category', ''),
|
||||
'type': request.args.get('type', ''),
|
||||
'isEnabled': request.args.get('isEnabled', None)
|
||||
|
||||
@ -790,6 +790,21 @@ class MaterialBaseService:
|
||||
try:
|
||||
# 1. 构造基础信息的筛选条件 (用于过滤库存)
|
||||
filter_conditions = []
|
||||
|
||||
# ============================================================
|
||||
# 【行级数据隔离】基于 JWT 多租户公司过滤
|
||||
# ★ 必须无条件执行:此前这段嵌套在 `if filters:` 内部,只要调用方
|
||||
# 不传或传空筛选条件,公司隔离就会被整段跳过且不报错(静默失效)。
|
||||
# company_limit 的取值规则见 get_current_company_filter():
|
||||
# - 普通用户 → JWT 中记录的本公司,强制隔离
|
||||
# - 超管 / 跨域角色 → 仅当请求显式带公司标识时才限制,否则返回 None
|
||||
# ============================================================
|
||||
from app.utils.decorators import get_current_company_filter
|
||||
|
||||
company_limit = get_current_company_filter()
|
||||
if company_limit is not None:
|
||||
filter_conditions.append(MaterialBase.company_name == company_limit)
|
||||
|
||||
if filters:
|
||||
if filters.get('keyword'):
|
||||
kw = f"%{filters['keyword']}%"
|
||||
@ -799,14 +814,6 @@ class MaterialBaseService:
|
||||
MaterialBase.spec_model.ilike(kw),
|
||||
MaterialBase.company_name.ilike(kw)
|
||||
))
|
||||
# ============================================================
|
||||
# 【行级数据隔离】基于 JWT 多租户公司过滤
|
||||
# ============================================================
|
||||
from app.utils.decorators import get_current_company_filter
|
||||
|
||||
company_limit = get_current_company_filter()
|
||||
if company_limit is not None:
|
||||
filter_conditions.append(MaterialBase.company_name == company_limit)
|
||||
|
||||
category = filters.get('category')
|
||||
if category is not None and category != '':
|
||||
|
||||
@ -1295,6 +1295,9 @@ const handleExport = () => {
|
||||
exportLoading.value = true;
|
||||
const params = {
|
||||
keyword: queryParams.keyword,
|
||||
// ★ company 必须保留:后端 export_excel 不消费 filters 里的 company 键,
|
||||
// 但 get_current_company_filter() 会直接读 query string 上的 company ——
|
||||
// 跨域角色(超管 / WAREHOUSE_MGR)导出时按所选公司收窄范围全靠它。
|
||||
company: queryParams.company,
|
||||
category: queryParams.category,
|
||||
type: queryParams.type,
|
||||
|
||||
Reference in New Issue
Block a user