Skip to main content
Version: 2.0.0

Developer API

The Szamlazz plugin exposes services, an invoice provider, an order-edit UI component, MCP tools, and console commands for integration with yStore's invoicing system and external/automation clients.

Services

Access services via the plugin instance:

use Yui\Szamlazz\Plugin;

$szamlazz = Plugin::getInstance();
$api = $szamlazz->getApi();
$invoices = $szamlazz->getInvoices();
$dashboard = $szamlazz->getDashboard();
$license = $szamlazz->getLicense();

ApiService

Builds the authenticated connection to the Szamlazz.hu Agent API.

  • setOrder(?Order $order) -- associates an order with the service before building a connection; the order is passed through to EVENT_BEFORE_API_CONNECTION listeners.
  • getConnection(): ?SzamlaAgent -- creates a SzamlaAgentAPI connection using the settings' API Key, applies Log::LOG_LEVEL_ERROR when Sandbox Mode is on, and sets the Log E-mail if configured. Returns null if the underlying SzamlaAgentException is thrown (for example on a malformed API key).

EVENT_BEFORE_API_CONNECTION

Triggered on ApiService immediately before the Szamlazz.hu connection is created, letting a listener inspect or override the settings array that will be used to build it (for example to swap the API key for a different site/brand at connection time).

use yii\base\Event;
use Yui\Szamlazz\services\ApiService;
use Yui\Szamlazz\events\BeforeApiConnectionEvent;

Event::on(
ApiService::class,
ApiService::EVENT_BEFORE_API_CONNECTION,
function (BeforeApiConnectionEvent $event) {
// $event->order -- the yui\craft\records\Order currently being processed, if any
// $event->settings -- the plugin settings array about to be used; mutate and it takes effect
$event->settings['apiKey'] = resolveApiKeyForOrder($event->order);
}
);

InvoiceService

Creates, deletes, regenerates, downloads, and lists Szamlazz.hu invoices from order data.

  • dispatchInvoiceGeneration(int $orderId, ?string $orderStatus, bool $manualCreate = false, bool $force = false, string $commentAction = 'generated') -- entry point used by the manual "Create" action and the MCP szamlazz_create_invoice tool. When Use queue for invoice generation is on and $manualCreate is false, pushes a GenerateInvoiceJob onto Craft's queue instead of running inline; falls back to a synchronous call if queueing fails.
  • isQueueEnabled(): bool -- whether queue-based generation is enabled and a queue component is available.
  • createInvoice(int $orderId, ?string $orderStatus, bool $manualCreate = false, bool $force = false, string $commentAction = 'generated'): bool|array -- loads the order, builds its invoice data via yStore's shared buildInvoiceData(), and delegates to createInvoiceFromData(). Returns false if the order can't be loaded, or if $manualCreate is false and $orderStatus isn't in Generate invoice when.
  • createInvoiceFromData(array $invoiceData, bool $manualCreate = false, bool $force = false, string $commentAction = 'generated'): bool|array -- the invoice-provider entry point (called by SzamlazzInvoiceProvider::createInvoice()); builds and sends the invoice to Szamlazz.hu from a normalized $invoiceData array (order/customer/items/totals under meta/customer/items/totals). Returns true on success, false on an unexpected failure, or an array of human-readable error messages (e.g. "the invoice already exists", or a zero-total order with Zero Total Orders disabled). Downloads and stores the resulting PDF as a Craft asset and adds an order comment recording the action.
  • getInvoicePreviewData(int $orderId): array -- builds the same invoice data (settings, details, client, items, totals) that would be sent to Szamlazz.hu, without calling the API; backs the order-edit Preview action and the szamlazz_preview_invoice MCP tool.
  • getInvoicesByOrderId(int $orderId): array -- returns every invoice record for an order (with file path, URL, status, and download/regenerate URLs when applicable); used by the order-edit menu, the SzamlazzInvoiceProvider::getAttachments() callback, and the szamlazz_get_invoices MCP tool.
  • deleteInvoice(int $orderId, bool $isRegeneration = false): bool|array -- generates a storno (reverse) invoice against Szamlazz.hu for each active invoice record, then archives (soft delete) or hard-deletes the local record and asset depending on Soft delete invoices.
  • regenerateInvoice(int $orderId): bool|array -- deletes the existing invoice (storno) and immediately creates a new one, forcing creation even if one already existed.
  • sendInvoice(int $orderId, ?string $orderStatus): bool -- emails the invoice PDF to the customer when Send Invoice to customer in email is on and the order status matches Send invoice when. Called automatically on the order-status-change event when queue-based generation is off, and by the szamlazz_send_invoice MCP tool.
  • downloadInvoice(int $orderId): bool|Asset / downloadInvoices(int $orderId): array -- returns the latest (or all) stored PDF asset(s) for an order; used by both the CP download action and the console download command.
  • resyncInvoiceAssets(): array{processed:int,updated:int,missingOrders:int,missingAssets:int,createdAssets:int} -- for invoice records missing an asset_id, attempts to find or import the matching PDF from the store's asset filesystem by filename (pdf-{incrementId}.pdf); backs the Resync invoices settings action and ResyncInvoiceAssetsJob.

