=== Brightfern E-Invoicing for WooCommerce ===
Contributors: ombel, freemius
Tags: e-invoicing, peppol, ksef, invoicing, vat, xrechnung, factur-x, en16931, b2b, einvoice
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 8.1
Stable tag: 0.1.17
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Generate, validate and receive EN 16931 e-invoices in WooCommerce — Peppol, XRechnung, Factur-X and Poland's KSeF, checked before you send.

== Description ==

Brightfern turns your WooCommerce orders into compliant, VAT-correct structured e-invoices for B2B and B2G sales, in whichever format the country you invoice actually requires — and checks each one before it leaves.

= Four formats, one plugin =

* **Peppol BIS Billing 3.0** (UBL) — the European network standard, used across Belgium, the Netherlands and beyond.
* **XRechnung** (Germany) — the same UBL syntax with the German specification identifier and its own rules, including the buyer reference public bodies require.
* **Factur-X** (France) — a PDF/A-3 your customer can read, with the machine-readable CII invoice embedded inside it, for the domestic PPF/PDP flow.
* **KSeF FA(3)** (Poland) — the national clearance format, mandatory since February 2026. Not a variant of the others but a separate model written against the Polish VAT act, mapped directly and checked against the Ministry of Finance's own schema.

Switch between them under WooCommerce → E-Invoicing → Format. Credit notes follow automatically from WooCommerce refunds.

= What makes it different =

* **It validates before it sends.** A pre-flight gate checks the invoice against the rules for the chosen format, confirms the buyer is actually reachable on the network (SMP lookup), and validates their VAT number and name (VIES) — so you find out now, not days later when a portal rejects it. It also tells you when a format simply cannot express an order, rather than producing a file that gets refused at filing time.
* **It also receives.** Not just sending — Brightfern takes inbound e-invoices into a WooCommerce inbox and matches them to your orders. Being able to receive is mandatory for all French businesses from September 2026, even before they must issue.
* **It doesn't lock you to one network.** Brightfern is **provider-agnostic**: bring your own certified Access Point. No per-document markup, no lock-in.

Correct on the hard cases: mixed VAT rates, discounts, reverse charge, intra-community supply, exempt small businesses, and cent-accurate rounding.

Available in English, Dutch, French, German and Polish.

= Free vs Pro =

* **Free:** generate the e-invoice (and credit notes) from an order in Peppol BIS UBL, XRechnung (Germany), Factur-X (France, a PDF/A-3 with the structured invoice embedded inside), or KSeF FA(3) (Poland), run the full validation + recipient + VAT checks, download the file, and **receive** inbound e-invoices into the WooCommerce inbox.
* **Pro:** transmit outbound over Peppol, and file to Poland's KSeF — either straight to the Ministry of Finance (no intermediary, no per-document cost) or through your Access Point — with delivery and status tracking, including the official KSeF number once it is assigned.

= Compliance notes =

EN 16931 is the semantic model. Peppol BIS Billing 3.0 (UBL syntax) is used for transmission. XRechnung (Germany) uses the same UBL syntax with its own specification identifier and business rules (e.g. a mandatory buyer reference for public-sector recipients). Factur-X (France) embeds a UN/CEFACT CII XML — a different syntax from UBL — inside a human-readable PDF/A-3, for the domestic PPF/PDP flow rather than Peppol transit. Select your format under WooCommerce → E-Invoicing → Format.

Poland's KSeF is a different kind of system again: a national clearance platform, mandatory since February 2026, where an invoice becomes legally issued only once KSeF accepts it and assigns a number. Its FA(3) format is not a syntax binding of EN 16931 but a separate national model written against the Polish VAT act, so Brightfern maps to it directly. Generating and validating FA(3) is free, and you can always download the file and submit it in the Ministry of Finance taxpayer application yourself. On Pro, Brightfern can also file it for you through the KSeF API and record the KSeF number it returns. FA(3) requires a Polish seller (a NIP), and Brightfern will tell you before generating if that is missing.

