1
0
forked from erp-dev/erp

fix: added permission for plate_order and printing_order api

This commit is contained in:
2026-01-14 18:14:22 +08:00
parent fae667c965
commit cae0f8434e
17 changed files with 867 additions and 15 deletions

View File

@@ -0,0 +1,106 @@
"""
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