---
name: developing-projectmoneyx
description: >
  指导 ProjectMoneyX 多源账单数据治理系统的全栈开发（Guides full-stack development of ProjectMoneyX bill data governance system）。
  包含：ETL Pipeline 编排（Parse → Normalize → Dedup → Link → Rule → Export）、插件化解析器对接、三层去重策略、规则引擎映射、Firefly III 适配、SQLite 数据模型、审计追溯。
  触发场景 Trigger: 开发/修改 ProjectMoneyX 的 Parser / Pipeline / 去重 / 规则 / 导入导出 / 审计 / 前端页面 / API 接口。
  关键词 Keywords: ProjectMoneyX, 账单, bill, ETL, parser, dedup, 去重, 链路合并, transfer link, rule engine, 规则引擎, Firefly III, 导入, import, export, audit, 审计, SQLite, GORM, GIN, Vue3, Vuetify。
argument-hint: "<action> <target>" 例如/ e.g.:
  "add parser for ccb", "implement dedup scorer", "create rule handler",
  "update transaction schema", "build import preview page"
allowed-tools:
  - Read
  - Write
  - Edit
  - Glob
  - Grep
  - Bash
---

# Developing ProjectMoneyX

ProjectMoneyX 是 Firefly III 生态的**本地化多源账单数据治理中间件**，技术栈为 Go (GIN + GORM) + Vue3 (TypeScript + Vuetify) + SQLite。系统核心是一条 ETL Pipeline：`Parse → Normalize → Dedup → Link → Rule → Export`，将支付宝/微信/银行账单标准化后推送至 Firefly III。

> **架构关键词**：DDD 分层 · 插件化 Adapter · 三层去重 · 规则可解释 · 全链路审计

## Quick Context

```bash
# 动态注入：后端项目结构
!`find projectmoneyx-server/internal -type f -name "*.go" | head -40`

# 动态注入：前端项目结构
!`find projectmoneyx-web/src -type f -name "*.ts" -o -name "*.vue" | head -30`

# 动态注入：数据库表定义
!`grep -rn "TableName\|func.*TableName" projectmoneyx-server/internal/ | head -20`

# 动态注入：API 路由注册
!`grep -rn "Group\|GET\|POST\|PUT\|DELETE" projectmoneyx-server/internal/handler/ | head -30`
```

## Architecture Overview

```
┌─────────────────────────────────────────────────────┐
│  展现层: Vue3 + TypeScript + Vuetify                  │
│  导入中心 / 清洗预览 / 去重处理 / 规则管理 / 导入任务 / 审计  │
├─────────────────────────────────────────────────────┤
│  接入层: GIN RESTful API (/api/v1/*)                  │
│  import / transactions / dedup / rules / export / audit │
├─────────────────────────────────────────────────────┤
│  应用服务层: Pipeline 编排                              │
│  ImportBatchService → PipelineService                 │
├─────────────────────────────────────────────────────┤
│  业务逻辑层 (ETL Core Domain)                          │
│  Parser(插件) → Normalize → Match → Link → Rule → Export │
├─────────────────────────────────────────────────────┤
│  数据持久层: GORM + SQLite (WAL)                       │
│  11 张核心表，分阶段事务                                 │
└─────────────────────────────────────────────────────┘
```

**分层依赖规则**：handler → service → domain（entity/repository）← dao。Parser/Matcher/Linker/Rule/Exporter 为独立可测试组件。

## Module Registry

