Metadata-Version: 2.4
Name: beancount-sieve
Version: 0.2.0
Summary: Rule-based statement importer and reconciler for Beancount
Project-URL: Homepage, https://github.com/Xm798/bean-sieve
Project-URL: Repository, https://github.com/Xm798/bean-sieve
Project-URL: Changelog, https://github.com/Xm798/bean-sieve/blob/master/CHANGELOG.md
Project-URL: Issues, https://github.com/Xm798/bean-sieve/issues
Author: Cyrus
License: MIT
Keywords: accounting,beancount,import,reconcile
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Accounting
Requires-Python: >=3.11
Requires-Dist: beancount-periodic>=0.2.1
Requires-Dist: beancount>=3.0.0
Requires-Dist: beanfmt>=0.6.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: click>=8.0.0
Requires-Dist: iterfzf>=1.0.0
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pymupdf>=1.24.0
Requires-Dist: rich>=13.0.0
Requires-Dist: ruamel-yaml>=0.18.0
Requires-Dist: xlrd>=2.0.2
Provides-Extra: dev
Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Description-Content-Type: text/markdown

# Bean-Sieve

Bean-Sieve 是一个基于规则的 [Beancount](https://github.com/beancount/beancount) 账单导入与对账工具。

与传统导入器只做「解析 → 导入」不同，Bean-Sieve 支持将账单与已有账本**智能对账**——自动识别已手动记录的交易，仅生成缺失条目，避免重复。同时也可作为独立的账单解析器，将各类账单统一导出为通用 CSV/XLSX 格式。

## 功能特性

- **解析** 支付宝、微信支付、银行信用卡/借记卡等各类账单
- **对账** 与已有 Beancount 账本比对，自动识别已记录交易，补充未记录交易
- **生成** 仅输出缺失的待录入条目，支持规则映射账户
- **导出** 可作为纯账单解析器，将账单统一导出为 CSV/XLSX

## 安装

### 作为 CLI 工具安装（推荐）

```bash
# 使用 uv（推荐）
uv tool install beancount-sieve

# 使用 pipx
pipx install beancount-sieve

# 或从源码安装
uv tool install git+https://github.com/Xm798/bean-sieve.git
```

以上命令会将 `bean-sieve` 安装到 `~/.local/bin`（Linux/macOS）或用户 PATH（Windows）。请确保该目录在 PATH 中。

### 开发安装

```bash
# 本地开发
uv sync

# 包含开发依赖
uv sync --extra dev
```

### 在其他项目中引入

```bash
# 从 Git 安装
uv add git+https://github.com/Xm798/bean-sieve.git

# 从本地路径安装
uv add --editable ../bean-sieve
```

### Shell 自动补全

```bash
# Bash - 添加到 ~/.bashrc
eval "$(bean-sieve completion bash)"

# Zsh - 添加到 ~/.zshrc
eval "$(bean-sieve completion zsh)"

# Fish
bean-sieve completion fish > ~/.config/fish/completions/bean-sieve.fish
```

## 支持的数据源

### 支付平台

| Provider | 名称     | 格式       | 说明                                              |
|----------|----------|------------|----------------------------------------------------|
| `alipay` | 支付宝   | CSV        | 支付宝导出的交易明细                              |
| `app_store` | App Store | HAR     | App Store 购买历史 (reportaproblem.apple.com HAR 导出) |
| `jd`     | 京东支付 | CSV        | 京东交易流水导出文件                              |
| `wechat` | 微信支付 | CSV / XLSX | 微信支付账单流水文件                              |

### 信用卡

| Provider       | 名称           | 格式 | 说明               |
|----------------|----------------|------|--------------------|
| `abc_credit`   | 农业银行信用卡 | EML  | 邮件账单           |
| `boc_credit`   | 中国银行信用卡 | PDF  | PDF 账单           |
| `bocom_credit` | 交通银行信用卡 | EML  | 邮件账单           |
| `bosc_credit`  | 上海银行信用卡 | EML  | 邮件账单           |
| `ccb_credit`   | 建设银行信用卡 | EML  | 邮件账单           |
| `cgb_credit`   | 广发银行信用卡 | EML  | 邮件账单           |
| `cib_credit`   | 兴业银行信用卡 | EML  | 邮件账单           |
| `cncb_credit`  | 中信银行信用卡 | XLS  | 网银导出账单       |
| `cmb_credit`   | 招商银行信用卡 | EML  | 邮件账单           |
| `cmbc_credit`  | 民生银行信用卡 | EML  | 邮件账单           |
| `hxb_credit`   | 华夏银行信用卡 | EML  | 邮件账单           |

### 借记卡

| Provider       | 名称           | 格式      | 说明               |
|----------------|----------------|-----------|--------------------|
| `boc_debit`    | 中国银行借记卡 | CSV       | 网银导出账单       |
| `abc_debit`    | 农业银行借记卡 | XLSX      | Excel 导出账单     |
| `icbc_debit`   | 工商银行借记卡 | CSV       | CSV 导出账单       |
| `ccb_debit`    | 建设银行借记卡 | XLS       | XLS 导出账单       |
| `bocom_debit`  | 交通银行借记卡 | XLS       | XLS 导出账单       |
| `cmb_debit`    | 招商银行借记卡 | CSV       | CSV 导出账单       |
| `cib_debit`    | 兴业银行借记卡 | XLS       | XLS 导出账单       |
| `pab_debit`    | 平安银行借记卡 | XLS/XLSX  | Excel 导出账单     |

更多 Provider 正在开发中。

## 使用方法

### 命令行

```bash
# 对账：解析账单 + 比对账本 + 生成缺失条目
bean-sieve reconcile data/statement/*.csv -l books/ -o pending.bean

# 仅解析：输出标准化交易
bean-sieve parse data/statement/*.csv

# 导出：将解析结果导出为 CSV 或 XLSX
bean-sieve export data/statement/*.csv -f csv -o output/

# 仅检查：显示对账结果，不生成文件
bean-sieve check data/statement/*.csv -l books/

# 提取账单中的支付方式并交互式映射到账本账户
bean-sieve extract-accounts data/statement/*.csv -l books/

# 从账本历史记录中自动生成规则建议
bean-sieve suggest-rules -l books/

# 列出支持的数据源
bean-sieve providers

# 生成 Shell 自动补全脚本
bean-sieve completion bash
```

### Python API

```python
from pathlib import Path
from bean_sieve.providers import get_provider, list_providers

# 查看所有可用的 Provider
for p in list_providers():
    print(f"{p['id']}: {p['name']} ({p['formats']})")

# 解析支付宝账单
alipay = get_provider("alipay")
transactions = alipay.parse(Path("data/statement/支付宝交易明细.csv"))

for txn in transactions[:5]:
    print(f"{txn.date} | {txn.payee:20s} | {txn.amount:>10} CNY | {txn.description}")

# 解析微信账单
wechat = get_provider("wechat")
transactions = wechat.parse(Path("data/statement/微信支付账单.xlsx"))
```

## 配置

配置文件搜索顺序：

1. 命令行 `-c/--config` 指定的路径
2. 当前目录 `./bean-sieve.yaml`
3. 系统配置目录：
   - Linux/macOS: `$XDG_CONFIG_HOME/bean-sieve/config.yaml` 或 `~/.config/bean-sieve/config.yaml`
   - Windows: `%APPDATA%\bean-sieve\config.yaml`

复制 `bean-sieve.example.yaml` 为 `bean-sieve.yaml`（当前目录）或 `config.yaml`（系统配置目录）并根据需要修改：

```yaml
# 默认设置
defaults:
  currency: CNY
  expense_account: Expenses:FIXME
  income_account: Income:FIXME
  date_tolerance: 0  # 日期模糊匹配容差（天）

# 账户映射（按 provider）
accounts:
  alipay:
    default: Assets:Current:Alipay

  wechat:
    default: Assets:Current:Wechat

# 规则匹配（优先级最高，按顺序匹配）
rules:
  # 正则匹配 description
  - description: ".*瑞幸.*"
    payee: 瑞幸咖啡
    contra_account: Expenses:Food:Coffee

  - description: ".*美团.*外卖.*"
    payee: 美团外卖
    contra_account: Expenses:Food:Delivery

  # 多关键词匹配（OR 逻辑）
  - description: "(滴滴|高德|T3出行)"
    payee: 打车
    contra_account: Expenses:Transport:Taxi

  # 时间范围
  - description: ".*食堂.*"
    time: "11:00-14:00"
    contra_account: Expenses:Food:Lunch

  - description: ".*食堂.*"
    time: "17:00-20:00"
    contra_account: Expenses:Food:Dinner

  # 忽略某些交易
  - description: ".*还款.*"
    ignore: true
```

## 账单下载方式

### 借记卡

| 银行 | 下载方式 | 系统要求 | 备注 |
| :--- | :--- | :--- | :--- |
| 中国银行 | [个人网上银行](https://ebsnew.boc.cn/boc15/login.html?locale=zh) | Windows / macOS | 卡号登录，复制查询表格保存为 CSV |
| 农业银行 | [个人网上银行](https://perbank.abchina.com/EbankSite/ebank/startup) | Windows / macOS | 需安装安全控件，macOS 需用 Safari |
| 工商银行 | [个人网上银行](https://mybank.icbc.com.cn/icbc/newperbank/perbank3/frame/frame_index.jsp) | Windows / macOS | 需安装安全控件，macOS 需用 Safari |
| 建设银行 | [个人网上银行](https://ibsbjstar.ccb.com.cn/CCBIS/V6/STY1/CN/login.jsp) | Windows / macOS | Chrome 即可，无需安全控件 |
| 交通银行 | [个人网上银行](https://pbank.bankcomm.com/personbank/) | Windows / macOS | 需安装安全控件，macOS 需用 Safari |
| 招商银行 | [专业版](https://cmbchina.com/pbankwebNew/downloadPage.aspx) PC 客户端 | Windows | 需安装客户端 |
| 兴业银行 | [个人网上银行](https://personalbank.cib.com.cn/) | Windows / macOS | 需安装安全控件，查询→交易明细查询→流水下载→Excel |
| 平安银行 | [个人网上银行](https://bank.pingan.com.cn/m/main/index.html) | Windows / macOS | 扫码登录无需安全控件 |

### 信用卡

信用卡账单通常通过邮件获取，在发卡行官网或 App 设置账单邮箱即可。部分银行支持网银导出：

| 银行 | 下载方式 | 备注 |
| :--- | :--- | :--- |
| 中信银行 | [信用卡网银](https://e.creditcard.ecitic.com/citiccard/ebank-ocp/ebankpc/bill.html) | 登录后导出已出账单明细 XLS |

### 其他

| 平台 | 下载方式 | 备注 |
| :--- | :--- | :--- |
| Apple | [Report a Problem](https://reportaproblem.apple.com) | 登录后 F12 打开控制台，滚动加载完后导出 search 请求为 HAR |

## 信用卡账单管理方式

| 管理方式 | 银行 | 特点 |
| :--- | :--- | :--- |
| **按户管理** | 招商银行、民生银行、华夏银行、平安银行、浦发银行、北京银行、上海银行 | 信报、还款、积分按户**合并管理** |
| **按卡管理** | 广发银行、建设银行 | 独立信报，**账单日合并**，**独立还款**。 |
| **按卡管理** | 中信银行、光大银行、交通银行、农业银行、工商银行、兴业银行、中国银行、邮政储蓄 | 独立信报，独立账单，独立还款。 |

## Provider Metadata 字段

每个 Provider 解析账单时，除了标准字段（日期、金额、描述、收款方等）外，还会将账单中的其他列存入 `metadata`。可通过 `output_metadata` 配置控制哪些字段输出到 Beancount 文件。

### 支付平台

| Provider | Metadata 字段 |
| :--- | :--- |
| `alipay` | `category`, `peer_account`, `method`, `status`, `merchant_id`, `tx_type`, `remarks` |
| `wechat` | `tx_type`, `method`, `status`, `merchant_id`, `remarks`, `order_type`, `commission`, `rebate`, `rebate_currency` |
| `jd` | `payment_method`, `transaction_type`, `transaction_status`, `transaction_category`, `merchant_order_id`, `notes`, `refund_amount` |
| `app_store` | `media_type`, `item_id`, `adam_id` |

### 信用卡

| Provider | Metadata 字段 |
| :--- | :--- |
| `boc_credit` | `original_trans_date`, `original_post_date` |
| `bocom_credit` | `original_date`, `section` |
| `cgb_credit` | `original_date`, `trans_type` |
| `cib_credit` | `original_date` |
| `cmb_credit` | `posting_date` |
| `cmbc_credit` | `posting_date` |
| `hxb_credit` | `original_date` |
| `abc_credit` | — |
| `bosc_credit` | — |
| `ccb_credit` | — |
| `cncb_credit` | — |

### 借记卡

#### 中国银行 `boc_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 业务摘要 |
| `balance` | 余额 |
| `channel` | 交易渠道/场所 |
| `counterparty_account` | 对方账户账号 |
| `cash_remit` | 钞/汇 |

#### 农业银行 `abc_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 交易摘要 |
| `balance` | 本次余额 |
| `counterparty_account` | 对方账号 |
| `bank` | 交易行 |
| `channel` | 交易渠道 |
| `tx_type` | 交易类型 |

#### 工商银行 `icbc_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 摘要 |
| `balance` | 余额 |
| `detail` | 交易详情 |
| `location` | 交易场所 |
| `counterparty_account` | 对方账户 |

#### 建设银行 `ccb_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 摘要 |
| `balance` | 账户余额 |
| `counterparty_account` | 对方账号 |
| `location` | 交易地点 |

#### 交通银行 `bocom_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 摘要 |
| `balance` | 余额 |
| `method` | 交易方式 |
| `location` | 交易地点 |
| `counterparty_account` | 对方账户 |
| `counterparty_bank` | 对方开户行 |

#### 招商银行 `cmb_debit`

| 字段 | 说明 |
| :--- | :--- |
| `type` | 交易类型 |
| `balance` | 余额 |
| `remark` | 交易备注 |

#### 兴业银行 `cib_debit`

| 字段 | 说明 |
| :--- | :--- |
| `summary` | 摘要 |
| `balance` | 账户余额 |
| `counterparty_bank` | 对方银行 |
| `counterparty_account` | 对方账号 |
| `purpose` | 用途 |
| `channel` | 交易渠道 |
| `remark` | 备注 |

#### 平安银行 `pab_debit`

| 字段 | 说明 |
| :--- | :--- |
| `tx_type` | 交易类型（转入/转出）|
| `summary` | 摘要 |
| `balance` | 账户余额 |
| `note` | 备注 |
| `counterparty_account` | 对方账号 |

### 配置示例

全局配置（所有 Provider 生效）：

```yaml
defaults:
  output_metadata:
    - time
```

Provider 级别配置（仅该 Provider 生效，与全局合并）：

```yaml
providers:
  cib_debit:
    output_metadata:
      - counterparty_bank
      - counterparty_account
```

## Provider 特定功能

### 借记卡余额断言 (Balance Directive)

对账后可自动生成 Beancount `balance` 指令，用于校验账户余额。取账单中最后一笔交易的余额，日期为账单结束日次日。

按 Provider 级别控制，默认关闭：

```yaml
providers:
  pab_debit:
    accounts:
      "6666": Assets:Bank:PAB:6666
    balance: true
```

输出示例：

```beancount
2026-04-01 balance Assets:Bank:PAB:6666  12345.67 CNY
```

### 农业银行信用卡 (abc_credit)

农业银行账单会显示刷卡金抵扣金额，但不会在交易明细中体现。Bean-Sieve 支持：

1. **自动核对**：比较解析的消费金额与账单应还金额，判断是否平账
2. **自动生成刷卡金条目**：平账时自动生成刷卡金收入记录

#### 配置

```yaml
providers:
  abc_credit:
    accounts:
      "1234": Liabilities:Credit:ABC:U-示例卡1234
    # 刷卡金收入账户（生成条目时使用）
    rebate_income_account: Income:Rebate:ABC
    # 关键词：用于识别账本中已存在的刷卡金记录
    rebate_keywords:
      - 刷卡金
      - 返现
```

#### 去重检测逻辑

配置 `rebate_income_account` 或 `rebate_keywords` 后，对账时会在账本的 Extra 条目中查找：

- 日期在账单周期内
- 账户包含卡号后四位
- 金额精确匹配
- 描述包含关键词 **或** posting 使用了指定的收入账户

如果找到匹配记录，显示 `✅ 平账 (刷卡金 X.XX 已记录)`；否则自动生成刷卡金条目。

#### 输出示例

```beancount
; --- 刷卡金抵扣 ---
2025-11-27 * "农业银行" "刷卡金抵扣 (尾号1234)"
  Liabilities:Credit:ABC:U-示例卡1234  1.33 CNY
  Income:Rebate:ABC

; ============================================================
; 农业银行信用卡 账单核对
; ============================================================
;
; 卡号: 620000******1234 (尾号 1234)
; 账单周期: 2025/10/28-2025/11/27
;
;   解析消费:           32036.00 CNY
;   账单应还:           32034.67 CNY
;   刷卡金抵扣:             1.33 CNY
;
;   状态: ✅ 平账 (刷卡金 1.33)
```

## 数据格式约定

### Transaction 字段

| 字段          | 类型    | 说明                       |
|---------------|---------|----------------------------|
| `date`        | date    | 交易日期                   |
| `time`        | time    | 交易时间（如有）           |
| `amount`      | Decimal | 金额（支出为正，收入为负） |
| `currency`    | str     | 币种                       |
| `description` | str     | 原始描述                   |
| `payee`       | str     | 交易对方                   |
| `order_id`    | str     | 订单号/流水号              |
| `provider`    | str     | 数据源标识                 |
| `metadata`    | dict    | 扩展元数据                 |

### Metadata 字段

不同 Provider 会提取不同的 metadata：

**Alipay:**

- `category`: 交易分类
- `peer_account`: 对方账号
- `method`: 收/付款方式
- `status`: 交易状态
- `merchant_id`: 商家订单号

**Wechat:**

- `tx_type`: 交易类型（商户消费、转账、红包等）
- `method`: 支付方式
- `status`: 当前状态
- `commission`: 服务费（如有）

## 开发

```bash
# 安装开发依赖
uv sync --extra dev

# 运行测试
uv run pytest

# 代码检查
uv run ruff check src/ tests/

# 格式化
uv run ruff format src/ tests/
```

## 项目结构

```
bean-sieve/
├── bean-sieve.example.yaml    # 配置示例
├── bean-sieve.schema.json     # 配置 JSON Schema
├── src/bean_sieve/
│   ├── api.py                 # API 层
│   ├── cli.py                 # CLI 入口
│   ├── core/
│   │   ├── types.py           # 数据类型定义
│   │   ├── sieve.py           # 去重/匹配引擎
│   │   ├── rules.py           # 规则匹配引擎
│   │   ├── preset_rules.py    # 内置预设规则
│   │   ├── output.py          # Beancount 输出生成
│   │   ├── export.py          # CSV/XLSX 导出
│   │   └── suggest.py         # 规则自动生成
│   ├── providers/
│   │   ├── base.py            # Provider 基类
│   │   ├── payment/           # 支付平台（支付宝、微信、京东）
│   │   └── banks/
│   │       ├── credit/        # 信用卡（农行、中行、交行等）
│   │       └── debit/         # 借记卡（建行、工行、平安）
│   └── config/
│       ├── schema.py          # 配置 Schema
│       └── wizard.py          # 账户映射向导
└── tests/
```

## Community

[LINUX DO](https://linux.do/) - 社区讨论与交流

## License

MIT
