=== itdatex E-Invoice Output ===
Contributors: itdatex
Tags: e-invoice, xrechnung, zugferd, invoice, billing
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 8.1
Stable tag: 0.1.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Issue German e-invoices (XRechnung, ZUGFeRD, Factur-X) directly in WordPress — KoSIT-validated, generated locally, never sent to any cloud.

== Description ==

Since 1 January 2025, German businesses must be able to receive electronic invoices under § 14 UStG. From 2027/2028 onwards, the *issuing* side becomes mandatory too: B2B invoices must be sent as e-invoices (XRechnung or ZUGFeRD), not as PDFs or Word documents. **itdatex E-Invoice Output** generates these formats directly inside your WordPress installation.

= What it does =

* Issues invoices in three formats:
  * **XRechnung 3.0.2 UBL** — the standard B2G format used via Leitweg-ID
  * **XRechnung 3.0.2 CII** (UN/CEFACT) — the EN 16931 syntax also used by ZUGFeRD and Factur-X
  * **ZUGFeRD-PDF** — a hybrid PDF/A-3 with both a human-readable invoice and the embedded CII XML
* Pre-validates the generated XML against the EN 16931 XSD schema before saving
* Stores each issued invoice with a random filename in a protected upload directory and chains every file's SHA-256 with the previous one
* Provides an admin form with built-in checks for KoSIT-mandatory fields (BR-DE-*, R010/R020 electronic address, BT-10 buyer reference, BR-DE-9 postal code, BR-DE-15 buyer reference)
* Catches SHA-256 duplicates: re-issuing the exact same draft returns the existing invoice id instead of creating a second row
* Logs every action (issue, download) in a dedicated audit table
* Ships a WP-CLI command `wp ausrg issue --from=draft.json [--format=cii]` for scripted issuing

= KoSIT-validated output =

The output of all three builders is accepted by the official KoSIT Validator using the XRechnung 3.0.2 / EN 16931 1.3.15 configuration. The plugin includes a test script (`tools/e2e-validate.php`) that you can run against a local KoSIT Validator instance to verify this on your own server.

= Privacy by design =

The free version performs all generation locally on your own server. No invoice data leaves your WordPress installation. There is no telemetry, no automatic update check against a third party, no analytics, no external font or asset loading.

A separate Pro version (sold via wp.itdatex.support, not part of this free plugin) adds optional cloud-assisted features — KoSIT deep validation via API, AI-based KoSIT-error explanations in plain German, e-mail dispatch — and is opt-in only.

= GoBD-supporting, not GoBD-certified =

The plugin supports GoBD-conformant processes through immutable storage, SHA-256 hash chaining and a complete audit trail. As with any tooling: software cannot be "GoBD-certified" — conformity is a property of *your* process. Consult your tax advisor.

= Sister plugin =

If you also need to *receive* incoming e-invoices, install **itdatex E-Invoice Intake** alongside this plugin. The two plugins share the same database schema and upload directory, so incoming and outgoing invoices live in the same hash chain. Either plugin works standalone; if both are installed, the order of activation does not matter.

= Open source =

The full source code is released under GPL-2.0-or-later. You can verify, audit and adapt the plugin yourself. Dependencies (`josemmo/einvoicing` for UBL, `horstoeko/zugferd` for CII/ZUGFeRD-PDF, `setasign/fpdf` for the PDF layout) are vendored with prefixed namespaces so they cannot conflict with other plugins in the same WordPress installation.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/itdatex-e-invoice-output/`, or install via the Plugins screen.
2. Activate the plugin.
3. Open **Ausgangsrechnung → Einstellungen** in the admin sidebar and fill in your seller data (company name, VAT ID, address, contact phone/email, electronic address) and default payment terms (IBAN, BIC, payment text). All KoSIT-mandatory seller fields are validated on save.
4. Use **Ausgangsrechnung → Neue Rechnung** to issue your first invoice.

The plugin creates three database tables (`*_reing_invoices`, `*_reing_files`, `*_reing_audit_log`) and a protected upload directory under `wp-content/uploads/itdatex-e-invoice-{random}/`. If the sister plugin "itdatex E-Invoice Intake" is already installed, the existing tables and upload directory are reused — no duplicate storage.

On uninstall, **invoice data and files are NOT deleted by default** because of statutory retention requirements (8 to 10 years under German tax and commercial law).

== Frequently Asked Questions ==

= Which format should I choose? =

For *B2G* invoices to German authorities (Bund, Länder, Kommunen): **XRechnung UBL** with a Leitweg-ID in the Buyer Reference. For *B2B* invoices: **ZUGFeRD-PDF** is the most polite choice — the recipient sees a normal PDF, machine-readable systems extract the XML. **CII** is useful when the recipient expects the EN 16931 CII payload without a PDF carrier (e.g. via PEPPOL).

= What about Kleinunternehmerregelung (§ 19 UStG) and reverse charge? =

In the position editor, set the VAT category to `E` (exempt — Kleinunternehmer) or `AE` (reverse charge) and the VAT rate to 0. The plugin generates the correct EN-16931 tax breakdown.

= Why does the plugin demand a "Leitweg-ID" even for B2B invoices? =

It does not. The field is labelled "Leitweg-ID / Buyer Reference" because BT-10 (BR-DE-15) is XRechnung-mandatory but its content is up to you: in B2G that is the official Leitweg-ID; in B2B you can use a customer- or order-number. The plugin does *not* validate the format against the Leitweg pattern.

= Does the plugin send anything to your server? =

The free version makes no external HTTP calls. All generation, validation and storage happens locally. You can verify this by inspecting the source — the only network code path would be the optional Pro upgrade, which is not part of this free plugin.

= Can I use the plugin without the sister "Intake" plugin? =

Yes. The plugin creates its own tables and upload directory on activation. If you later install the Intake plugin, both plugins share the existing schema — no migration needed.

= How does the duplicate detection work? =

Every issued file is hashed (SHA-256) and compared against the file table. Re-running the same draft (same numbers, same VAT, same line items) produces an identical XML/PDF byte sequence and triggers a duplicate response with the existing invoice id. This is intentional: invoice numbers should be re-used at the *invoice level*, not at the file level. To re-issue a corrected version, change at least one byte (e.g. the issue date or the buyer reference).

= Does this work behind nginx? =

Yes. The protected upload directory uses both `.htaccess` (Apache/LiteSpeed) and a randomized directory name so that path guessing fails. File downloads always go through a capability-and-nonce-checked endpoint, never via a direct URL.

= How do I issue invoices from a script? =

`wp ausrg issue --from=draft.json --format=ubl|cii|zugferd-pdf` reads a JSON draft and runs the same pipeline as the admin form. Useful for migrations from a different billing system. The seller data falls back to the plugin Settings if not present in the JSON.

== Screenshots ==

1. The list view shows all issued invoices with date, due date, buyer, gross amount and validation status.
2. The "Neue Rechnung" form has inline hints for every KoSIT-mandatory field (BT/BR codes).
3. The single-invoice view shows the generated file, header data, validation report and audit trail.
4. The Settings page validates seller data against BR-DE-5 to BR-DE-28 on save (contact details, electronic address, VAT ID).

== Changelog ==

= 0.1.0 =
* Initial release: UBL, CII and ZUGFeRD-PDF builders; admin form with KoSIT-mandatory field validation; seller-data settings; WP-CLI command; secure download endpoint; SHA-256 hash chain; audit log; standalone activation (own schema + upload dir, or shared with the sister Intake plugin).

== Upgrade Notice ==

= 0.1.0 =
First public release.