Every invoice/client/item detail sent to Szamlazz.hu is assembled from the normalized invoice data (billing/ shipping address, company/tax IDs, line items and configurable sub-items, discounts, shipping, payment) and the plugin's settings (tax payer status, tax class, invoice language, and whether shipping/payment are added as line items).

DashboardService

Extends the shared yui\craftcore\services\CoreDashboardService to build the Szamlazz.hu → Dashboard modules: Total invoices, In this period, and Archived KPI tiles, a Status breakdown list, and a Recent invoices table (date, order, type, status).

LicenseService

Extends the shared yui\craftcore\services\CoreLicenseService to back the Szamlazz.hu → License CP page (shared yui/craft-core license activation/status UI), persisting entitlement/validation state on the plugin's own settings model.

Invoice provider

Yui\Szamlazz\providers\SzamlazzInvoiceProvider registers itself with handle szamlazz (label "Számlázz.hu") on yui\craft\services\sales\InvoiceService::EVENT_REGISTER_INVOICE_PROVIDERS, so it appears alongside any other invoice provider yStore has registered.

public function isEnabled(): bool
{
return Plugin::getInstance()?->getSettings()?->enabled ?? false;
}

The provider is enabled purely based on the Enabled settings toggle. createInvoice(array $invoiceData) delegates to InvoiceService::createInvoiceFromData(), and getAttachments(array $invoiceData) returns the invoices already recorded for the order (via $invoiceData['meta']['order_id']) using InvoiceService::getInvoicesByOrderId(). Automatic invoice creation on order-status change is driven by yStore's shared invoicing system calling this provider, not by a Szamlazz-specific status listener; the Szamlazz-specific EVENT_AFTER_ORDER_STATUS_CHANGE handler only handles Delete invoice when the order status is and, when queueing is off, sending the invoice email.

Order-edit component

When Show Szamlazz Button is on, the plugin hooks into the order-edit-extra-actions template hook and renders a menu (szamlazz/components/order/edit/manage-invoice.twig) on the order edit page. The available actions are computed per order from the existing invoice record and the order's status:

  • Create Invoice -- shown when the order has no active invoice yet.
  • Preview, Download Invoice, Regenerate Invoice, Delete Invoice -- shown when an active invoice exists.
  • The whole menu is hidden when the order's status is in Hide Szamlazz controls when an order has one of these statuses.

These map to InvoiceController::actionCreate(), actionPreview(), actionDownload(), actionRegenerate(), and actionDelete(). InvoiceController and InvoiceService::getInvoicesByOrderId() independently enforce the same Hide Szamlazz controls restriction against the order's current status, so manual actions stay blocked even if a request reaches the controller directly. This restriction is separate from automatic invoice creation/deletion, which run purely off Generate invoice when and Delete invoice when the order status is regardless of this setting.

Notifications

Yui\Szamlazz\plugin\Events registers three notification types on yui\craftcore\services\NotificationService::EVENT_REGISTER_NOTIFICATION_TYPES, so they appear with a human-readable label and description in the shared CP notification preferences UI:

TypeSeverityLabel
invoice.createdinfoInvoice created
invoice.failedwarningInvoice creation failed
invoice.errorcriticalInvoice system unavailable

InvoiceService emits these (source szamlazz) at the same points it records an order comment or logs an error inside createInvoiceFromData():

  • invoice.created -- after an invoice is successfully created and its PDF stored.
  • invoice.failed -- when creation is skipped because the invoice already exists, or because the order's grand total is zero and Zero Total Orders is disabled.
  • invoice.error -- when createInvoiceFromData() catches an exception (for example an unreachable Szamlazz.hu API), with the exception message as the notification body.

Each notification is created via yui\craftcore\Plugin::getInstance()->getNotifications()->createNotification(); if yui/craft-core's plugin instance isn't available, the call is silently skipped so a notification failure never blocks invoice creation itself.

