git:20260705.848fd9b to git:20260803.ffe2aeb

3 added, 0 removed. Audit A to A.

---
name: receipt-expense-workflow
description: "Company expense receipt workflow. OCR, rename, sort, summarize, and prepare receipt images/PDFs/videos for D365 expense mapping and attachment. Use when sorting company expense receipts, organizing travel expense files, OCR renaming, receipt sorting, レシート仕分け, D365経費カテゴリマッピング, or D365経費精算."
argument-hint: "仕分けたい領収書フォルダ、対象プロジェクト、必要な出力"
user-invocable: true
license: CC BY-NC-SA 4.0
metadata:
author: yamapan (https://github.com/aktsmm)
---
# Receipt Expense Workflow
OCR(Surya)を使った領収書の自動仕分け・リネーム・集計ツール。
## When to Use
- **領収書を仕分けて**, **レシートを整理して**, **receipt sorting**
- フォルダ内の領収書画像をプロジェクト単位で自動整理したい
- 大量のレシート写真に日付・金額・用途でファイル名を付けたい
- 出張経費の領収書を一括でリネーム&集計したい
## Core Workflow
1. 入力フォルダの画像 / PDF / ZIP / 動画を受け取る
2. OCR で日付・金額・国・カード・用途を抽出する
3. 品質補正をかけて標準ファイル名へ正規化する
4. プロジェクト単位で仕分ける
5. Markdown サマリーを出す
## Architecture
```
入力フォルダ(incoming/unassigned 等)
├─ JPEG/PNG/PDF/ZIP → OCR → 抽出 → リネーム → PJフォルダへ移動
├─ MP4/MOV → ffmpeg → JPG → OCR → ...
├─ カード不明 or テキスト不可 → 未分類フォルダ → 再仕分け可能
└─ 個人経費(D365対象外) → PJフォルダ/private/
```
> **`private/` フォルダ**: D365 に申請しない個人経費レシートを格納する。OCR後にユーザーが「個人経費」と判断した場合に移動する。
## Naming Convention
```
YYYY-MM-DD-国コード-金額[-カード]-分類.ext
例:
2026-02-09-jpn-14320-amex-shinkansen.jpeg
2026-02-11-us-272-amex-hotel.jpeg
2026-02-12-us-190.38-meal.jpeg ← カードなし
2026-02-09-us-6.80-amex-meal-starbucks.jpeg
```
国コード一覧、分類一覧、D365 カテゴリ対応、添付手順は [references/d365-expense-guide.md](references/d365-expense-guide.md) を参照。
## CLI Usage
```powershell
# Dry-run(確認のみ、ファイル移動なし)
python receipt_sorter.py --project "202602_Domestic_Trip" --dry-run
# 本実行
python receipt_sorter.py --project "202602_Domestic_Trip" --input "incoming\unassigned"
# ログ指定
python receipt_sorter.py --project "202602_Domestic_Trip" --input "incoming\unassigned" --log "result.csv"
```
### Options
| オプション | 説明 | デフォルト |
| ----------- | ---------------------------- | ----------------------------------------------------- |
| `--project` | 出力PJフォルダ名(必須) | - |
| `--input` | 入力フォルダ | `incoming/unassigned/` |
| `--dry-run` | ファイル移動せず結果のみ表示 | false |
| `--log` | 結果CSVパス | `<PJフォルダ>/csv/<PJ名>_dryrun.csv` or `_result.csv` |
## Markdown Summary Output
本実行後、PJフォルダに `<PJ名>_summary.md` が自動生成される。
含む内容:
- プロジェクト合計(通貨混在・参考値)
- 国コード別合計テーブル
- 日付×国コード別合計テーブル
- 全明細テーブル(日付・国・金額・カード・分類・日本語概要・ファイル名)
## Intake Pattern
- 未分類の生ファイルは、workspace root ではなく専用の intake folder に集約する
- 例: `incoming/unassigned/`
- 案件が確定しているファイルは、intake folder を経由せず project folder へ直接入れてよい
+ - 案件が不明な出張明細は、移動前に read-only の承認記録、予定表、予約記録を日付・区間・目的で照合する。一致しなければ `--project` を推測せず、未分類に残して確認する
+ - システム発行の交通領収書は表示日や購入日ではなくサービス日・乗車日を使う。出発地と到着地が両方確認できる場合だけ、分類末尾へ `origin-to-destination` を付けて往復を区別する
+ - 実行対象を専用 intake に限定し、dry-run の結果を確認してから本実行する
- dry-run 用のコピーや検証入力は一時フォルダで扱い、完了後に削除する
## Setup
→ **[references/setup-guide.md](references/setup-guide.md)**
## Script Reference
→ **[references/receipt_sorter.py](references/receipt_sorter.py)**
## D365 Expense Integration
OCR 後のファイルを D365 Expense に添付する運用はこの skill の重要ユースケースだが、カテゴリ表と添付手順は本体から分離する。
- Report 作成 / metadata 編集
- Expense line の Category / Description / Country / tax group 編集
- line-level receipt upload / 差し替え / 照合
- D365 UI の stale 表示や active row ずれの回避
詳細は [references/d365-expense-guide.md](references/d365-expense-guide.md) を参照。
## Known Limitations
- OCRの精度はSuryaモデルに依存(手書きや歪みが大きい領収書は誤読あり)
- 金額は最大候補を採用するが、複数明細のあるレシートでは個別明細は取れない
- **金額連結誤読**: OCRが改行をまたいで数字を結合し巨大整数を返すことがある(例: `14520` + `300` → `14520300`)。上限チェック(500万超は除外)で防御しているが、完全ではない
- 動画は中間フレーム1枚のみ抽出(最適フレーム選択は未実装)
- 日本語の漢字店名はスラッグ化時にASCII変換で落ちる(カタカナはローマ字化される)
- **Windows PIL ファイルロック**: `Image.open()` がハンドルを保持し `shutil.move()` が `WinError 32` で失敗する。`with` + `img.copy()` + リトライで対応済み
## Done Criteria
- OCR 抽出からリネームまで一貫して処理できる
- 標準ファイル名でプロジェクト単位に仕分けできる
- 未分類と private の扱いを説明できる
- Markdown サマリーが出力される
- D365 へ載せる場合は reference の照合ルールに従って添付できる