diff --git a/finance/views.py b/finance/views.py
index 22eb24c..980ad8c 100644
--- a/finance/views.py
+++ b/finance/views.py
@@ -1992,6 +1992,8 @@ class PaymentRequest(APIView):
payee_account = request.data.get('payee_account') # 收款方银行账号
payee_bank = request.data.get('payee_bank') # 收款方开户行
payment_description = request.data.get('payment_description') # 支付说明
+ payment_type = request.data.get('payment_type', '律所支付') # 支付方式(可选,保留字段,但不影响审批流程)
+ applicant = request.data.get('applicant') # 申请人(可选,如果前端传递则使用,否则从token获取)
approvers = request.data.get('approvers') # 审核人列表(可选,多人团队时需要,推荐:用户ID数组如[1,2,3],兼容:用户名数组)
# 兼容旧接口:如果传了 personincharge,转换为 approvers
personincharge = request.data.get('personincharge')
@@ -2003,7 +2005,7 @@ class PaymentRequest(APIView):
bankcard = request.data.get('bankcard') or payee_account
BankName = request.data.get('BankName') or payee_bank
- # 必填字段验证(申请人通过token获取,不需要验证)
+ # 必填字段验证
if not all([payment_reason or reason, amount, payee_name or payee, payee_account or bankcard, payee_bank or BankName, payment_description]):
missing_params = []
if not (payment_reason or reason):
@@ -2024,14 +2026,28 @@ class PaymentRequest(APIView):
'code': 1
}, status=status.HTTP_400_BAD_REQUEST)
- # 从token获取申请人
+ # 获取申请人:优先使用前端传递的applicant,如果没有则从token获取
+ applicant_user = None
token = request.META.get('token')
- try:
- applicant_user = User.objects.get(token=token, is_deleted=False)
- applicant = applicant_user.username
- except User.DoesNotExist:
- return Response({'status': 'error', 'message': '用户不存在或已被删除', 'code': 1},
- status=status.HTTP_401_UNAUTHORIZED)
+
+ if applicant:
+ # 如果前端传递了申请人,验证申请人是否存在
+ try:
+ applicant_user = User.objects.get(username=applicant, is_deleted=False)
+ except User.DoesNotExist:
+ return Response({'status': 'error', 'message': '申请人不存在或已被删除', 'code': 1},
+ status=status.HTTP_400_BAD_REQUEST)
+ else:
+ # 如果前端没有传递申请人,从token获取
+ if not token:
+ return Response({'status': 'error', 'message': '缺少参数:请提供applicant或token', 'code': 1},
+ status=status.HTTP_400_BAD_REQUEST)
+ try:
+ applicant_user = User.objects.get(token=token, is_deleted=False)
+ applicant = applicant_user.username
+ except User.DoesNotExist:
+ return Response({'status': 'error', 'message': '用户不存在或已被删除', 'code': 1},
+ status=status.HTTP_401_UNAUTHORIZED)
from datetime import datetime
now = datetime.now()
diff --git a/付款申请接口文档.md b/付款申请接口文档.md
new file mode 100644
index 0000000..58758a6
--- /dev/null
+++ b/付款申请接口文档.md
@@ -0,0 +1,344 @@
+# 付款申请接口文档
+
+## 概述
+
+付款申请接口用于创建新的付款申请单。申请人可以通过前端传递,也可以从token自动获取(优先使用前端传递的申请人),审批逻辑与离职逻辑一致,根据团队类型决定是否需要审批流程。
+
+## 接口地址
+
+**POST** `/finance/payment-request`
+
+## 请求头
+
+| 参数名 | 类型 | 必填 | 说明 |
+|--------|------|------|------|
+| token | String | 是 | 用户认证token(用于自动获取申请人) |
+
+## 请求参数
+
+### 必填参数
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| payment_reason | String | 付款事由 |
+| amount | String | 付款金额 |
+| payee_name | String | 收款方名称 |
+| payee_account | String | 收款方银行账号 |
+| payee_bank | String | 收款方开户行 |
+| payment_description | String | 支付说明 |
+
+### 可选参数
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| applicant | String | 申请人(可选)
- 如果前端传递,则使用传递的申请人
- 如果前端不传递,则从token自动获取
- **推荐**:前端传递申请人,便于灵活控制 |
+| times | String | 付款日期(格式:YYYY-MM-DD) |
+| approvers | Array/String | 审批人列表(团队类型时需要)
- 推荐格式:用户ID数组,如 `[1, 2, 3]` 或 `["1", "2", "3"]`
- 兼容格式:用户名数组,如 `["张三", "李四", "王五"]`
- 字符串格式:逗号分隔,如 `"1,2,3"` 或 `"张三,李四,王五"` |
+| payment_type | String | 支付方式(可选,默认:"律所支付")
- "律所支付"
- "自己账户支付" |
+
+### 兼容旧字段(可选)
+
+以下字段为兼容旧接口保留,建议使用新字段:
+
+| 参数名 | 类型 | 说明 |
+|--------|------|------|
+| reason | String | 付款理由(兼容字段,等同于payment_reason) |
+| payee | String | 收款人(兼容字段,等同于payee_name) |
+| bankcard | String | 银行卡(兼容字段,等同于payee_account) |
+| BankName | String | 开户行(兼容字段,等同于payee_bank) |
+| personincharge | String | 审批人(兼容字段,会自动转换为approvers) |
+
+## 审批逻辑
+
+### 团队类型判断
+
+系统会根据申请人的团队类型自动判断审批流程:
+
+1. **个人团队(personal/独立律师)**:
+ - 不触发审批流程
+ - 直接抄送财务
+ - 状态直接设为"已通过"
+
+2. **团队(team/团队律师)**:
+ - 需要审批流程
+ - 必须提供 `approvers` 参数(审批人列表)
+ - 按审批人顺序依次审批
+ - 最后一个审批人通过后,抄送财务
+ - 状态初始为"审核中"
+
+3. **无团队**:
+ - 默认按团队类型处理(需要审批)
+ - 必须提供 `approvers` 参数
+
+### 审批流程
+
+```
+提交申请 → 审批人1 → 审批人2 → ... → 审批人N → 财务 → 完成
+```
+
+- 每个审批人按顺序审核
+- 如果任一审批人拒绝,流程终止,状态设为"未通过"
+- 所有审批人通过后,自动抄送财务
+- 财务查看后,状态更新为"已通过"
+
+## 请求示例
+
+### 示例1:个人团队(不需要审批)
+
+```json
+{
+ "applicant": "张三",
+ "payment_reason": "案件代理费",
+ "amount": "10000",
+ "times": "2024-01-15",
+ "payee_name": "XX律师事务所",
+ "payee_account": "1234567890123456",
+ "payee_bank": "XX银行XX支行",
+ "payment_description": "支付案件代理费用"
+}
+```
+
+**说明**:
+- 前端传递了 `applicant` 参数,使用传递的申请人
+- 个人团队不需要提供 `approvers`
+- 系统自动判断为个人团队,直接抄送财务
+- 状态直接设为"已通过"
+
+**注意**:如果不传递 `applicant`,系统会从token自动获取申请人
+
+### 示例2:团队类型(需要审批)
+
+```json
+{
+ "applicant": "李四",
+ "payment_reason": "差旅费",
+ "amount": "5000",
+ "payee_name": "XX酒店",
+ "payee_account": "9876543210987654",
+ "payee_bank": "XX银行XX支行",
+ "payment_description": "支付差旅住宿费",
+ "approvers": [1, 2, 3]
+}
+```
+
+**说明**:
+- 前端传递了 `applicant` 参数,使用传递的申请人
+- 团队类型必须提供 `approvers` 参数
+- `approvers` 可以是用户ID数组或用户名数组
+- 系统会按顺序创建审批流程
+
+### 示例3:使用用户名数组(兼容格式)
+
+```json
+{
+ "payment_reason": "办公用品采购",
+ "amount": "3000",
+ "payee_name": "XX办公用品公司",
+ "payee_account": "1111222233334444",
+ "payee_bank": "XX银行XX支行",
+ "payment_description": "采购办公用品",
+ "approvers": ["张三", "李四", "王五"]
+}
+```
+
+### 示例4:使用字符串格式(兼容格式)
+
+```json
+{
+ "payment_reason": "案件费用",
+ "amount": "8000",
+ "payee_name": "XX公司",
+ "payee_account": "5555666677778888",
+ "payee_bank": "XX银行XX支行",
+ "payment_description": "支付案件相关费用",
+ "approvers": "1,2,3"
+}
+```
+
+## 响应数据
+
+### 成功响应
+
+**HTTP状态码**:200
+
+```json
+{
+ "message": "提交成功",
+ "code": 0,
+ "data": {
+ "id": 1,
+ "state": "审核中",
+ "approval_id": 10,
+ "needs_approval": true,
+ "team_type": "team",
+ "team_name": "XX团队"
+ }
+}
+```
+
+### 响应字段说明
+
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| id | Integer | 付款申请记录ID |
+| state | String | 付款申请状态
- "审核中":正在审批流程中
- "已通过":审批完成
- "未通过":审批被拒绝 |
+| approval_id | Integer | 审批记录ID(如果创建了审批记录)
个人团队可能为null |
+| needs_approval | Boolean | 是否需要审批
- `true`:需要审批(团队类型)
- `false`:不需要审批(个人团队)
**前端用这个字段判断是团队还是个人** |
+| team_type | String | 团队类型
- "team":团队类型
- "personal":个人团队
- `null`:无团队
**前端用这个字段判断团队类型** |
+| team_name | String | 团队名称
- 如果有团队,返回团队名称
- 如果没有团队,返回 `null` |
+
+### 错误响应
+
+**HTTP状态码**:400/401
+
+```json
+{
+ "status": "error",
+ "message": "缺少必填参数: payment_reason(付款事由), amount(付款金额)",
+ "code": 1
+}
+```
+
+## 错误码说明
+
+| 错误码 | 说明 |
+|--------|------|
+| 1 | 参数错误或业务逻辑错误 |
+| 401 | 用户认证失败(token无效或用户不存在) |
+
+## 常见错误
+
+### 1. 缺少必填参数
+
+**错误信息**:`缺少必填参数: payment_reason(付款事由), amount(付款金额)`
+
+**解决方案**:检查请求参数,确保所有必填字段都已提供
+
+### 2. 用户不存在
+
+**错误信息**:`用户不存在或已被删除` 或 `申请人不存在或已被删除`
+
+**解决方案**:
+- 如果传递了 `applicant` 参数,检查申请人用户名是否正确
+- 如果没有传递 `applicant`,检查token是否有效,确保用户账号未被删除
+
+### 2.1. 缺少申请人或token
+
+**错误信息**:`缺少参数:请提供applicant或token`
+
+**解决方案**:确保传递了 `applicant` 参数,或者请求头中包含有效的 `token`
+
+### 3. 缺少审批人(团队类型)
+
+**错误信息**:`XX团队需要指定审批人,请提供approvers参数(推荐:用户ID数组如[1,2,3],兼容:用户名数组)`
+
+**解决方案**:
+- 如果是团队类型,必须提供 `approvers` 参数
+- 确保审批人列表不为空
+- 确保审批人用户ID或用户名正确
+
+### 4. 审批人不存在
+
+**错误信息**:`部分审批人不存在或已被删除`
+
+**解决方案**:检查审批人列表中的用户ID或用户名是否正确
+
+## 前端判断逻辑
+
+前端可以通过返回数据中的字段判断团队类型和是否需要审批:
+
+```javascript
+// 判断是否需要审批
+if (response.data.needs_approval) {
+ // 需要审批(团队类型)
+ // 显示审批人选择组件
+ // 要求用户填写审批人列表
+} else {
+ // 不需要审批(个人团队)
+ // 隐藏审批人选择组件
+ // 直接提交即可
+}
+
+// 判断团队类型
+if (response.data.team_type === 'team') {
+ // 团队类型
+ console.log('团队类型,需要审批');
+} else if (response.data.team_type === 'personal') {
+ // 个人团队
+ console.log('个人团队,不需要审批');
+} else {
+ // 无团队
+ console.log('无团队,默认需要审批');
+}
+```
+
+## 审批流程说明
+
+### 1. 提交申请
+
+调用 `/finance/payment-request` 接口提交付款申请。
+
+### 2. 审批处理
+
+审批人通过 `/user/approval_processing` 接口处理审批:
+
+```json
+{
+ "id": 10,
+ "type": "付款申请",
+ "state": "已通过"
+}
+```
+
+### 3. 查看待办
+
+审批人可以通过 `/user/roxyexhibition` 接口查看待办列表。
+
+### 4. 查看申请列表
+
+通过 `/finance/PaymentDisplay` 接口查看付款申请列表。
+
+## 数据模型
+
+### Payment 模型字段
+
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| payment_reason | TextField | 付款事由 |
+| amount | CharField | 付款金额 |
+| times | CharField | 付款日期(可选) |
+| payee_name | CharField | 收款方名称 |
+| payee_account | CharField | 收款方银行账号 |
+| payee_bank | CharField | 收款方开户行 |
+| applicant | CharField | 申请人(自动从token获取) |
+| payment_description | TextField | 支付说明 |
+| payment_type | CharField | 支付方式(可选) |
+| submit_tiem | CharField | 提交时间 |
+| state | CharField | 状态(审核中/已通过/未通过) |
+| approvers_order | TextField | 审核人顺序(JSON格式) |
+| is_deleted | BooleanField | 软删除标记 |
+
+## 注意事项
+
+1. **申请人获取**:
+ - **推荐**:前端传递 `applicant` 参数,便于灵活控制
+ - **备选**:如果不传递 `applicant`,系统会从token自动获取申请人
+ - 如果传递了 `applicant`,系统会验证申请人是否存在
+2. **审批人必填**:团队类型必须提供 `approvers` 参数,否则会返回错误
+3. **审批顺序**:审批人列表的顺序就是审批顺序,请确保顺序正确
+4. **状态管理**:个人团队直接设为"已通过",团队类型初始为"审核中"
+5. **兼容性**:接口支持旧字段格式,但建议使用新字段名称
+
+## 相关接口
+
+- **审批处理**:`POST /user/approval_processing`
+- **查看待办**:`POST /user/roxyexhibition`
+- **查看申请列表**:`POST /finance/PaymentDisplay`
+- **编辑付款申请**:`POST /finance/editPayment`
+- **删除付款申请**:`POST /finance/deletePayment`
+
+## 更新日志
+
+- 2024-01-XX:优化接口,申请人通过token自动获取,审批逻辑与离职逻辑一致
+- 2024-01-XX:添加审批人字段,支持团队类型审批流程
+- 2024-01-XX:返回数据中添加团队类型信息,方便前端判断