Skip to main content
Version: 2.0.0

Invoices

Invoice settings define the generated PDF document, the seller details shown on it, and the payment metadata included in the invoice template.

yStore uses a provider-based invoice architecture. The built-in invoice settings control PDF appearance and branding. External accounting integrations (Billingo, SuperFaktura, iDoklad, etc.) register additional providers that create and store invoices in their own systems.

General
  • Enable or disable invoice generation.
  • Debug mode can be used while troubleshooting templates.
  • Paper size, title, date format, time format, due days, and filename format are controlled here.
Branding
  • Set the invoice logo and its dimensions.
  • Choose the invoice color scheme.
  • Maintain the seller name, company name, address, country, city, and ZIP details here.
Templates and payment items
  • The invoice reference format can include order and invoice variables.
  • Payment instructions can include bank and account details.
  • Variable, constant, and specific symbols are supported by the template engine.
  • Keep the PDF filename format aligned with your archival workflow.

Invoice generation flow

When an order reaches the configured completion status, InvoiceService::createInvoicesForOrder() is called:

  1. buildInvoiceData() assembles a normalized data snapshot from the order record (line items, taxes, totals, customer, discounts).
  2. Each registered and enabled provider receives the data snapshot via createInvoice().
  3. For order confirmation emails, collectInvoiceAttachments() calls each provider's getAttachments() method to attach generated PDFs.

If a provider is disabled, it is skipped silently. Errors from individual providers are logged and do not block other providers.

Normalized invoice data structure

All providers receive the same data array built by InvoiceService::buildInvoiceData():

meta
order_number, order_id, date, currency, site_id, language,
payment_method, shipping_method, order_status, is_paid, due_date_days

customer
first_name, last_name, email, company, ico, dic, vat_id,
billing (address array), shipping (address array)

items[]
name, sku, qty,
unit_price_excl_tax, unit_price_incl_tax,
row_total_excl_tax, row_total_incl_tax,
tax_percent, tax_amount, tax_class_id,
is_configurable, sub_items[]

discounts[]
label, amount, code

totals
subtotal, subtotal_incl_tax,
shipping_amount, shipping_amount_excl_tax,
discount_amount, payment_amount, grand_total, tax_amount

tax_payer (bool — from store setting)
configurable_price_handling (string — 'include' | 'exclude')

is_paid is true when order_status === 'complete'. Override this in your provider if your store uses a different status for paid orders.

due_date_days comes from the salesOrderInvoicesDueDays store setting (default: 7).


Developer reference

Adding a custom invoice provider

Implement yui\craft\base\BaseInvoiceProvider and register it via RegisterInvoiceProvidersEvent.

Step 1 — Implement the provider

namespace my\plugin\invoices;

use yui\craft\base\BaseInvoiceProvider;

class MyInvoiceProvider extends BaseInvoiceProvider
{
public function getHandle(): string
{
return 'my-provider';
}

public function getLabel(): string
{
return 'My Invoice Provider';
}

public function isEnabled(): bool
{
return (bool) \yui\craft\helpers\CraftHelper::getSettingValueByKey('myProviderEnabled');
}

public function createInvoice(array $invoiceData): void
{
$meta = $this->getOrderMeta($invoiceData);
$customer = $this->getCustomer($invoiceData);
$items = $this->getOrderItems($invoiceData);
$totals = $this->getOrderTotals($invoiceData);

// Send to your accounting API
MyApi::createInvoice($meta['order_number'], $customer, $items, $totals);
}

public function getAttachments(array $invoiceData): array
{
$meta = $this->getOrderMeta($invoiceData);
$path = '/path/to/stored/' . $meta['order_number'] . '.pdf';

if (!file_exists($path)) {
return [];
}

return [
['path' => $path, 'name' => $meta['order_number'] . '.pdf'],
];
}
}

Step 2 — Register the provider

use yui\craft\services\sales\InvoiceService;
use yui\craft\events\RegisterInvoiceProvidersEvent;
use yui\craft\support\EventManager;

EventManager::listen(
InvoiceService::class,
InvoiceService::EVENT_REGISTER_INVOICE_PROVIDERS,
function (RegisterInvoiceProvidersEvent $event) {
$event->providers[] = MyInvoiceProvider::class;
}
);

BaseInvoiceProvider helper methods

MethodReturnsDescription
getOrderMeta($invoiceData)arrayOrder number, date, currency, status, is_paid, due_date_days
getCustomer($invoiceData)arrayCustomer name, email, company, ICO, DIC, VAT ID, billing/shipping addresses
getOrderItems($invoiceData)arrayLine items with excl/incl prices, tax, and configurable sub-items
getOrderTotals($invoiceData)arraySubtotal, shipping, discount, payment, grand total, tax
getOrderDiscounts($invoiceData)arrayApplied coupon/gift-card discounts
getShippingItem($invoiceData)array|nullShipping as a line-item shape, or null if shipping is 0
getPaymentItem($invoiceData)array|nullPayment surcharge as a line-item shape, or null if 0

Full invoice data for attachments

By default, getAttachments() receives a lightweight data snapshot (only meta fields). If your provider needs the full invoice data to look up stored PDFs, override:

public function requiresFullInvoiceDataForAttachments(): bool
{
return true;
}

Configurable product price handling

The configurable_price_handling key reflects the store setting configurableProductPriceHandling. Its value is 'include' (child prices included in parent row total) or 'exclude' (child items shown separately). Use it to decide how to present bundle line items on your invoice.

Events

EventClassDescription
InvoiceService::EVENT_REGISTER_INVOICE_PROVIDERSInvoiceServiceRegister additional invoice providers

Service methods

yui\craft\services\sales\InvoiceService (access via Plugin::getInstance()->getInvoice())

MethodDescription
getRegisteredProviders()Return all registered providers, keyed by handle
getRegisteredProviderByHandle($handle)Return a single provider by its handle
buildInvoiceData($order)Build the normalized data array from an OrderDataRecord
createInvoicesForOrder($order)Call createInvoice() on all enabled providers
collectInvoiceAttachments($order)Call getAttachments() on all enabled providers and merge results