FCHubFCHub.co

Invoice Generation

How FCHub Fakturownia creates invoices from FluentCart orders, maps buyer data, handles B2B and B2C invoices, calculates VAT rates, and processes correction invoices on refund.

FCHub Fakturownia automatically creates invoices in Fakturownia when FluentCart orders are paid. This page covers the complete invoice creation flow, data mapping, VAT rate handling, and correction invoices.

Invoice Creation Flow

The end-to-end process from payment to invoice:

Order Payment Confirmed

FluentCart fires the order_paid_done event when a payment is successfully processed. This is the trigger for the Fakturownia integration.

Duplicate Check

Before creating anything, the plugin checks if an invoice already exists for this order by looking for the _fakturownia_invoice_id meta key. If it finds one, the process stops. This prevents duplicate invoices if the event fires more than once.

Data Mapping

The InvoiceHandler maps the FluentCart order data into Fakturownia's invoice format. This includes buyer information, line items, VAT rates, payment method, and seller department.

API Request

The mapped data is sent to Fakturownia's /invoices.json endpoint. If KSeF auto-send is enabled, the gov_save_and_send flag is included to trigger simultaneous KSeF submission.

Metadata Storage

On success, the plugin stores the invoice ID, invoice number, invoice URL, client ID, and (if applicable) KSeF status as order metadata. All of this is visible in the FluentCart admin.

Order Log Entry

A log entry is added to the order: "Fakturownia: Invoice created -- Invoice [number] created in Fakturownia (ID: [id])". If the creation fails, an error log is recorded instead.

B2B vs B2C Invoices

The plugin automatically determines whether to create a business (B2B) or consumer (B2C) invoice based on the checkout data.

A B2B invoice is created when the customer checks "I want a company invoice" at checkout and provides a valid NIP (tax ID).

Buyer data on the invoice:

  • buyer_company is set to true
  • buyer_tax_no contains the NIP
  • buyer_name uses the company name from the billing address, or falls back to the customer's full name

B2B invoices are the standard for Polish inter-company transactions. The NIP on the invoice allows both parties to use it for VAT deductions.

Data Mapping Reference

Here's exactly how FluentCart order data maps to Fakturownia invoice fields.

Invoice Header

Fakturownia FieldSourceNotes
kindSettings: Invoice Typevat, proforma, or bill
payment_typeOrder payment method or Settings fallbackSee payment type mapping below
langSettings: Invoice Languagepl, en, de, fr, pl/en
statusDepends on invoice typepaid for VAT/bill, issued for proforma
sell_dateOrder payment dateFalls back to creation date, then today
issue_dateCurrent date (WordPress timezone)Y-m-d format via wp_date()
paid_dateOrder payment dateOnly set for non-proforma invoices
payment_to_kindDepends on invoice type7-day term for proforma, other_date for paid
currencyOrder currencyFalls back to PLN if not set
oidOrder invoice numberFalls back to FC-{order_id}
oid_uniqueHardcodedAlways yes (prevents duplicates in Fakturownia)
descriptionFeed note settingOptional, truncated to 3,500 chars for KSeF
department_idSettings: Department IDIf set, seller data is pulled from this department
seller_nameWordPress site nameOnly used if no department ID is configured

Buyer Information

Fakturownia FieldSource
buyer_companytrue if NIP provided, false otherwise
buyer_tax_noNIP from billing address meta
buyer_tax_no_kindAuto-detected: '' for PL, 'nip_ue' for EU, 'other' for rest
buyer_nameCompany name (B2B), truncated to 255 chars
buyer_first_nameFirst name (B2C)
buyer_last_nameLast name (B2C)
buyer_streetAddress line 1 + line 2
buyer_cityBilling city
buyer_post_codeBilling postcode
buyer_countryBilling country code
buyer_emailCustomer email
buyer_phonePhone from billing meta (truncated to 16 chars for KSeF)

Line Items (Positions)

Each order item becomes a position on the invoice:

Fakturownia FieldSourceNotes
nameItem titleTruncated to 256 characters
quantityItem quantityInteger value
quantity_unitHardcodedszt (Polish for "pieces")
total_price_grossItem line totalConverted from cents to decimal
taxCalculated from item tax dataMapped to standard Polish VAT rate

If the order has shipping charges, a separate line item is added for shipping with its own VAT rate.

