Holding for Craft CMS

Craft Commerce 5 · Holded

Every order in Holded, with the right IVA

Holded is where most Spanish shops keep their books. Getting Craft Commerce into it is not the hard part — the hard part is that one checkout produces domestic sales, intra‑community reverse charges, exports and OSS sales, and Holded will file whichever one it is told to without complaint. Holding works out which, records why, and checks the invoice against the order before it calls the job done.

Holding

Rehearse it first

Before a single document exists, ask what one would look like. `holding/sync/preview` prints the VAT treatment, the reasoning behind it, every line with its rate and Holded tax key, and the document total against the order total — without touching Holded.

bash
$ php craft holding/sync/preview 1042

Order #1042
  Treatment: Reverse charge
    · B2B sale to Germany with VAT number DE123456789 — reverse charge.
  Note: Operación exenta de IVA por inversión del sujeto pasivo (art. 84.Uno.2º LIVA).

  Lines
    Ceramic tile, 30×30                     12.00 ×     14.50  VAT  0.00% s_iva_0
    Gastos de envío                          1.00 ×      9.90  VAT  0.00% s_iva_0

  Document total: 183.90   Order total: 183.90

Features

An accounting integration is judged on the documents it leaves behind, not on the API calls it makes.

VAT that knows which kind of sale it is

Domestic, intra‑community reverse charge, export, One Stop Shop and the territories that are inside a member state and outside the VAT area — each with the legal wording it requires printed on the document.

  • Canarias, Ceuta and Melilla are checked before the country, because they are in Spain and not in Spanish VAT
  • Büsingen, Helgoland, Livigno, Campione, Åland and Mount Athos as well
  • Every classification shows its reasoning on the order screen

The invoice says what was charged

Commerce has already taken the customer's money, and an invoice that disagrees with the payment is worse than none. Holding classifies the sale; it never quietly changes a number.

  • A rate that disagrees with the classification is a warning on the document
  • An adjustment from another plugin becomes a line, not a discrepancy
  • Tax‑inclusive pricing is unwound properly

Checks its own work

Every document is read back out of Holded and its total compared with the order's. Anything that disagrees is flagged and counted, so a bad quarter is something you find in August rather than in January.

  • One extra API call per document, and worth it
  • Filtered on the Documents screen under “With warnings”
  • The payload and the response are kept for every call

Spanish tax identifiers, validated

NIF, NIE and CIF check characters computed properly, and the VAT number formats of all 27 member states checked before VIES is ever asked.

  • A customer who pastes ES‑12.345.678‑Z gets it read correctly
  • Optional VIES validation — and you decide what happens when VIES will not answer
  • A bad tax id is a warning, or a refusal, whichever you prefer

Paid invoices and proper rectificativas

Successful Commerce transactions are registered against the document as they happen, so nobody chases a customer who has already paid. Refunds become credit notes, because an issued invoice is locked the moment it is issued.

  • One transaction is registered once, ever — the unique index is the guarantee
  • Holded's bank account is attached in a follow‑up call, because /pay will not take one
  • Two partial refunds are two credit notes, not one overwriting the other

Never in the way of a checkout

Everything happens in the queue. A checkout does not wait on Holded and does not fail because Holded is down — the order completes, and the document follows.

  • Retries with a ceiling, then it waits for a human
  • A per‑minute cap so a backfill cannot spend the month's API allowance
  • Console commands for the backfill, the retry and the housekeeping

Frequently Asked Questions

The questions worth answering before you install it.

Put the books on rails

$149, one edition, everything in it. Install it, send one order by hand, and look at what arrives in Holded before you let it loose on the rest.