forked from erp-dev/erp
182 lines
6.6 KiB
Python
182 lines
6.6 KiB
Python
from rest_framework import serializers, status
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from basic_info import models as basic_models
|
|
from basic_info.models import FrontendPage, FrontendPageTypeEnum
|
|
|
|
|
|
class CustomerEmployeeBindingSerializer(serializers.Serializer):
|
|
"""客户员工绑定序列化器"""
|
|
customer_name = serializers.CharField(max_length=100, help_text='客户名称')
|
|
employee_name = serializers.CharField(max_length=100, help_text='员工姓名')
|
|
|
|
|
|
class CustomerEmployeeBindingView(APIView):
|
|
"""
|
|
客户员工可见性绑定 API
|
|
|
|
将指定员工添加到指定客户的可见员工列表中。
|
|
|
|
POST /api/v2/customers/bind-employee/
|
|
"""
|
|
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
serializer = CustomerEmployeeBindingSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
employee_name = serializer.validated_data['employee_name']
|
|
customer_name = serializer.validated_data['customer_name']
|
|
|
|
# 查询员工
|
|
employees = basic_models.Employee.objects.filter(name=employee_name)
|
|
if employees.count() == 0:
|
|
return Response(
|
|
{'error': f'未找到名为 "{employee_name}" 的员工'},
|
|
status=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
if employees.count() > 1:
|
|
return Response(
|
|
{'error': f'找到多个名为 "{employee_name}" 的员工({employees.count()} 个),请使用更精确的标识'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
# 查询客户
|
|
customers = basic_models.Customer.objects.filter(name=customer_name)
|
|
if customers.count() == 0:
|
|
return Response(
|
|
{'error': f'未找到名为 "{customer_name}" 的客户'},
|
|
status=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
if customers.count() > 1:
|
|
return Response(
|
|
{'error': f'找到多个名为 "{customer_name}" 的客户({customers.count()} 个),请使用更精确的标识'},
|
|
status=status.HTTP_403_FORBIDDEN
|
|
)
|
|
|
|
# 建立绑定关系
|
|
employee = employees.first()
|
|
customer = customers.first()
|
|
|
|
# 检查是否已经绑定
|
|
if customer.visible_employees.filter(id=employee.id).exists():
|
|
return Response(
|
|
{
|
|
'message': f'员工 "{employee_name}" 已在客户 "{customer_name}" 的可见列表中',
|
|
'customer_id': customer.id,
|
|
'employee_id': employee.id,
|
|
},
|
|
status=status.HTTP_200_OK
|
|
)
|
|
|
|
# 添加绑定
|
|
customer.visible_employees.add(employee)
|
|
|
|
return Response(
|
|
{
|
|
'message': f'成功将员工 "{employee_name}" 添加到客户 "{customer_name}" 的可见列表',
|
|
'customer_id': customer.id,
|
|
'customer_name': customer.name,
|
|
'employee_id': employee.id,
|
|
'employee_name': employee.name,
|
|
},
|
|
status=status.HTTP_201_CREATED
|
|
)
|
|
|
|
|
|
class FrontendPageSerializer(serializers.ModelSerializer):
|
|
"""前端页面序列化器"""
|
|
parent_key = serializers.CharField(source='parent.key', read_only=True, allow_null=True)
|
|
|
|
class Meta:
|
|
model = FrontendPage
|
|
fields = ['key', 'label', 'page_type', 'parent_key', 'sort_order']
|
|
|
|
|
|
class MyVisiblePagesView(APIView):
|
|
"""
|
|
获取当前登录用户的可见页面 API
|
|
|
|
根据当前登录用户关联的员工岗位,返回其可见的前端页面列表。
|
|
授予主菜单会自动包含其所有子菜单。
|
|
|
|
GET /api/v2/me/visible-pages/
|
|
|
|
响应示例:
|
|
{
|
|
"employee_id": 1,
|
|
"employee_name": "张三",
|
|
"position_id": 2,
|
|
"position_title": "生产主管",
|
|
"visible_pages": [
|
|
{"key": "production", "label": "生产管理", "page_type": "main", "parent_key": null, "sort_order": 100},
|
|
{"key": "production-kanban", "label": "生产看板", "page_type": "sub", "parent_key": "production", "sort_order": 101}
|
|
],
|
|
"visible_keys": ["production", "production-kanban", "printing-order-list"]
|
|
}
|
|
"""
|
|
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
# 从 request.user 获取关联的员工
|
|
user = request.user
|
|
|
|
# 检查用户是否关联员工
|
|
if not hasattr(user, 'employee'):
|
|
return Response({
|
|
'employee_id': None,
|
|
'employee_name': None,
|
|
'position_id': None,
|
|
'position_title': None,
|
|
'visible_pages': [],
|
|
'visible_keys': [],
|
|
})
|
|
|
|
employee = user.employee
|
|
|
|
# 检查员工是否有岗位
|
|
if not employee.position:
|
|
return Response({
|
|
'employee_id': employee.id,
|
|
'employee_name': employee.name,
|
|
'position_id': None,
|
|
'position_title': None,
|
|
'visible_pages': [],
|
|
'visible_keys': [],
|
|
})
|
|
|
|
# 获取岗位直接授予的页面
|
|
granted_pages = employee.position.visible_pages.filter(is_active=True).select_related('parent')
|
|
|
|
# 计算所有可见页面(含子菜单继承)
|
|
visible_pages = []
|
|
visible_keys = set()
|
|
|
|
for page in granted_pages:
|
|
visible_pages.append(page)
|
|
visible_keys.add(page.key)
|
|
|
|
# 如果是主菜单,自动包含所有子菜单
|
|
if page.page_type == FrontendPageTypeEnum.MAIN:
|
|
children = page.children.filter(is_active=True).select_related('parent')
|
|
for child in children:
|
|
if child.key not in visible_keys:
|
|
visible_pages.append(child)
|
|
visible_keys.add(child.key)
|
|
|
|
# 按 sort_order 排序
|
|
visible_pages.sort(key=lambda p: (p.sort_order, p.id))
|
|
|
|
return Response({
|
|
'employee_id': employee.id,
|
|
'employee_name': employee.name,
|
|
'position_id': employee.position.id,
|
|
'position_title': employee.position.title,
|
|
'visible_pages': FrontendPageSerializer(visible_pages, many=True).data,
|
|
'visible_keys': sorted(visible_keys),
|
|
})
|