1
0
forked from erp-dev/erp

feat: prod clean

This commit is contained in:
2026-05-01 22:43:22 +08:00
parent 1afcfde151
commit d7b388e935
19 changed files with 1198 additions and 134 deletions

View File

@@ -135,6 +135,10 @@
"content_type": null,
"content_type_label": null,
"content_id": null,
"extra": {
"source": "wechat",
"ticket_no": "TK-001"
},
"has_ending_reply": false,
"can_reply": true,
"created_at": "2026-04-10T12:00:00+08:00",
@@ -155,6 +159,9 @@
"merchant_id": 10
},
"content": "已处理",
"extra": {
"attachment_ids": [1001, 1002]
},
"replied_at": "2026-04-10T12:10:00+08:00",
"ends_task": true,
"is_rejected": false,
@@ -165,6 +172,106 @@
}
```
### MissionWithReplies
`Mission` 结构基础上,额外返回 `replies` 字段:
```json
{
"id": 1,
"merchant": 10,
"description": "跟进客户问题",
"category": 1,
"category_name": "通用",
"is_urgent": false,
"is_completed": false,
"is_cancelled": false,
"notify_if_unreplied": false,
"unreplied_notify_interval_minutes": null,
"unreplied_notify_max_count": 5,
"unreplied_notify_sent_count": 0,
"unreplied_last_notified_at": null,
"cancelled_at": null,
"creator": {
"id": 20,
"name": "张三",
"merchant_id": 10
},
"cancelled_by": null,
"participants": [],
"content_type": 33,
"content_type_label": "printing.printingorder",
"content_id": 123,
"extra": {
"source": "printing-order"
},
"has_ending_reply": false,
"can_reply": true,
"created_at": "2026-04-10T12:00:00+08:00",
"updated_at": "2026-04-10T12:00:00+08:00",
"replies": [
{
"id": 100,
"mission": 1,
"merchant": 10,
"responder": {
"id": 20,
"name": "张三",
"merchant_id": 10
},
"content": "已处理",
"extra": {
"attachment_ids": [1001, 1002]
},
"replied_at": "2026-04-10T12:10:00+08:00",
"ends_task": false,
"is_rejected": false,
"rejected_by": null,
"rejected_at": null,
"created_at": "2026-04-10T12:10:00+08:00",
"updated_at": "2026-04-10T12:10:00+08:00"
}
]
}
```
### MissionLite
用于按印花订单查询任务时的轻量响应结构,不返回参与者、结束回应状态和回复列表:
```json
{
"id": 1,
"merchant": 10,
"description": "跟进客户问题",
"category": 1,
"category_name": "通用",
"is_urgent": false,
"is_completed": false,
"is_cancelled": false,
"notify_if_unreplied": false,
"unreplied_notify_interval_minutes": null,
"unreplied_notify_max_count": 5,
"unreplied_notify_sent_count": 0,
"unreplied_last_notified_at": null,
"cancelled_at": null,
"creator": {
"id": 20,
"name": "张三",
"merchant_id": 10
},
"cancelled_by": null,
"content_type": 33,
"content_type_label": "printing.printingorder",
"content_id": 123,
"extra": {
"source": "printing-order"
},
"created_at": "2026-04-10T12:00:00+08:00",
"updated_at": "2026-04-10T12:00:00+08:00"
}
```
## 任务分类列表
- URL: `/api/v2/mission-categories/`
@@ -255,6 +362,7 @@
| `category` | int | 否 | 任务分类 ID不传时默认使用当前商户下名称为“通用”的分类不存在则自动创建 |
| `content_type` | int/null | 否 | Django ContentType ID必须与 `content_id` 同时提供或同时省略 |
| `content_id` | int/null | 否 | 关联业务对象 ID必须与 `content_type` 同时提供或同时省略 |
| `extra` | object/null | 否 | 任务扩展字段,原样保存为 JSON可传 `null` |
| `notify_if_unreplied` | boolean | 否 | 是否开启“未回复持续提醒”,默认 `false` |
| `unreplied_notify_interval_minutes` | int/null | 否 | 未回复提醒间隔(分钟);开启未回复提醒时必填 |
| `unreplied_notify_max_count` | int | 否 | 最大提醒次数,默认 `5` |
@@ -275,6 +383,10 @@
{
"description": "跟进客户问题",
"category": 1,
"extra": {
"source": "wechat",
"ticket_no": "TK-001"
},
"notify_if_unreplied": true,
"unreplied_notify_interval_minutes": 30,
"unreplied_notify_max_count": 5,
@@ -293,6 +405,44 @@
跨商户访问返回 `404`
## 按印花订单查询任务及回复
- URL: `/api/v2/missions/by-printing-order/<printing_order_id>/`
- Method: `GET`
查询参数:
| 参数 | 类型 | 说明 |
|------|------|------|
| `category_ids` | int[] / comma-separated string | 可选任务分类筛选。支持重复参数 `?category_ids=1&category_ids=2`,也支持逗号分隔 `?category_ids=1,2` |
| `include_details` | boolean | 是否返回完整详情,默认 `true`。传 `false` 时返回轻量结构,不带 `participants``has_ending_reply``can_reply``replies` |
说明:
- 只查询 `content_type=printing.printingorder``content_id=<printing_order_id>` 的任务
- 只返回当前登录员工所属商户下的任务
- `include_details=true` 时返回 `MissionWithReplies[]`
- `include_details=false` 时返回 `MissionLite[]`
- 完整模式下每个任务会内嵌其全部回复,按 `replied_at``id` 升序返回
- `Mission.extra``MissionReply.extra` 都会原样返回
- 该接口启用了 180 秒的低层缓存;缓存键会区分当前商户、`printing_order_id``category_ids``include_details`
- 在缓存有效期内,如果任务、参与者或回复刚发生变化,接口结果最多可能延迟约 3 分钟刷新
- 若该 `printing_order_id` 不属于当前商户,返回 `404`
请求示例:
```http
GET /api/v2/missions/by-printing-order/123/
GET /api/v2/missions/by-printing-order/123/?category_ids=1,2
GET /api/v2/missions/by-printing-order/123/?include_details=false
GET /api/v2/missions/by-printing-order/123/?category_ids=2&include_details=false
```
成功响应:
- `include_details=true``MissionWithReplies[]`
- `include_details=false``MissionLite[]`
## 更新任务
- URL: `/api/v2/missions/<mission_id>/`
@@ -306,6 +456,7 @@
| `category` | int | 任务分类 ID |
| `content_type` | int/null | 关联对象类型;必须与 `content_id` 同时提供 |
| `content_id` | int/null | 关联对象 ID必须与 `content_type` 同时提供 |
| `extra` | object/null | 任务扩展字段,原样保存为 JSON可传 `null` |
| `notify_if_unreplied` | boolean | 是否开启“未回复持续提醒” |
| `unreplied_notify_interval_minutes` | int/null | 未回复提醒间隔(分钟) |
| `unreplied_notify_max_count` | int | 最大提醒次数 |
@@ -360,10 +511,12 @@ HTTP 状态码:`405 Method Not Allowed`
|------|------|------|------|
| `content` | string | 是 | 回应内容 |
| `ends_task` | boolean | 否 | 是否结束任务,默认 `false` |
| `extra` | object/null | 否 | 回应扩展字段,原样保存为 JSON可传 `null` |
说明:
- `responder` 使用当前登录用户的 employee
- `extra` 由后端原样存储并原样返回,不做结构校验
- 如果 `ends_task=true`,后端会同步设置 `Mission.is_completed=true`
- 已取消任务、或已有有效结束回应的任务不允许继续回应

View File

@@ -0,0 +1,103 @@
# API v2 Shipment Delivery Photo 文档
本文档说明司机按出货单上传送达照片的 API。
## 数据结构
```json
{
"id": 1,
"shipment_id": 100,
"delivery_id": 20,
"photo": "https://image.yuwen.cloud/media/shipment_delivery_photos/demo.jpg",
"remark": "已送达并签收",
"created_by": 8,
"created_at": "2026-04-28T20:00:00+08:00",
"updated_at": "2026-04-28T20:00:00+08:00"
}
```
说明:
- `photo` 使用项目现有七牛存储。
- `shipment_id``delivery_id` 都是必填。
- 同一个 `shipment_id + delivery_id` 组合允许多次写入,不做唯一性限制。
- 后端会校验 `shipment.delivery_id == delivery_id`,不一致时拒绝写入。
## 列表查询
- URL: `/api/v2/shipment-delivery-photos/`
- Method: `GET`
查询参数:
| 参数 | 类型 | 说明 |
|------|------|------|
| `shipment_id` | int | 可选,按出货单筛选 |
| `delivery_id` | int | 可选,按送货单筛选 |
说明:
- 支持只传 `shipment_id`
- 支持只传 `delivery_id`
- 支持同时传两者,按 AND 过滤
成功响应:`ShipmentDeliveryPhoto[]`
## 创建送达照片
- URL: `/api/v2/shipment-delivery-photos/`
- Method: `POST`
- Content-Type: `multipart/form-data`
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `shipment` | int | 是 | 出货单 ID |
| `delivery` | int | 是 | 送货单 ID |
| `photo` | file | 是 | 送达照片 |
| `remark` | string | 否 | 备注 |
说明:
- `created_by` 由当前登录用户自动写入
- `shipment``delivery` 必须属于当前商户
- `delivery` 必须与 `shipment.delivery_id` 一致
成功响应:`201 Created`,返回 `ShipmentDeliveryPhoto`
## 详情查询
- URL: `/api/v2/shipment-delivery-photos/<photo_id>/`
- Method: `GET`
成功响应:`ShipmentDeliveryPhoto`
## 更新送达照片
- URL: `/api/v2/shipment-delivery-photos/<photo_id>/`
- Method: `PATCH` / `PUT`
- Content-Type: `multipart/form-data`
允许更新:
| 参数 | 类型 | 说明 |
|------|------|------|
| `shipment` | int | 出货单 ID |
| `delivery` | int | 送货单 ID |
| `photo` | file | 照片 |
| `remark` | string | 备注 |
说明:
- 更新时仍会执行 `shipment.delivery_id == delivery_id` 一致性校验
- `PATCH` 支持部分更新
- `PUT` 需要传完整字段
## 删除送达照片
- URL: `/api/v2/shipment-delivery-photos/<photo_id>/`
- Method: `DELETE`
成功响应:`204 No Content`