| 模块 | 包路径 | 职责 | 优先级 |
|------|--------|------|--------|
| 导入中心 | `handler/import` + `service/import_batch` | 文件上传、批次管理 | P0 |
| 解析引擎 | `parser/` | 插件化平台解析器 | P0 |
| 标准化引擎 | `normalize/` | 异构字段 → 统一 Transaction 模型 | P0 |
| 去重引擎 | `matcher/` | 严格去重 + 模糊去重(P1) | P0/P1 |
| 链路引擎 | `linker/` | 转账闭环 + 订单链路合并 | P0 |
| 规则引擎 | `rule/` | 6 类规则按序执行 | P0/P1 |
| 导出引擎 | `exporter/` | Firefly API/CSV 导出 | P0 |
| 审计中心 | `service/audit` | 全链路追溯 | P0 |
| 系统设置 | `handler/settings` + `config/` | Firefly 连接、阈值参数 | P1 |

## Plan

### 产物清单

| 动作 | 产物 |
|------|------|
| `add parser` | `parser/<platform>/<platform>_parser.go` — 实现 `BillParser` 接口 |
| `create handler` | `handler/<resource>_handler.go` — GIN Handler |
| `create service` | `service/<resource>_service.go` — 应用服务 |
| `create dao` | `dao/<resource>_dao.go` — GORM 数据访问 |
| `create entity` | `domain/entity/<resource>.go` — 领域实体 |
| `add rule type` | `rule/<type>_mapper.go` — 规则映射器 |
| `scaffold module` | 上述全部 + DTO + repository 接口 |

### 决策点

1. **Parser 选择**：先检查 `parser/registry.go` 中已注册的解析器，确认目标平台是否已有实现
2. **去重层级**：严格去重(P0) vs 模糊去重(P1) — 新功能默认只实现严格去重
3. **规则执行顺序**：必须遵守 6 步固定顺序（`reference/04-rule-engine/rule-execution.md`）
4. **事务边界**：ETL 每阶段独立事务，禁止跨阶段长事务
5. **SQLite 约束**：单写连接 `MaxOpenConns=1`，启用 WAL 模式

---

## Execute

### 1. 新增平台解析器

```go
// 1. 实现 BillParser 接口 (parser/<platform>/<platform>_parser.go)
type Parser struct{}

func (p *Parser) Platform() string { return "<platform>" }

func (p *Parser) Detect(meta FileMeta, header []string) bool {
    // 基于文件名/表头特征判定
}

func (p *Parser) Parse(ctx context.Context, reader io.Reader) ([]RawBillRecord, error) {
    // 逐行读取 → 填充 RawBillRecord.RawFields
    // 必须设置 SourcePlatform, SourceRecordID, RowNo, RowFingerprint
}

// 2. 注册到 Registry (parser/registry.go)
r.Register(&<platform>.Parser{})
```

**字段映射要求**（参考 `reference/02-parser-engine/field-mappings.md`）：
- `trade_time`：统一 UTC+8，`time.Time`
- `amount`：去除货币符号，正数 `decimal(18,6)`
- `direction`：`income` / `expense` / `transfer` / `refund` / `fee` / `other`
- `category_raw`：保留原始分类，不在 Parser 中做映射
- `order_id`：去除空格，作为唯一标识

### 2. ETL Pipeline 阶段开发

每个阶段必须：
1. 接收 `context.Context` + 数据切片
2. 返回处理后切片 + error
3. 在独立事务中持久化（`db.Transaction`，每批 500 条 `CreateInBatches`）
4. 更新批次状态

```go
// 阶段签名模式
func (s *StageService) Execute(ctx context.Context, txns []*Transaction) ([]*Transaction, error)
```

### 3. 规则引擎扩展

新增规则类型时：
1. 在 `rule/engine.go` 的 `executionOrder` 中确认位置
2. 实现 `MatchConditions(txn)` 和 `ApplyActions(txn)` 方法
3. 确保 `RuleHit` 记录命中日志（含 `BeforeValue` / `AfterValue`）
4. 规则条件 JSON 存储，参考 `reference/04-rule-engine/rule-conditions.md`

### 4. API 开发

遵循统一响应格式：
```go
type Response struct {
    Code    int         `json:"code"`    // 0=成功
    Message string      `json:"message"`
    Data    interface{} `json:"data"`
}
```

