notion-bill

Notion 记账系统 — 创建/查询账单、管理收支记录

SKILL.md

GitHub

notion-bill — Notion 记账系统

基于拉琪奥 Agent 迁移的 Notion 账本系统,管理「收支记录」数据库。

数据库配置

配置 值
账本 database_id 12366ad7-c9c4-8141-8f05-e335b3d0cb5b
账本 data_source_id 12366ad7-c9c4-81d6-9cbc-000bcd11a4d0
人脉 database_id 1f766ad7-c9c4-8007-a335-d4f650b7217f
人脉 data_source_id 1f766ad7-c9c4-809b-b8aa-000b9c738b61
API Key 路径 ~/.config/notion/api_key
Notion-Version 2025-09-03

⚠️ 铁律(违反会出严重问题)

1. 选项验证铁律

创建账单前必须查询数据库元数据,验证所有 select/multi_select 值已存在,绝对不允许直接创建新选项。

验证方式:用 data_source_id 查询数据库元数据 GET /v1/data_sources/{data_source_id}

2. 审核流程铁律

所有账单创建/删除操作,必须先展示计划,用户确认(Y/N)后再执行。

审核清单:项目、金额、日期、大项、小项、渠道、平台、标签、相关人员

3. 平台字段处理

  • 不确定填什么 → 留空(不传该字段)
  • 不要随意填「其他」
  • 预设平台:拼多多、淘宝、京东、美团、steam、闲鱼

4. 状态字段

  • ✅ 用「已结算」
  • ❌ 不要用「已完成」

5. 金额正负号铁律

所有金额都用正数,无论收入还是支出。 方向由「大项」区分(收入 vs 饮食/日常购物等),不由正负号区分。

  • ✅ 支出:正数(¥35.79)
  • ✅ 收入:正数(¥10.00)
  • ✅ 资金流转入/出:正数
  • ❌ 收入不要用负数(¥-10.00 是错的)
  • ⚠️ 唯一的例外:退款 — 退款记录用负数金额,标题含「退款」

6. 标题与图标分离

标题字段不要包含 emoji。 Emoji 通过 icon 属性单独设置。

  • ✅ 标题 = "上海燕矽食品",icon = "🥡"
  • ❌ 标题 = "🥡 上海燕矽食品" — emoji 重复,icon 已经设了
  • 查询脚本展示时会自动根据 icon 加 emoji 前缀,那是展示层的行为,不影响存储

分类规则

大项(16 项)

饮食、日用杂货、休闲娱乐、日常购物、固定消费、生活服务、金融投资、收入、贷款、借款、退款、他人消费、信息遗失、仅记录、资金流转出、资金流转入

小项(53 项)

外卖、外出就餐、食材、日用品、房租、电费、电话费、电子产品、数字产品、内容消费、工资、兼职、打工、投资分红、转账、代单、交通、退款、利息、零食、饮料、服装、速食、生活费、资金流转、游戏、水费、学费、卡券包、医社保、户外活动、红包、酒店、租赁、流量、他人消费、借款、仅记录、打印、文创周边、信息遗失、服务费、班费、报销、报名费、投资理财、邮寄、贷款、理发、食堂、其他 等

交易渠道(16 项)

微信零钱、微信零钱通、支付宝(余额交易统一用这个,没有单独的「支付宝余额」渠道)、京东白条、美团月付、平安银行储蓄卡、中国银行储蓄卡、中国银行信用卡、中国银行社保卡、邮储银行储蓄卡、工商银行信用卡-银联/VISA、京东小金库、余额宝(余额宝内交易)、其他

