forked from erp-dev/erp
107 lines
3.5 KiB
Python
107 lines
3.5 KiB
Python
"""
|
||
Printing API Mixins
|
||
|
||
提供客户可见性过滤等通用功能
|
||
"""
|
||
from django.db.models import Q
|
||
|
||
|
||
class CustomerVisibilityFilterMixin:
|
||
"""
|
||
基于客户可见性的查询过滤 Mixin
|
||
|
||
适用于关联了 Customer 的模型(PlateOrder, PrintingOrder, PrintingJob)
|
||
|
||
使用方式:
|
||
1. 在 ViewSet 中继承此 Mixin(放在 LimitedModelViewSet 之前)
|
||
2. 设置 customer_field 指定关联 customer 的字段路径
|
||
3. 设置 view_all_permission 指定突破限制的权限名
|
||
|
||
可见性规则:
|
||
- superuser: 无限制
|
||
- 有 view_all_permission 权限: 无限制
|
||
- 订单.customer 为空: 全员可见(同 merchant)
|
||
- 订单.customer 不为空: 按客户绑定关系判断
|
||
- customer.created_by == 当前员工 → 可见
|
||
- 当前员工 in customer.visible_employees → 可见
|
||
"""
|
||
# 子类需要指定:通过哪个字段关联到 customer
|
||
customer_field = 'customer' # PlateOrder/PrintingOrder 直接关联
|
||
# customer_field = 'printing_order__customer' # PrintingJob 间接关联
|
||
|
||
# 子类需要指定:突破限制的权限名(完整格式如 'printing.view_all_plateorders')
|
||
view_all_permission = None
|
||
|
||
def can_bypass_customer_visibility(self) -> bool:
|
||
"""
|
||
是否可以突破客户可见性限制
|
||
|
||
注意:view_all_customers 权限不影响此判断
|
||
"""
|
||
user = self.request.user
|
||
if user.is_superuser:
|
||
return True
|
||
# 仅检查订单级别的专属权限
|
||
if self.view_all_permission and user.has_perm(self.view_all_permission):
|
||
return True
|
||
return False
|
||
|
||
def filter_by_customer_visibility(self, queryset):
|
||
"""
|
||
应用客户可见性过滤
|
||
|
||
Returns:
|
||
过滤后的 queryset
|
||
"""
|
||
if self.can_bypass_customer_visibility():
|
||
return queryset
|
||
|
||
user = self.request.user
|
||
emp = getattr(user, 'employee', None)
|
||
if emp is None:
|
||
return queryset.none()
|
||
|
||
# 可见的客户条件:
|
||
# 1. customer.created_by == 当前员工
|
||
# 2. 当前员工 in customer.visible_employees
|
||
visible_customer_filter = (
|
||
Q(**{f'{self.customer_field}__created_by': emp}) |
|
||
Q(**{f'{self.customer_field}__visible_employees': emp})
|
||
)
|
||
|
||
# customer 为空时全员可见(同 merchant 下)
|
||
no_customer_filter = Q(**{f'{self.customer_field}__isnull': True})
|
||
|
||
return queryset.filter(visible_customer_filter | no_customer_filter).distinct()
|
||
|
||
def filter_by_merchant(self, queryset):
|
||
"""
|
||
应用 merchant 隔离过滤
|
||
|
||
Returns:
|
||
过滤后的 queryset,如果用户没有关联 merchant 则返回空
|
||
"""
|
||
user = self.request.user
|
||
if user.is_superuser:
|
||
return queryset
|
||
|
||
emp = getattr(user, 'employee', None)
|
||
if emp is None or emp.merchant is None:
|
||
return queryset.none()
|
||
|
||
return queryset.filter(merchant=emp.merchant)
|
||
|
||
def get_queryset(self):
|
||
"""
|
||
重写 get_queryset,应用 merchant 隔离和客户可见性过滤
|
||
"""
|
||
queryset = super().get_queryset()
|
||
|
||
# 1. merchant 隔离(必须)
|
||
queryset = self.filter_by_merchant(queryset)
|
||
|
||
# 2. 客户可见性过滤
|
||
queryset = self.filter_by_customer_visibility(queryset)
|
||
|
||
return queryset
|