forked from erp-dev/erp
feat: bind employee to customer (v2)
This commit is contained in:
@@ -11,9 +11,11 @@ from api_v2.views import (
|
|||||||
PlateOrderBatchUpdateView,
|
PlateOrderBatchUpdateView,
|
||||||
BusinessObjectCloneView,
|
BusinessObjectCloneView,
|
||||||
)
|
)
|
||||||
|
from api_v2.views.basic_info import CustomerEmployeeBindingView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('users/quick-create/', QuickCreateEmployeeUserView.as_view(), name='api_v2_user_quick_create'),
|
path('users/quick-create/', QuickCreateEmployeeUserView.as_view(), name='api_v2_user_quick_create'),
|
||||||
|
path('customers/bind-employee/', CustomerEmployeeBindingView.as_view(), name='api_v2_customer_bind_employee'),
|
||||||
path('printing-jobs/by-customer/', PrintingJobByCustomerView.as_view(), name='api_v2_printing_job_by_customer'),
|
path('printing-jobs/by-customer/', PrintingJobByCustomerView.as_view(), name='api_v2_printing_job_by_customer'),
|
||||||
path('printing-jobs/batch-advance/preview/', PrintingJobBatchAdvancePreviewView.as_view(), name='api_v2_printing_job_batch_advance_preview'),
|
path('printing-jobs/batch-advance/preview/', PrintingJobBatchAdvancePreviewView.as_view(), name='api_v2_printing_job_batch_advance_preview'),
|
||||||
path('printing-jobs/batch-advance/', PrintingJobBatchAdvanceSubmitView.as_view(), name='api_v2_printing_job_batch_advance_submit'),
|
path('printing-jobs/batch-advance/', PrintingJobBatchAdvanceSubmitView.as_view(), name='api_v2_printing_job_batch_advance_submit'),
|
||||||
|
|||||||
86
api_v2/views/basic_info.py
Normal file
86
api_v2/views/basic_info.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
105
docs/api_v2_customer_employee_binding.md
Normal file
105
docs/api_v2_customer_employee_binding.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# 客户员工绑定 API
|
||||||
|
|
||||||
|
## 接口说明
|
||||||
|
|
||||||
|
将指定员工添加到指定客户的可见员工列表中(`Customer.visible_employees`)。
|
||||||
|
|
||||||
|
## 接口信息
|
||||||
|
|
||||||
|
- **URL**: `/api/v2/customers/bind-employee/`
|
||||||
|
- **方法**: `POST`
|
||||||
|
- **认证**: 需要登录(Bearer Token)
|
||||||
|
|
||||||
|
## 请求参数
|
||||||
|
|
||||||
|
| 参数名 | 类型 | 必填 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| customer_name | string | 是 | 客户名称 |
|
||||||
|
| employee_name | string | 是 | 员工姓名 |
|
||||||
|
|
||||||
|
## 请求示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "http://your-domain/api/v2/customers/bind-employee/" \
|
||||||
|
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"customer_name": "张三服装厂",
|
||||||
|
"employee_name": "李四"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## 响应说明
|
||||||
|
|
||||||
|
### 成功响应(201 Created)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "成功将员工 \"李四\" 添加到客户 \"张三服装厂\" 的可见列表",
|
||||||
|
"customer_id": 123,
|
||||||
|
"customer_name": "张三服装厂",
|
||||||
|
"employee_id": 456,
|
||||||
|
"employee_name": "李四"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 已存在响应(200 OK)
|
||||||
|
|
||||||
|
如果该员工已经在客户的可见列表中:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "员工 \"李四\" 已在客户 \"张三服装厂\" 的可见列表中",
|
||||||
|
"customer_id": 123,
|
||||||
|
"employee_id": 456
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 错误响应
|
||||||
|
|
||||||
|
#### 未找到数据(400 Bad Request)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "未找到名为 \"李四\" 的员工"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
或
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "未找到名为 \"张三服装厂\" 的客户"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 找到多条数据(403 Forbidden)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "找到多个名为 \"李四\" 的员工(3 个),请使用更精确的标识"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
或
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "找到多个名为 \"张三服装厂\" 的客户(2 个),请使用更精确的标识"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 参数验证失败(400 Bad Request)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"customer_name": ["该字段是必填项。"],
|
||||||
|
"employee_name": ["该字段是必填项。"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 该操作是**幂等的**:重复绑定同一对客户和员工不会报错,会返回 200 状态码
|
||||||
|
2. 如果客户或员工名称不唯一,系统会返回 403 错误,建议在数据库中确保名称唯一性
|
||||||
|
3. 绑定关系为多对多,一个客户可以有多个可见员工,一个员工也可以被多个客户可见
|
||||||
Reference in New Issue
Block a user