特殊场景规则

  • 转账/红包:小项用「生活费」(家人转账)或「资金流转」(一般转账),不能用「工资」
    • ⚠️ 数据库中无「转账」小项,不要使用
  • 代付/请客:区分方向(看钱往哪流):
    场景 大项 小项 示例
    你帮舍友付(你支出) 饮食 代单 你下单付两份,舍友之后转账给你
    舍友还你钱(你收入) 收入 代单 舍友把AA份额转给你
    食堂带饭(你支出,帮舍友带一份) 饮食 代单 支付宝付给食堂摊主(如马海涛),20自己的+17舍友的;自己的记为食堂,舍友的记为代单。银行账单显示为"支付宝-马海涛",不要被收款人姓名误导
    • 两种方向都需设父项指向对应的实际消费记录
    • 食堂带饭场景的父项指向用户自己那份食堂记录
    • 室友间AA吃饭通过微信转账付款,不要因为截图写着"转账"就分类为资金流转
  • 大额餐饮(>200元):需确认
  • 负数金额:标题需含「退款」
  • 外卖红包/卡券:大项=饮食,标签=卡券包

退款场景

场景 A:单一退款(正常退货退款)

有退款的消费必须创建两条关联记录:

记录 1:原始消费

  • 项目:实际名称
  • 金额:原值
  • 大项:实际类别(如饮食)
  • 小项:实际小项(如外卖)
  • 标签:实际标签

记录 2:退款记录(关联父项)

  • 项目:「退款」+ 商户名(如"退款(肯德基)")
  • 金额:原值(正数)
  • 大项:退款
  • 小项:退款
  • 标签:退款
  • 父项:relation → 原始消费的 page ID

场景 B:先付 → 退款 → 再付(同一商品重新下单)

银行账单上会出现三条记录:一笔消费、一笔退款、再一笔消费。 必须创建三条关联记录:

记录 1:第一单(被退款的)

  • 大项/小项/金额/渠道:正常分类
  • 标签:按首次下单时间

记录 2:退款(关联第一单)

  • 大项=退款,小项=退款
  • 父项 → 第一单 page ID

记录 3:第二单(实际的消费)

  • 大项/小项/金额/渠道:正常分类
  • 标签:按第二次下单时间(可能不同餐时)

净效果:两笔支出 + 一笔退款 = 一笔净支出 ✅

时间标签规则

  • 06:00-10:00 → 早餐
  • 11:00-14:00 → 午餐
  • 17:00-21:00 → 晚餐
  • 22:00-06:00 → 夜宵

默认值

用户无特殊说明时:

  • 项目名 = 「外卖」(零食/饮料类用「零食」/「饮料」)
  • 大项 = 饮食
  • 小项 = 外卖(零食/饮料类用零食/饮料)
  • 交易渠道 = 微信零钱
  • 平台 = 留空
  • 标签 = 外卖 + 午餐/晚餐(按时间)—— 零食/饮料类用零食/饮料代替"外卖"
  • 图标 = 🥡(零食=🍿,饮料=🥤,外出就餐=🍜)
  • 状态 = 已结算

易错点与经验教训(实战沉淀)

1. 白条/美团月付等「未结算分期」去重铁律

触发条件:银行账单显示白条/美团月付扣款时。

错误模式:直接在库中新建一条「白条还款 ¥金额」,导致库里出现两条同月同金额的重复记录。

正确做法:

  1. 先用 POST /v1/data_sources/{id}/query 查:平台=京东 + 小项=还款 + 状态=未结算 + 交易渠道=空 的同月记录
  2. 找到原版后 PATCH:金额 → 银行实际值、交易日期 → 银行扣款日、交易渠道 → 扣款卡、状态 → 已结算、父项 → 补全涉及商品
  3. ❌ 绝对不要新建

搜索模板:

{"filter":{"and":[
  {"property":"平台","select":{"equals":"京东"}},
  {"property":"小项","select":{"equals":"还款"}},
  {"property":"状态","status":{"equals":"未结算"}}
]}}

2. 人脉关联不要只查我记得的

错误模式:用户告知几个名字后,我只查了"阮承远"+"冯忠耀"(因为我"记得"这俩在库),其他人漏了关联。

