1
0
forked from erp-dev/erp
Files
erpnew/docs/api_v1_customer_address_api_2026-07-07.md

225 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API v1 Customer Address API
## Scope
客户地址 API 用于维护客户的一对多地址资料。地址归属 `basic_info.Customer`,并通过 `merchant` 做商户隔离。
所有接口需要登录。普通员工只能访问自己可见客户的地址;拥有 `basic_info.view_all_customers` 权限的员工可以访问本商户全部客户地址superuser 可以访问全部数据。
## Data Model
| Field | Type | Description |
| --- | --- | --- |
| `id` | integer | 客户地址 ID |
| `merchant` | integer | 所属商户 ID创建时由后端根据客户自动写入 |
| `merchant_name` | string | 所属商户名称,只读 |
| `customer` | integer | 客户 ID |
| `customer_name` | string | 客户名称,只读 |
| `address` | string | 地址 |
| `contact_name` | string | 联系人,可为空字符串 |
| `contact_phone` | string | 联系电话,可为空字符串 |
| `area` | string | 地区,可为空字符串 |
| `coordinates` | string/null | 经纬度字符串,格式由调用方决定 |
| `is_default` | boolean | 是否默认地址 |
| `remark` | string | 备注,可为空字符串 |
| `extra` | object/null | 扩展 JSON |
| `created_by` | integer/null | 创建员工 ID只读 |
| `created_by_name` | string/null | 创建员工姓名,只读 |
| `deleted_at` | datetime/null | 软删除时间,只读 |
| `deleted_by` | integer/null | 删除员工 ID只读 |
| `deleted_by_name` | string/null | 删除员工姓名,只读 |
| `created_at` | datetime | 创建时间,只读 |
| `updated_at` | datetime | 更新时间,只读 |
## Endpoints
| Method | Path | Description |
| --- | --- | --- |
| GET | `/api/v1/customer-addresses/` | 查询客户地址列表 |
| POST | `/api/v1/customer-addresses/` | 创建客户地址 |
| GET | `/api/v1/customer-addresses/{id}/` | 查询客户地址详情 |
| PUT | `/api/v1/customer-addresses/{id}/` | 完整更新客户地址 |
| PATCH | `/api/v1/customer-addresses/{id}/` | 部分更新客户地址 |
| DELETE | `/api/v1/customer-addresses/{id}/` | 软删除客户地址 |
| POST | `/api/v1/customer-address/{id}/set-default/` | 将客户地址设为默认地址 |
## Visibility Rules
普通员工可访问的客户地址必须同时满足:
- 地址所属商户等于当前员工商户。
- 地址所属客户对当前员工可见。
客户可见性规则:
- `customer.created_by == 当前员工`
- 或当前员工在 `customer.visible_employees` 中。
权限例外:
- `basic_info.view_all_customers`:可访问本商户全部客户地址。
- superuser可访问全部客户地址。
创建地址时,`customer` 也必须在当前用户可访问范围内。`merchant` 不由前端传入,后端使用客户所属商户自动写入。
## Query Parameters
`GET /api/v1/customer-addresses/` 支持以下查询参数:
| Parameter | Description |
| --- | --- |
| `customer` | 按客户 ID 精确过滤 |
| `customer_name` | 按客户名称模糊过滤 |
| `address` | 按地址模糊过滤 |
| `contact_name` | 按联系人模糊过滤 |
| `contact_phone` | 按联系电话模糊过滤 |
| `area` | 按地区模糊过滤 |
| `is_default` | 按默认地址过滤,支持 `true/false/1/0/yes/no` |
| `include_deleted` | 是否包含软删除记录,支持 `true/false/1/0/yes/no` |
| `only_deleted` | 是否只查询软删除记录,支持 `true/false/1/0/yes/no` |
| `search` | 对客户名称、地址、联系人、电话、地区、备注做模糊搜索 |
| `ordering` | 排序字段,支持 `id``created_at``updated_at``is_default` 及其 `-` 倒序形式 |
| `limit` | 分页数量 |
| `offset` | 分页偏移 |
默认行为:
- 不传 `include_deleted``only_deleted` 时,只返回未删除地址。
- `only_deleted=true` 优先于 `include_deleted=true`
## Create
`POST /api/v1/customer-addresses/`
Request body:
```json
{
"customer": 3,
"address": "杭州市测试路 1 号",
"contact_name": "张三",
"contact_phone": "13800138000",
"area": "杭州",
"coordinates": "120.1,30.2",
"is_default": true,
"remark": "默认收货地址",
"extra": {
"source": "manual"
}
}
```
Success response: HTTP 201
```json
{
"id": 10,
"merchant": 1,
"merchant_name": "测试印花厂",
"customer": 3,
"customer_name": "客户A",
"address": "杭州市测试路 1 号",
"contact_name": "张三",
"contact_phone": "13800138000",
"area": "杭州",
"coordinates": "120.1,30.2",
"is_default": true,
"remark": "默认收货地址",
"extra": {
"source": "manual"
},
"created_by": 5,
"created_by_name": "业务员A",
"deleted_at": null,
"deleted_by": null,
"deleted_by_name": null,
"created_at": "2026-07-07T12:00:00Z",
"updated_at": "2026-07-07T12:00:00Z"
}
```
## Update
`PATCH /api/v1/customer-addresses/{id}/`
Example:
```json
{
"address": "杭州市更新路 2 号",
"contact_phone": "13900139000",
"coordinates": null
}
```
Notes:
- 不允许修改 `customer`
- 不允许修改 `merchant`
- `created_by``deleted_at``deleted_by` 为只读字段。
## Default Address
同一客户最多一个未删除默认地址。
以下操作会自动取消同一客户其他未删除地址的默认状态:
- 创建地址时传 `is_default=true`
- 更新地址时传 `is_default=true`
- 调用 `set-default` 接口。
`POST /api/v1/customer-address/{id}/set-default/`
Success response: HTTP 200返回更新后的地址对象。
如果地址已经软删除,返回 HTTP 400。
## Soft Delete
`DELETE /api/v1/customer-addresses/{id}/`
删除是软删除,不会物理删除记录。后端会写入:
- `deleted_at`
- `deleted_by`
- `is_default=false`
Success response: HTTP 204。
查询软删除记录:
```http
GET /api/v1/customer-addresses/?include_deleted=true
GET /api/v1/customer-addresses/?only_deleted=true
```
## Error Cases
| Condition | Status | Notes |
| --- | --- | --- |
| 未登录 | 401 | 全部接口需要登录 |
| 查询不可见地址详情 | 404 | 不暴露不可见数据存在性 |
| 给不可见客户创建地址 | 400 | `customer` 字段校验失败 |
| 修改 `customer` | 400 | 不允许地址跨客户移动 |
| 已删除地址设为默认 | 400 | 通过 `set-default` 接口返回校验错误 |
## Test Coverage
Dedicated tests:
```bash
docker compose exec -T -e DB_HOST=postgres -e DB_PORT=5432 web uv run python manage.py test api_v1.test_customer_address_api --keepdb --noinput
```
Covered behavior:
- 商户隔离和客户可见性。
- `visible_employees` 授权后可见。
- `basic_info.view_all_customers` 可访问本商户全部客户地址。
- 创建地址时自动写入 `merchant``created_by`
- 不可见客户创建地址失败。
- 默认地址互斥。
- `set-default` 接口互斥设置默认地址。
- 软删除和 `include_deleted` / `only_deleted` 查询。
- 常用过滤参数。