Polish VAT Rates

The plugin calculates the VAT rate for each line item from the order's tax data and maps it to the closest standard Polish rate.

Calculation

For each order item:

  1. The tax amount and post-discount line total are extracted
  2. The effective rate is calculated: (tax_amount / line_total) * 100
  3. The result is rounded and mapped to the nearest standard rate

Using line_total (not subtotal) is critical — tax is calculated on the discounted amount. Using the pre-discount subtotal produced wrong rates for discounted items.

Standard Rates

RateDescription
23%Standard rate. Applied to most goods and services.
8%Reduced rate. Applied to certain food products, construction services, etc.
5%Reduced rate. Applied to basic food products, books, periodicals.
0%Zero rate. Applied to intra-EU supplies and certain exports.
zwExempt (zwolniony). Applied when the calculated rate is negative (shouldn't happen in practice).

If the tax amount is zero, the item gets a 0 rate (not zw — zero-rate and exempt are legally different in Polish tax law). If a rate cannot be determined, the default is 23%. When KSeF is enabled and any position uses zw, the plugin auto-sets exempt_tax_kind to prevent KSeF rejection.

Rate Normalization

The plugin maps calculated rates to the nearest standard Polish rate. For example, if the effective rate calculates to 22.8% or 23.2%, it will be normalized to 23%. This handles rounding differences between FluentCart's tax calculation and Polish standard rates.

Price Conversion

FluentCart stores prices in cents (integer values). Fakturownia expects prices in decimal format. The plugin converts automatically:

FluentCart: 9900 (cents) → Fakturownia: 99.00 (decimal)
FluentCart: 1550 (cents) → Fakturownia: 15.50 (decimal)

The conversion uses round($cents / 100, 2) to ensure precision to two decimal places.

Payment Type Mapping

The plugin maps FluentCart payment gateway slugs to Fakturownia payment type values. If the order's payment method matches a known gateway, the mapped value is used. Otherwise, the default from settings is applied.

Default Mapping

FluentCart GatewayFakturownia Payment Type
przelewy24transfer
stripecard
paypalpaypal
bacstransfer
codcash

Custom Mapping

You can customize the mapping using the fchub_fakturownia/payment_type_map filter:

functions.php or custom plugin
add_filter('fchub_fakturownia/payment_type_map', function ($map) {
    // Add a custom gateway mapping
    $map['my_custom_gateway'] = 'transfer';

    // Override an existing mapping
    $map['stripe'] = 'transfer';

    return $map;
});

Correction Invoices (Refunds)

When an order is fully refunded, the plugin automatically creates a correction invoice in Fakturownia.

Correction Flow

Refund Triggered

FluentCart fires the order_fully_refunded event or the integration's revoke hook. The RefundHandler takes over.

Original Invoice Check

The handler checks for _fakturownia_invoice_id on the order. If no original invoice exists, a warning log is added and the process stops -- you can't correct an invoice that doesn't exist.

Duplicate Prevention

The handler checks for _fakturownia_correction_id. If a correction already exists, the process stops to prevent duplicate corrections.

Correction Created

A correction invoice is created via the /invoices.json endpoint with kind: correction and a reference to the original invoice ID. The reason is set to "Refund -- Order #[order_number]".

KSeF Submission (If Enabled)

If KSeF auto-send is active, the correction invoice is also submitted to KSeF using Fakturownia's send_to_ksef API endpoint. The correction KSeF status is stored separately.

Metadata and Log

The correction invoice ID and number are stored as order metadata. A log entry is added: "Fakturownia: Correction invoice created -- Correction [number] created for invoice [original_number]".

Admin Order View

When an order has a Fakturownia invoice, the plugin displays invoice information in the FluentCart admin order receipt view. This section appears below the standard order details and includes:

Error Handling

Invoice creation can fail for several reasons. The plugin handles errors gracefully:

  • API connection failure -- logged as an error on the order. The invoice can be retried by re-triggering the payment event.
  • Validation errors -- Fakturownia returns field-level validation errors. These are formatted into a readable string and logged on the order (e.g., "buyer_tax_no: is invalid").
  • Duplicate invoice -- if an invoice already exists for the order, the creation is silently skipped with an error return.

All errors are recorded in the FluentCart order logs with the source "Fakturownia" for easy filtering.

On this page