Skill: ivangdavila/invoices (version 1.0.1)

--- name: Invoices description: Capture, extract, and organize received invoices with automatic OCR, provider detection, and searchable archive. --- ## Trigger Use when user receives invoices (email, photo, PDF) and wants them organized automatically. **Key difference:** This skill MANAGES received invoices. The `invoice` skill CREATES invoices to send. --- ## Storage ``` ~/invoices/ ├── inbox/ # Unprocessed files awaiting extraction ├── archive/ # Organized by year/month │ └── 2026/ │ └── 02/ │ └── 2026-02-13_Hetzner_INV-12345_89.50.pdf ├── providers/ # Provider metadata │ └── index.json ├── entries.json # All invoice metadata (searchable) └── state.json # Processing state ``` --- ## Quick Reference | Topic | File | |-------|------| | Capture and extraction workflow | `process.md` | | Fields to extract | `extraction.md` | | Search queries and reports | `search.md` | | Legal requirements by country | `legal.md` | --- ## Process Summary 1. **Capture** — Receive invoice (email attachment, photo, direct PDF). Copy to `inbox/`. 2. **Extract** — OCR if needed, parse fields (provider, date, amounts, tax). 3. **Validate** — Check required fields, detect duplicates. 4. **Organize** — Rename, move to `archive/YYYY/MM/`, update `entries.json`. 5. **Confirm** — Show extracted data, allow corrections. See `process.md` for detailed workflow. --- ## Critical Rules - **Never delete originals** — Keep PDFs permanently. Legal requirement (4-6 years depending on country). - **Detect duplicates** — Same invoice number + provider = duplicate. Alert, don't overwrite. - **Validate tax math** — Base + tax should equal total. Flag discrepancies. - **Provider normalization** — "HETZNER ONLINE GMBH" = "Hetzner". Maintain provider aliases. --- ## Alerts - Invoice pending >48h in inbox - Payment due in <7 days - Unusual amount (>50% higher than same provider average) - Missing expected recurring invoice

path: extraction.md
content: # Invoice Data Extraction

## Required Fields

| Field | Description | Example |
|-------|-------------|---------|
| `provider` | Company name | "Hetzner Online GmbH" |
| `invoice_number` | Unique identifier | "INV-12345" |
| `date` | Issue date | "2026-02-13" |
| `total` | Final amount | 89.50 |
| `currency` | ISO currency | "EUR" |

## Optional Fields (extract if present)

| Field | Description |
|-------|-------------|
| `provider_id` | Tax ID (CIF/NIF/VAT) |
| `provider_address` | Full address |
| `due_date` | Payment deadline |
| `subtotal` | Before tax |
| `tax_rate` | Percentage (21%, 10%, etc.) |
| `tax_amount` | Tax in currency |
| `line_items` | Array of {description, quantity, unit_price, total} |
| `payment_method` | Bank transfer, card, etc. |
| `iban` | For bank transfers |
| `reference` | Payment reference |

## Provider Normalization

Maintain aliases in `providers/index.json`:
```json
{
  "hetzner": {
    "canonical": "Hetzner",
    "aliases": ["Hetzner Online GmbH", "HETZNER ONLINE GMBH"],
    "tax_id": "DE812871812",
    "category": "hosting",
    "expected_day": 1
  }
}
```

## Category Detection

Auto-assign category based on provider or keywords:

| Category | Triggers |
|----------|----------|
| hosting | Hetzner, AWS, Google Cloud, DigitalOcean |
| software | Figma, Notion, GitHub, JetBrains |
| telecom | Vodafone, Movistar, Orange |
| utilities | electricity, gas, water |
| insurance | "seguro", "insurance", "policy" |
| office | "material", "supplies", "papelería" |
| professional | "consultoría", "asesoría", "legal" |

## Tax ID Validation

| Country | Format | Regex |
|---------|--------|-------|
| Spain (NIF) | 12345678A or X1234567A | `^[XYZ]?\d{7,8}[A-Z]$` |
| Spain (CIF) | A12345678 | `^[A-Z]\d{8}$` |
| Germany (VAT) | DE123456789 | `^DE\d{9}$` |
| EU (VIES) | XX + 8-12 chars | Validate via VIES API |

