补全 PR3 Phase 2.4–2.7,列表 apply_data_scope、详情/CUD assert_row_in_data_scope,合同/报价主表支持 owner_user_id。 Co-authored-by: Cursor <cursoragent@cursor.com>
103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
"""CRM 数据权限辅助(负责人 owner_user_id + 标准 create_by/create_dept_id)。"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, Optional
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.data_scope import apply_data_scope, row_in_data_scope
|
|
|
|
CRM_OWNER_FIELD = "owner_user_id"
|
|
|
|
|
|
def crm_user_info(user: Optional[dict]) -> Optional[Dict[str, Any]]:
|
|
if not user:
|
|
return None
|
|
uid = (user.get("user_id") or user.get("id") or "").strip()
|
|
return {
|
|
"user_id": uid or None,
|
|
"role": user.get("role"),
|
|
"dept_id": user.get("dept_id") or user.get("region_id"),
|
|
"region_id": user.get("region_id") or user.get("dept_id"),
|
|
}
|
|
|
|
|
|
def apply_crm_owner_scope(query, model, user_info, db: Session, tenant_no: str):
|
|
if not user_info:
|
|
return query
|
|
return apply_data_scope(
|
|
query, model, user_info, db, tenant_no, owner_field=CRM_OWNER_FIELD
|
|
)
|
|
|
|
|
|
def apply_crm_create_by_scope(query, model, user_info, db: Session, tenant_no: str):
|
|
if not user_info:
|
|
return query
|
|
return apply_data_scope(query, model, user_info, db, tenant_no)
|
|
|
|
|
|
def ensure_crm_owner_row_in_scope(
|
|
db: Session, row, user_info, tenant_no: str, *, message: str = "无权访问该数据"
|
|
) -> None:
|
|
if not user_info or row is None:
|
|
return
|
|
if not row_in_data_scope(db, row, user_info, tenant_no, owner_field=CRM_OWNER_FIELD):
|
|
raise ValueError(message)
|
|
|
|
|
|
def ensure_crm_create_by_row_in_scope(
|
|
db: Session, row, user_info, tenant_no: str, *, message: str = "无权访问该数据"
|
|
) -> None:
|
|
if not user_info or row is None:
|
|
return
|
|
if not row_in_data_scope(db, row, user_info, tenant_no):
|
|
raise ValueError(message)
|
|
|
|
|
|
def ensure_crm_contact_row_in_scope(
|
|
db: Session, row, user_info, tenant_no: str, *, message: str = "无权访问该联系人"
|
|
) -> None:
|
|
"""联系人:create_by 在范围内,或关联客户在 owner 范围内。"""
|
|
if not user_info or row is None:
|
|
return
|
|
if row_in_data_scope(db, row, user_info, tenant_no):
|
|
return
|
|
customer_id = getattr(row, "customer_id", None) or ""
|
|
if customer_id:
|
|
from app.crud.crm.customer import get_customer
|
|
|
|
customer = get_customer(db, customer_id)
|
|
if customer and customer.tenant_no == tenant_no:
|
|
if row_in_data_scope(
|
|
db, customer, user_info, tenant_no, owner_field=CRM_OWNER_FIELD
|
|
):
|
|
return
|
|
raise ValueError(message)
|
|
|
|
|
|
def ensure_crm_customer_linked_row_in_scope(
|
|
db: Session,
|
|
row,
|
|
user_info,
|
|
tenant_no: str,
|
|
*,
|
|
customer_id: str = None,
|
|
message: str = "无权访问该数据",
|
|
) -> None:
|
|
"""客户子表(开票信息等):先校验关联客户 owner scope,否则校验 create_by。"""
|
|
if not user_info or row is None:
|
|
return
|
|
cid = customer_id or getattr(row, "customer_id", None) or ""
|
|
if cid:
|
|
from app.crud.crm.customer import get_customer
|
|
|
|
customer = get_customer(db, cid)
|
|
if customer and customer.tenant_no == tenant_no:
|
|
if row_in_data_scope(
|
|
db, customer, user_info, tenant_no, owner_field=CRM_OWNER_FIELD
|
|
):
|
|
return
|
|
if row_in_data_scope(db, row, user_info, tenant_no):
|
|
return
|
|
raise ValueError(message)
|