正确做法:用户每给一个名字 → 立即用 POST /v1/search 在人脉库(database_id=1f766ad7-c9c4-8007-a335-d4f650b7217f)查。人脉库是源头不是记忆。

昵称≠真实姓名("拿琛橡"="阮承远"、"马老师"="马涵君"、"裘隅闿"="谢雨婷"、"郑钩杰"="郑钧杰")。同时尝试昵称+真实姓名。

3. 项目名用真实姓名,不用微信昵称

触发场景:群收款/转账/红包等含人名的记录。

  • ❌ "群收款-来自马老师" → 保留昵称
  • ✅ "群收款-来自马涵君" → 改为真实姓名

项目名是查询/检索的字符串,用真实姓名保证按"姓名"搜索能命中。

4. 金额"全款 vs 定金"必问

触发场景:银行卡账单显示"扣 ¥X、退款 ¥X、再付 ¥X"三连。

必问用户:

  • ¥X 是全款还是定金?
  • 实际成交价?
  • 退款后再付走闲鱼还是支付宝?

经典案例:买移动空调 ¥420 → 原本想走闲鱼,但线下交易后支付宝扣 ¥420 → 卖家孙明良支付宝退款 ¥420 → 再付 ¥420 走中行储蓄卡。

  • 建 3 条:原始消费(移动空调 ¥420 平台=闲鱼)+ 退款(¥420)+ 再付
  • 不关联人脉(一次性交易,无后续交集)

5. /tmp 下的脚本会被定期清理

症状:写完 /tmp/batch5.py 跑完后,下一轮说"can't open file"。

正确做法:

  • 脚本写到持久目录:/home/po/.hermes/scripts/ 或 ~/workspace/
  • 或每轮重新 inline 写脚本
  • 关键中间结果(page_id 映射表)保存到 .hermes/cache/ 不是 /tmp/

API 调用要点

关键端点

  • POST /v1/search — 查询记录和人脉(推荐,比 /data_sources/{id}/query 稳定)
  • POST /v1/pages — 创建账单页
  • PATCH /v1/pages/{id} — 更新账单
  • GET /v1/data_sources/{data_source_id} — 获取数据库元数据(验证选项用)

⚠️ Python 脚本编写注意

不要在 write_file 或 terminal -c 中直接写 Path.home().joinpath(...) 长路径。 工具可能在序列化时截断为 Path.h...。

正确做法:用 terminal 的 heredoc 写脚本文件再执行:

cat > /tmp/script.py << 'SCRIPTEOF'
import ...
apikey = Path.home().joinpath('.config/notion/api_key').read_text().strip()
...
SCRIPTEOF
python3 /tmp/script.py

或者用 os.path.expanduser 避免长链式调用:

import os
apikey = Path(os.path.expanduser("~/.config/notion/api_key")).read_text().strip()

⚠️ 金额浮点精度陷阱

Python 的 float 序列化与 Notion API 返回的金额可能有精度差异:

Notion API 返回: 60.9    (float from JSON)
Python f-string: 60.90   (float → "60.9")

当通过 POST /v1/search 按标题+金额+日期查找页面时,不要直接用精确字符串匹配金额。正确做法:

# ❌ 会漏匹配
key = f"{title}|{amount}|{date_str}"  # 60.9 vs 60.90

# ✅ 用容差比较
if title == t_title and abs(amount - t_amount) < 0.01 and date_str == t_date:
    # match!

更稳健的方案:用 data_sources/{id}/query 拉取整页列表,按金额+日期+标题三元组模糊匹配。

Python 模板

import urllib.request, json
from pathlib import Path

key = Path.home().joinpath(".config/notion/api_key").read_text().strip()
headers = {
    "Authorization": f"Bearer {key}",
    "Notion-Version": "2025-09-03",
    "Content-Type": "application/json"
}

