Files
billai/server/adapter/adapter.go
cheliangzhao e2e1beb6f7 feat: implement cross-batch Alipay refund reconciliation
When a refund row in an uploaded Alipay bill has no matching expense
row in the same batch (because the original purchase was uploaded in a
prior batch), the refund is now reconciled against the stored record in
bills_cleaned rather than being silently discarded.

Changes:
- analyzer/cleaners/base.py: add unresolved_refunds list to BaseCleaner
- analyzer/cleaners/alipay.py: _aggregate_refunds stores full refund
  metadata (dict); _process_expenses tracks matched keys and populates
  self.unresolved_refunds for unmatched refunds
- analyzer/server.py: thread unresolved_refunds through do_clean,
  CleanResponse, and both /clean endpoints
- server/adapter/adapter.go: add UnresolvedRefund type and field to CleanResult
- server/adapter/http/cleaner.go: deserialize unresolved_refunds from
  Python response and populate CleanResult
- server/repository/repository.go: add ReconcileRefund to BillRepository interface
- server/repository/mongo/repository.go: implement ReconcileRefund —
  full refund soft-deletes the bill, partial refund reduces amount and
  appends remark with original amount and refund order number
- server/handler/upload.go: capture clean result and call ReconcileRefund
  for each unresolved refund after saving cleaned bills
- server/model/response.go: add ReconciledRefundCount to UploadData

Also: add CLAUDE.md (@AGENTS.md), update AGENTS.md, fix DailyTrendChart
missing-date gap by filling zero-expense dates in daily map.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:29:47 +08:00

52 lines
1.9 KiB
Go
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.
// Package adapter 定义与外部系统交互的抽象接口
// 这样可以方便后续更换通信方式(如从子进程调用改为 HTTP/gRPC/消息队列等)
package adapter
// CleanOptions 清洗选项
type CleanOptions struct {
Year string // 年份筛选
Month string // 月份筛选
Start string // 起始日期
End string // 结束日期
Format string // 输出格式: csv/json
}
// CleanResult 清洗结果
type CleanResult struct {
BillType string // 检测到的账单类型: alipay/wechat/jd
Output string // 脚本输出信息
UnresolvedRefunds []UnresolvedRefund // 本次清洗未在同批次内匹配到对应支出的退款
}
// UnresolvedRefund 本次清洗未在同批次内匹配到对应支出的退款
type UnresolvedRefund struct {
OrderNo string // 原订单号(去除退款后缀)
MerchantOrderNo string // 商家订单号(备用匹配字段)
RefundOrderNo string // 退款行自身的完整订单号(用于备注追溯)
Amount float64 // 退款金额
Time string // 退款时间
Merchant string // 交易对方
Description string // 商品说明
}
// ConvertResult 格式转换结果
type ConvertResult struct {
OutputPath string // 转换后的文件路径
BillType string // 检测到的账单类型: alipay/wechat/jd
}
// Cleaner 账单清洗器接口
// 负责将原始账单数据清洗为标准格式
type Cleaner interface {
// Clean 执行账单清洗
// inputPath: 输入文件路径
// outputPath: 输出文件路径
// opts: 清洗选项
Clean(inputPath, outputPath string, opts *CleanOptions) (*CleanResult, error)
// Convert 转换账单文件格式xlsx -> csv处理 GBK 编码等)
// inputPath: 输入文件路径
// 返回: 转换后的文件路径, 检测到的账单类型, 错误
Convert(inputPath string) (outputPath string, billType string, err error)
}