MCP Tools

When the yui/craft-mcp plugin is installed, Szamlazz registers six MCP tools on yui\mcp\Plugin::EVENT_REGISTER_TOOLS, all extending the shared AbstractSzamlazzTool base, which accepts an order identifier (order_id and/or increment_id).

Tool namePurposePermission
szamlazz_get_invoicesList invoices (including storno/archived) for an order.read
szamlazz_preview_invoicePreview invoice customer/items/totals without creating or sending anything.read
szamlazz_create_invoiceManually create an invoice, bypassing the status trigger and forcing creation.WRITE
szamlazz_send_invoiceEmail the invoice PDF to the customer, subject to Send Invoice settings.WRITE
szamlazz_regenerate_invoiceDelete the existing invoice and generate a fresh one.WRITE
szamlazz_delete_invoiceStorno (reverse) and archive the invoice for an order.DESTRUCTIVE

Each tool returns a success/found flag plus order_id and either the requested data or an errors/ error field describing why the operation failed (for example a disabled sendInvoiceViaEmail setting).

Console commands

Yui\Szamlazz\console\controllers\InvoicesController exposes the same regenerate/download operations as Craft console commands, for scripting and ops tooling:

php craft szamlazz/invoices/regenerate <orderId>
php craft szamlazz/invoices/download <orderId> [--destination=<path>] [--all]
  • regenerate <orderId> -- deletes and re-creates the invoice for the order; exits non-zero and prints each error message to stderr on failure.
  • download <orderId> [-d|--destination=<path>] [-a|--all] -- prints the on-disk path of the order's latest invoice PDF (or every invoice PDF for the order, with --all), and additionally copies each file into --destination if provided (auto-renaming to avoid overwriting an existing file with the same name).

Both commands resolve the invoice service through Plugin::getInstance(), so they run against whichever site/environment the CLI request is scoped to. GenerateInvoiceJob swaps in a QueueRequest shim when it runs under a console request that doesn't expose getUserIP(), so queued invoice generation behaves correctly whether it's processed by a web-triggered listener queue runner or php craft queue/run.

CP Routes

RoutePurpose
szamlazz, szamlazz/dashboardDashboard
szamlazz/invoices, /invoices/table-data, /invoices/deleteInvoice list, AJAX table data, bulk delete
szamlazz/invoice/create/<orderId>Manual invoice creation from the order edit page
szamlazz/invoice/preview/<orderId>Invoice preview (no API call)
szamlazz/invoice/update/<orderId>Manual invoice update
szamlazz/invoice/download/<orderId>Invoice PDF download
szamlazz/invoice/delete/<orderId>Invoice deletion (storno)
szamlazz/invoice/regenerate/<orderId>Delete + re-create the invoice
szamlazz/settings, /settings/save-settings, /settings/resync-invoicesSettings page, save, PDF resync
szamlazz/license, /license/redeem, /revoke, /activate, /delete, /copy-tokenLicense activation/status

Data model

Yui\Szamlazz\records\InvoiceRecord (table {{%yui_szamlazz_invoices}}, see Yui\Szamlazz\db\Table) stores one row per invoice/storno document: order_id, invoice_id, invoice_type (invoice or storno), reference_number, status (issued, notification_failed, storno, archived, …), last_status_change, invoice_data (JSON metadata -- invoice number, customer portal URL, net/gross amounts, raw API response headers), asset_id (linked PDF asset), archived/archived_at (soft-delete state), and the standard dateCreated/dateUpdated columns.

Settings model

Yui\Szamlazz\models\Settings (extends yui\craftcore\models\BasePluginSettingsModel) holds every field documented in Settings, plus license/dashboard-layout persistence fields used internally by LicenseService and DashboardService. Validation: API Key is required only when the plugin is enabled (Settings::rules()). siteOverridableAttributes() returns sandboxMode, apiKey, logEmail, company_id, invoiceLanguage, and szamlazzMarketCountry, so a multi-site store can invoice against different Szamlazz.hu accounts/markets per site.

Compatibility

  • Craft CMS 5+ (craftcms/cms ^5.2.0)
  • yui/craft-core ^1, declared in require -- Settings extends yui\craftcore\models\BasePluginSettingsModel at runtime. (yui/craft-plugin ^2 also appears in composer.json, but only in require-dev -- it is not a runtime dependency.)
  • benjaminhu/szamlazz-php-api 2.10.* (unofficial Szamlazz.hu Agent API client)
  • Optional: yui/craft-mcp, for the MCP tools described above