Automatic receipt sorting, renaming, and aggregation tool using OCR (Surya).
When to Use
- Sort receipts, Organize receipts, receipt sorting
- Want to automatically organize receipt images in a folder by project
- Want to name large numbers of receipt photos with date, amount, and purpose
- Want to batch rename and aggregate business trip expense receipts
Core Workflow
- Receive images / PDFs / ZIPs / videos from the input folder
- Extract date, amount, country, card, and purpose via OCR
- Apply quality correction and normalize to standard file names
- Sort by project
- Output a Markdown summary
Architecture
入力フォルダ(incoming/unassigned 等)
│
├─ JPEG/PNG/PDF/ZIP → OCR → 抽出 → リネーム → PJフォルダへ移動
├─ MP4/MOV → ffmpeg → JPG → OCR → ...
│
├─ カード不明 or テキスト不可 → 未分類フォルダ → 再仕分け可能
│
└─ 個人経費(D365対象外) → PJフォルダ/private/
private/Folder: Store personal expense receipts that are not to be submitted to D365. Move here when the user determines after OCR that it is a "personal expense".
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
For the country code list, classification list, D365 category mapping, and attachment procedure, see references/d365-expense-guide.md .
CLI Usage
# 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
| Options | Description | Default |
|---|---|---|
--project |
Output PJ folder name (required) | - |
--input |
Input folder | incoming/unassigned/ |
--dry-run |
Display results only without moving files | false |
--log |
Result CSV path | <PJフォルダ>/csv/<PJ名>_dryrun.csv or _result.csv |
Markdown Summary Output
After this execution, <PJ名>_summary.md is automatically generated in the PJ folder.
Contents included:
- Project total (mixed currencies, reference value)
- Total table by country code
- Total table by date x country code
- All line items table (date, country, amount, card, classification, Japanese summary, file name)
Intake Pattern
- Unclassified raw files should be consolidated into a dedicated intake folder, not the workspace root
- Example:
incoming/unassigned/ - Files whose project is already confirmed may be placed directly in the project folder without going through the intake folder
- Handle copies and verification inputs for dry-run in a temporary folder, and delete them after completion
Setup
Script Reference
→ references/receipt_sorter.py
D365 Expense Integration
Attaching OCR-processed files to D365 Expense is an important use case of this skill, but the category table and attachment procedure are separated from the main body.
- Category mapping table
- Attachment / replacement procedure
- Verification rules at attachment time
- Notes on browser operation
For details, see references/d365-expense-guide.md .
Known Limitations
- OCR accuracy depends on the Surya model (misreads occur for handwritten or heavily distorted receipts)
- The maximum candidate is used for the amount, but individual line items cannot be extracted from receipts with multiple line items
- Amount concatenation misread: OCR may join digits across line breaks and return a huge integer (example:
14520+300→14520300). It is defended against by an upper limit check (excluding over 5 million), but it is not perfect - For videos, only one intermediate frame is extracted (optimal frame selection not implemented)
- Japanese kanji store names are dropped during slugification due to ASCII conversion (katakana is romanized)
- Windows PIL file lock:
Image.open()holds the handle andshutil.move()がWinError 32fails.with+img.copy()Handled with + retry
Done Criteria
- Consistent processing from OCR extraction to renaming
- Can be sorted by project using standard file names
- Can explain how unclassified and private items are handled
- A Markdown summary is output
- When uploading to D365, files can be attached according to the reference matching rules