Developer notes
How a document is built
Section titled “How a document is built”- Number and date: Invoices & Credit Notes (
Tygh\Addons\KvInvoiceBuilder\Issuer::issueInvoice()when the order has no invoice yet) or the add-on’s own series (kv_einv_counters, counter row locked withSELECT ... FOR UPDATE, retried on deadlocks; a rolled back transaction never consumes a number). - Model:
Model\Builder::invoice()readsfn_get_order_info()and builds the EN 16931 semantic model (array): seller (seller data with company fallback), buyer (billing address, profile fields, EU VAT Number Validation row), delivery (shipping address, first shipment date or the issue date), lines, allowances and charges, payment instructions.Model\Calculator::finish()adds the VAT breakdown per category and rate (tax = taxable amount × rate, rounded to 2 decimals) and the totals; the difference to the charged order total becomes a rounding amount (BT-114) or, above 1.00, a prepaid amount (gift certificates). - Freeze + check: the model is stored as JSON in
kv_einv_documents.data;Validator::all()stores the check per format inchecks. - Files on demand:
Formats::render($model, $format)adapts the model to the format (electronic addresses, contact point) and writes it:Format\Ubl(Peppol BIS 3.0 / XRechnung UBL, Invoice and CreditNote),Format\Cii(XRechnung CII / Factur-X),Pdf\FacturX(PDF/A-3b withfactur-x.xml, AFRelationship Alternative).
Order lines are matched to taxes through order.taxes[tax_id].applies: P_<item_id> (tax per unit price) or items.P[<item_id>] (tax on the subtotal); shipping through S_<group>_<shipping_id> / items.S, the payment surcharge through PS_* / items.PS. Rates of several taxes on one line are added up (with a warning); fixed-amount taxes are left out (warning). Prices that include tax are turned into net amounts with the stored tax of the line, or by the rate when the tax was calculated on the subtotal. Order discounts are split over the VAT groups in proportion to their gross value.
The PDF
Section titled “The PDF”Plain PHP, no library: Pdf\Document writes PDF 1.7 objects with Type0 / CIDFontType2 fonts (Identity-H, ToUnicode), XMP metadata (pdfaid part 3, conformance B, the Factur-X extension schema), an sRGB output intent with an ICC profile generated by Pdf\Icc, and the embedded file. Pdf\TrueType reads the bundled Noto Sans fonts (SIL Open Font License, resources/fonts/OFL.txt, Latin, Greek and Cyrillic) and embeds only the glyphs used. Pdf\Layout draws the A4 page; labels are language variables kv_eu_e_invoicing.pdf_*.
Peppol access point drivers
Section titled “Peppol access point drivers”The add-on ships no access point account. A driver is any class implementing Tygh\Addons\KvEuEInvoicing\Peppol\TransportInterface, registered from your own add-on:
// init.php of your add-onfn_register_hooks('kv_eu_e_invoicing_peppol_transports');
function fn_my_addon_kv_eu_e_invoicing_peppol_transports(&$transports){ $transports['my_ap'] = new \Tygh\Addons\MyAddon\AccessPoint();}class AccessPoint implements \Tygh\Addons\KvEuEInvoicing\Peppol\TransportInterface{ public function getName() { return 'My access point'; } public function isConfigured() { return (bool) $this->apiKey(); } public function send($xml, array $document) { // $xml: Peppol BIS Billing 3.0 UBL Invoice or CreditNote // $document: doc_id, doc_type (I|C), number, order_id, company_id, seller_id, buyer, buyer_vat, // data (the EN 16931 model; data.buyer.endpoint / endpoint_scheme = receiver) // POST it to your access point here. return ['ok' => true, 'message_id' => 'AP-12345', 'error' => '']; }}The driver then appears in Send e-invoices with. Sending is refused while the license is not valid or the Peppol check of the document has errors. The result is stored in peppol_status (S sent, E error), peppol_ref, peppol_error, peppol_at.
Hooks of the add-on
Section titled “Hooks of the add-on”| Hook | Arguments | Use |
|---|---|---|
kv_eu_e_invoicing_peppol_transports |
&$transports (id => TransportInterface) |
Register Peppol drivers |
Public PHP API
Section titled “Public PHP API”use Tygh\Addons\KvEuEInvoicing\Documents;use Tygh\Addons\KvEuEInvoicing\Issuer;use Tygh\Addons\KvEuEInvoicing\Output;
$doc = Documents::invoiceForOrder($order_id); // or Issuer::issueInvoice($order_id, 'manual')['doc']$file = Output::file($doc, 'xrechnung_cii'); // facturx | xrechnung_cii | xrechnung_ubl | peppol// $file = ['content' => ..., 'filename' => 'INV-2026-00042-xrechnung-cii.xml', 'mime' => 'application/xml']Database tables
Section titled “Database tables”| Table | Contents |
|---|---|
kv_einv_documents |
doc_id, doc_type (I/C), order_id, company_id, seller_id, number, issue_date, issued_at, invoice_id (credit note → invoice), ib_doc_id (Invoices & Credit Notes document), source, source_key (unique, idempotency), series_key + seq_no (own numbers), currency, total (amount due), with_vat, tax_total, buyer, buyer_vat, buyer_ref, email, user_id, status (check of the main format), checks (JSON), peppol_status / ref / error / at, data (JSON model), order_deleted |
kv_einv_counters |
series_key (`I |
kv_einv_sellers |
company_id (0 = store / marketplace, storefront, vendor) + seller data fields |
kv_einv_maps |
map_type (tax, payment), map_key (tax_id, payment_id), value (category / means code), extra (exemption text) |
kv_einv_products |
product_id, unit_code |
Documents are never deleted while the add-on is installed. When an order is deleted, its documents are kept and flagged order_deleted.
Hooks used
Section titled “Hooks used”PHP: change_order_status (create e-invoices, own credit notes, pick up Invoices & Credit Notes credit notes), mailer_send_pre (attachment), delete_order, update_product_post / delete_product_post (unit), delete_company (seller data), rma_update_details_post (credit notes of returns), kv_invoice_builder_document_issued (Invoices & Credit Notes 1.0.1+: e-credit note at once for every credit note issued there). All exist with the same arguments in 4.17.2 and 4.21.2. The add-on priority is 1100, so Invoices & Credit Notes (1000) has issued its number first in shared hooks.
Templates: admin orders:tabs_extra (post), orders:details_tools (post), products:update_product_amount (post), index:styles; storefront orders:details_tools (post), index:styles. Context menu: orders (Print documents → e-Invoices (ZIP)).
Nothing is printed on cacheable storefront pages. Customer links are on the session-bound order page; downloads are sent with Cache-Control: private, no-store.
Other Kavio Labs add-ons
Section titled “Other Kavio Labs add-ons”| Add-on | Integration |
|---|---|
| Invoices & Credit Notes | Numbers, dates and credit notes (read through its public classes; when it is not active, own numbering). Its per-vendor numbering makes vendors the sellers (Multi-Vendor, automatic mode). |
| EU VAT Number Validation | Buyer VAT ID and reverse-charge decision from kv_vat_orders; store VAT number as the seller VAT fallback. |
| Sell by Weight & Length | Measured quantity (extra.kv_fq.qty / 10000) and unit (kg → KGM, m → MTR, l → LTR …). |
File map
Section titled “File map”app/addons/kv_eu_e_invoicing/ addon.xml, init.php, func.php controllers/backend/kv_eu_e_invoicing.php list, document page, downloads, ZIP, issue, rebuild, credit, send, seller data, mapping controllers/backend/orders.post.php order page tab controllers/backend/products.post.php unit field data controllers/frontend/kv_eu_e_invoicing.php customer download controllers/frontend/orders.post.php customer order page links resources/fonts/ Noto Sans Regular/Bold (subset) + OFL.txt schemas/ context_menu, menu, permissions, settings Tygh/Addons/KvEuEInvoicing/ Config, Codes, Lang, Sellers, Maps, Buyer, InvoiceBuilder, Series, Documents, Issuer, Validator, Formats, Output, Access, Hooks, View, Model/{Builder,Calculator}, Format/{Xml,Ubl,Cii}, Pdf/{Document,TrueType,Icc,Layout,FacturX}, Peppol/{TransportInterface,Transports}, License/*, Upgrade/Synchronizerdesign/backend/templates/addons/kv_eu_e_invoicing/ views, components, hooks, settings, licensedesign/backend/css/addons/kv_eu_e_invoicing/styles.lessdesign/backend/media/images/addons/kv_eu_e_invoicing/icon.pngvar/themes_repository/responsive/templates/addons/kv_eu_e_invoicing/hooksvar/themes_repository/responsive/css/addons/kv_eu_e_invoicing/styles.lessvar/langs/en/addons/kv_eu_e_invoicing.poLicense
Section titled “License”The license client is Tygh\Addons\KvEuEInvoicing\License\Client (isActive()); the gate is Config::canIssue() (enabled and licensed). Gated: creating, rebuilding and crediting documents, e-mail attachments, Peppol sending. Not gated: lists, document pages, downloads (admin, vendor, customer).