# ProjectMoneyX 系统详细设计说明书(DDS) **项目名称**:ProjectMoneyX **文档类型**:系统详细设计说明书 **版本**:v1.0 **设计目标**:构建面向 Firefly III 生态的本地化多源账单数据治理中间件,实现账单导入、解析、标准化、去重、链路合并、规则映射与导入编排闭环。 --- ## 1. 设计目标与范围 ### 1.1 设计目标 本系统负责将多源账单文件(优先支付宝、微信)导入后,完成以下处理链路: 1. 原始文件接入与批次化管理 2. 多平台账单解析与字段标准化 3. 统一交易模型入库 4. 严格去重、模糊去重、链路合并 5. 分类/账户/标签/商户归一化规则映射 6. 导出为 Firefly III / Data Importer 可消费的数据格式 7. 提供预览、审计、失败重试与可回溯能力。 ### 1.2 本期范围(V1 / MVP) * 支持支付宝、微信账单导入 * 支持 CSV / Excel / 常见文本格式 * 支持本地 SQLite 持久化 * 支持基础规则映射(分类/账户) * 支持严格去重 + 转账闭环链路合并 * 支持导入预览与确认 * 支持 API 推送或中间文件导出至 Firefly III / Data Importer。 ### 1.3 非目标 * 不直接登录第三方平台抓取账单 * 不实现完整 BI 平台 * 不替代 Firefly III 本体记账能力 * 不做高频实时同步。 --- ## 2. 需求分析与架构判断 ### 2.1 核心业务意图 PRD 的真实意图不是“导入工具”,而是一个 **本地账单数据治理层**,核心是先统一语义与规则,再输出给 Firefly III。换言之,系统的重点不在“上传文件”,而在: * 多源异构字段收敛 * 多因子去重与链路恢复 * 可沉淀、可解释、可迁移的本地规则体系。 ### 2.2 关键设计约束 1. **本地优先**:财务数据敏感,必须本地部署,默认不上传云端。 2. **插件化解析器**:平台格式变化频繁,适配逻辑必须隔离。 3. **统一交易模型稳定**:避免下游 Firefly III 或上游平台格式污染核心域模型。 4. **支付宝分类为主标准**:账单说明明确支付宝交易类型最丰富,其他平台应映射到支付宝分类体系。 5. **微信分类需推断**:微信“交易类型”较粗,需要结合“商品”字段推断细分分类。 ### 2.3 技术风险 * 平台格式变更导致解析失败 * 模糊去重误判造成误合并 * 内部转账闭环识别不准确 * Firefly III 字段映射不完整导致导入失败 * 用户规则不断增加后性能退化。 --- ## 3. 总体架构设计 ## 3.1 分层架构 ```mermaid flowchart TB UI[Web UI / CLI] API[GIN API Layer] APP[Application Service Layer] ADAPTER[Adapter Layer\n账单解析器插件] NORMALIZE[Normalize Layer\n字段标准化] MATCH[Match Layer\n去重/链路合并] RULE[Rule Engine Layer\n分类/账户/标签映射] EXPORT[Export Layer\nFirefly III / Data Importer 适配] REPO[Repository Layer\nGORM] DB[(SQLite)] FF[Firefly III / Data Importer] UI --> API API --> APP APP --> ADAPTER APP --> NORMALIZE APP --> MATCH APP --> RULE APP --> EXPORT APP --> REPO REPO --> DB EXPORT --> FF ``` ### 3.2 分层职责 * **UI 层**:上传文件、批次管理、预览确认、规则配置、人工确认、导入结果展示 * **API 层**:RESTful 接口,统一鉴权、参数校验、响应封装 * **应用服务层**:编排完整业务流程,不承载具体解析规则 * **Adapter 层**:按平台解析原始文件,输出平台原始记录 DTO * **Normalize 层**:统一字段、金额、方向、时间、分类原始值 * **Match 层**:严格去重、模糊去重、链路聚合、转账闭环 * **Rule 层**:分类、账户、对手方、标签映射 * **Export 层**:适配 Firefly III / Data Importer API 或 CSV/JSON * **Repository 层**:隔离数据库访问,面向领域对象持久化。 --- ## 4. 系统模块划分 ## 4.1 模块清单 | 模块 | 职责 | 优先级 | | ------------------- | --------------- | ----- | | import-center | 文件上传、批次管理、来源识别 | P0 | | parser-engine | 平台解析器装载与执行 | P0 | | normalize-engine | 统一模型转换 | P0 | | dedup-engine | 严格去重与模糊去重 | P0/P1 | | link-engine | 转账闭环与订单链路合并 | P0 | | rule-engine | 分类/账户/标签/商户归一 | P0/P1 | | import-orchestrator | 导入预览、执行、重试 | P0 | | audit-center | 审计日志、处理链追溯 | P0 | | settings-center | Firefly 配置、阈值参数 | P1 | ### 4.2 后端包结构建议(Go) ```text projectmoneyx/ ├── cmd/server ├── internal/ │ ├── handler/ │ ├── service/ │ ├── domain/ │ │ ├── entity/ │ │ ├── valueobject/ │ │ ├── enum/ │ │ └── repository/ │ ├── parser/ │ │ ├── alipay/ │ │ ├── wechat/ │ │ └── registry/ │ ├── normalize/ │ ├── matcher/ │ ├── linker/ │ ├── rule/ │ ├── exporter/ │ ├── dao/ │ ├── dto/ │ ├── middleware/ │ └── config/ ├── migrations/ └── web/ ``` ### 4.3 前端结构建议(Vue3) ```text src/ ├── api/ ├── views/ │ ├── ImportCenterView.vue │ ├── BatchDetailView.vue │ ├── PreviewView.vue │ ├── DedupReviewView.vue │ ├── RuleConfigView.vue │ ├── ImportTaskView.vue │ └── AuditTraceView.vue ├── components/ ├── stores/ ├── types/ └── router/ ``` --- ## 5. 核心业务流程设计 ## 5.1 主流程时序图 ```mermaid sequenceDiagram participant U as User participant FE as Web UI participant API as Gin API participant IMP as Import Service participant PARSER as Parser Engine participant NORM as Normalize Engine participant MATCH as Match/Link Engine participant RULE as Rule Engine participant EXP as Export Engine participant DB as SQLite participant FF as Firefly/Data Importer U->>FE: 上传账单文件 FE->>API: 创建导入批次 API->>IMP: startImport(batchId) IMP->>DB: 保存 source_files / import_batch IMP->>PARSER: 解析文件 PARSER->>DB: 保存 raw_records IMP->>NORM: 标准化转换 NORM->>DB: 保存 transactions(待清洗) IMP->>MATCH: 严格去重/模糊去重/链路合并 MATCH->>DB: 保存 dedup_relations / link_relations IMP->>RULE: 应用映射规则 RULE->>DB: 更新 category/account/tag API-->>FE: 返回预览结果 U->>FE: 确认导入 FE->>API: 执行导入 API->>EXP: export(batchId) EXP->>FF: 调用 API / 导出 CSV FF-->>EXP: 返回结果 EXP->>DB: 保存 import_results API-->>FE: 展示导入结果 ``` ## 5.2 批次状态机 ```mermaid stateDiagram-v2 [*] --> CREATED CREATED --> UPLOADED: 文件已上传 UPLOADED --> PARSED: 解析完成 PARSED --> NORMALIZED: 标准化完成 NORMALIZED --> MATCHED: 去重/链路完成 MATCHED --> RULE_APPLIED: 规则映射完成 RULE_APPLIED --> PREVIEW_READY: 可预览 PREVIEW_READY --> IMPORTING: 用户确认导入 IMPORTING --> IMPORT_SUCCESS: 全部成功 IMPORTING --> PARTIAL_FAILED: 部分失败 IMPORTING --> IMPORT_FAILED: 全部失败 PARTIAL_FAILED --> RETRYING: 用户重试失败项 RETRYING --> IMPORT_SUCCESS RETRYING --> PARTIAL_FAILED IMPORT_FAILED --> RETRYING ``` --- ## 6. 账单解析与标准化设计 ## 6.1 解析器接口设计 ```go type BillParser interface { Platform() string Detect(fileMeta FileMeta, header []string) bool Parse(ctx context.Context, filePath string) ([]RawBillRecord, error) } ``` ### 解析器注册中心 * 启动时注册所有 Parser * 上传后根据文件头、列名、用户指定来源进行匹配 * 匹配失败时进入“未知来源待人工选择”状态 ## 6.2 支付宝解析规则 支付宝字段包括: * 交易时间 * 交易分类 * 交易对方 * 对方账号 * 商品说明 * 收/支 * 金额 * 收/付款方式 * 交易状态 * 交易订单号 * 商家订单号 * 备注。 ### 支付宝映射策略 | 原字段 | 目标字段 | | ------ | ----------------------------------- | | 交易时间 | trade_time | | 交易分类 | category_raw | | 交易对方 | counterparty | | 对方账号 | counterparty_account | | 商品说明 | merchant_name / note | | 收/支 | direction | | 金额 | amount | | 收/付款方式 | payment_method_raw | | 交易状态 | trade_status | | 交易订单号 | source_record_id / order_id | | 商家订单号 | merchant_order_id / parent_order_id | | 备注 | note | ### 特别说明 支付宝交易类型最丰富,系统将其作为 **一级业务分类基准字典**。其他平台最终都应落到这套分类枚举上。 ## 6.3 微信解析规则 微信字段包括: * 交易时间 * 交易类型 * 交易对方 * 商品 * 收/支 * 金额(元) * 支付方式 * 当前状态 * 交易单号 * 商户单号 * 备注。 ### 微信映射策略 | 原字段 | 目标字段 | | ----- | ----------------------------------- | | 交易时间 | trade_time | | 交易类型 | category_raw / wechat_trade_type | | 交易对方 | counterparty | | 商品 | merchant_name / product_desc | | 收/支 | direction | | 金额(元) | amount | | 支付方式 | payment_method_raw | | 当前状态 | trade_status | | 交易单号 | source_record_id / order_id | | 商户单号 | merchant_order_id / parent_order_id | | 备注 | note | ### 微信分类推断规则 由于微信“交易类型”较粗(如商户消费、扫二维码付款、转账、红包等),系统必须结合“商品”字段推断更细分类。 #### 示例推断逻辑 | 微信交易类型 | 商品关键词 | 推断分类 | | ------ | ----------- | --------- | | 商户消费 | 美团/外卖/餐厅/咖啡 | 餐饮美食 | | 商户消费 | 滴滴/打车/地铁/高铁 | 交通出行 | | 商户消费 | 京东/超市/便利店 | 日用百货 | | 商户消费 | 电费/水费/话费 | 充值缴费 | | 转账 | 无 | 转账红包 / 其他 | | 微信红包 | 无 | 转账红包 | | xxx-退款 | 无 | 退款 | > 若商品内容无法识别,先落入“其他”,并允许用户通过规则管理补充映射。 ## 6.4 统一交易模型 ```mermaid classDiagram class Transaction { +string transaction_id +string source_platform +string source_record_id +datetime trade_time +decimal amount +string currency +string direction +string counterparty +string merchant_name +string category_raw +string category_mapped +string order_id +string parent_order_id +string note +json raw_payload +string import_batch_id +string status } ``` 该模型与 PRD 保持一致,作为系统核心领域对象。 ### 标准化规则 1. 时间统一存储为 **Asia/Shanghai (UTC+8)** 2. 金额统一使用正数,方向独立用 `direction` 表达 3. 币种默认 CNY,后续可扩展多币种 4. 状态初始为 `PENDING_CLEAN` 5. 原始记录完整写入 `raw_payload` 以便审计。 --- ## 7. 去重与链路合并设计 ## 7.1 三层处理模型 PRD 明确采用: * 基础去重(严格) * 模糊去重(多因子) * 链路合并(转账/订单闭环)。 ```mermaid flowchart LR A[新标准化交易] --> B{严格去重} B -- 命中 --> X[标记重复并建立关系] B -- 未命中 --> C{模糊去重} C -- 高置信 --> X C -- 低置信 --> D[进入人工确认队列] C -- 未命中 --> E{链路合并} E -- 命中 --> F[生成合并链路] E -- 未命中 --> G[保留独立交易] ``` ## 7.2 严格去重 ### 唯一判定键 1. `source_platform + source_record_id` 2. `source_file_hash + row_fingerprint` 3. `可信订单号(order_id)` ### 行指纹算法建议 对以下字段标准化后做 SHA256: * trade_time(分钟粒度) * amount * direction * counterparty * merchant_name * order_id 这样可防止同一文件重复导入。 ## 7.3 模糊去重 ### 多因子评分模型 | 因子 | 分值 | | ---------- | -- | | 时间在 ±5 分钟内 | 30 | | 金额一致 | 30 | | 方向一致 | 10 | | 订单号相同/相近 | 15 | | 对手方相似 | 10 | | 来源关联规则命中 | 5 | ### 判定阈值 * `>= 85`:自动判定重复 * `60 ~ 84`:疑似重复,进入人工确认 * `< 60`:不判定重复 ### 对手方相似算法 * 统一大小写/空格/符号 * 去除平台前缀后再比较 * 使用 `contains + Levenshtein` 混合评分 ## 7.4 链路合并(转账闭环) ### 典型场景 * 银行卡支出 1000 * 支付宝收入 1000 * 时间接近、金额相同、方向互补 则合并为一笔内部转账: * from_account = 银行卡 * to_account = 支付宝 * type = transfer。 ### 转账识别规则 1. 金额一致 2. 一条为支出,一条为收入 3. 时间在可配置窗口内 4. 来源平台不同但账户映射可闭环 5. 非退款、非手续费 ### 订单链路合并 对于“京东订单 + 微信支付”类场景: * 保留更完整的业务记录为主交易 * 其他记录挂为关联来源 * 形成 `parent_order_id` 聚合链路。 --- ## 8. 规则引擎设计 ## 8.1 规则模型 ```mermaid classDiagram class Rule { +string id +string rule_type +int priority +string platform_scope +json conditions +json actions +bool enabled } ``` ### 规则类型 * CATEGORY_MAPPING * ACCOUNT_MAPPING * COUNTERPARTY_NORMALIZE * TAG_MAPPING * FIREFLY_FIELD_MAPPING ## 8.2 规则匹配条件 支持: * 平台 * 原始分类 * 交易类型 * 商品/商户关键词 * 金额范围 * 方向 * 对手方关键字 * 正则匹配 ### 示例 ```json { "platform": "wechat", "conditions": { "trade_type": "商户消费", "product_keywords": ["美团", "外卖"] }, "actions": { "category_mapped": "餐饮美食", "merchant_name_normalized": "美团" } } ``` ## 8.3 执行顺序 1. 对手方归一化 2. 商户归一化 3. 分类映射 4. 账户映射 5. 标签映射 6. Firefly 字段映射 ### 原因 先做归一化,再做分类,可提升规则命中率与稳定性。 ## 8.4 可解释性设计 每条交易保留: * 命中的规则 ID * 命中条件摘要 * 规则执行前后字段对比 用于前端“为何被分到餐饮/交通”的解释展示。 --- ## 9. Firefly III / Data Importer 适配设计 ## 9.1 导出模式 ### 模式 A:API 推送 * 系统生成 Firefly 兼容 DTO * 调用 Data Importer / Firefly API * 接收导入结果并更新任务状态。 ### 模式 B:文件导出 * 生成标准 CSV / JSON * 用户手动导入 * 适用于 API 不可用或权限受限场景。 ## 9.2 Firefly 交易类型映射 | 内部 direction | Firefly type | | ------------ | ----------------------- | | expense | withdrawal | | income | deposit | | transfer | transfer | | refund | deposit / reversal(按配置) | | fee | withdrawal | ## 9.3 导入前校验 * 必填字段完整 * 金额与时间合法 * 账户映射完整 * 是否已导入过 * 是否存在未确认疑似重复记录。 --- ## 10. 数据库详细设计(SQLite) ## 10.1 ER 图 ```mermaid erDiagram SOURCE_FILES ||--o{ RAW_RECORDS : contains SOURCE_FILES ||--o{ IMPORT_BATCHES : belongs_to IMPORT_BATCHES ||--o{ TRANSACTIONS : generates TRANSACTIONS ||--o{ DEDUP_RELATIONS : source TRANSACTIONS ||--o{ LINK_RELATIONS : linked TRANSACTIONS ||--o{ RULE_HITS : matched IMPORT_BATCHES ||--o{ IMPORT_TASKS : owns IMPORT_TASKS ||--o{ IMPORT_RESULTS : produces RULES ||--o{ RULE_HITS : referenced TRANSACTIONS ||--o{ AUDIT_LOGS : traced ``` ## 10.2 表结构 ### 10.2.1 source_files | 字段 | 类型 | 说明 | | --------------- | ------------ | ------------ | | id | varchar(36) | 主键 | | file_name | varchar(255) | 文件名 | | file_hash | varchar(64) | 文件哈希 | | source_platform | varchar(32) | 来源平台 | | file_type | varchar(32) | csv/xlsx/txt | | uploaded_at | datetime | 上传时间 | | batch_id | varchar(36) | 批次 ID | ### 10.2.2 raw_records | 字段 | 类型 | 说明 | | ---------------- | ------------ | ------- | | id | varchar(36) | 主键 | | source_file_id | varchar(36) | 来源文件 | | row_no | int | 行号 | | source_platform | varchar(32) | 平台 | | source_record_id | varchar(128) | 原始流水号 | | row_fingerprint | varchar(64) | 行指纹 | | raw_payload | text | 原始 JSON | | parse_status | varchar(32) | 解析状态 | | parse_error | text | 错误信息 | ### 10.2.3 transactions | 字段 | 类型 | 说明 | | ---------------- | ------------- | ----- | | id | varchar(36) | 主键 | | transaction_id | varchar(64) | 业务 ID | | batch_id | varchar(36) | 导入批次 | | source_platform | varchar(32) | 来源平台 | | source_record_id | varchar(128) | 原始记录号 | | trade_time | datetime | 交易时间 | | amount | decimal(18,6) | 金额 | | currency | varchar(16) | 币种 | | direction | varchar(16) | 方向 | | counterparty | varchar(255) | 对手方 | | merchant_name | varchar(255) | 商户名 | | category_raw | varchar(128) | 原始分类 | | category_mapped | varchar(128) | 映射分类 | | order_id | varchar(128) | 订单号 | | parent_order_id | varchar(128) | 父链路号 | | note | text | 备注 | | status | varchar(32) | 状态 | | imported_at | datetime | 导入时间 | ### 10.2.4 dedup_relations | 字段 | 类型 | 说明 | | --------------------- | ----------- | ------------ | | id | varchar(36) | 主键 | | src_transaction_id | varchar(64) | 原交易 | | target_transaction_id | varchar(64) | 目标交易 | | relation_type | varchar(32) | strict/fuzzy | | confidence | int | 置信度 | | reason_json | text | 判定依据 | ### 10.2.5 link_relations | 字段 | 类型 | 说明 | | --------------------- | ----------- | ------------------------- | | id | varchar(36) | 主键 | | parent_transaction_id | varchar(64) | 主交易 | | child_transaction_id | varchar(64) | 子交易 | | link_type | varchar(32) | transfer/order/refund/fee | | reason_json | text | 关联依据 | ### 10.2.6 rules | 字段 | 类型 | 说明 | | --------------- | ----------- | ---- | | id | varchar(36) | 主键 | | rule_type | varchar(64) | 规则类型 | | priority | int | 优先级 | | platform_scope | varchar(32) | 平台范围 | | conditions_json | text | 条件 | | actions_json | text | 动作 | | enabled | bool | 是否启用 | ### 10.2.7 import_tasks / import_results / audit_logs 按 PRD 设计分别记录导入任务、结果与操作日志。 --- ## 11. API 接口设计(Gin) ## 11.1 导入中心 ### 上传账单文件 `POST /api/v1/import/batches` * form-data: * files[] * sourcePlatform(可选) * autoDetect(bool) 返回: ```json { "code": 0, "message": "ok", "data": { "batchId": "xxx", "status": "UPLOADED" } } ``` ### 获取批次详情 `GET /api/v1/import/batches/{batchId}` ### 触发解析与清洗 `POST /api/v1/import/batches/{batchId}/process` ### 获取预览结果 `GET /api/v1/import/batches/{batchId}/preview` ## 11.2 去重确认 ### 获取疑似重复列表 `GET /api/v1/dedup/reviews?batchId=xxx` ### 确认合并 `POST /api/v1/dedup/reviews/{reviewId}/confirm` ### 拒绝合并 `POST /api/v1/dedup/reviews/{reviewId}/reject` ## 11.3 规则管理 * `GET /api/v1/rules` * `POST /api/v1/rules` * `PUT /api/v1/rules/{id}` * `DELETE /api/v1/rules/{id}` ## 11.4 导入执行 ### 确认导入到 Firefly `POST /api/v1/import/tasks` ### 获取导入结果 `GET /api/v1/import/tasks/{taskId}` ### 重试失败项 `POST /api/v1/import/tasks/{taskId}/retry` --- ## 12. 前端页面设计 ## 12.1 信息架构 PRD 已定义一级模块: * 导入中心 * 数据清洗 * 去重处理 * 规则管理 * 导入任务 * 数据审计 * 系统设置。 ## 12.2 页面职责 ### 导入中心 * 拖拽上传 * 批量文件列表 * 来源自动识别结果 * 批次创建与处理按钮 ### 清洗结果预览 * 交易列表 * 原始字段 vs 标准字段对比 * 规则命中说明 * 待人工处理标记 ### 去重处理页 * 疑似重复列表 * 评分与命中因子展开 * 合并/拒绝操作 ### 规则配置页 * 规则列表 * 优先级排序 * 条件编辑器 * 测试命中预览 ### 导入结果页 * 成功/失败统计 * 失败原因 * 单条重试 ### 审计追溯页 * 交易全处理链 * 原始文件 → 原始记录 → 标准化 → 规则 → 导入结果 --- ## 13. 非功能设计 ## 13.1 性能 目标:单次 1 万条记录在主流程内完成解析与清洗,建议 30 秒内完成主要去重流程。 ### 优化策略 * 批量插入 raw_records / transactions * 构建关键索引: * `source_platform + source_record_id` * `batch_id` * `trade_time` * `order_id` * 模糊去重按时间分桶,降低全表扫描 * 规则按平台和启用状态预筛选 ## 13.2 安全 * API Token 加密存储 * 审计日志默认脱敏(账号、订单号局部遮罩) * 本地部署,不上传云端。 ## 13.3 可维护性 * 解析器插件化 * 规则条件 JSON 化 * 导入器解耦,可替换下游目标 * 统一 DTO / VO / Entity 分层。 --- ## 14. 关键实现建议(面向 Go + GIN + GORM) ## 14.1 分层规范 * `handler`:仅做参数绑定、返回 * `service`:负责编排 * `domain`:承载核心规则 * `dao/repository`:数据访问 * `parser/matcher/rule/exporter`:独立可测试组件 ## 14.2 推荐关键对象 * `ImportBatchService` * `ParserRegistry` * `TransactionNormalizeService` * `DedupMatchService` * `TransferLinkService` * `RuleApplyService` * `FireflyExportService` * `AuditTraceService` ## 14.3 事务边界 建议以下阶段分别事务化: 1. 文件入库 + 原始记录入库 2. 标准化结果落库 3. 去重/链路关系落库 4. 规则命中落库 5. 导入结果落库 避免一个超长事务覆盖整个批次。 --- ## 15. MVP 与后续版本演进建议 ## 15.1 MVP(优先上线) * 支付宝 / 微信 Parser * 严格去重 * 转账闭环 * 基础规则映射 * 导入预览 * CSV / API 两种导出 ## 15.2 V1.5 * 模糊去重评分 * 手动合并/拆分 * 商户别名库 * 批次管理增强 ## 15.3 V2.0 * 京东 / 美团链路增强 * 多币种 * 可视化规则调试 * 统计报表。 --- ## 16. 结论 ProjectMoneyX 的最佳实现方式,不是把逻辑堆到 Firefly III 导入器里,而是建设一个本地、分层、插件化的 **账单治理中台**: * **Adapter** 收敛平台差异 * **Normalize** 建立统一交易语义 * **Match/Link** 解决重复与交易链碎片 * **Rule Engine** 沉淀可解释、可复用的分类知识 * **Export** 以最小耦合接入 Firefly 生态。 同时,基于账单格式说明,V1 必须把下面两点做成产品级能力: 1. **支付宝分类字典作为统一分类基准** 2. **微信“交易类型 + 商品”联合推断分类**。