mcpField
T
transaction-deduplicator

transaction-deduplicator

github.com/lyndonkl数据与数据库18738 次安装9 周前更新
代码仓库

关于 transaction-deduplicator

用于处理交易数据的 Skill,可识别重叠账单导入中的重复及近似重复记录。它结合账户、带符号金额、描述和日期判断,并保留合法的重复消费。

主要功能

  1. 01按账户、带符号金额和描述匹配
  2. 02容许日期相差一天
  3. 03保留合法的重复消费
  4. 04标记近似重复项供复核
  5. 05将重复项关联到已有记录

适用场景

  1. 01去除重叠账单导入的重复交易
  2. 02保留详情相同的同日多笔消费
  3. 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,以便用户追溯某笔交易为何未出现在新导入的数据中。

评论

支持 Markdown