SuperAPI AI Directory

receipt-ocr-sorter

Design & creation

View repository

Updated 10-15 16:46

About this skill

Receipt OCR Sorter

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

  1. Receive images / PDFs / ZIPs / videos from the input folder
  2. Extract date, amount, country, card, and purpose via OCR
  3. Apply quality correction and normalize to standard file names
  4. Sort by project
  5. 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

→ references/setup-guide.md

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 and shutil.move() が WinError 32 fails.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