Brightfern integrates a certified Access Point provider's API; it is not itself a certified Access Point.

== Installation ==

1. Install and activate the plugin (WooCommerce required).
2. Go to **WooCommerce → E-Invoicing** and fill in your seller identity (legal name, VAT number, Peppol electronic address, address, IBAN).
3. Choose your Access Point provider and enter its credentials (or keep **Mock** to try it offline).
4. Pick the order status that should generate an invoice (default: Completed).
5. (Receiving) Set a webhook secret and paste the shown webhook URL into your provider, or enable polling.

== Frequently Asked Questions ==

= Do I need to be a certified Peppol Access Point? =

No. You connect your own certified provider; Brightfern speaks to it through a provider-agnostic interface.

= Which countries are supported? =

Belgium (Peppol BIS UBL) is fully supported. Germany (XRechnung), France (Factur-X) and Poland (KSeF FA(3)) are supported — select the format under WooCommerce → E-Invoicing → Format. For Poland, generating and validating the FA(3) file is free and you can upload it to KSeF yourself; on Pro, Brightfern can file it through the KSeF API for you. For France, Brightfern produces the Factur-X PDF/A-3 and you submit it yourself — there is no automatic transmission to the French portal in this version.

= Can it receive invoices, not just send? =

Yes — that's a core feature. Received documents appear in a WooCommerce inbox and are matched to orders.

= Does it check VAT numbers and get the VAT breakdown right? =

Yes. Before you download an invoice, Brightfern validates the buyer's VAT number and registered name against VIES, and gets mixed VAT rates, discounts, reverse charge, intra-community supply and VAT-exempt small businesses right on the invoice itself — not just a flat total.

= Which languages is the interface available in? =

English, Dutch, French, German and Polish. It follows the site language, or the language set on your own user profile under Settings → General.

= Do I need a Polish company to use KSeF? =

Yes. The FA(3) format requires a Polish tax identifier (NIP) for the seller — that is the format's own rule, not a limitation here. Brightfern checks it before generating and tells you if it is missing.

== External services ==

This plugin's free pre-flight validation and inbound-receiving features connect to the following third-party and public infrastructure services. No invoice line items, prices, or customer personal data beyond what is listed below are ever sent.

