关于 transaction-deduplicator
用于处理交易数据的 Skill,可识别重叠账单导入中的重复及近似重复记录。它结合账户、带符号金额、描述和日期判断,并保留合法的重复消费。
主要功能
- 01按账户、带符号金额和描述匹配
- 02容许日期相差一天
- 03保留合法的重复消费
- 04标记近似重复项供复核
- 05将重复项关联到已有记录
适用场景
- 01去除重叠账单导入的重复交易
- 02保留详情相同的同日多笔消费
- 03复核待处理与最终入账的交易
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lyndonkl/ claude --skill transaction-deduplicator安装后在 Claude Code 中输入/transaction-deduplicator确认已加载。
详细介绍
交易去重器
目录
概述
账单文件经常存在重叠。1 月账单涵盖 12 月 15 日至 1 月 14 日;12 月账单涵盖 11 月 15 日至 12 月 14 日;同一笔 12 月 15 日的交易会同时出现在两份账单中。此技能可以识别这些重复项,同时避免误删同一天、同金额、同商户的真实重复扣款(例如一天内买了两杯咖啡)。
输入约定
调用方提供:
incoming— 新提取的交易数组:{date, post_date, account_id, amount_cents, description_raw, source}。existing— 存储中已有的交易数组,包含相同字段以及id。
去重键
通过以下元组识别重复项:
(account_id, abs(amount_cents), description_normalized, |date_a - date_b| <= 1 day)
description_normalized使用与分类器相同的规范化方式(转为大写、移除商户代码、移除地理信息、合并空格、删除日期)。- 1 天的时间窗口用于处理两个来源之间
date和post_date不一致的情况。 - 使用
abs(amount_cents)会导致退款与原始购买匹配时不被视为重复项(符号不同)。复合键使用带符号的金额。
使用带符号的 amount_cents。退款(符号相反)永远不会与购买构成重复项。
工作流
Dedupe Progress:
- [ ] Step 1: Index existing transactions by (account_id, signed_amount, normalized_desc)
- [ ] Step 2: For each incoming, look up the index
- [ ] Step 3: Filter index hits by date proximity (≤ 1 day)
- [ ] Step 4: If no hit, mark as new
- [ ] Step 5: If exactly one hit, mark as duplicate of that id
- [ ] Step 6: If multiple hits, run the multi-instance same-day rule
- [ ] Step 7: Surface near-duplicates (different amount or desc) for review
步骤 1 — 建立索引
构建 existing_by_key[(account_id, amount_cents, description_normalized)] = [tx, …]。
步骤 2 — 查找
对每笔传入交易计算其键元组,并查找对应分组。
步骤 3 — 按日期接近程度筛选
对于分组中的每个候选项,仅保留满足 |incoming.date − candidate.date| ≤ 1 day 的项。如果存在 post_date,则两侧都使用 min(date, post_date)。
步骤 4 — 无匹配项
标记 decision: "new"。记账员会将其追加到 transactions.json。
步骤 5 — 恰好一个匹配项
标记 decision: "duplicate",并关联 duplicate_of: <existing_id>。不要导入。
步骤 6 — 多个匹配项(真实的同日重复交易)
如果现有存储中同一天已有 N 笔键完全相同的交易,而传入批次中同一天有 M 笔键相同的交易:
- 如果
M ≤ N→ 所有传入交易都视为现有交易的重复项(按日期顺序一对一配对)。 - 如果
M > N→ 前 N 笔传入交易为重复项;剩余的M − N笔为新交易(真实的同日重复扣款,例如买了两杯咖啡、加油站预授权加最终扣款)。
此规则既能保留真实的重复扣款,也能抑制因账单重叠导致的重复导入。
步骤 7 — 审查近似重复项
近似重复项除金额或描述外均相同,且日期相差不超过 1 天。这类情况通常包括:
- 待处理扣款($45.00)以略有不同的金额($45.83)结算——保留最终扣款,删除待处理扣款。
- 商户名称在账单周期中发生变化("AMAZON.COM*ABC123" → "AMZN Mktp US")。
将这些项连同两条记录并列输出到 review[],并给出建议操作:keep_incoming_drop_existing | keep_existing_drop_incoming | keep_both | merge。
近似重复项处理
计算近似匹配项的相似度分数:
- 金额差异:金额相同为 1.0;相差不超过 $1 或 2% 为 0.9;相差不超过 $5 或 10% 为 0.5;否则为 0.0。
- 描述的 Jaccard 相似度:基于词元集合,范围为 0.0–1.0。
- 日期接近程度:同一天为 1.0;相差不超过 1 天为 0.7;相差不超过 3 天为 0.4。
near_dup_score = 0.4*amount + 0.4*description + 0.2*date。
当 0.7 ≤ near_dup_score < 0.95 时提交审查。高于 0.95 时视为重复项;低于 0.7 时视为独立交易。
输出约定
{
"new": [
{ "id": "tx_20260115_017", "decision": "new" }
],
"duplicates": [
{
"incoming_index": 4,
"decision": "duplicate",
"duplicate_of": "tx_20251220_003",
"reason": "exact key match within 1 day window"
}
],
"review": [
{
"incoming_index": 12,
"matched_existing_id": "tx_20260108_005",
"near_dup_score": 0.86,
"diff": {
"amount_cents": [-4500, -4583],
"description_raw": ["AMAZON PENDING", "AMZN MKTP US*AB12CD"]
},
"suggested_action": "keep_incoming_drop_existing",
"rationale": "incoming is the finalized charge (post_date set, definite merchant code)"
}
],
"summary": {
"incoming_total": 142,
"new_count": 96,
"duplicate_count": 44,
"review_count": 2
}
}
防护规则
- 符号很重要。 绝不能按绝对值将退款和消费合并。键中应使用带符号的金额。
- 仅限一天的时间窗口。 更长的时间窗口会在不同发薪周期之间产生误报。
- 仅限同一账户。 绝不能跨账户去重。从支票账户转出的 50 美元和存入储蓄账户的 50 美元是两条记录,并非重复记录。
- 在审核时保留原始描述。 向用户展示两个
description_raw字符串;不要展示规范化后的形式。 - 幂等性。 对相同输入运行两次去重,产生的输出相同。该技能绝不修改
existing。 - 审计。 对每条被抑制的重复记录,记录
duplicate_of,以便用户追溯某笔交易为何未出现在新导入的数据中。