| name | invoice-processing |
| description | Process invoices from messages (PDF/image attachments or URLs).
Extract key values, validate mandatory fields, organize by month, update Excel.
Use when: receiving invoices, processing receipts, bookkeeping tasks.
|
Invoice Processing Workflow
When you receive a message containing an invoice (PDF, image attachment, or URL),
follow the steps below. The detailed instructions for each step are in separate
files โ read them before processing.
| Step | File | Description |
|---|
| 0 | (this file) | Initialize invoice database (first run only) |
| 1 | (this file) | Determine current month folder |
| 2โ3 | PROCESSING.md | Download invoice โ Extract data (PDF Phase โ Image Phase) |
| 4 | VALIDATION.md | Validate mandatory fields before write |
| 5โ6 | EXCEL.md | Insert via invoice_add, reply with summary |
| 7โ8 | EXCEL.md | Monthly close/export via invoice_close/invoice_export (when requested) |
| 9 | VALIDATION.md | List errors (when requested) |
Mandatory Fields (ๅ็ฅจๅฟ
ๅกซๅญๆฎต)
A valid Chinese invoice (ๅ็ฅจ) MUST contain these 2 fields. If ANY is missing,
the invoice is invalid and must NOT be written to the database.
| Field | Description | Format | Required? |
|---|
| ้ๅฎๆน็จๅท (Seller Tax ID) | ้ๅฎๆน็บณ็จไบบ่ฏๅซๅท | 18 characters (alphanumeric) | MANDATORY |
| ไปท็จๅ่ฎก | Total amount (incl. tax) | Positive number | MANDATORY |
Optional fields (extract if available, do NOT reject if missing):
| Field | Description | Notes |
|---|
| ๆ ก้ช็ | Verification code (20 numeric digits) | Some invoices don't have it; still record in ๅคๆณจ if present |
| ๅ็ฅจๅท็ | Invoice number | Extract if possible; warn if missing but do NOT reject |
Processing Flow Overview
Email Received
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PDF Phase (see PROCESSING.md) โ
โ 1. PDF attachments (>50KB) โ
โ โ Extract with Python PdfReader โ
โ โ Validate 2 mandatory fields โ
โ โ If valid โ SUCCESS, stop โ
โ โ
โ 2. Extract URLs from email body โ
โ โ Download each URL (max 5) โ
โ โ If PDF โ extract with PdfReader โ
โ โ If HTML โ html_parser.py โ
โ โ If fails โ playwright_extractor.py โ
โ โ Re-download extracted URL โ
โ โ If Image โ tag for Image Phase โ
โ โ Validate 2 mandatory fields โ
โ โ If valid โ SUCCESS, stop โ
โ โ
โ If ALL PDF sources fail โ Image Phase โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Image Phase (LAST RESORT, see PROCESSING.md)โ
โ 3. Tagged image URLs from PDF Phase โ
โ โ Use vision MCP tool โ
โ โ Validate 2 mandatory fields โ
โ โ If valid โ SUCCESS, stop โ
โ โ
โ 4. Image attachments (>50KB, not QR codes) โ
โ โ Use vision MCP tool โ
โ โ Validate 2 mandatory fields โ
โ โ If valid โ SUCCESS, stop โ
โ โ
โ 5. Extract URLs from email body for images โ
โ โ Download each URL (max 5) โ
โ โ If Image โ use vision MCP โ
โ โ If HTML โ html_parser.py โ
โ โ If fails โ playwright_extractor.py โ
โ โ Validate 2 mandatory fields โ
โ โ If valid โ SUCCESS, stop โ
โ โ
โ If ALL image sources fail โ FINAL FAILURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
SUCCESS โ Step 4 (validate) โ Step 5 (insert via invoice_add) โ Step 6 (reply)
FAILURE โ Log to errors.jsonl โ Reply with error details
Step 0: Initialize Invoice Database (First Run Only)
The invoice skill now uses the invoice MCP for database storage.
Excel files are only generated on-demand when the user requests them.
On first use (or if .invoice/ directory doesn't exist):
Use the invoice_init MCP tool to initialize the database.
The invoice database is stored at .invoice/invoice.db within the thread directory.
It stores all invoice records across all months in a single file.
Database management:
invoice_init โ Creates SQLite database and downloads OCR models (if needed)
invoice_add โ Inserts a new invoice record
invoice_list โ Queries invoices (supports --month, --year, --category filters)
invoice_show โ Shows details of a specific invoice
invoice_close โ Monthly/yearly closing, generates Excel reports and ZIP archive
invoice_export โ Exports reports (without closing)
Step 1: Determine Current Month Folder
IMPORTANT: The month folder is based on when the invoice is RECEIVED/processed, NOT the invoice date (ๅผ็ฅจๆฅๆ).
For example:
- Invoice dated 2026-03 (March) but received in 2026-04 (April) โ file into
invoice_2026-04/
- The ๅผ็ฅจๆฅๆ is still recorded in the Excel, but the file goes to the current month
The Excel files are now generated on-demand by invoice MCP tools (invoice_export, invoice_close)
using rust_xlsxwriter internally โ no template copying needed.
Thread directory structure:
<thread_dir>/
.invoice/ โ invoice MCP ๆฐๆฎ็ฎๅฝ
invoice.db โ SQLite ๆฐๆฎๅบ๏ผinvoice MCP ็ฎก็๏ผ
data/ โ ้ไปถๆไปถ๏ผinvoice MCP ็ฎก็๏ผ
invoice_YYYY-MM/ โ ๆๆๆไปถๅคน๏ผไฟ็๏ผๅญๅจไธ่ฝฝ็ PDF๏ผ
errors.jsonl โ ๅคฑ่ดฅ่ฎฐๅฝ๏ผไฟ็๏ผ
INV-2026-0042.pdf โ ไธ่ฝฝ็ๅ็ฅจ PDF
INV-2026-0043.jpg
...
invoice_list_YYYY-MM.xlsx โ Generated on-demand (when user requests export)
invoice_summary_YYYY-MM.xlsx โ Generated on-demand (when user requests summary)
Check if the current month's folder exists:
MONTH=$(date +%Y-%m)
FOLDER="invoice_${MONTH}"
if [ ! -d ".invoice" ]; then
echo "Run invoice_init MCP tool to initialize database"
fi
if [ ! -d "$FOLDER" ]; then
mkdir -p "$FOLDER"
fi
Rules
Processing Rules
- ALWAYS check/create the monthly folder before processing
- ALWAYS initialize invoice database via
invoice_init if .invoice/ directory does not exist (Step 0)
- ALWAYS validate file format โ only PDF and image (JPG/PNG) are valid certified vouchers (ๅ่งๅญ่ฏ)
- ALWAYS validate 2 mandatory fields (้ๅฎๆน็จๅท, ไปท็จๅ่ฎก) before writing via
invoice_add
- ALWAYS follow the STRICT sequential order: PDF attachments โ PDF URLs โ Image sources (see PROCESSING.md)
- NEVER skip PDF URL extraction (Step 2b) โ if no PDF attachment found, you MUST try to extract URLs from the email body BEFORE processing any image sources
- NEVER write incomplete or failed invoices to the database โ log to errors.jsonl instead
- NEVER save non-PDF/non-image files to the monthly folder โ they are not valid vouchers
- NEVER use vision MCP tool on PDF files โ use Python PdfReader (pypdf) only for PDFs
- Vision MCP is ONLY for image files (JPG/PNG)
Extraction Rules
- For PDF files: use Python PdfReader (pypdf) text extraction ONLY
- For image files: use vision MCP tool ONLY
- If PDF text extraction fails โ mark that PDF source as failed, try next source
- Do NOT fall back to vision for PDFs โ proceed to the next source instead
- If ALL PDF sources fail โ proceed to Image Phase
- If ALL image sources fail โ log to errors.jsonl as final failure
- NEVER assume an invoice URL requires login โ all known platforms (51fapiao, Maycur) use public links where the URL itself contains the access credential (hash, code, signatureString). Always try to download first.
- ALWAYS search
chat_history_*.jsonl for invoice URLs โ the incoming message prompt may be truncated (forwarded content stripped). The full email body including forwarded URLs is saved in the chat history file. Search ONLY the latest received message record (the last "type":"received" entry), NOT the entire file. See PROCESSING.md "URL Extraction from Email Body" for the exact script.
Validation Rules
- ้ๅฎๆน็จๅท (Seller Tax ID): 18 characters, alphanumeric โ MANDATORY
- ไปท็จๅ่ฎก (Total amount): positive number โ MANDATORY
- ๆ ก้ช็ (Verification Code): 20 numeric digits โ stored in dedicated
verify_code field
- ๅ็ฅจๅท็ (Invoice number): recommended, warn if missing, but NOT mandatory
- If ๆ ก้ช็ is present, store in dedicated
verify_code field (not just in ๅคๆณจ)
File Handling Rules
- Do NOT overwrite existing invoice files
- Do NOT process QR code images โ small images (< 50KB) are likely QR codes
- Do NOT follow or scan QR code URLs
- Only PDF and image files (JPG/PNG) are valid โ HTML, XML, text are NOT valid invoices
- Maximum 5 URLs processed per phase (PDF Phase and Image Phase each)
- ALWAYS clean up processed attachments from
attachments/ after successful database insert via invoice_add
- Do NOT clean up attachments on failure โ keep them for manual processing or retry
Error Handling Rules
- If extraction fails but file IS valid format (PDF/image), save it for manual processing
- If file is NOT valid format (HTML, XML, etc.), do NOT save it
- Report all errors clearly in the reply
- See VALIDATION.md for error log format and error types
Browser Automation for Complex HTML Pages
Some invoice platforms serve JavaScript-heavy pages (e.g. React apps) instead
of direct PDF links. The system handles this automatically:
- Lightweight parser (
scripts/html_parser.py) โ tries regex-based
extraction first (fast, no dependencies beyond Python stdlib)
- Playwright fallback (
scripts/playwright_extractor.py) โ launches
a headless Chromium browser to render the page and extract the PDF URL
The switch is fully automatic. The user only sees the final result.
One-time Playwright setup (Debian headless server):
bash .opencode/skills/invoice-processing/bin/install-playwright.sh