feat: 全模块公司隔离 + crossDomain权限码动态跨域控制
- get_current_company_filter: 新增_has_cross_domain_permission, 权限码替代硬编码 - 补全11个Service的get_current_company_filter调用(semi/product/service/outbound/bom/trans/scrap/summary) - base/search修复: search_material此前无隔离, 已补全 - get_current_company_filter兜底: JWT缺company_name时返回__NO_COMPANY__防止放行 - permission.py: _get_operator_company补全返回值, 修复权限页保存逻辑 - 新增crossDomain迁移脚本, element_type=element挂system_mgmt下
This commit is contained in:
@ -274,11 +274,12 @@ class OutboundService:
|
||||
raise e
|
||||
|
||||
@staticmethod
|
||||
def get_grouped_list(page=1, per_page=10, keyword=None, search_type='all', start_date=None, end_date=None):
|
||||
def get_grouped_list(page=1, per_page=10, keyword=None, search_type='all', start_date=None, end_date=None, company=None):
|
||||
"""
|
||||
查询出库记录(按出库单号分组),包含详细物品信息
|
||||
支持跨表搜索:单号、领用人、SKU、物料名称、规格型号
|
||||
search_type: all, no, name, sku, material_name, spec_model
|
||||
company: 可选的公司过滤参数
|
||||
"""
|
||||
# 日期补全:解决零点截断问题
|
||||
if end_date and len(str(end_date).strip()) == 10:
|
||||
@ -436,6 +437,44 @@ class OutboundService:
|
||||
else:
|
||||
keyword_conditions = None
|
||||
|
||||
# 【行级数据隔离】基于 JWT 多租户公司过滤
|
||||
# 通过三个库存表路径,找到匹配公司的出库单号(排除 trans_repair,因其无 MaterialBase 关联)
|
||||
from app.utils.decorators import get_current_company_filter
|
||||
|
||||
company_limit = get_current_company_filter()
|
||||
if company_limit is not None:
|
||||
buy_comp = db.session.query(TransOutbound.outbound_no).join(
|
||||
StockBuy, and_(
|
||||
TransOutbound.stock_id == StockBuy.id,
|
||||
TransOutbound.source_table == 'stock_buy'
|
||||
)
|
||||
).join(MaterialBase, StockBuy.base_id == MaterialBase.id).filter(
|
||||
MaterialBase.company_name == company_limit
|
||||
).subquery()
|
||||
|
||||
semi_comp = db.session.query(TransOutbound.outbound_no).join(
|
||||
StockSemi, and_(
|
||||
TransOutbound.stock_id == StockSemi.id,
|
||||
TransOutbound.source_table == 'stock_semi'
|
||||
)
|
||||
).join(MaterialBase, StockSemi.base_id == MaterialBase.id).filter(
|
||||
MaterialBase.company_name == company_limit
|
||||
).subquery()
|
||||
|
||||
prod_comp = db.session.query(TransOutbound.outbound_no).join(
|
||||
StockProduct, and_(
|
||||
TransOutbound.stock_id == StockProduct.id,
|
||||
TransOutbound.source_table == 'stock_product'
|
||||
)
|
||||
).join(MaterialBase, StockProduct.base_id == MaterialBase.id).filter(
|
||||
MaterialBase.company_name == company_limit
|
||||
).subquery()
|
||||
|
||||
comp_all = db.session.query(buy_comp.c.outbound_no).union(
|
||||
db.session.query(semi_comp.c.outbound_no),
|
||||
db.session.query(prod_comp.c.outbound_no)
|
||||
).subquery()
|
||||
|
||||
stmt = db.session.query(
|
||||
TransOutbound.outbound_no,
|
||||
func.max(TransOutbound.outbound_time).label('max_time')
|
||||
@ -447,6 +486,10 @@ class OutboundService:
|
||||
if start_date and end_date:
|
||||
stmt = stmt.filter(TransOutbound.outbound_time.between(start_date, end_date))
|
||||
|
||||
# 【行级数据隔离】应用公司过滤到主查询
|
||||
if company_limit is not None:
|
||||
stmt = stmt.filter(TransOutbound.outbound_no.in_(comp_all))
|
||||
|
||||
stmt = stmt.order_by(desc('max_time'))
|
||||
|
||||
# 使用 distinct 确保跨表查询不重复
|
||||
|
||||
Reference in New Issue
Block a user