# 创建账单
body = {
    "parent": {"database_id": "12366ad7-c9c4-8141-8f05-e335b3d0cb5b"},
    "properties": {
        "项目": {"title": [{"text": {"content": "外卖"}}]},
        "金额": {"number": 19.07},
        "交易日期": {"date": {"start": "2026-04-30"}},
        "交易渠道": {"select": {"name": "微信零钱"}},
        "大项": {"select": {"name": "饮食"}},
        "小项": {"select": {"name": "外卖"}},
        "标签": {"multi_select": [{"name": "外卖"}, {"name": "晚餐"}]},
        "状态": {"status": {"name": "已结算"}}
    },
    "icon": {"type": "emoji", "emoji": "🥡"}
}

查询人脉

search_body = {"query": "姓名"}
# POST /v1/search → 筛选人脉数据库的页面
# 用页面 ID 关联
"相关人员": {"relation": [{"id": "联系人页面ID"}]}

⚠️ 人脉创建流程

当代单/关联记录用到的人不在人脉库时,必须先创建联系人再创建账单:

  1. 先用 POST /v1/search + 人脉 database_id 搜索姓名
  2. 如果未找到,POST /v1/pages 到人脉库创建(只需「姓名」字段)
  3. 拿到联系人 page_id 后在账单中设置 "相关人员": {"relation": [{"id": "xxx"}]}
  4. 常见情况:微信昵称≠真实姓名(如"让漪聃"=王怡然),需要用户确认对应关系

京东白条分期管理

白条分期涉及三层数据结构,不要混淆:

数据结构

层级 说明 大项 小项 金额 示例
购买记录 在京东白条上买的商品本身 日常购物 电子产品/服装等 商品全价 OPPO Find X8 4399元
分期记录 每期还款的独立记录 日常购物 还款 每期金额 (183.27) OPPO第19/24期
月度账单 当月实际扣款的汇总记录 日常购物 还款 各分期之和 (309.60) 5月账单

关系(父项指向)

月度账单 (309.60)
  ├── 父项 → 购买记录 (OPPO, 正装)        ← 指向商品
  │
分期记录 (183.27, 第19期)
  └── 父项 → 购买记录 (OPPO)              ← 指向商品

分期记录 (126.33, 第2期)
  └── 父项 → 购买记录 (正装)              ← 指向商品

关键规则

1. 先查已有分期记录,不要新建

数据库中已有按到期日自动创建的 未结算 分期记录(平台=京东,无渠道,节点为未结算)。当银行账单显示白条扣款时:

❌ 不要新建一条分期记录
✅ 找到已有的那条,PATCH 更新:
   - 交易日期 → 改为实际扣款日(银行截图上的日期)
   - 交易渠道 → 扣款卡(如中国银行储蓄卡)
   - 状态 → 已结算

2. 银行端扣款名称对照

京东白条还款在银行账单中可能显示为:

  • 网银在线-肯特瑞小额贷... → 白条还款

不要被商户名误导,直接记作:

  • 项目名:「白条还款」
  • 大项=日常购物,小项=还款,标签=还款
  • 平台=京东

3. 月度账单记录

每月会用扣款卡一次性扣款(金额=所有到期分期之和),需要建一条月度账单记录:

项目:白条还款
金额:各分期之和(如 126.33 + 183.27 = 309.60)
渠道:扣款卡(如中国银行储蓄卡)
大项:日常购物
小项:还款
标签:还款
平台:京东
状态:已结算
父项 → 所有涉及的商品购买记录(如 OPPO、正装)

4. 补全缺失的分期记录

如果京东白条账单显示有分期(如正装第2期 126.33),但数据库中查不到对应记录,需要手动创建:

项目:白条还款
金额:分期金额(如 126.33)
渠道:扣款卡
大项:日常购物
小项:还款
标签:还款
平台:京东
状态:(如果已还=已结算,如果未还=未结算)
父项 → 对应商品购买记录

5. 提前建好未来分期