## Extraction Confidence

Rate each field:
- `high`: Clear text, validated format
- `medium`: OCR successful but unvalidated
- `low`: Partial match, needs review

Flag invoice for review if any required field is `low` confidence.


path: legal.md
content: # Legal Requirements for Invoice Storage

## Retention Periods

| Country | Period | Notes |
|---------|--------|-------|
| Spain | 4 years | From end of tax year |
| Germany | 10 years | For VAT invoices |
| France | 6 years | General commercial |
| UK | 6 years | VAT records |
| USA | 3-7 years | Varies by state/type |

**Default:** Keep everything for 10 years. Storage is cheap, audits are expensive.

---

## Spain Specifics

### Required Invoice Fields (RD 1619/2012)

For invoice to be valid for VAT deduction:
- Número de factura (correlativo)
- Fecha de expedición
- Nombre/razón social emisor
- NIF/CIF emisor
- Domicilio emisor
- Descripción operación
- Base imponible
- Tipo impositivo (% IVA)
- Cuota tributaria (IVA en €)
- Total factura

### IVA Types
| Rate | Applies to |
|------|------------|
| 21% | General (most services/products) |
| 10% | Reduced (food, transport, hotels) |
| 4% | Super-reduced (bread, books, medicine) |
| 0% | Exempt (insurance, finance, health) |

### Deductibility Rules
- Must have valid invoice (not just receipt)
- Must be necessary for business activity
- Must be registered in accounting
- Proportional deduction for mixed use (e.g., home office)

---

## Quarterly Obligations (Spain)

| Model | Deadline | What |
|-------|----------|------|
| 303 | 1-20 Apr/Jul/Oct, 1-30 Jan | Quarterly VAT |
| 347 | February | Annual ops >3,005.06€ per provider |
| 390 | January | Annual VAT summary |

### Modelo 303 Preparation

Agent should track and provide:
- Sum of bases by IVA type (21%, 10%, 4%)
- Sum of IVA soportado (paid, deductible)
- Comparison with previous quarters

---

## GDPR Considerations

- Invoices may contain personal data
- Don't share invoices externally without consent
- Redact personal data if exporting for analysis
- Provider data is typically business data (not personal)

---

## Backup Requirements

- Invoices must be readable for entire retention period
- PDF/A format recommended for long-term archival
- Regular backups (cloud + local)
- Test restore periodically


path: process.md
content: # Invoice Processing Workflow

## Phase 1: Capture

**Sources:**
- Email attachment forwarded/sent to agent
- Photo/scan from mobile
- PDF uploaded directly
- URL to invoice portal (agent downloads)

**Actions:**
1. Copy file to `~/invoices/inbox/`
2. Generate temp name: `{timestamp}_{original_filename}`
3. Update `state.json` with new entry

**Agent capabilities:**
- Monitor email for invoices (if configured)
- Accept direct file uploads
- Download from URL if provided

---

## Phase 2: Extract

**OCR Pipeline:**
1. If PDF is text-based → extract text directly
2. If image/scanned PDF → use vision model for OCR
3. Parse structured data (see `extraction.md` for fields)

**Extraction approach:**
```
Send to vision model:
"Extract invoice data: provider name, provider tax ID, invoice number, 
date, due date, line items, subtotal, tax rate, tax amount, total, currency."
```

**Output:** JSON with extracted fields + confidence scores

---

## Phase 3: Validate

**Checks:**
- [ ] Provider tax ID format valid (if available)
- [ ] Date is parseable and reasonable (not future, not >1 year old)
- [ ] Math: sum(line_items) ≈ subtotal, subtotal + tax ≈ total
- [ ] No duplicate: same provider + invoice_number doesn't exist

**On validation failure:**
- Flag for human review
- Store in `inbox/` with `_REVIEW` suffix
- Ask user to confirm/correct

---

## Phase 4: Organize

**File naming:**
```
{date}_{provider}_{invoice_number}_{total}.pdf
Example: 2026-02-13_Hetzner_INV-12345_89.50.pdf
```

**Folder structure:**
```
archive/
└── 2026/
    └── 02/
        └── 2026-02-13_Hetzner_INV-12345_89.50.pdf
```

