Developer notes
File map
Section titled “File map”app/addons/kv_invoice_builder/ addon.xml settings, tables, document + e-mail templates (resources/) init.php / func.php hook registration and handlers resources/document_templates.xml document types kv_ib_invoice, kv_ib_credit_note (code "default") + snippets resources/email_templates.xml e-mail kv_invoice_builder_document controllers/backend/kv_invoice_builder.php lists, view/PDF, credit notes, bulk tools, vendor settings, CSV controllers/backend/orders.post.php "Invoices" tab on the order page controllers/frontend/kv_invoice_builder.php customer document page / PDF controllers/frontend/orders.post.php links on the customer's order page schemas/documents/ types.post.php, kv_ib_invoice.php, kv_ib_credit_note.php, order.post.php schemas/menu, permissions, context_menu, settings Tygh/Addons/KvInvoiceBuilder/ Issuer.php numbering transaction, invoices and credit notes Series.php series keys, formats, vendor settings Snapshot.php frozen content of an invoice Credit.php credit note content Documents.php storage (read side), lists View.php escaped output values Output.php HTML, print page, PDF, ZIP Mail.php e-mail attachments and sending Hooks.php automatic triggers Access.php admin, vendor and customer access Document/Type.php, Document/Context.php core document type classes License/, Upgrade/ licence client, self-healing upgradesdesign/backend/templates/addons/kv_invoice_builder/ admin views, order hooks, settings infovar/themes_repository/responsive/templates/addons/kv_invoice_builder/hooks/orders/details_tools.post.tplNumbering
Section titled “Numbering”A number is taken inside one database transaction:
SELECT last_no FROM ?:kv_ib_counters WHERE series_key = … FOR UPDATElocks the counter row of the series (the row is created when the series is new). Parallel issues in the same series wait here.- The idempotency key of the document (
inv:<order>,full:<invoice>,rma:<return>,wallet:<ledger entry>) is checked under the lock; credit notes also re-check the open amount of the invoice. - The document is inserted with
last_no + 1and the counter is moved; then the transaction commits.
Any failure rolls the transaction back, so no number is lost or used twice. Deadlocks and lock wait timeouts are retried (6 attempts with back-off). Unique keys on (series_key, seq_no), inv_order_id and source_key are the last line of defence.
Series key: I|C + scope (s<company> storefront on CS-Cart, v<company> vendor or m marketplace on Multi-Vendor) + year (or 0 without the yearly reset). Changing a format does not start a new series.
Tables
Section titled “Tables”| Table | Contents |
|---|---|
?:kv_ib_documents |
One row per invoice (doc_type I) or credit note (C): order, company, series, sequence, number, issue time, invoice link, source and idempotency key, totals in the base currency, customer, data (JSON snapshot: seller, buyer, lines, taxes, totals, currency with its rate, texts) |
?:kv_ib_counters |
Last number per series |
?:kv_ib_vendor_settings |
Multi-Vendor: own formats, tax ID, notes and footer per vendor |
Documents are never updated after insert, except the order_deleted flag when an order is deleted (the documents stay).
Document types
Section titled “Document types”kv_ib_invoice and kv_ib_credit_note are registered in schemas/documents/types.post.php and as template.document.<type>.type services (ServiceProvider). Both implement IType and IPreviewableType; variables are defined in schemas/documents/kv_ib_invoice.php (d, s, b, escaped by View). Templates are valid in Twig 2.14 (CS-Cart 4.17/4.18) and Twig 3.11 (4.21). Loops live in snippets because the visual editor of Design → Documents moves Twig tags placed between table rows.
schemas/documents/order.post.php adds kv_invoice (number, date, credit_notes) to the core order documents.
Render a document from code:
$doc = \Tygh\Addons\KvInvoiceBuilder\Documents::invoiceForOrder($order_id);$html = \Tygh\Addons\KvInvoiceBuilder\Output::html($doc); // document HTML$file = \Tygh\Addons\KvInvoiceBuilder\Output::pdfFile([$doc]); // '' when PDF is not availableHooks for other add-ons
Section titled “Hooks for other add-ons”kv_invoice_builder_document_issued($doc) fires once after a new invoice or credit note was issued and committed (status change, manual issue, bulk issue, return, wallet refund, manual credit note). $doc is the decoded document (doc_type I or C, doc_id, order_id, invoice_id, number, total, data). Register it like a core hook (fn_register_hooks('kv_invoice_builder_document_issued'), handler fn_<your_addon>_kv_invoice_builder_document_issued($doc)); errors thrown by a handler are logged and never undo the document. Since 1.0.1.
Hooks used
Section titled “Hooks used”change_order_status (issue invoice / full credit note, before the status e-mails), rma_update_details_post (returns), kv_customer_wallet_post_entry_post (wallet refunds), delete_order (flag documents), get_orders_post (invoice column), mailer_send_pre (attach documents issued in this request to the customer’s status e-mail), template_document_get_name (document names). All handlers are store-safe: errors are logged (general/runtime) and never interrupt the order flow.
Full page cache
Section titled “Full page cache”Nothing is printed on cacheable pages. Customer output appears on the order details page and the document page, which are session pages, and the document page sends Cache-Control: private, no-store.
License check
Section titled “License check”The licence client (License\Client) verifies the key for the store’s domain once a day, only in the admin panel or from cron. Without a valid license no new numbers are issued (status changes, manual and bulk issue, returns, wallet refunds) and nothing is attached to e-mails; lists, print views, PDF, ZIP and CSV of issued documents keep working.