# API v2 成本模块接口文档 本文档面向前端,描述 `cost` 成本模块的 API。 ## 基本约定 - Base URL: `/api/v2` - 认证:所有接口都需要登录(JWT)。 - 人员身份:后端使用 `request.user.employee` 作为当前员工身份。 - 多商户隔离:所有类目、支出明细只允许访问当前员工所属商户的数据;可通过 `?merchant_id=` 参数跨商户查询(如果权限允许)。 - 时间格式:请求参数中的日期使用 `YYYY-MM-DD`(如 `2026-06-01`),响应中的日期时间使用 ISO 8601。 --- ## 1. 支出类目 ### 1.1 类目列表 ``` GET /api/v2/cost-categories/ ``` 查询参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `merchant_id` | int | 否 | 按商户筛选,不传则使用当前员工的商户 | 成功响应 `200`: ```json [ { "id": 1, "merchant_id": 1, "unique_key": "electricity", "name": "电费", "parent_id": null, "description": "每月电费支出", "created_at": "2026-06-06T10:00:00Z", "updated_at": "2026-06-06T10:00:00Z" } ] ``` ### 1.2 创建类目 ``` POST /api/v2/cost-categories/ ``` 请求体(JSON): | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `unique_key` | string | **是** | 唯一标识键,同商户不可重复,如 `electricity` | | `name` | string | **是** | 类目名称 | | `parent_id` | int | 否 | 父类目 ID,用于层级 | | `description` | string | 否 | 描述 | 请求示例: ```json { "unique_key": "electricity", "name": "电费", "description": "每月电费支出" } ``` 成功响应 `201`: ```json { "id": 1, "merchant_id": 1, "unique_key": "electricity", "name": "电费", "parent_id": null, "description": "每月电费支出", "created_at": "2026-06-06T10:00:00Z", "updated_at": "2026-06-06T10:00:00Z" } ``` 错误响应 `400`:缺少必填字段时返回校验错误。 ### 1.3 类目详情 ``` GET /api/v2/cost-categories/{category_id}/ ``` 成功响应 `200`:返回单个类目对象,结构同上。 错误响应 `404`:类目不存在或不属于当前商户。 ### 1.4 修改类目 ``` PUT /api/v2/cost-categories/{category_id}/ ``` 请求体(JSON,所有字段可选): | 字段 | 类型 | 说明 | |------|------|------| | `unique_key` | string | 唯一标识键 | | `name` | string | 类目名称 | | `parent_id` | int | 父类目 ID,传 `null` 清除 | | `description` | string | 描述 | 成功响应 `200`:返回更新后的类目对象。 ### 1.5 删除类目 ``` DELETE /api/v2/cost-categories/{category_id}/ ``` 成功响应 `204`(无响应体)。 错误响应 `404`:类目不存在或不属于当前商户。 --- ## 2. 支出明细 ### 2.1 支出明细列表 ``` GET /api/v2/cost-entries/ ``` 查询参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `merchant_id` | int | 否 | 按商户筛选 | | `category_id` | int | 否 | 按支出类目筛选 | | `start` | date | 否 | 发生日期起始,格式 `YYYY-MM-DD` | | `end` | date | 否 | 发生日期截止,格式 `YYYY-MM-DD` | 默认按 `occurred_at` 降序排列。 成功响应 `200`: ```json [ { "id": 1, "merchant_id": 1, "category_id": 1, "category_name": "电费", "amount": "350.00", "occurred_at": "2026-06-01", "operator_id": 12, "image1": "", "image2": "", "source_module": "", "source_id": "", "remarks": "六月份电费", "created_at": "2026-06-06T10:00:00Z", "updated_at": "2026-06-06T10:00:00Z" } ] ``` 字段说明: | 字段 | 类型 | 说明 | |------|------|------| | `amount` | string | 金额(Decimal 转字符串,前端展示时注意格式化) | | `occurred_at` | string | 发生日期,`YYYY-MM-DD` | | `operator_id` | int | 经办人 ID,自动从当前登录用户获取 | | `image1` | string | 凭证图片 URL(七牛云 CDN),无则为空字符串 | | `image2` | string | 备用凭证图片 URL,无则为空字符串 | | `source_module` | string | 来源模块名,手工录入时为空 | | `source_id` | string | 来源记录 ID,手工录入时为空 | ### 2.2 创建支出明细 ``` POST /api/v2/cost-entries/ ``` Content-Type: `multipart/form-data`(支持图片上传)或 `application/json` 请求体: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `category_id` | int | **是** | 支出类目 ID | | `amount` | decimal | **是** | 金额,如 `"350.00"` | | `occurred_at` | date | **是** | 发生日期,`YYYY-MM-DD` | | `image1` | file | 否 | 凭证图片 | | `image2` | file | 否 | 备用凭证图片 | | `source_module` | string | 否 | 来源模块名 | | `source_id` | string | 否 | 来源记录 ID | | `remarks` | string | 否 | 备注 | 请求示例(JSON): ```json { "category_id": 1, "amount": "350.00", "occurred_at": "2026-06-01", "remarks": "六月份电费" } ``` 成功响应 `201`:返回创建的支出明细对象。 错误响应 `400`:校验失败。 错误响应 `404`:`category_id` 不存在或不属于当前商户。 ### 2.3 支出明细详情 ``` GET /api/v2/cost-entries/{entry_id}/ ``` 成功响应 `200`:返回单个支出明细对象,含 `category_name`。 错误响应 `404`:明细不存在或不属于当前商户。 ### 2.4 修改支出明细 ``` PUT /api/v2/cost-entries/{entry_id}/ ``` Content-Type: `multipart/form-data` 或 `application/json` 请求体(所有字段可选): | 字段 | 类型 | 说明 | |------|------|------| | `category_id` | int | 切换类目 | | `amount` | decimal | 金额 | | `occurred_at` | date | 发生日期 | | `image1` | file | 凭证图片 | | `image2` | file | 备用凭证图片 | | `source_module` | string | 来源模块名 | | `source_id` | string | 来源记录 ID | | `remarks` | string | 备注 | 成功响应 `200`:返回更新后的支出明细对象。 ### 2.5 删除支出明细 ``` DELETE /api/v2/cost-entries/{entry_id}/ ``` 成功响应 `204`。 错误响应 `404`:明细不存在或不属于当前商户。 --- ## 3. 按类目汇总 ``` GET /api/v2/cost-summary/by-category/ ``` 查询参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `merchant_id` | int | 否 | 按商户筛选 | | `start` | date | 否 | 发生日期起始 | | `end` | date | 否 | 发生日期截止 | 按 `total_amount` 降序排列。 成功响应 `200`: ```json { "merchant_id": 1, "start_date": "2026-06-01", "end_date": "2026-06-30", "results": [ { "category_id": 1, "category_name": "电费", "category_key": "electricity", "total_amount": "500.00", "entry_count": 2 }, { "category_id": 2, "category_name": "水费", "category_key": "water", "total_amount": "80.00", "entry_count": 1 } ] } ``` 字段说明: | 字段 | 类型 | 说明 | |------|------|------| | `total_amount` | string | 该类别在查询时间段内的总金额 | | `entry_count` | integer | 该类别在查询时间段内的记录数 | | `category_key` | string | 类目唯一键,可用于前端做图表的 key 映射 | --- ## 快速参考 | Method | URL | 说明 | |--------|-----|------| | GET | `/api/v2/cost-categories/` | 类目列表 | | POST | `/api/v2/cost-categories/` | 创建类目 | | GET | `/api/v2/cost-categories/{id}/` | 类目详情 | | PUT | `/api/v2/cost-categories/{id}/` | 修改类目 | | DELETE | `/api/v2/cost-categories/{id}/` | 删除类目 | | GET | `/api/v2/cost-entries/` | 支出明细列表 | | POST | `/api/v2/cost-entries/` | 创建支出明细 | | GET | `/api/v2/cost-entries/{id}/` | 支出明细详情 | | PUT | `/api/v2/cost-entries/{id}/` | 修改支出明细 | | DELETE | `/api/v2/cost-entries/{id}/` | 删除支出明细 | | GET | `/api/v2/cost-summary/by-category/` | 按类目汇总 |