**Metadata update:**
1. Add entry to `entries.json`:
```json
{
  "id": "uuid",
  "file": "archive/2026/02/2026-02-13_Hetzner_INV-12345_89.50.pdf",
  "provider": "Hetzner",
  "provider_id": "DE812871812",
  "invoice_number": "INV-12345",
  "date": "2026-02-13",
  "due_date": "2026-03-13",
  "subtotal": 75.21,
  "tax_rate": 19,
  "tax_amount": 14.29,
  "total": 89.50,
  "currency": "EUR",
  "category": "hosting",
  "status": "pending",
  "paid_date": null,
  "captured_at": "2026-02-13T14:30:00Z"
}
```
2. Update `providers/index.json` if new provider
3. Remove from `inbox/`

---

## Phase 5: Confirm

**Show user:**
```
📥 Invoice captured:
• Provider: Hetzner
• Invoice #: INV-12345
• Date: 2026-02-13
• Total: €89.50 (€75.21 + 19% VAT)
• Category: hosting (auto-detected)

✓ Saved to: archive/2026/02/
```

**Allow corrections:**
- "Change category to 'infrastructure'"
- "Mark as paid"
- "This is a duplicate, delete it"

---

## State Management

`state.json` tracks:
```json
{
  "last_processed": "2026-02-13T14:30:00Z",
  "inbox_count": 2,
  "total_processed": 147,
  "providers_count": 23,
  "pending_review": ["inbox/1234567890_invoice.pdf"]
}
```

---

## Email Integration (Optional)

If user configures email access:
1. Scan inbox for invoices (common sender patterns, PDF attachments)
2. Auto-forward to processing queue
3. Mark as processed in email

Patterns to detect:
- Subject contains: "invoice", "factura", "rechnung", "bill"
- Sender is known provider
- PDF attachment named with invoice patterns


path: search.md
content: # Search and Reporting

## Natural Language Queries

Support these patterns:

### By Provider
- "facturas de Hetzner"
- "todo lo de AWS"
- "invoices from Google"

### By Date
- "facturas de enero"
- "invoices from last quarter"
- "this year's invoices"
- "facturas de 2025"

### By Amount
- "facturas de más de 500€"
- "invoices over 1000"
- "facturas entre 100 y 200"

### By Status
- "facturas pendientes de pago"
- "paid invoices"
- "overdue invoices"

### By Category
- "gastos de hosting"
- "software expenses"
- "todas las facturas de seguros"

### Combined
- "facturas de Hetzner de más de 50€ en 2025"
- "unpaid invoices from last month"

---

## Reports

### Monthly Summary
```
📊 February 2026 Summary

Total invoices: 23
Total amount: €2,847.50

By category:
• Hosting: €890.00 (5 invoices)
• Software: €450.00 (8 invoices)
• Professional: €1,200.00 (2 invoices)
• Other: €307.50 (8 invoices)

Payment status:
• Paid: 18 (€2,100.00)
• Pending: 5 (€747.50)
```

### Quarterly Tax Report
```
📋 Q1 2026 Tax Summary (Spain - Modelo 303)

Base imponible: €12,450.00
IVA soportado:
• 21%: €2,180.00
• 10%: €120.00
• 4%: €15.00
Total IVA: €2,315.00

⚠️ Missing invoices for deduction:
• February telecom (usually €45)
```

### Provider Analysis
```
📈 Hetzner - 12 months

Total spend: €1,068.00
Monthly average: €89.00
Trend: +5% vs last year

Invoices:
• INV-12340 (Jan): €89.00
• INV-12345 (Feb): €89.00
...
```

### Annual Summary (for accountant)
```
📁 2025 Annual Export

Generating:
• invoices_2025.csv (147 records)
• invoices_2025.zip (all PDFs)
• providers_2025.json (summary by provider)

Ready to send to accountant.
```

---

## Export Formats

### CSV (Standard)
```csv
date,provider,invoice_number,subtotal,tax_rate,tax_amount,total,currency,category,status
2026-02-13,Hetzner,INV-12345,75.21,19,14.29,89.50,EUR,hosting,paid
```

### Modelo 303 (Spain)
Grouped by tax rate, ready for quarterly VAT declaration.

### Full Archive
ZIP with folder structure + CSV index.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: clean (LOW)