Files
billai/server/README.md

488 lines
11 KiB
Markdown
Raw Permalink 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.
# BillAI 服务器 API 文档
## 概述
BillAI 服务器是一个基于 Go 的后端服务,用于处理账单的上传、清洗、分析和存储。提供 REST API 接口供前端调用。
**服务地址**: `http://localhost:8080`
---
## API 接口列表
### 1. 健康检查
**端点**: `GET /health`
**功能**: 检查服务器健康状态
**参数**: 无
**响应示例**:
```json
{
"status": "ok",
"version": "1.0.0"
}
```
---
## 账单管理 API
### 2. 上传账单文件
**端点**: `POST /api/upload`
**功能**: 上传支付宝或微信账单文件进行清洗和分析
**请求方式**: `multipart/form-data`
**请求参数**:
| 参数名 | 类型 | 必需 | 说明 |
|-------|------|------|------|
| file | File | ✓ | 账单文件CSV格式 |
| type | string | ✓ | 账单类型:`alipay``wechat` |
| format | string | - | 输出格式:`csv``json`(默认: csv |
| year | number | - | 账单年份(用于数据验证) |
| month | number | - | 账单月份(用于数据验证) |
**响应示例** (成功):
```json
{
"result": true,
"message": "账单处理完成",
"data": {
"bill_type": "alipay",
"raw_count": 50,
"cleaned_count": 48,
"duplicate_count": 2,
"needs_review_count": 5,
"file_name": "20260110_150405_alipay_1.csv"
}
}
```
**响应示例** (全部重复):
```json
{
"result": true,
"message": "文件中的 50 条记录全部已存在,无需重复导入",
"data": {
"bill_type": "alipay",
"raw_count": 0,
"cleaned_count": 0,
"duplicate_count": 50
}
}
```
**响应示例** (失败):
```json
{
"result": false,
"message": "账单类型无效,仅支持 alipay 或 wechat"
}
```
---
### 3. 获取账单列表
**端点**: `GET /api/bills`
**功能**: 获取清洗后的账单数据,支持分页、筛选和排序
**请求参数** (Query):
| 参数名 | 类型 | 必需 | 说明 |
|-------|------|------|------|
| page | number | - | 页码从1开始默认: 1 |
| page_size | number | - | 每页数量(默认: 20最大: 100 |
| start_date | string | - | 开始日期YYYY-MM-DD 格式) |
| end_date | string | - | 结束日期YYYY-MM-DD 格式) |
| category | string | - | 交易分类筛选 |
| type | string | - | 账单来源:`alipay``wechat``manual` |
| income_expense | string | - | 收支类型:`收入``支出` |
**响应示例**:
```json
{
"result": true,
"data": {
"total": 150,
"page": 1,
"page_size": 20,
"pages": 8,
"total_expense": 5250.50,
"total_income": 8000.00,
"bills": [
{
"_id": "507f1f77bcf86cd799439011",
"bill_type": "alipay",
"transaction_id": "2021123456789",
"merchant_order_no": "2021123456",
"time": "2026-01-10T10:30:00Z",
"category": "餐饮美食",
"merchant": "星巴克",
"description": "咖啡",
"income_expense": "支出",
"amount": 28.00,
"pay_method": "支付宝",
"status": "交易成功",
"remark": "员工补贴",
"review_level": "",
"created_at": "2026-01-10T10:30:00Z",
"updated_at": "2026-01-10T10:30:00Z",
"source_file": "20260110_150405_alipay_1.csv",
"upload_batch": "20260110_150405"
}
]
}
}
```
**错误响应**:
```json
{
"result": false,
"message": "数据库未连接"
}
```
---
### 4. 手动创建账单
**端点**: `POST /api/bills/manual`
**功能**: 手动添加单条或批量账单,支持去重
**请求方式**: `application/json`
**请求体**:
```json
{
"bills": [
{
"time": "2026-01-10 14:30:00",
"category": "餐饮美食",
"merchant": "测试餐厅",
"description": "午餐",
"income_expense": "支出",
"amount": 50.00,
"pay_method": "支付宝",
"status": "交易成功",
"remark": "测试账单"
}
]
}
```
**请求参数说明**:
| 参数名 | 类型 | 必需 | 说明 |
|-------|------|------|------|
| bills | Array | ✓ | 账单数组 |
| bills[].time | string | ✓ | 交易时间(格式: `YYYY-MM-DD HH:mm:ss` |
| bills[].category | string | ✓ | 交易分类 |
| bills[].income_expense | string | ✓ | 收支类型:`收入``支出` |
| bills[].amount | number | ✓ | 金额(>0 |
| bills[].merchant | string | - | 交易对方(可选) |
| bills[].description | string | - | 商品说明 |
| bills[].pay_method | string | - | 支付方式 |
| bills[].status | string | - | 交易状态(默认: `交易成功` |
| bills[].remark | string | - | 备注 |
**响应示例** (成功):
```json
{
"result": true,
"message": "创建成功",
"data": {
"success": 1,
"failed": 0,
"duplicates": 0
}
}
```
**响应示例** (部分失败):
```json
{
"result": true,
"message": "创建成功",
"data": {
"success": 3,
"failed": 1,
"duplicates": 0
}
}
```
**错误响应**:
```json
{
"result": false,
"message": "时间格式错误: 2026-01-10"
}
```
---
### 5. 获取需要复核的记录
**端点**: `GET /api/review`
**功能**: 获取清洗过程中标记为需要人工复核的记录
**请求参数** (Query):
| 参数名 | 类型 | 必需 | 说明 |
|-------|------|------|------|
| file | string | ✓ | 输出文件名(来自上传接口返回值) |
| page | number | - | 页码(默认: 1 |
| page_size | number | - | 每页数量(默认: 20 |
**响应示例**:
```json
{
"result": true,
"data": {
"total": 5,
"page": 1,
"page_size": 20,
"high_count": 2,
"low_count": 3,
"records": [
{
"row": 15,
"time": "2026-01-10 10:30:00",
"merchant": "未知商户",
"amount": 100.00,
"category": "未分类",
"review_level": "HIGH",
"issue": "无法识别的商户名称",
"suggestion": "请手动确认或修改商户名称"
}
]
}
}
```
---
### 6. 获取月度统计数据
**端点**: `GET /api/monthly-stats`
**功能**: 获取每个月的收入、支出统计(不受日期筛选影响,返回全部月份数据)
**请求参数**: 无
**响应示例**:
```json
{
"result": true,
"data": [
{
"month": "2025-12",
"expense": 8234.50,
"income": 15000.00
},
{
"month": "2026-01",
"expense": 5250.50,
"income": 8000.00
}
]
}
```
**错误响应**:
```json
{
"result": false,
"message": "数据库未连接"
}
```
---
## 数据模型
### 账单数据 (CleanedBill)
```go
type CleanedBill struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
BillType string `bson:"bill_type" json:"bill_type"` // alipay/wechat/manual
TransactionID string `bson:"transaction_id" json:"transaction_id"`
MerchantOrderNo string `bson:"merchant_order_no" json:"merchant_order_no"`
Time time.Time `bson:"time" json:"time"`
Category string `bson:"category" json:"category"`
Merchant string `bson:"merchant" json:"merchant"`
Description string `bson:"description" json:"description"`
IncomeExpense string `bson:"income_expense" json:"income_expense"` // 收入/支出
Amount float64 `bson:"amount" json:"amount"`
PayMethod string `bson:"pay_method" json:"pay_method"`
Status string `bson:"status" json:"status"`
Remark string `bson:"remark" json:"remark"`
ReviewLevel string `bson:"review_level" json:"review_level"` // HIGH/LOW/""
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
SourceFile string `bson:"source_file" json:"source_file"`
UploadBatch string `bson:"upload_batch" json:"upload_batch"`
}
```
### 月度统计 (MonthlyStat)
```go
type MonthlyStat struct {
Month string `bson:"month" json:"month"` // YYYY-MM
Expense float64 `bson:"expense" json:"expense"` // 支出总额
Income float64 `bson:"income" json:"income"` // 收入总额
}
```
---
## 错误处理
所有 API 响应都遵循以下格式:
```json
{
"result": boolean,
"message": "错误或成功消息",
"data": {}
}
```
### 常见错误码
| HTTP 状态码 | result | 说明 |
|-----------|--------|------|
| 200 | true | 请求成功 |
| 200 | false | 业务逻辑错误(如参数不合法) |
| 400 | false | 请求参数错误 |
| 404 | false | 资源不存在 |
| 500 | false | 服务器内部错误 |
---
## 时区说明
- **存储**: 所有时间在数据库中按 **UTC 时区** 存储ISO 8601 格式)
- **输入**: 手动添加账单时,时间按 **本地时区** 解析(使用 `time.ParseInLocation`
- **输出**: API 返回的时间均为 ISO 8601 UTC 格式
### 时间格式
- 手动创建账单时: `YYYY-MM-DD HH:mm:ss`(本地时间)
- 日期筛选参数: `YYYY-MM-DD`(本地日期)
- API 返回时间: ISO 8601 UTC 格式(如 `2026-01-10T10:30:00Z`
---
## 使用示例
### 上传账单文件
```bash
curl -X POST http://localhost:8080/api/upload \
-F "file=@statement.csv" \
-F "type=alipay" \
-F "format=csv"
```
### 查询账单列表
```bash
curl "http://localhost:8080/api/bills?page=1&page_size=20&start_date=2026-01-01&end_date=2026-01-10&type=alipay"
```
### 手动添加账单
```bash
curl -X POST http://localhost:8080/api/bills/manual \
-H "Content-Type: application/json" \
-d '{
"bills": [
{
"time": "2026-01-10 14:30:00",
"category": "餐饮美食",
"merchant": "星巴克",
"income_expense": "支出",
"amount": 28.00,
"pay_method": "支付宝"
}
]
}'
```
### 获取月度统计
```bash
curl http://localhost:8080/api/monthly-stats
```
---
## 配置
服务器配置文件位于 `config.yaml`,主要配置项:
```yaml
server:
port: "8080"
mongodb:
uri: "mongodb://admin:password@localhost:27017"
database: "billai"
collections:
raw: "bills_raw"
cleaned: "bills_cleaned"
analyzer:
mode: "http" # http 或 process
url: "http://analyzer:8001"
```
---
## 开发信息
### 目录结构
```
server/
├── main.go # 程序入口
├── router/ # 路由配置
├── handler/ # 请求处理器
├── service/ # 业务逻辑
├── repository/ # 数据访问层
├── database/ # 数据库连接
├── model/ # 数据模型
├── adapter/ # 外部服务适配器
├── config/ # 配置管理
└── README.md # 本文件
```
### 主要依赖
- **Gin**: Web 框架
- **MongoDB Driver**: 数据库驱动
- **Go 1.21**: 运行环境
---
## 版本历史
| 版本 | 日期 | 说明 |
|-----|------|------|
| 1.0.0 | 2026-01-10 | 初始版本,支持账单上传、查询、手动添加和统计 |