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:
buildInvoiceData()assembles a normalized data snapshot from the order record (line items, taxes, totals, customer, discounts).- Each registered and enabled provider receives the data snapshot via
createInvoice(). - For order confirmation emails,
collectInvoiceAttachments()calls each provider'sgetAttachments()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
| Method | Returns | Description |
|---|---|---|
getOrderMeta($invoiceData) | array | Order number, date, currency, status, is_paid, due_date_days |
getCustomer($invoiceData) | array | Customer name, email, company, ICO, DIC, VAT ID, billing/shipping addresses |
getOrderItems($invoiceData) | array | Line items with excl/incl prices, tax, and configurable sub-items |
getOrderTotals($invoiceData) | array | Subtotal, shipping, discount, payment, grand total, tax |
getOrderDiscounts($invoiceData) | array | Applied coupon/gift-card discounts |
getShippingItem($invoiceData) | array|null | Shipping as a line-item shape, or null if shipping is 0 |
getPaymentItem($invoiceData) | array|null | Payment 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
| Event | Class | Description |
|---|---|---|
InvoiceService::EVENT_REGISTER_INVOICE_PROVIDERS | InvoiceService | Register additional invoice providers |
Service methods
yui\craft\services\sales\InvoiceService (access via Plugin::getInstance()->getInvoice())
| Method | Description |
|---|---|
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 |