路由分组：`/api/v1/import/*`、`/api/v1/transactions/*`、`/api/v1/dedup/*`、`/api/v1/rules/*`、`/api/v1/export/*`、`/api/v1/audit/*`、`/api/v1/settings/*`

### 5. 前端页面开发

7 个核心页面，全部使用 Vue3 + Composition API + TypeScript：
- 导入中心：`FileUploader.vue` + 拖拽上传 + 进度条
- 清洗预览：`TransactionTable.vue` + `v-data-table` + 行展开对比
- 去重处理：`DedupCompare.vue` + 左右分栏 + 评分因子展开
- 规则管理：`RuleEditor.vue` + 条件构建器 + 测试预览
- 导入任务：统计概览 + 失败列表 + 单条/批量重试
- 审计追溯：`AuditTimeline.vue` + `v-timeline` + 快照展开
- 系统设置：Firefly 连接配置 + 测试连接 + 去重参数配置

---

## Verify

### 架构层级检查
- [ ] handler 层不包含业务逻辑，仅做参数绑定 + 调用 service + 返回响应
- [ ] service 层不直接操作 `*gorm.DB`，通过 repository 接口访问数据
- [ ] domain/entity 不依赖 handler/service
- [ ] 无循环依赖（handler → service → domain ← dao）

### Parser 检查
- [ ] 新增 Parser 实现了 `BillParser` 接口的全部 3 个方法（`Platform()`, `Detect()`, `Parse()`）
- [ ] 已注册到 `parser/registry.go`（`reference/02-parser-engine/parser-interface.md`）
- [ ] 字段映射覆盖了所有原始字段（对照 `reference/02-parser-engine/field-mappings.md`）
- [ ] `amount` 为正数，`direction` 独立表达收支方向
- [ ] `RowFingerprint` 使用 SHA256 生成（`reference/03-dedup-engine/fingerprint.md`）

### 去重与链路检查
- [ ] 严格去重判定键按优先级 3 级执行（`reference/03-dedup-engine/strict-dedup.md`）
- [ ] 模糊去重评分因子 6 项，阈值可配置（`reference/03-dedup-engine/fuzzy-dedup.md`）
- [ ] 转账闭环 5 条件全部满足才匹配（`reference/03-dedup-engine/transfer-link.md`）
- [ ] 疑似重复（60-84 分）进入 `PENDING_REVIEW` 人工确认队列

### 规则引擎检查
- [ ] 6 类规则按固定顺序执行：对手方归一 → 商户归一 → 分类 → 账户 → 标签 → Firefly（`reference/04-rule-engine/rule-execution.md`）
- [ ] 同类型内按 `priority` 升序执行，首条命中即停止
- [ ] 每条命中记录 `RuleHit`，含 `BeforeValue` / `AfterValue`
- [ ] 规则条件 JSON 结构正确（`reference/04-rule-engine/rule-conditions.md`）

### 数据库检查
- [ ] 表结构 11 张表齐全（`reference/05-database/db-schema.md`）
- [ ] 关键索引已创建（`reference/05-database/indexes.md`）
- [ ] SQLite 配置：`MaxOpenConns=1`, WAL 模式, `cache_size=-64000`
- [ ] ETL 每阶段独立事务，`CreateInBatches` 每批 500 条

### API 检查
- [ ] 路由路径遵循 `reference/06-api-design/api-catalog.md`
- [ ] 统一 `Response` / `PageResponse` 结构
- [ ] 导入前 6 项校验完整（`reference/07-export-engine/import-validation.md`）

### 前端检查
- [ ] 所有页面使用 `<script setup lang="ts">` + Composition API
- [ ] 数据表格使用 `v-data-table` + `fixed-header`
- [ ] 处理三种 UI 状态：加载中（skeleton）、空数据（empty-state）、错误（snackbar + 重试）
- [ ] 路由定义匹配 `reference/08-frontend/routes.md`

---

## Pitfalls