当前月还完后,剩余的未还分期需要提前建好(设为 未结算,无渠道),有规律可循:

  • 分期期数 = 24总期 - 已还期数
  • 每期金额固定(如 OPPO 183.27/期)
  • 到期日按原记录的间隔推算(如5/31 → 7/1 → 7/31 → 8/31 → 10/1 → 10/31)
  • 父项 → 对应商品购买记录
  • 参考已有的分期记录格式(平台=京东,渠道留空,标签=还款)

6. 分期记录快速查询

# 搜索所有 白条分期(小项=还款 且 平台=京东)
search 项目 含 "白条还款" OR 平台 = "京东"

# 区分:
# - 渠道为空 + 未结算 = 未来的分期(不要手动设为已结算)
# - 渠道有值 + 已结算 = 已还的分期
# - 平台=京东 + 小项≠还款 = 商品购买记录(用作父项)

截图记账工作流(通用版)

用户发送任意渠道的账单截图时(微信零钱、银行储蓄卡/信用卡、支付宝等),按以下流程处理:

第一步:视觉识别

使用视觉工具提取所有交易记录,注意识别:

  • 交易日期、商户名称、金额(区分支出/收入)
  • 交易类型(网上快捷支付、跨行转账、代收扣款、工资等)
  • 卡号信息(确认是哪个银行/渠道)

⚠️ 视觉工具选择(铁律):

  • 直接用 mmx vision describe <image_path> — 不要调用 vision_analyze,它走 MiniMax M2.7(纯文本模型),永远返回 "I don't see any image"
  • mmx 路径:~/.npm-global/bin/mmx。mmx quota 可查 VLM 额度(coding-plan-vlm 配额)
  • Feishu 收到的截图是 WebP 格式(文件名虽为 .jpg),不需要转换——mmx vision describe 直接支持 WebP
  • 如需通过 Python 发送给 MiniMax API,需先 PIL.Image.open() 转 JPEG 再 base64
  • ⚠️ mmx 超时:prompt 太长会超时(30s 不够,建议 60s)。保持 prompt 简洁——「逐条列出所有交易:日期、金额、商户名」即可
  • 新方式:Hermes 原生 vision 工具可用 —— 用户发送图片后 Hermes 自动提取图片文本描述。如果已有描述可直接使用,不用重复调用 mmx

第二步:查询已有记录,交叉比对去重

关键步骤:先查询数据库中近期的所有记录(POST /v1/search 拉取最近 100 条),与截图内容做交叉比对:

  • 已存在的记录:金额 + 商户 + 日期能对应上的,标记为已有,不再创建
  • 需要更新的记录:用户可能要求修改已有记录的日期/渠道/状态(如白条还款改日期+加渠道),识别后进入更新流程
  • 新增记录:未在数据库中出现的交易,进入分类环节
  • 特殊:还款类账单(白条还款等定期还款)—— 数据库中可能已有记录(按还款日创建),截图中的扣款可能是同一条的银行端体现。改已有记录不加新记录

第三步:查询同渠道历史记录,参考分类风格

在分类前,先搜索数据库中使用同一交易渠道的历史记录:

  • 如中国银行储蓄卡的电话费 → 固定消费/电话费/移动话费
  • 同渠道同类型的分类规则具有一致性,优先沿用
  • 这比单纯按商户名判断更准确

第四步:分类

按本 skill 的分类规则对每笔新交易分类:

  • 餐饮店/餐厅 → 默认小项=外卖(外卖订单),仅当明确堂食才用外出就餐
  • 按"外卖 vs 外出就餐"判断表确定
  • 数字产品/API → 日常购物/数字产品
  • 物理桌面配件(鼠标垫、数据线等)→ 日用杂货/日用品(不是数字产品!)
  • 家人转账 → 收入/生活费
  • 退款 → 退款/退款 + 关联父项
  • 自贩机零食 → 饮食/零食
  • 自贩机饮料 → 饮食/饮料
  • 食堂 → 饮食/食堂
  • 代单方向判断:
    • 你转给舍友(你付钱)→ 饮食/代单
    • 舍友转给你(你还钱)→ 收入/代单
  • 个人转账 → 资金流转出/资金流转