**VIES (VAT Information Exchange System)**, operated by the European Commission. Used to confirm that the buyer's VAT number is valid and to check the registered business name, as part of the free pre-flight validation shown before you download an invoice. Only the buyer's VAT number is sent, and only when you trigger validation for that order. [Terms of use](https://ec.europa.eu/taxation_customs/vies/#/disclaimer), [Privacy Policy](https://ec.europa.eu/info/privacy-policy_en).

**Peppol SML/SMP network**, the DNS- and HTTP-based lookup infrastructure of the Peppol e-delivery network, governed by OpenPeppol and built on the European Commission's eDelivery building block. Used to confirm the buyer's Peppol participant identifier (VAT/company id + electronic address scheme) is registered and can receive documents. Only that identifier is sent, as part of the free pre-flight validation; no invoice content is transmitted. [OpenPeppol](https://peppol.org/).

**Storecove**, one of several certified Peppol Access Points you can configure under WooCommerce → E-Invoicing. Brightfern is provider-agnostic and ships Storecove's API base URL only as a pre-filled example — you may point it at any certified Access Point, or leave the bundled offline **Mock** provider selected to use the plugin without any external service. When Storecove (or any configured provider) is selected, the plugin polls it for inbound e-invoices addressed to you (free tier) and, on the Pro tier, transmits outbound invoices through it. [Storecove](https://www.storecove.com/), [Privacy Policy](https://www.storecove.com/fileadmin/editors-filemount/documents/Data_Privacy_Policy_Storecove_final_website.pdf).

== Screenshots ==

1. Seller identity settings (WooCommerce → E-Invoicing).
2. The e-invoice status on the order edit screen: status, validation findings, and download link.
3. The inbound inbox: received e-invoices matched to orders.

== Changelog ==

= 0.1.17 =
* Pro: an invoice rejected by KSeF (for example, flagged as a duplicate) is now recorded as rejected instead of staying "pending" indefinitely.
* Pro: switching your e-invoicing provider no longer risks the hourly status check asking the newly-selected provider about an invoice that was actually sent through a different one.
* Pro: added a safety check that stops the KSeF (direct) provider from filing a document that was built for a different format.
* Pro: a bad response from KSeF's public-key service could previously block filing for up to 24 hours; it is no longer cached when that happens.
* Smaller reliability fixes to the hourly status-check pass: it now works through a backlog oldest-first, and a single failed check no longer gives up on the rest of that invoice's status poll.

= 0.1.16 =
* Pro: Poland's KSeF can now be filed automatically, instead of downloading the FA(3) file and uploading it in the Ministry's taxpayer application yourself. Two routes are available — directly to the Ministry of Finance (no intermediary and no per-document cost), or through Storecove if you already use them as your Access Point. Pick "Poland KSeF (direct)" under WooCommerce → E-Invoicing and paste in the authorization token you generate once at ksef.podatki.gov.pl.
* Pro: transmitted invoices that the network hadn't confirmed yet are now followed up automatically once an hour, so a KSeF invoice that takes a while to clear still gets its official KSeF number recorded on the order instead of an internal reference. Peppol delivery confirmations are picked up the same way.
* Provider API addresses are now restricted to https. A typo used to be able to silently downgrade the connection to plain http, which for KSeF also carries the credential used to file your invoices.
* Generating an invoice can no longer fail in a way that interrupts the order it belongs to: an unexpected error during transmission now fails just that invoice, with the reason recorded on the order.

= 0.1.15 =
* Fixed a data-loss edge case: a very large invoice (many line items) could fail to save under WooCommerce's High-Performance Order Storage without any visible error. Brightfern now detects this before it happens and fails the invoice with a clear message instead of silently losing it.
* Fixed a race condition where triggering invoice generation twice in quick succession for the same order (e.g. an automatic status-change trigger overlapping a manual "Generate now" click) could corrupt which document ended up stored.
* KSeF: line-level discounts are now included on the invoice (P_10), and the seller's tax id is clamped to the length KSeF actually allows.
* Fixed VAT numbers for Greek businesses being incorrectly flagged as invalid.
* Fixed the VAT breakdown being able to show the wrong sign for a shipping charge on some orders, and orders consisting only of fees or shipping (no product lines) failing to generate an invoice at all.
* Credit notes now double-check that the refunded amount matches what WooCommerce recorded before finalizing.
* Fixed a case where a failure to store a received e-invoice could go unnoticed instead of being reported so the sender's system retries.
* Fixed inbound invoice matching being able to attach a document to the wrong order in one of its two matching paths.
* Several smaller fixes: inbox order links under High-Performance Order Storage, a settings-save edge case, an empty inbound file being rejected safely instead of erroring, and more consistent Pro gating for Peppol-only checks.

= 0.1.14 =
* Pro: "Generate & send now" no longer re-transmits an invoice that was already sent and confirmed delivered — it now tells you to issue a credit note (or a new invoice) instead, since resending different content under the same invoice number isn't valid on Peppol or KSeF. Resending an invoice that failed or was blocked still works exactly as before.

= 0.1.13 =
* KSeF: the reason you give when refunding an order in WooCommerce now appears on the correction invoice itself, matching what already happened for Peppol, XRechnung and Factur-X.

= 0.1.12 =
* Added Poland's KSeF FA(3) as a Format option in Settings. Generating and validating it is free, same as the other formats: Brightfern produces the FA(3) XML and checks it against the Ministry of Finance's own schema, and you submit it in the taxpayer application to obtain the KSeF number. There is no automatic submission through the KSeF API in this version.
* Pre-flight now tells you before generating if KSeF cannot be used for an order: a seller without a valid Polish NIP, or a VAT rate that has no equivalent in the Polish rate scheme. Invoices in a currency other than PLN generate a warning, because FA(3) also expects the VAT restated in PLN.
* The Peppol recipient and electronic-address checks no longer run for Poland, the same fix already made for France — those documents never travel over Peppol, so the warnings were misleading.
* Added a Polish translation, alongside the existing Dutch, French and German. Set the site or user language under Settings → General (or your user profile) to switch.
* KSeF: long product names, SKUs and barcodes are now shortened to the lengths the Polish schema allows, instead of producing a file KSeF rejects. A buyer whose VAT field holds only a country code, and a correction invoice that cannot name the invoice it corrects, are handled properly too.

= 0.1.10 =
* Removed two files that were being packaged into the plugin by mistake: a copy of the plugin's own zip (shipped since 0.1.5) and a copy of the Composer tool. Together roughly 4.5 MB of dead weight that did nothing.

= 0.1.9 =
* Factur-X: fixed the seller's legal and trading name being swapped in the embedded XML.
* Factur-X: removed the currency attribute from amounts that must not carry it, which could cause a document to be rejected by a receiving portal.
* Factur-X: invoices to buyers who aren't on the Peppol network are no longer blocked or warned about — Factur-X doesn't use Peppol at all.
* Factur-X: the printed PDF now shows the VAT breakdown per rate, including the exemption reason for reverse charge and similar cases, plus any amount already paid.
* Fixed a stale Factur-X PDF being offered for download after an order was regenerated in a different format.

= 0.1.8 =
* Packaging fix for the 0.1.7 Factur-X release: corrected how the free build is generated so it contains no references to paid-only code. No functional change to the plugin itself.

= 0.1.7 =
* Added Factur-X (France) as a Format option in Settings: generates a PDF/A-3 invoice with a UN/CEFACT CII XML embedded inside it, ready to submit or email. Generating and downloading it is free, same as Peppol and XRechnung — there is no automatic transmission to Chorus Pro in this version, you download and submit it yourself.

= 0.1.6 =
* Added XRechnung (Germany) as a Format option in Settings — same UBL syntax as Peppol BIS with the correct XRechnung specification identifier, plus a check for the mandatory buyer reference (BT-10) that format requires. Generating and validating XRechnung is free, same as Peppol; transmitting it is Pro.

= 0.1.5 =
* Added Dutch, French and German translations (in addition to English). Set the site or user language under Settings → General (or your user profile) to switch.

= 0.1.4 =
* Text domain now matches the assigned WordPress.org slug, brightfern-e-invoicing-for-woocommerce.
* Reworded the description to drop comparative language about other plugins.
* Documented the third-party/public services this plugin calls (VIES, the Peppol SML/SMP network, and the configurable Access Point provider) in a new "External services" section below.

= 0.1.3 =
* Fixed the settings form: a naming mismatch introduced during the rename made every save silently discard the submitted values (and clear stored ones).
* Added a Payment means (BT-81) setting: credit transfer or SEPA credit transfer.
* Fixed the licensing menu wiring so account/opt-in screens render on the settings page instead of a permissions error.
* Inbound XML is now parsed with network access disabled (LIBXML_NONET).
* Corrected the Contributors header to the actual WordPress.org account.
* Removed the Plugin URI header: it duplicated the Author URI, which WordPress.org rejects. There is no separate product page yet.

= 0.1.2 =
* Providers reference the premium send types by fully-qualified name, so the free build carries no imports pointing at the stripped directory.

= 0.1.1 =
* Outbound Peppol transmission is now excluded from the WordPress.org build rather than disabled at runtime, per plugin directory guideline 5.
* Receiving inbound e-invoices moved from Pro to free.
* Uninstall cleanup now also clears the polling cron on a normal uninstall.

= 0.1.0 =
* Initial MVP: EN 16931 mapping, Peppol BIS UBL serialization, three-layer pre-flight validation (business rules + optional XSD + optional schematron), SMP recipient lookup, VIES VAT check, provider-agnostic send + receive (Storecove reference provider + offline mock), admin inbox, order metabox, settings.