1. **支付宝分类是全局基准字典**：系统使用支付宝 22 种分类作为统一标准。微信/银行等平台必须映射到此分类枚举，不要在 Parser 中创造新的分类值体系（参考 `reference/02-parser-engine/field-mappings.md` 中的分类枚举表）

2. **微信分类需要"交易类型 + 商品"联合推断**：微信的"交易类型"是支付动作（商户消费/转账/红包），不是消费语义。必须结合"商品"字段做关键词推断，未命中的归入"其他"并记录。不要直接把微信交易类型当作分类使用（参考 `reference/02-parser-engine/field-mappings.md` 中的微信推断规则流程图）

3. **规则执行顺序不可变**：6 类规则的执行顺序是固定的（对手方归一 → 商户归一 → 分类 → 账户 → 标签 → Firefly），先归一再分类可提升命中率。修改顺序会导致规则相互依赖断裂（参考 `reference/04-rule-engine/rule-execution.md`）

4. **SQLite 单写连接**：`MaxOpenConns` 必须设为 1，SQLite 不支持多写。ETL Pipeline 已通过分阶段事务避免超长锁定。如果遇到 `database is locked` 错误，检查是否有未关闭的事务（参考 `reference/05-database/db-schema.md` 中的 SQLite 配置）

5. **转账闭环需 5 条件全部满足**：金额一致 + 方向互补 + 时间窗口内 + 不同平台 + 非退款/手续费。漏掉任何一项都会导致误合并。特别注意退款交易（direction=refund）不应参与转账闭环（参考 `reference/03-dedup-engine/transfer-link.md`）

6. **行指纹是分钟粒度**：`GenerateRowFingerprint` 使用 `2006-01-02 15:04` 格式（分钟级），不是秒级。这是为了容忍不同平台对同一交易记录的秒级时间差异（参考 `reference/03-dedup-engine/fingerprint.md`）

7. **批次状态机严格受控**：批次状态只能按 `CREATED → UPLOADED → PARSING → ... → IMPORT_SUCCESS` 的线性路径推进，不可跳跃。失败时只能回退至上一可重试状态（参考 `reference/01-architecture/batch-state-machine.md`）

---

## Related References

| 需要了解... | 查阅... |
|------------|--------|
| 系统架构与模块依赖 | `reference/01-architecture/system-overview.md` |
| 批次状态机定义 | `reference/01-architecture/batch-state-machine.md` |
| Parser 接口与注册 | `reference/02-parser-engine/parser-interface.md` |
| 平台字段映射规则 | `reference/02-parser-engine/field-mappings.md` |
| 严格去重判定键 | `reference/03-dedup-engine/strict-dedup.md` |
| 模糊去重评分模型 | `reference/03-dedup-engine/fuzzy-dedup.md` |
| 转账闭环识别规则 | `reference/03-dedup-engine/transfer-link.md` |
| 行指纹生成算法 | `reference/03-dedup-engine/fingerprint.md` |
| 规则条件 JSON 格式 | `reference/04-rule-engine/rule-conditions.md` |
| 规则执行顺序与可解释性 | `reference/04-rule-engine/rule-execution.md` |
| 数据库 11 张表结构 | `reference/05-database/db-schema.md` |
| 关键索引设计 | `reference/05-database/indexes.md` |
| API 接口目录 | `reference/06-api-design/api-catalog.md` |
| 统一响应与错误码 | `reference/06-api-design/response-format.md` |
| Firefly 导出适配 | `reference/07-export-engine/firefly-mapping.md` |
| 导入前校验清单 | `reference/07-export-engine/import-validation.md` |
| 前端路由与页面 | `reference/08-frontend/routes.md` |
| 前端组件交互 | `reference/08-frontend/components.md` |
| 非功能设计要求 | `reference/09-nonfunctional/performance.md` |
| 部署与安全 | `reference/09-nonfunctional/deployment.md` |
