---
name: dolibarr-recurring-templates
description: Inspect Arcodange recurring invoice templates (modèles de factures récurrentes) — the templates that auto-generate monthly invoices for KissMetrics and any future recurring billing. Two workflows — (1) enumerate all templates (the API has no list endpoint, this skill probes ids 1..N and stops after consecutive empties); (2) inspect one template end-to-end (identification, schedule frequency / unit / next-fire / last-fire / counts, customer, payment terms, lines with French legal mentions, child invoices generated from it). Surfaces health issues: `frequency=0` (NOT auto-firing — every child was manually duplicated), `nb_gen_done=0` while children exist (mismatched counter), `date_when` in the past (overdue), `suspended=1` (paused). Use when the user asks "le template KM va-t-il auto-générer la prochaine facture", "quand fire la prochaine M-N", "audit des templates récurrents", "pourquoi la facture n'a pas été émise automatiquement". Depends on the `dolibarr` skill. SKIP for one-off invoice audits (handled by `dolibarr-invoice-audit`), for payment tracking (`dolibarr-payments-state`), for TVA basis (`dolibarr-tva-reconciliation`), or for writing/triggering a template fire (the API is read-only — manual fire goes through the Dolibarr UI).
requires:
  bins: ["curl", "jq", "python3"]
  auth: true
---

# dolibarr-recurring-templates — modèles de factures récurrentes

**CLI shortcuts:** `bin/arcodange templates list` · `bin/arcodange templates inspect <id>`

Recurring invoice templates are the Dolibarr objects that drive automated monthly (or arbitrary-frequency) billing. This skill answers: **does the template actually fire on schedule? when's the next one? and what does it generate?**

Depends on the [dolibarr](../dolibarr/SKILL.md) base skill.

## API quirks worth knowing

The Dolibarr API exposes templates only via `GET /invoices/templates/{id}` — there's **no list endpoint**. Two consequences:

1. **Enumerating requires probing.** `list-templates.sh` probes `id=1`, then `id=2`, etc., until it hits 5 consecutive empty responses.
2. **"Empty" looks like 200.** A non-existent id returns HTTP **200** with a hollow object (`id=null`, `ref=null`). The script treats `id=null` as the sentinel — Dolibarr returns mostly-null fields for missing templates rather than a clean 404.

(Captured for reference at [../dolibarr/examples/invoice_template_km.json](../dolibarr/examples/invoice_template_km.json).)

## Workflow 1 — Enumerate templates

```bash
./scripts/list-templates.sh                # probe 1..50, default
./scripts/list-templates.sh --max-id 200   # raise the upper bound
```

Live output (captured at [examples/list-templates.txt](examples/list-templates.txt)):

```
# Probed ids 1..6, found 1 template(s) (stopped after 5 consecutive empties)

 id  ref                          socid  freq          gen next         last         sus auto_val    total_ht
-------------------------------------------------------------------------------------------------------------------
  1  Kiss Metrics Invoice             1  OFF (0)       0/∞ -            -              0        0  5100.00000000
```

Columns:
- **freq** — `OFF (0)` if `frequency=0` (no auto-fire). Otherwise `every Nu` (e.g. `every 1m` = monthly).
- **gen** — `nb_gen_done / nb_gen_max`. `∞` means unbounded.
- **next** / **last** — `date_when` / `date_last_gen`.
- **sus** — `suspended` flag.

## Workflow 2 — Inspect one template (full audit)

```bash
./scripts/inspect-template.sh 1
echo "exit: $?"   # 0 if no health issues, 1 otherwise
```

Live output (captured at [examples/inspect-template-1.txt](examples/inspect-template-1.txt)):

```
================================================================================
 Template 1 — Kiss Metrics Invoice
================================================================================
  Customer       : socid=1
  Schedule       : frequency=0 m    (OFF — manual generation only)
  Counts         : generated=0 / max=unbounded
  Next fire date : (unset)
  Last fire date : (none)
  Suspended      : False
  ...
  Lines:
    - ref=KM-cloud-devops  qty=10  subprice=510.00000000  tva=0.0000  HT=5100.00000000
        TVA non applicable – Article 259-1 du CGI – Prestation de services localisée hors de France (USA)

  Generated children (by note_private match on 'Kiss Metrics Invoice'):
    - 2026-02-24  id=  12  FAC002-CL0001002          HT=5100.00000000  paye=1
    - 2026-02-24  id=  13  FAC003-CL0001003          HT=2550.00000000  paye=1

  Health checks:
    [!!] frequency=0 — template is NOT auto-generating; every child was created manually
    [!!] nb_gen_done=0 but 2 child invoice(s) match by note — they were duplicated, not auto-generated
```

**The Kiss Metrics Invoice template is OFF.** It exists, it has the right lines and the 259-1° CGI mention, it points at the right bank account (Wise), but its `frequency=0` and `nb_gen_done=0` mean **Dolibarr is not auto-generating M3 / M4 / etc.** Each cohort-month invoice today is a manual duplication from the Dolibarr UI.

**Cohort-review implication:** the deferred 9-month cycle depends on someone (Gabriel) clicking "Generate" each month. If you want it automated, the template's frequency needs to be set to `1m` (monthly), the `date_when` set to the next fire date, and ideally `auto_validate=1`. That's a UI configuration change — not done by this read-only skill.

**Children matching by note_private** is a heuristic: when an invoice is generated from a template, Dolibarr writes `"Généré depuis la facture modèle récurrente <ref>"` to `note_private`. We grep for the template ref in that field. False positives are rare in practice but possible; treat it as a strong signal, not proof.

## Out of scope

- **Triggering a fire.** Manual fire is a UI button; programmatic fire would need `POST /invoices/templates/{id}/createrecurringinvoices` (or similar), which isn't read-only.
- **Changing frequency / auto-validate / suspended.** UI-only from this skill's perspective.
- **Templates for things other than invoices** (recurring quotes, recurring orders) — would be sibling skills.
