| name | quarterly-add-receipt |
| description | Ingest a received invoice or receipt into the QuarterlyAssistant bookkeeping. Use whenever the user drops a receipt/invoice PDF and wants it recorded, says "add this receipt", "book this", "this is a gasto/expense for Qn", "file this invoice", or references a purchase/subscription/bill that should be captured for the quarterly Modelo 130 — even if they just upload a PDF in this project with no explanation. Extracts the data, then asks clarifying questions until the classification is unambiguous (it never guesses), and records the file per the repo conventions. Requires the QuarterlyAssistant folder to be connected. |
Add a received receipt — QuarterlyAssistant
Record a received invoice/receipt so the quarterly pipeline (AGENTS.md Stages 2–4) can consume it without re-extraction and without ever asking about this document or vendor again. Until those pipeline scripts exist, this skill performs Stage 2 conventions manually — same outputs, same folder contract. Tenant is a folder under tenants/; if more than one exists, ask which.
The core rule: no guessing, ever
A record enters the books only when it is unambiguous. Extract everything you can, check memory/rules.yaml, and then ask the user about every remaining open point before writing anything. A wrong silent classification costs more than three questions. Conversely: never ask what memory or the document already answers — batch the genuinely open questions into one round if possible.
What must be resolved before recording:
- What is it? Vendor, what was purchased, and its business meaning (e.g. "Starlink = dedicated business internet line").
- Deductibility — business %, category (AGENTS.md §6 heuristics: mixed-use asks for a %, vehicle/clothing default non-deductible, hardware > 300 € is an asset →
memory/assets.yaml, meals need date+establishment+payment method). Be skeptical like the §6 table; flag rather than optimistically deduct.
- Tax treatment — IGIC/IVA soportado deducible? For a Canarias tenant: if a mainland/EU vendor charged IVA, flag it (generally not recoverable — the user may want to reclaim it from the vendor); the IVA then stays part of the deductible expense.
- How was it paid? Which bank account (see
config.yaml → bank_accounts), card, cash, or a private account. Cash/private → it will never match a bank transaction; note it so reconciliation expects that (this is what manual-entries.yaml logic exists for).
- Which quarter? From the invoice issue date. Place it in the matching
declarations/<YYYY-Qn>/ folder; if that quarter's folder doesn't exist, create the skeleton.
Write every new teaching (vendor meaning, business %, category) into memory/rules.yaml using the existing entry format, so it is never asked twice.
Getting the text (token-economy contract, AGENTS.md §8)
- PDF has a text layer → extract with
pdftotext -layout locally. This is the default path.
- Sidecar
<name>.txt exists → use it verbatim.
- Scanned/no text layer: as an interim exception to the pipeline's no-OCR rule, you may read the dropped PDF visually in chat — but then write the extracted text as a sidecar
.txt next to the processed file, so the pipeline never has to look at the image again. Tell the user the proper fix is running tools/extract-text-macos.sh (or ocrmypdf) over scans first.
Recording (Stage 2 conventions)
- Extract: vendor, vendor NIF, invoice number, issue date, base, tax type/rate/amount (IGIC/IVA %), retención if present, total, currency. Direction: issuer NIF == tenant NIF → income, else expense.
- Resolve all open questions (section above).
- Compute
sha256 of the file; canonical name: YYYY-MM-DD_vendor-slug_total__hash8.pdf.
- Move the file to
tenants/<tenant>/declarations/<YYYY-Qn>/receipts-processed/ under the canonical name, plus a .json sidecar with the full extraction + classification + payment answers (this sidecar is what makes re-runs free).
- If the file was uploaded in chat rather than already in
receipts-incoming/, copy it into the repo — never leave the only copy in the chat uploads folder.
- Confirm to the user in one line: vendor, date, total, category, deductible %, quarter. If anything was flagged (wrongly charged IVA, asset, conservative deduction), say so.
Idempotency
Before recording, check whether a sidecar with the same file hash already exists anywhere under declarations/ — if yes, report the duplicate and stop instead of recording twice. Same-hash detection is the dedupe mechanism; filename differences don't matter.