最終更新: 2026/06/22 18:56
MAS-159: 銀行・クレカCSV取込の重複防止(冪等性)ガード
概要
| 項目 | 内容 |
|---|---|
| 案件ID | MAS-159 |
| カテゴリ | 自動入力パイプライン(即効) |
| Phase | Phase 1.5 |
| 優先度 | P1 (★★★) |
| 所要時間 | 1-2時間 |
| 対象ファイル | 100_config/101_sys_config.js, 500_import/501_cc_importer.js, 500_import/502_bank_importer.js |
| 前提案件 | MAS-145, MAS-146 |
目的
銀行CSV(MAS-145)やクレジットカードCSV(MAS-146)を取り込む際、ユーザーが誤って「同じ期間のCSVを2回アップロード」したり「期間が重複するCSVをアップロード」した場合に、二重取込(B/Sの現預金残高の崩壊)を防ぐ。トランザクションのハッシュ値を用いて冪等性を担保する。
現在のコード
500_import/502_bank_importer.js (L116-120)
if (importIdx['取込ハッシュ'] !== undefined) {
importSheet.getRange(row, importIdx['取込ハッシュ'] + 1).setValue(
computeTxHash_(tx.txDate, tx.memo, tx.deposit, tx.withdrawal)
);
}
※ハッシュは計算・出力されているが、重複チェックには使われていない。また、クレカ(501_cc_importer.js)にはハッシュ計算自体が存在しない。
修正方針
Step 1: DDLスキーマ変更
100_config/101_sys_config.js を修正し、33_wrk_bank と 34_wrk_card に「取込ハッシュ」列を追加する。
WRK_BANK: 末尾に取込ハッシュを追加。WRK_CARD:確認FLGの直前に取込ハッシュを追加。
Step 2: 銀行CSVの重複チェック実装
500_import/502_bank_importer.js を修正:
importBankStatement内で、33_wrk_bankの全行から取込ハッシュを読み込み、出現回数をカウントするマップ(bankHashMap)を作成。36_wrk_bank_importの各行を処理する際、現在のインポート内でのハッシュ出現回数(importHashMap)をカウントアップ。importHashMap[hash] <= (bankHashMap[hash] || 0)の場合、既に取込済みの重複データと判定し、処理結果を重複(取込済)、確認FLGをTRUEにしてマッチング処理をスキップする。applyBankSettlement内で、33_wrk_bankを更新する際、36_wrk_bank_importの取込ハッシュを33_wrk_bankに書き込む。
Step 3: クレカCSVの重複チェック実装
500_import/501_cc_importer.js を修正:
computeCcHash_(payDate, merchant, amount)ヘルパー関数を追加。importCcStatement内で、Step 2 と同様に33_wrk_bankのハッシュ出現回数マップを作成。34_wrk_cardの各行に対してハッシュを計算・出力し、重複判定を行う。重複の場合は処理結果を重複(取込済)、確認FLGをTRUEにしてスキップ。applyCcSettlement内で、33_wrk_bankを更新する際、34_wrk_cardの取込ハッシュを33_wrk_bankに書き込む。
影響範囲
33_wrk_bankと34_wrk_cardの列構成が変更される。- 銀行・クレカの取込処理において、既に消込済みの明細と同じ内容の明細がインポートされた場合、自動的に「重複」としてスキップされるようになる。
注意事項
- 同日・同額・同摘要の複数明細への対応: 単純なハッシュの存在チェック(
Set)ではなく、**出現回数のカウント(Map)**を用いること。これにより、本当に1日に2回同じ振込があった場合(例: 10,000円を2回振込)でも、1回目は重複、2回目は新規として正しく処理される。 101_sys_config.jsのautoColsやsetValiの列インデックス変更を正確に行うこと。
エッジケース
| 条件 | 表示値 | 理由 |
|---|---|---|
| 過去に1件取込済みのハッシュが、今回のCSVに2件含まれている場合 | 1件目: 重複(取込済)2件目: 通常処理 | 出現回数ベースで判定するため、差分の1件のみが新規として扱われる |
33_wrk_bank の有効フラグがFALSEの行 | カウントしない | 論理削除された明細は「無かったこと」として扱い、再取込を許可するため |
実データ検証
33_wrk_bankの既存データに取込ハッシュ列が追加された後、過去のデータにはハッシュが空欄となるが、空欄のハッシュは重複チェックから除外(無視)されるロジックになっているか確認。
関連ドキュメント
| 仕様書リンク | 関連箇所 |
|---|---|
| dev_mas-145_bank_csv_import.md | 銀行CSV取込ロジック |
| dev_mas-146_cc_auto_settlement.md | クレカ自動消込ロジック |
人間が検討すべき事項
なし(即実装可)
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-159「銀行・クレカCSV取込の重複防止(冪等性)ガード」を実装してください。
## 実行前タスク
以下のファイルを読み込んでください:
1. `100_config/101_sys_config.js` — `WRK_BANK` と `WRK_CARD` のヘッダー定義、`autoCols`、`setVali` の位置
2. `500_import/502_bank_importer.js` — `importBankStatement` と `applyBankSettlement` の既存ロジック
3. `500_import/501_cc_importer.js` — `importCcStatement` と `applyCcSettlement` の既存ロジック
## 修正対象ファイル
- `100_config/101_sys_config.js` (変更)
- `500_import/502_bank_importer.js` (変更)
- `500_import/501_cc_importer.js` (変更)
## 実装内容
### Step 1: DDLスキーマ変更
`100_config/101_sys_config.js` を修正:
- `WRK_BANK` のヘッダー: 末尾に `取込ハッシュ` を追加。
- 変更前: `["有効フラグ","決済ID(STL)","消込対象請求ID(INV)","決済日_計画","立替日","決済日_実績","決済ステータス","入出金区分","決済口座","取引先名","税込金額_決済","差額(手数料等)","差額処理科目","組織名","摘要","消込手段","自動仕訳JNL_ID"]`
- 変更後: `["有効フラグ","決済ID(STL)","消込対象請求ID(INV)","決済日_計画","立替日","決済日_実績","決済ステータス","入出金区分","決済口座","取引先名","税込金額_決済","差額(手数料等)","差額処理科目","組織名","摘要","消込手段","自動仕訳JNL_ID","取込ハッシュ"]`
- `WRK_CARD` のヘッダー: `確認FLG` の直前に `取込ハッシュ` を追加。
- 変更前: `["決済日_実績","ご利用者","カテゴリ","発生日(P/L計上日)","ご利用先など","税込金額_決済","決済区分","今回回数","訂正サイン","税抜金額_決済","国内/海外","摘要","備考","確認FLG","処理結果","マッチ決済ID(STL)","STL決済日_計画","STL税込金額_決済","STL取引先名","STL摘要"]`
- 変更後: `["決済日_実績","ご利用者","カテゴリ","発生日(P/L計上日)","ご利用先など","税込金額_決済","決済区分","今回回数","訂正サイン","税抜金額_決済","国内/海外","摘要","備考","取込ハッシュ","確認FLG","処理結果","マッチ決済ID(STL)","STL決済日_計画","STL税込金額_決済","STL取引先名","STL摘要"]`
- `autoCols` の修正: `WRK_BANK` に `18` を追加。
- `setVali` の修正: `WRK_BANK` の列番号変更はなし(末尾追加のため)。
### Step 2: 銀行CSVの重複チェック実装
`500_import/502_bank_importer.js` を修正:
- `importBankStatement` 内で、`33_wrk_bank` のデータを読み込み、有効フラグがTRUEの行の `取込ハッシュ` の出現回数をカウントする `bankHashMap` を作成(空欄は無視)。
- `36_wrk_bank_import` のループ内で、`importHashMap` を用いて現在のハッシュ出現回数をカウント。
- `importHashMap[hash] <= (bankHashMap[hash] || 0)` の場合、`処理結果` に `重複(取込済)`、`確認FLG` に `true` をセットし、マッチング処理(`extractBankCandidateStls_` 等の呼び出しや `isMemoFuzzyMatch_`)をスキップする。
- `applyBankSettlement` 内で、`33_wrk_bank` を更新する際、`36_wrk_bank_import` の `取込ハッシュ` を `33_wrk_bank` の `取込ハッシュ` 列に書き込む。
### Step 3: クレカCSVの重複チェック実装
`500_import/501_cc_importer.js` を修正:
- ファイル末尾に `computeCcHash_(payDate, merchant, amount)` を追加(`yyyyMMdd|merchant|amount` の形式)。
- `importCcStatement` 内で、Step 2 と同様に `bankHashMap` を作成。
- `34_wrk_card` のループ内でハッシュを計算し、`取込ハッシュ` 列に出力。
- `importHashMap` を用いて重複判定を行い、重複の場合は `処理結果` に `重複(取込済)`、`確認FLG` に `true` をセットしてスキップ。
- `applyCcSettlement` 内で、`33_wrk_bank` を更新する際、`34_wrk_card` の `取込ハッシュ` を `33_wrk_bank` の `取込ハッシュ` 列に書き込む。
## 制約
- 重複判定は必ず「出現回数(カウント)」ベースで行うこと。単純な `Set` による存在チェックは不可(同日同額同摘要の複数明細が処理できなくなるため)。
## エッジケース
- データなし: `33_wrk_bank` の `取込ハッシュ` が空欄の過去データは、`bankHashMap` に含めない(無視する)。
## 実データ検証
- `101_sys_config.js` の `WRK_CARD` のヘッダー追加により、既存の `確認FLG` 以降の列インデックスが1つずれるため、`501_cc_importer.js` 内の列インデックス参照(`findCardCol_` 等)が正しく追従するか確認。
## 動作確認
1. `npm run push:dev` を実行。
2. GASエディタで `setupAllSchemas` を実行し、`33_wrk_bank` と `34_wrk_card` に `取込ハッシュ` 列が追加されることを確認。
3. `36_wrk_bank_import` にテストデータを入力し、「🏦 銀行CSV 取込・マッチング」を実行。
4. マッチした明細を「🏦 銀行CSV 消込実行」で `33_wrk_bank` に反映(`取込ハッシュ` が書き込まれることを確認)。
5. 再度「🏦 銀行CSV 取込・マッチング」を実行し、先ほど消込した明細が `重複(取込済)` と判定されることを確認。
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|:--------:|------|
| Step 2-3 | あり | 同日同額同摘要の複数明細を正しく処理するための、出現回数ベースの重複判定ロジックの構築 |
推奨実行モデル
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| 仕様書作成(本ドキュメント) | Claude Opus 4.6 | 複数ファイルにまたがるデータフローと、出現回数ベースの高度な冪等性ロジックの設計が必要なため |
| 実装 | Claude Sonnet 4.6 | DDL変更と、既存のインポート処理への重複判定ロジックの組み込みが必要 |
変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-16 | 初版作成 |
| 2026-04-20 | 実装完了 (PR #221)。WRK_BANK / WRK_CARD に「取込ハッシュ」列追加。出現回数カウントベースで同日同額同摘要の複数明細に対応(単純ハッシュでは衝突する正当なケースを救う設計)。銀行: 金額完全一致 + 日付±3日 でマッチ、クレカ: computeCcHash_(yyyyMMdd|merchant|amount) でハッシュ化。UX 改善として集計ダイアログに重複検知件数を表示。drive-by fix: CC UNMATCHED 時の 確認FLG=FALSE セット漏れを同時修正。後続: MAS-171 クレカ N:1 消込合算マッチ / MAS-172 CC MATCHED 自動承認化検討 を新規起票 |