第五步:更新已有记录

当用户要求修改已有记录时(如改日期、改渠道、改状态):

  1. 用 POST /v1/search 找到该记录的 page ID
  2. 用 PATCH /v1/pages/{id} 更新对应字段
  3. 更新后验证确认

常见更新场景:白条还款修改

  • 数据库中已有按还款日创建的白条还款记录(无渠道、未结算)
  • 收到银行账单截图后,需要改已有记录:
    1. 查询该还款记录(按日期+标题)
    2. 获取完整 page ID(不可用截断的前8位)
    3. PATCH 更新:金额(按实际账单值)、交易日期(银行实际扣款日)、交易渠道(扣款卡)、状态→已结算
    4. 父项补充:如果账单中有新的分期商品不在已有父项里,需要先创建该商品的购买记录,再把父项添加进去
  • 父项去重:PATCH relation 前检查是否有重复 ID,去重后再提交

银行端显示名对照:

  • 京东白条还款:银行显示"网银在线-肯特瑞小额贷..." → 记"白条还款"
  • 基金定投:银行显示"支付宝-蚂蚁(杭州)..." → 记"支付宝·基金定投"
  • 公交卡扣款:银行显示"支付宝-宁德市公共" / "支付宝-上海公共交通" → 记"公共交通卡"
  • 注意:银行账单的中间商户名 != 实际消费内容,如实际是 SteamPY 退款,银行显示"支付宝-上海部恩科",应记作"退款(SteamPY)"

第六步:审核(铁律)

展示完整计划给用户确认:

  • 更新操作:说明原值→新值
  • 新增操作:项目、金额、日期、大项、小项、渠道、标签

第七步:批量创建

用 Notion API 批量创建新页面。

父项-子项关联(退款 / 代单)

当有退款或代单需要关联父项时,必须分两阶段创建:

阶段 1:创建所有原始消费记录(父项)

  • 用 POST /v1/pages 逐一创建,每条间隔 ≥0.3 秒(API 限速)
  • 捕获每个返回的 page.id
parent_ids = {}  # index → {title, amount, date, id}
for i, bill in enumerate(parent_bills):
    result = notion_post("pages", body)
    parent_ids[i] = {"title": bill["title"], "id": result["id"]}
    time.sleep(0.3)

阶段 2:创建关联记录(子项),设置 relation

  • 退款记录:大项=退款、小项=退款,设置 "父项": {"relation": [{"id": parent_id}]}
  • 代单记录(方向决定大项):
    • 你帮舍友付(你支出)→ 大项=饮食、小项=代单
    • 舍友还你钱(你收入)→ 大项=收入、小项=代单
  • 无论方向,代单的 父项 都指向对应的实际消费记录(不是反过来)
"父项": {"relation": [{"id": "父项的pageID"}]}

页面 ID 查找模式

创建完成后如果需要回头查找页面 ID(例如脚本中断后补跑),首选模式:

  1. 调用 POST /v1/data_sources/{DATA_SOURCE_ID}/query 拉取最近记录
  2. 按 (title, round(amount, 2), date) 三元组匹配
  3. 注意 float 精度:API 返回 60.9 而非 60.90,用 abs(amount - target) < 0.01 比较
  4. ⚠️ 页面创建后需要获取完整 ID(数据库中查到的才是完整 UUID),仅用创建返回值的前8位 PATCH 会 404

第八步:验证

查询确认写入成功

核心分类原则

⚠️ 关键区分:同一家店(如雪芳餐饮、象郡餐饮),叫外卖 vs 堂食,小项和标签完全不同:

消费方式 项目名 大项 小项 标签 图标 说明
外卖(点餐平台送到) 「外卖」或商户简称 饮食 外卖 外卖+餐食 🥡 默认值——不确定走这个
堂食/到店吃 商户全名 饮食 外出就餐 外食+餐食 🍜 仅当用户明确说去店里吃
食堂 「外食」(用户偏好,不用商户名) 饮食 食堂 餐时(午餐/晚餐) 🍚
零食(自贩机/小卖部) 「零食」 饮食 零食 零食+餐食 🍿
饮料(自贩机/超市) 「饮料」 饮食 饮料 饮料+餐食(或饮料+夜宵) 🥤 注意:自贩机非代单时用饮料/零食
奶茶/饮品店(悸动烧仙草等) 商户简称 饮食 饮料 饮料+餐时 🥤 即时饮品消费,非外卖
淘宝/平台买饮料(整箱/多瓶) 「淘宝·盐汽水」 饮食 饮料 饮料 🥤 平台=淘宝,不标餐时标签

常见分类对照

微信商户类型 默认小项 标签 示例
餐饮店/餐厅(外卖订单) 外卖 外卖+餐食 雪芳餐饮、象郡餐饮、牛哥酸菜鱼、正新鸡排
餐饮店/餐厅(堂食) 外出就餐 外食+餐食 上海市食堂三楼**(食堂)**
快递/电商平台(外卖) 外卖 外卖+餐食 京东(外卖)
全国连锁快餐(微信支付) 外卖 外卖+餐食 塔斯汀、正新鸡排
自动售货机(零食) 零食 零食+餐食 农夫山泉自贩机
自动售货机(饮料) 饮料 饮料+餐食 农夫山泉自贩机(饮料)
自动售货机(泡面/非饮料即食) 零食 零食+餐食 农夫山泉(安吉)智能生活(泡面)
食堂/学校餐厅 食堂 餐食 上海市食堂三楼
食堂(支付宝付给个人) 饮食/食堂 餐食 支付宝-马海涛(食堂摊位收款人)
电费代扣(学校代收) 固定消费/电费 电费 上海中侨职业技术大学-代收扣款
电费代单还款(舍友分摊) 收入/代单 代单 zzh/王怡然/sjh各转75,父项指向电费记录
AI/API 服务 日常购物/数字产品 数字产品 杭州深度求索
阿里云/云服务 日用杂货或日常购物/数字产品 API, 数字产品 阿里云百炼、阿里云计算
移动话费/手机充值 固定消费/电话费 移动话费 中移电子商务(电话费)中国银行储蓄卡
蜜雪冰城/悸动烧仙草等奶茶店 饮食/饮料 饮料 蜜雪冰城、悸动烧仙草。标签=饮料(+餐时如果知道时间)
基金定投(银行端"支付宝-蚂蚁(杭州)") 金融投资/基金 基金 支付宝-蚂蚁(杭州)扣款。项目名=「支付宝·基金定投」,渠道=扣款卡。智能定投金额随涨跌幅浮动(如 ¥274→¥299→¥599),不要用之前金额当固定值比对
学校补贴工资("上海中侨职业技术大学"收入) 收入/工资 工资 学校打款,项目名=「学校补贴工资」,渠道=入账卡
食堂(支付宝/校园卡) 饮食/食堂 午餐或晚餐 支付宝-孙利纳 中国银行储蓄卡
公交卡扣款(银行端"支付宝-宁德市公共"/"支付宝-上海公共交通") 固定消费/交通 交通 项目名=「公共交通卡」,渠道=扣款卡。金额常见 ¥1/¥2/¥3/¥4/¥5
  • 家人转账 → 收入/生活费 | 生活费 | 「生活费」,关联人脉库对应的人
  • 家人暂存 → 资金流转入/资金流转 | 暂存 | 爸转的临时存放资金,不是生活费!标签=暂存,以后转回时做资金流转出对冲
  • 刷课收入(微信收款/转账) → 收入/工资 | 刷网课 | 项目名可简写如"来自hy老师"/"来自花椰菜",小项=工资,标签=刷网课,关联人脉
  • 代做作业收入 → 收入/工资 | 作业 | 项目名如"来自翩",小项=工资,标签=作业。与刷网课同理,属于劳务收入
  • 二手回收收入 → 收入/其他 | 二手回收 | OPPO Find X8 回收,回收宝打款到支付宝余额。父项关联原始购买记录。 | 余额宝收益 | 收入/利息 | 利息 | 渠道=余额宝,标签=利息 | | 自贩机泡面/非饮料即食 | 饮食/零食 | 零食+餐食 | 农夫山泉(安吉)智能生活(泡面,非自产饮料) | | 拼多多/淘宝买饮料 | 饮食/饮料 | 饮料 | 不标餐时标签,平台=拼多多/淘宝 | 付费通(拼多多支付),记实际商品名 | | 退款(平台退款) | 退款/退款 | 退款 | 项目名=「退款(平台名)」,如退款(SteamPY)、退款(肯德基)。不要用银行账单显示的中间商户名(如银行显示"支付宝-上海部恩科",实际是 SteamPY 退款,记作退款(SteamPY)) | | 个人转账 | 资金流转出/资金流转 | 资金流转 | 转给 zzh | | 物理配件/周边(鼠标垫、手机壳、数据线等) | 日用杂货/日用品 | 日用品 | 淘宝鼠标垫。❌ 不要错分类为"数字产品" | | 多件杂类日用品(京东白条一单多品如散热器+空气清新剂+扫把) | 日用杂货/日用品 | 日用品 | 按总价记一条,如酷睿冰尊等3种 ¥186.50。平台=京东 |

