Changelog
Invoice history for the invoice plugin. Yes, we went there.
What changed, when, and whether it's worth reading.
March 2026
v1.1.1
Released 14 March 2026 — GitHub Release
The audit that wouldn't end. We ran 206 unit tests, found 50+ bugs across five audit rounds (including a security audit, Fakturownia API spec review, and a full frontend wiring teardown), and discovered the settings page was completely blank the whole time. Nobody complained. We're choosing to find that encouraging.
Fixed: settings page was entirely broken
The Fakturownia settings page at Integrations > Fakturownia showed absolutely nothing. A white void. No fields, no buttons, no error. Just the quiet despair of a misconfigured REST response wrapper. FluentCart's Vue expected response.data.integration but got raw JSON with no data key. Every integration that uses FluentCart's getGlobalSettingsData() has this problem — we just happened to be the first to notice.
The page now loads, renders all 8 fields, shows a green "Connected to your-domain.fakturownia.pl" status, and the Save button actually tells you whether it worked.
Fixed: Settings button missing from integration card
On the Integrations page, every other plugin had install/configure buttons. Fakturownia had nothing — just a card you could technically click if you happened to know the cursor changed. Now there's a visible Settings button. Revolutionary.
Fixed: NIP validation never actually ran
The NIP checksum validation at checkout was wired to the wrong data path. FluentCart passes {data: formData, cart: cart} but we read formData.billing_nip directly — one level too shallow. Every NIP was accepted. 0000000000? Sure. ABCDEFGHIJ? Why not. Fixed with a proper nested lookup and a fallback for backwards compatibility.
Fixed: invoices sent without currency
Multi-currency stores were creating invoices in Fakturownia's default currency (PLN) regardless of what the customer actually paid in. A EUR order got a PLN invoice. Now sends the order's actual currency.
Fixed: proforma invoices sent as "paid"
Proformas are payment requests. Sending them with status: paid defeats the entire point. They now get status: issued, no paid_date, and a 7-day payment term. Also no longer sent to KSeF (proformas aren't KSeF-eligible — gov_status: not_applicable).
Fixed: invoices crashed on null billing address
Digital-only orders or orders where the billing address insert failed would crash with a TypeError before any null check could save them. Every property access now uses null-safe operators. Guest orders with deleted customer records are also handled.
Fixed: discounted items got wrong VAT rate
Tax rate was calculated using the pre-discount subtotal as the denominator. A 50%-off product at 23% VAT would calculate as 11.5% and snap to 8%. Now uses line_total (post-discount amount) — where the tax was actually calculated.
Fixed: 0% VAT treated as exempt
normalizeVatRate(0) returned 'zw' (exempt). But 0% VAT and exempt are legally different things — 0% is a real rate (e.g. intra-community supply), 'zw' means no VAT applies at all. KSeF cares about this distinction. Fixed.
Security: SSRF prevention on domain field
An admin could set the Fakturownia domain to 169.254.169.254 or evil.attacker.com and the plugin would happily send API requests (including the API token) to that host. Now validates that the domain matches *.fakturownia.pl and rejects anything else.
Security: Content-Type hardcoded on PDF proxy
The PDF download proxy was forwarding the upstream Content-Type header verbatim. If a MitM (or a very confused Fakturownia API) returned text/html, your browser would render the response body as a page — potential XSS. Now hardcoded to application/pdf.
Security: ZIP URL validated in auto-updater
The GitHub auto-updater accepted any browser_download_url from the releases API without checking the domain. A compromised API response (or poisoned transient) could redirect the download to a backdoored ZIP. Now validates URLs start with github.com/vcode-sh/fchub-plugins/.
New: connection status on settings page
The settings page now shows a clear "Connected to X.fakturownia.pl" indicator in green when the API connection is active. If credentials are wrong, a red error banner explains what to do. No more guessing whether your token works.
New: EU VAT number support (buyer_tax_no_kind)
Non-Polish buyers with EU VAT numbers (e.g. DE123456789) now get the correct buyer_tax_no_kind: 'nip_ue' on the invoice. Non-EU tax IDs get 'other'. KSeF requires this field — without it, invoices to EU companies were rejected.
New: correction invoices follow Fakturownia API spec
Correction invoice positions now include kind: 'correction' and correction_before_attributes.kind: 'correction_before' as the API spec requires. Also stores initial KSeF data (gov_id, gov_link) from the correction create response instead of waiting for the first cron poll.
New: feed note wired to invoice description
The "Invoice Note" field in the integration feed settings existed in the UI but did exactly nothing. It now passes through to Fakturownia as the invoice description field, truncated to 3,500 characters (KSeF limit).
New: KSeF sandbox support
Fakturownia sandbox environments return demo_ok, demo_processing, demo_send_error etc. The plugin only checked for the non-prefixed versions, so sandbox KSeF statuses would retry 30 times and give up. Now strips the demo_ prefix automatically.
New: server_error KSeF status triggers retry
KSeF server_error is transient (KSeF is down, not your invoice). Previously treated as terminal — the plugin would just stop checking. Now retries alongside processing, giving KSeF time to recover.
Other improvements
exempt_tax_kindauto-set when KSeF is enabled and positions use'zw'tax — prevents KSeF 422 rejectionpayment_toandpayment_to_kindnow sent to Fakturownia (payment deadline visible on documents)- API token masked in admin settings API response (
****+ last 4 chars) department_idvalidated as numeric — no more SQL injection via settings field (admin-only, but still)- NIP mod-11=10 explicitly rejected (was only working by accident)
returnafter everywp_send_jsonerror for defensive safety- All buyer/position fields truncated to Fakturownia's documented limits (255/256/3500/16 chars)
mb_substrused everywhere instead ofsubstr— Polish characters no longer split mid-byte- Strict
=== 0.0comparison instead of loose== 0for tax amount checks - GitHubUpdater markdown code blocks no longer render with backtick delimiters
- 206 unit tests covering every bug fix, edge case, and adversarial input
v1.1.0
Released 14 March 2026 — GitHub Release
A thorough audit of the entire plugin. The kind where you find out nothing actually worked. Invoice amounts were wrong, the settings page crashed, the checkout NIP field was invisible, and the order confirmation showed nothing. Eleven fixes, zero new features, one very long day.
Fixed: invoices had wrong amounts
Every invoice sent to Fakturownia was missing the VAT. A 123 zł order would generate a 100 zł invoice. Shipping tax was also hardcoded to 23% regardless of the actual rate. Both are now calculated correctly from the order data.
Fixed: settings page didn't load
Opening Fakturownia settings inside FluentCart's integration panel either showed a broken page or nothing at all. The settings form now loads and saves reliably.
Fixed: invoice info missing from order confirmation
The Fakturownia info block (invoice number, PDF link, KSeF status) never appeared on the thank-you page or the order admin view. It does now.
Fixed: NIP field invisible at checkout
The "I want a company invoice" checkbox and NIP field never rendered on the checkout page. Completely rewritten — the toggle and NIP input now appear correctly and hide/show as expected.
Fixed: correction invoices on refund
Refund corrections were sent to Fakturownia without proper line items, relying on undocumented behaviour. Now builds explicit correction positions from the original invoice. KSeF submission for corrections is also handled in a single step instead of two.
Fixed: PDF link leaked your API credentials
The invoice PDF download link contained your Fakturownia API token in plain text in the page HTML. PDF downloads now go through a secure proxy — your token stays on the server where it belongs.
Fixed: KSeF status check ran forever
If KSeF took a while to process an invoice, the status check would retry every 2 minutes — indefinitely. Now gives up after about an hour and logs a warning so you know to check Fakturownia manually.
Other fixes
- Invoice dates (
sell_date,issue_date) are now set from the actual payment date instead of defaulting to whenever the cron job happened to run - Plugin uninstall now actually cleans up its settings from the correct database table
- KSeF status checks no longer run if Fakturownia credentials are missing
- Removed dead code from the checkout field registration
v1.0.3
Released 6 March 2026 — GitHub Release
Fixed a fatal error when multiple FCHub plugins are active at the same time. The shared GitHubUpdater class used a class_exists guard that PHP's OPcache cheerfully ignored during early class binding — so the second plugin to load would redeclare the class and take the site down. Wrapped the class inside the conditional so OPcache actually respects it.
v1.0.2
Released 3 March 2026 — GitHub Release
PHP 8.1 and WordPress 6.4 are now the minimums. PHP 7.4 has been retired with all the fanfare it deserves. No functional changes — your invoices still work exactly as before.
v1.0.1
Released 3 March 2026 — GitHub Release
Version bump only. First release under the monorepo tag convention. The plugin itself is unchanged; the CI pipeline just needed a properly tagged release.
v1.0.0
Released 2 March 2026 — GitHub Release
Initial release of FCHub Fakturownia. FluentCart order gets paid → invoice appears in Fakturownia. That's the pitch. There's rather more going on under the bonnet.
Automatic invoicing
When an order is paid in FluentCart, an invoice is created in Fakturownia without you having to do anything. Several invoice types are supported:
| Type | When to use |
|---|---|
| VAT invoice | Standard — for most businesses |
| Proforma | Issued before payment is confirmed |
| Bill (rachunek) | For sellers not registered for VAT |
Invoices are created only once per order — duplicate prevention is built in. Polish VAT rates (0%, 5%, 8%, 23%, exempt) are detected and mapped automatically. Prices are converted from FluentCart's internal format to whatever Fakturownia expects without any manual intervention.
Invoice language options: Polish, English, German, French, bilingual PL/EN.
B2B and B2C invoices
Customers who need a company invoice can tick "I want a company invoice" at checkout, which reveals a NIP (Polish tax ID) field. The NIP is validated client-side (checksum check) before the order goes through.
- B2B invoices include the customer's company name and NIP
- B2C invoices go out as standard consumer documents
- The checkout field initialises correctly even with FluentCart's dynamic rendering
KSeF 2.0
Poland's national e-invoicing system. If you need it, it's here.
- Invoices submitted to KSeF automatically after creation
- Status is checked asynchronously — WordPress cron polls for the result
- KSeF ID and verification link are stored on the order once confirmed
- Status visible in the order admin panel with colour-coded labels
Correction invoices (see below) are also submitted to KSeF when auto-send is enabled.
KSeF submission is optional. You can leave it off until you actually need it.
Correction invoices on refund
When you issue a refund in FluentCart, a correction invoice is created in Fakturownia and linked to the original. Duplicate corrections are prevented. KSeF submission for corrections follows the same auto-send setting as regular invoices.
Order admin panel
From the FluentCart order screen you can see:
- Invoice number with a direct link into Fakturownia
- PDF download link
- KSeF status (with colour-coded label)
- Correction invoice details if a refund was issued
- An order log entry for every invoice operation (created, submitted, error)
Configuration
Settings live inside FluentCart's integration panel. You can configure invoice type, payment method, language, KSeF, and NIP behaviour without touching code.
Credentials (API domain, token, department ID) can be set via wp-config.php constants if you'd rather not store them in the database.
Connection is tested automatically when you save settings.
Full uninstall
Deactivating clears the cron jobs. Deleting the plugin removes all settings and order metadata. Fakturownia invoices already created are unaffected — those live on their servers, not yours.