外卖 vs 外出就餐 快速判断

线索 判定
商户名是正新鸡排/塔斯汀/京东等外卖平台 ✅ 外卖
用户没说"去吃了"、"堂食" ✅ 默认=外卖
商户名带具体楼层(中侨一楼) ✅ 默认=外卖(中侨一楼商户除非用户明确说是堂食,否则默认外卖)
用户说"去吃的"、"到店"、"堂食" ✅ 外出就餐

支付宝 ↔ 余额宝 多账户资金流转

参见 references/alipay-yuebao-flow.md。

核心原则:双账户视角,每一跳都记,不跳过任何环节。

跨账户资金流转(如银行充值微信)的对端关联模式参见 references/cross-account-flow-pairing.md。

渠道速查

渠道 用途
支付宝 支付宝余额变动(回收款到账、转入余额宝、余额宝转回、提现)
余额宝 余额宝内交易(转入、转出、收益)
⚠️ 不存在「支付宝余额」渠道,余额交易统一用「支付宝」

完整链路模式(以 OPPO 回收为例)

支付宝侧:

回收宝 +1382 → ①OPPO回收(收入/其他, 支付宝)
  → ②转入余额宝(资金流转出, 支付宝)  ← 子→①
  → 钱在余额宝里...
  → ⑦余额宝转回余额(资金流转入, 支付宝) ← 子→①
  → ⑥提现到社保卡(资金流转入, 中国银行社保卡) ← 子→⑦

余额宝侧(独立记录):

③自动转入余额宝(资金流转入, 余额宝)
④余额宝收益(收入/利息, 余额宝)
⑤余额宝转出(资金流转出, 余额宝)

父项子项关系

  • ①②⑦都挂在 ①OPPO回收 下作为子项
  • ⑥提现到社保卡挂在 ⑦余额宝转回余额 下
  • 余额宝侧的 ③④⑤ 独立,不需挂到 OPPO 回收
  • 所有资金流转记录必须加标签「资金流转」

正负号:金额全是正数,方向靠大项

  • 收入/资金流转入 → 流入
  • 饮食/资金流转出/日常购物 → 流出
  • 不存在负数金额(退款除外)

用户偏好

  • ❌ 不需要查还款类账单(白条还款等定期还款)
  • ✅ 只处理最近几笔日常交易
  • ✅ 重点关注最新消费记录
  • ⚠️ 平台字段不确定时留空
  • ⚠️ 所有账单操作必须先展示计划,用户确认