CoolCMS API

OrderCheckoutManager
in package

FinalYes

Orchestrates the front checkout; the only place where an order is created from a customer cart.

The admin path (OrderPresenter::internalActionBuild()) is separate: it is trusted and takes prices and VAT from the form, while checkout is untrusted. The browser sends only setId and quantity, tariffId, paymentMethodId, voucher codes and address fields. Every price, rate and discount is computed by the server from the catalog through the resolver path (OrderSnapshotBuilder::buildItems(), buildShipper(), buildPaymentMethod()), so there is no field through which a price could be forged.

Enforced rules:

  • Strict reservation (allowPartial = false): the customer must not pay for uncovered goods. The pre-flight gate checkStrictStockGate() decides before any write; reserve() in completedSave remains the final judge.
  • A missing seller is a hard failure: without 4/invoicer.sellerId (fallback 7/invoice.default.sellerId) the order is not created and the customer gets a plain message without technical detail; the incident goes to the Tracy channel eshop.general.
  • The Invoicer customer record (OrderCustomerManager) is resolved as the very first step, before any getReference(). The resolver calls Api findAll(), which empties the identity map via GetAllTrait::clearDoctrine() and would detach a half-built graph.
  • The state transition after creation goes only through OrderTransitionManager::apply() and always after the save transaction commits; apply() rejects a nested transaction (nestedTransaction).
Tags
phpstan-import-type

SellerSnapshot from \App\UI\Api\Invoicer\Models\Repositories\Db\SellerRepository

Table of Contents

Constants

PURCHASED_STATUS_KEYS  : array<string|int, mixed> = ['PAID', 'PAID-APPROVED', 'SENT', 'DONE']
States that mean the customer really bought the goods: paid, sent or done. Used by {@see self::buyersOfSet()} (verified purchase, right to rate). The same four states the front `OrderDonePresenter` treats as a paid order; `CREATED`, `WAITING-ON-PAYMENT` and `APPROVED` deliberately do not count (not paid yet).
STATUS_APPROVED  : string = 'APPROVED'
Target for orders paid on receipt (cash on delivery, cash) when `4/order.approval.auto` is on.
STATUS_CANCELLED  : string = 'CANCELLED'
Cancellation target for an order whose stock could not be reserved after commit.
STATUS_CREATED  : string = 'CREATED'
Initial state of every front order (`create_order = 1`).
STATUS_WAITING_ON_PAYMENT  : string = 'WAITING-ON-PAYMENT'
Target for orders awaiting payment (gateway or bank transfer); issues the proforma and sends an e-mail.

Properties

$giftManager  : GiftManager|null
See the constructor; a plain property, unit tests build the manager without the constructor.
$adminNoticeManager  : OrderAdminNoticeManager
$calculator  : OrderCalculator
$carrierRegistry  : CarrierRegistry
$currencyManager  : CurrencyManager
$customerManager  : OrderCustomerManager
$em  : EntityManagerInterface
$freeShippingFlags  : OrderFreeShippingFlags
$invoiceGenerator  : OrderInvoiceGenerator
$invoiceManager  : InvoiceManager
$languageManager  : LanguageManager
$localizationManager  : LocalizationManager
$orderManager  : OrderManager
$orderPaymentManager  : OrderPaymentManager
$orderTaxManager  : OrderTaxManager
$paymentGateManager  : PaymentGateManager
$paymentManager  : PaymentManager
$paymentMethodManager  : PaymentMethodManager
$paymentRegionManager  : PaymentRegionManager
$pickupPointApplier  : OrderPickupPointApplier
$sellerManager  : SellerManager
$settingContext  : SettingContext
$shipperTariffManager  : ShipperTariffManager
$snapshotBuilder  : OrderSnapshotBuilder
$stockItemManager  : StockItemManager
$transitionManager  : OrderTransitionManager
$unpricedItems  : array<int, array{productSetId: int, name: string}>
Cart sets (id + name) that have no price in the order currency; the preview omitted them (see `$strict` in {@see OrderSnapshotBuilder::buildItems()}). Sent in `serializeOrder()` so the front marks the row as unavailable in this currency and blocks the customer from continuing.
$userGroupManager  : UserGroupManager
$userTypeManager  : UserTypeManager
$voucherManager  : VoucherManager

Methods

__construct()  : mixed
buyersOfSet()  : array{success: bool, userIds: list}
Returns which of the given users really bought the set (verified purchase).
listForUser()  : array{success: bool, orders: list>, total: int}
Returns the "My orders" list. `$userId` is not a client filter: the caller (front `MyOrderListPresenter`) takes it only from `$this->getUser()->getId()` after the login check (the page requires `logged=1`, `BasePresenter` redirects an anonymous user earlier). This method never widens the `userId` WHERE or takes it from elsewhere; it is a server-side ACL, not a hidden element in the template.
place()  : array{success: bool, errorCode?: string, message?: string, id?: int, orderNumber?: string, statusKey?: string, paymentId?: ?int, requiresGateway?: bool, order?: array, warnings?: list}
Places the order. The order of steps is deliberate and must not change: customer record, snapshot, strict gate, `save()` (inside the transaction; `completedSave` reserves stock after commit), payment, state transition (outside the transaction).
preview()  : array{success: bool, errorCode?: string, message?: string, order?: array, options?: array, totalWeight?: string}
Builds the cart/checkout preview in memory, recalculates totals and returns the shipping and payment options for the current cart.
repeatItems()  : array{success: bool, errorCode?: string, message?: string, items?: list, skippedCount?: int}
Returns the data for repeating an order: `setId` and `quantity` of the original order's items that can be added to the cart again. Prices are never copied; checkout recomputes them from the current catalog ({@see OrderSnapshotBuilder}). Items whose `productSet` disappeared meanwhile (deleted set, `SET NULL` FK) are skipped and counted in `skippedCount` (the template shows a warning).
summary()  : array{success: bool, errorCode?: string, message?: string, order?: array}
Returns the data for the return page (step 4). The state is read only from the order and its paired payment, never from gateway GET parameters (anyone can type `?result=success`).
applyAutomaticGifts()  : Result
Gifts of an order from the website (decision of the site owner): those linked to the ordered product sets and those for the order total, chosen by {@see GiftManager::findForOrder()} against the final total. They do not change the price; the administrator sees them in the order, the customer in the summary and documents.
applyBranchToDeliveryAddress()  : void
Turns the selected branch into the order's delivery address; the schema has no other field for it (`expedition_shipper_branch_id` is filled by the admin at dispatch), and the delivery address is what the document and the carrier need anyway. The chosen branch is verified against the tariff: a foreign id is ignored, so goods are never delivered to another carrier's branch.
applyPickupPoint()  : array{success: false, errorCode: string, message: string}|null
Thin bridge to {@see OrderPickupPointApplier::apply()} (shared with admin `order/build`).
applySeller()  : void
buildOptions()  : array{shipping: list>, payment: list>}
Builds the offer for checkout step 2. Prices go through the same resolvers that later build the snapshot, so what the customer sees is what gets stored.
buildOrder()  : array{success: bool, errorCode?: string, message?: string, totalWeight?: string, unpricedOnly?: bool}
checkStrictStockGate()  : array{success: false, errorCode: string, message: string, shortItems?: list}|null
Strict pre-flight stock check, like the admin `checkStrictStockGate()` but a separate implementation: checkout has no payload override and never edits an existing order, so own reservations are not added back.
customerFacingFailure()  : array{success: false, errorCode: string, message: string}
Returns a failure whose technical description (tariff id, weight, set id, currency code) does not belong to the customer: a plain sentence goes out and the original message goes to the Tracy channel `eshop.general`, so the operator knows what is misconfigured. Voucher messages are not rewritten, "Voucher X is exhausted" is exactly what the customer needs to hear.
deliveryCountryCode()  : string|null
Returns the country the order ships to, by the same rule the VAT engine reads the address (`OrderTaxManager`): the delivery address when used, otherwise the billing one.
errorCodeOf()  : string
failure()  : array{success: false, errorCode: string, message: string}
flag()  : bool
Converts a DBAL scalar (mixed) to bool; `tinyint(1)` columns arrive as string or int.
generateOrderDocumentForCreatedOrder()  : void
Issues the ORDER document for an order that stays in `CREATED` (see the comment in {@see place()}). Reads the configuration directly from state `CREATED` (`create_invoice`, `invoiceTypeId`), the same DB-driven gate as the invoice step of a state transition, so without the matching migration this is a no-op. Also sends the `CREATED` confirmation e-mail (`send_email`) with the recap and the document attached; no transition runs here (same-state no-op), so without this call a cash-on-delivery order without automatic approval would get no confirmation.
int()  : int|null
isPaymentMethodOffered()  : bool
Whether the checkout offers the method: `available = 1` and its gateway (if any) is offered to the customer.
loadBranches()  : array<int, array<int, array{id: int, name: string, address: string}>>
Returns active branches (pickup points) of tariffs from `shipper_tariff_branches`.
loadTariffPickupContext()  : array{externalPickup: bool, shipperId: ?int, scriptName: ?string}|null
Reads the tariff pickup context via {@see OrderPickupPointApplier::loadTariffContext()}; the admin build path needs the same context, so it lives in the service.
money()  : numeric-string
Returns a numeric value for bcmath (non-numeric or empty = zero), like `OrderCalculator::norm()`.
nullIfEmpty()  : string|null
payloadLines()  : array<int, array{setId: int, quantity: int}>
Reads cart lines from the payload, which carries only `setId` and `quantity`; never a price, rate or discount (see the class docblock). Invalid rows are skipped silently, an empty result is handled by the caller.
payloadStringList()  : array<int, string>
paymentGateIdForMethod()  : int|null
Returns the id of the active payment gateway assigned to the method, or `null`. The FK is read from the module's own `cms_mod_eshop_payment_methods`; the gateway activation is confirmed by its owner ({@see PaymentGateManager::isActivated()}).
ref()  : T
Returns a managed reference without a DB query (like {@see OrderSnapshotBuilder::ref()}).
resolveDefaultPaymentRegionId()  : int
Priority of the VAT region for a new snapshot: `4/invoicer.paymentRegionId`, then `7/invoice.default.paymentRegionId` (without prefix), then the locale default ({@see PaymentRegionManager::getDefaultPaymentRegionId()}).
resolveSellerSnapshot()  : SellerSnapshot|null
Resolves `4/invoicer.sellerId`, then `7/invoice.default.sellerId`, plus the snapshot from the data owner ({@see SellerManager::getSellerSnapshot()}).
resolveUserTypeId()  : int|null
Resolves the customer type from the two checkout checkboxes: private person, company non-payer or company VAT payer. The code list `cms_system_user_types` carries exactly these two axes (`requires_company_data`, `requires_vat_id`), so the type is derived without a select the customer would not understand. Without a matching row it falls back to the setting `4/invoicer.userTypeId`, then `7/invoice.default.userTypeId`.
scalarStr()  : string
serializeOrder()  : array<string, mixed>
settingFlag()  : bool
Reads a setting through {@see SettingContext} (a framework service a manager may hold). The context is filled by `SettingInitTrait` in the startup of every base presenter (Api, Front, Admin, Cron, Script); a CLI harness must fill it itself.
statusIdByKey()  : int|null
str()  : string|null
targetStatusKey()  : string
Returns the target state after the order is created: - a gateway or a method sending a proforma (bank transfer) -> `WAITING-ON-PAYMENT` (issues the proforma and sends an e-mail, `allow_cancelling = 0`), - otherwise (cash on delivery, cash) `APPROVED` when `4/order.approval.auto` is on, - otherwise the order stays in `CREATED` (confirmed manually by staff).
tariffCountryCodes()  : string|null
Stored delivery coverage of the tariff's region (null = no restriction).
widgetConfigFor()  : array{scriptUrl: string, apiKey: ?string, mechanism: string, options: array, elementTag: ?string, eventName: ?string}|null
Returns the carrier widget configuration for a single `tariffRows` row from {@see buildOptions()}.
withdrawUncoveredOrder()  : void
Cancels an order whose stock could not be reserved after commit through the regular state machine (stock remnant released, voucher usage returned), silently: the customer sees the checkout error right away, a "cancelled" e-mail would only confuse.

Constants

PURCHASED_STATUS_KEYS

States that mean the customer really bought the goods: paid, sent or done. Used by {@see self::buyersOfSet()} (verified purchase, right to rate). The same four states the front `OrderDonePresenter` treats as a paid order; `CREATED`, `WAITING-ON-PAYMENT` and `APPROVED` deliberately do not count (not paid yet).

public array<string|int, mixed> PURCHASED_STATUS_KEYS = ['PAID', 'PAID-APPROVED', 'SENT', 'DONE']

STATUS_APPROVED

Target for orders paid on receipt (cash on delivery, cash) when `4/order.approval.auto` is on.

public string STATUS_APPROVED = 'APPROVED'

STATUS_CANCELLED

Cancellation target for an order whose stock could not be reserved after commit.

public string STATUS_CANCELLED = 'CANCELLED'

STATUS_CREATED

Initial state of every front order (`create_order = 1`).

public string STATUS_CREATED = 'CREATED'

STATUS_WAITING_ON_PAYMENT

Target for orders awaiting payment (gateway or bank transfer); issues the proforma and sends an e-mail.

public string STATUS_WAITING_ON_PAYMENT = 'WAITING-ON-PAYMENT'

Properties

$giftManager

See the constructor; a plain property, unit tests build the manager without the constructor.

protected GiftManager|null $giftManager = null

$unpricedItems

Cart sets (id + name) that have no price in the order currency; the preview omitted them (see `$strict` in {@see OrderSnapshotBuilder::buildItems()}). Sent in `serializeOrder()` so the front marks the row as unavailable in this currency and blocks the customer from continuing.

private array<int, array{productSetId: int, name: string}> $unpricedItems = []

Methods

__construct()

public __construct(EntityManagerInterface $em, SettingContext $settingContext, OrderManager $orderManager, OrderSnapshotBuilder $snapshotBuilder, OrderCalculator $calculator, OrderTaxManager $orderTaxManager, OrderCustomerManager $customerManager, OrderTransitionManager $transitionManager, OrderPaymentManager $orderPaymentManager, OrderInvoiceGenerator $invoiceGenerator, VoucherManager $voucherManager, ShipperTariffManager $shipperTariffManager, PaymentMethodManager $paymentMethodManager, OrderFreeShippingFlags $freeShippingFlags, CarrierRegistry $carrierRegistry, OrderPickupPointApplier $pickupPointApplier, CurrencyManager $currencyManager, LanguageManager $languageManager, UserTypeManager $userTypeManager, PaymentGateManager $paymentGateManager, PaymentManager $paymentManager, InvoiceManager $invoiceManager, SellerManager $sellerManager, StockItemManager $stockItemManager, UserGroupManager $userGroupManager, PaymentRegionManager $paymentRegionManager, LocalizationManager $localizationManager, OrderAdminNoticeManager $adminNoticeManager[, GiftManager|null $giftManager = null ]) : mixed
Parameters
$em : EntityManagerInterface
$settingContext : SettingContext
$orderManager : OrderManager
$snapshotBuilder : OrderSnapshotBuilder
$calculator : OrderCalculator
$orderTaxManager : OrderTaxManager
$customerManager : OrderCustomerManager
$transitionManager : OrderTransitionManager
$orderPaymentManager : OrderPaymentManager
$invoiceGenerator : OrderInvoiceGenerator
$voucherManager : VoucherManager
$shipperTariffManager : ShipperTariffManager
$paymentMethodManager : PaymentMethodManager
$freeShippingFlags : OrderFreeShippingFlags
$carrierRegistry : CarrierRegistry
$pickupPointApplier : OrderPickupPointApplier
$currencyManager : CurrencyManager
$languageManager : LanguageManager
$userTypeManager : UserTypeManager
$paymentGateManager : PaymentGateManager
$paymentManager : PaymentManager
$invoiceManager : InvoiceManager
$sellerManager : SellerManager
$stockItemManager : StockItemManager
$userGroupManager : UserGroupManager
$paymentRegionManager : PaymentRegionManager
$localizationManager : LocalizationManager
$adminNoticeManager : OrderAdminNoticeManager
$giftManager : GiftManager|null = null

buyersOfSet()

Returns which of the given users really bought the set (verified purchase).

public buyersOfSet(int $setId, array<int, int> $userIds) : array{success: bool, userIds: list}

Used twice with the same policy: the "verified purchase" badge on reviews (input = review authors on the page) and the permission to write a review (input = the logged-in user id). That is why there is no second singular method.

A purchase is an order in a state meaning paid/sent/done (PAID, PAID-APPROVED, SENT, DONE, the same four as the front OrderDonePresenter uses) that is not canceled.

IMPORTANT: order_items.cms_mod_eshop_product_sets_product_set_id is ON DELETE SET NULL, so a purchase of a deleted set cannot be found. That is harmless here (reviews hang on an existing set).

Returns only a subset of the input ids, no order data: a bought/not-bought flag about another user is the same information the displayed review already carries.

Parameters
$setId : int
$userIds : array<int, int>
Return values
array{success: bool, userIds: list}

listForUser()

Returns the "My orders" list. `$userId` is not a client filter: the caller (front `MyOrderListPresenter`) takes it only from `$this->getUser()->getId()` after the login check (the page requires `logged=1`, `BasePresenter` redirects an anonymous user earlier). This method never widens the `userId` WHERE or takes it from elsewhere; it is a server-side ACL, not a hidden element in the template.

public listForUser(int $userId[, int $limit = 20 ][, int $offset = 0 ]) : array{success: bool, orders: list>, total: int}
Parameters
$userId : int
$limit : int = 20
$offset : int = 0
Return values
array{success: bool, orders: list>, total: int}

place()

Places the order. The order of steps is deliberate and must not change: customer record, snapshot, strict gate, `save()` (inside the transaction; `completedSave` reserves stock after commit), payment, state transition (outside the transaction).

public place(array<string, mixed> $payload) : array{success: bool, errorCode?: string, message?: string, id?: int, orderNumber?: string, statusKey?: string, paymentId?: ?int, requiresGateway?: bool, order?: array, warnings?: list}
Parameters
$payload : array<string, mixed>
Return values
array{success: bool, errorCode?: string, message?: string, id?: int, orderNumber?: string, statusKey?: string, paymentId?: ?int, requiresGateway?: bool, order?: array, warnings?: list}

preview()

Builds the cart/checkout preview in memory, recalculates totals and returns the shipping and payment options for the current cart.

public preview(array<string, mixed> $payload) : array{success: bool, errorCode?: string, message?: string, order?: array, options?: array, totalWeight?: string}

Never calls flush() (only getReference() and raw selects), so it has no side effects.

Parameters
$payload : array<string, mixed>

see OrderPresenter::internalActionCheckout()

Return values
array{success: bool, errorCode?: string, message?: string, order?: array, options?: array, totalWeight?: string}

repeatItems()

Returns the data for repeating an order: `setId` and `quantity` of the original order's items that can be added to the cart again. Prices are never copied; checkout recomputes them from the current catalog ({@see OrderSnapshotBuilder}). Items whose `productSet` disappeared meanwhile (deleted set, `SET NULL` FK) are skipped and counted in `skippedCount` (the template shows a warning).

public repeatItems(int $orderId, int $userId) : array{success: bool, errorCode?: string, message?: string, items?: list, skippedCount?: int}

Authorization is stricter than in summary(): userId must match and the order must be bound to an account (boundToUser), so a guest order is rejected too; otherwise a logged-in customer could "repeat" a guest's order by guessing its id.

Parameters
$orderId : int
$userId : int
Return values
array{success: bool, errorCode?: string, message?: string, items?: list, skippedCount?: int}

summary()

Returns the data for the return page (step 4). The state is read only from the order and its paired payment, never from gateway GET parameters (anyone can type `?result=success`).

public summary(int $orderId[, int|null $userId = null ]) : array{success: bool, errorCode?: string, message?: string, order?: array}

Authorization has two layers: here a logged-in customer's foreign order is rejected (order.userId differs from $userId); for orders without an account ownership is guarded by the front session (CartManager::ownsOrder()), since a guest has no persistent identifier.

Parameters
$orderId : int
$userId : int|null = null
Return values
array{success: bool, errorCode?: string, message?: string, order?: array}

applyAutomaticGifts()

Gifts of an order from the website (decision of the site owner): those linked to the ordered product sets and those for the order total, chosen by {@see GiftManager::findForOrder()} against the final total. They do not change the price; the administrator sees them in the order, the customer in the summary and documents.

private applyAutomaticGifts(Order $order, DateTimeInterface $at) : Result
Parameters
$order : Order
$at : DateTimeInterface
Return values
Result

applyBranchToDeliveryAddress()

Turns the selected branch into the order's delivery address; the schema has no other field for it (`expedition_shipper_branch_id` is filled by the admin at dispatch), and the delivery address is what the document and the carrier need anyway. The chosen branch is verified against the tariff: a foreign id is ignored, so goods are never delivered to another carrier's branch.

private applyBranchToDeliveryAddress(Order $order, int $tariffId, int|null $branchId) : void
Parameters
$order : Order
$tariffId : int
$branchId : int|null

applyPickupPoint()

Thin bridge to {@see OrderPickupPointApplier::apply()} (shared with admin `order/build`).

private applyPickupPoint(Order $order, array{externalPickup: bool, shipperId: ?int, scriptName: ?string}|null $tariffPickup, mixed $rawPickupPoint, bool $persist) : array{success: false, errorCode: string, message: string}|null

Manual entry (pickupPointManual) is an admin-only path: front checkout always passes null to the applier, so a customer cannot invent a pickup point outside the carrier widget.

Parameters
$order : Order
$tariffPickup : array{externalPickup: bool, shipperId: ?int, scriptName: ?string}|null
$rawPickupPoint : mixed
$persist : bool
Return values
array{success: false, errorCode: string, message: string}|null —

null = OK

buildOptions()

Builds the offer for checkout step 2. Prices go through the same resolvers that later build the snapshot, so what the customer sees is what gets stored.

private buildOptions(Order $order, string $totalWeight, DateTimeInterface $at) : array{shipping: list>, payment: list>}

A tariff with external_pickup = 1 additionally gets requiresPickup and pickupWidget (widget configuration from CarrierRegistry). pickupWidget === null means the carrier has no driver or API key, and the front then does not offer the pickup point button (a carrier without a driver must not crash).

Parameters
$order : Order
$totalWeight : string
$at : DateTimeInterface
Return values
array{shipping: list>, payment: list>}

buildOrder()

private buildOrder(Order $order, array<string, mixed> $payload, DateTimeInterface $at, bool $persist) : array{success: bool, errorCode?: string, message?: string, totalWeight?: string, unpricedOnly?: bool}
Parameters
$order : Order
$payload : array<string, mixed>
$at : DateTimeInterface
$persist : bool
Return values
array{success: bool, errorCode?: string, message?: string, totalWeight?: string, unpricedOnly?: bool}

checkStrictStockGate()

Strict pre-flight stock check, like the admin `checkStrictStockGate()` but a separate implementation: checkout has no payload override and never edits an existing order, so own reservations are not added back.

private checkStrictStockGate(Order $order[, bool $allowOutOfStock = false ]) : array{success: false, errorCode: string, message: string, shortItems?: list}|null
Parameters
$order : Order
$allowOutOfStock : bool = false

4/order.outOfStock.allowed: the operator also sells what is not in stock. It relaxes only the stock check; an item without a stock item (notInStock > 0 from the snapshot) is always rejected, because neither a reservation nor an issue can be made for it. That is a catalog defect, not a sale to order (which is why the catalog does not offer it for the cart, ProductSet::isOrderable()).

Return values
array{success: false, errorCode: string, message: string, shortItems?: list}|null

customerFacingFailure()

Returns a failure whose technical description (tariff id, weight, set id, currency code) does not belong to the customer: a plain sentence goes out and the original message goes to the Tracy channel `eshop.general`, so the operator knows what is misconfigured. Voucher messages are not rewritten, "Voucher X is exhausted" is exactly what the customer needs to hear.

private customerFacingFailure(string $errorCode, string $customerMessage, string $technicalMessage) : array{success: false, errorCode: string, message: string}
Parameters
$errorCode : string
$customerMessage : string
$technicalMessage : string
Return values
array{success: false, errorCode: string, message: string}

deliveryCountryCode()

Returns the country the order ships to, by the same rule the VAT engine reads the address (`OrderTaxManager`): the delivery address when used, otherwise the billing one.

private deliveryCountryCode(Order $order) : string|null
Parameters
$order : Order
Return values
string|null

errorCodeOf()

private errorCodeOf(Result $result, string $fallback) : string
Parameters
$result : Result
$fallback : string
Return values
string

failure()

private failure(string $errorCode, string $message) : array{success: false, errorCode: string, message: string}
Parameters
$errorCode : string
$message : string
Return values
array{success: false, errorCode: string, message: string}

flag()

Converts a DBAL scalar (mixed) to bool; `tinyint(1)` columns arrive as string or int.

private flag(mixed $value) : bool
Parameters
$value : mixed
Return values
bool

generateOrderDocumentForCreatedOrder()

Issues the ORDER document for an order that stays in `CREATED` (see the comment in {@see place()}). Reads the configuration directly from state `CREATED` (`create_invoice`, `invoiceTypeId`), the same DB-driven gate as the invoice step of a state transition, so without the matching migration this is a no-op. Also sends the `CREATED` confirmation e-mail (`send_email`) with the recap and the document attached; no transition runs here (same-state no-op), so without this call a cash-on-delivery order without automatic approval would get no confirmation.

private generateOrderDocumentForCreatedOrder(Order $order, array<int, string> &$warnings) : void

Fail-soft: a missing or failed document never blocks order creation, it only adds a warning and a log entry.

Parameters
$order : Order
$warnings : array<int, string>

int()

private int(array<string|int, mixed> $payload, string $key) : int|null
Parameters
$payload : array<string|int, mixed>
$key : string
Return values
int|null

isPaymentMethodOffered()

Whether the checkout offers the method: `available = 1` and its gateway (if any) is offered to the customer.

private isPaymentMethodOffered(Order $order, int $paymentMethodId) : bool
Parameters
$order : Order
$paymentMethodId : int
Return values
bool

loadBranches()

Returns active branches (pickup points) of tariffs from `shipper_tariff_branches`.

private loadBranches(array<int, int> $tariffIds) : array<int, array<int, array{id: int, name: string, address: string}>>
Parameters
$tariffIds : array<int, int>
Return values
array<int, array<int, array{id: int, name: string, address: string}>>

loadTariffPickupContext()

Reads the tariff pickup context via {@see OrderPickupPointApplier::loadTariffContext()}; the admin build path needs the same context, so it lives in the service.

private loadTariffPickupContext(int $tariffId) : array{externalPickup: bool, shipperId: ?int, scriptName: ?string}|null
Parameters
$tariffId : int
Return values
array{externalPickup: bool, shipperId: ?int, scriptName: ?string}|null

money()

Returns a numeric value for bcmath (non-numeric or empty = zero), like `OrderCalculator::norm()`.

private money(string $value) : numeric-string
Parameters
$value : string
Return values
numeric-string

nullIfEmpty()

private nullIfEmpty(string $value) : string|null
Parameters
$value : string
Return values
string|null

payloadLines()

Reads cart lines from the payload, which carries only `setId` and `quantity`; never a price, rate or discount (see the class docblock). Invalid rows are skipped silently, an empty result is handled by the caller.

private payloadLines(mixed $raw) : array<int, array{setId: int, quantity: int}>
Parameters
$raw : mixed
Return values
array<int, array{setId: int, quantity: int}>

payloadStringList()

private payloadStringList(mixed $raw) : array<int, string>
Parameters
$raw : mixed
Return values
array<int, string>

paymentGateIdForMethod()

Returns the id of the active payment gateway assigned to the method, or `null`. The FK is read from the module's own `cms_mod_eshop_payment_methods`; the gateway activation is confirmed by its owner ({@see PaymentGateManager::isActivated()}).

private paymentGateIdForMethod(int $paymentMethodId) : int|null
Parameters
$paymentMethodId : int
Return values
int|null

ref()

Returns a managed reference without a DB query (like {@see OrderSnapshotBuilder::ref()}).

private ref(T> $class, int $id) : T
Parameters
$class : T>
$id : int
Tags
template
Return values
T

resolveDefaultPaymentRegionId()

Priority of the VAT region for a new snapshot: `4/invoicer.paymentRegionId`, then `7/invoice.default.paymentRegionId` (without prefix), then the locale default ({@see PaymentRegionManager::getDefaultPaymentRegionId()}).

private resolveDefaultPaymentRegionId() : int
Return values
int

resolveSellerSnapshot()

Resolves `4/invoicer.sellerId`, then `7/invoice.default.sellerId`, plus the snapshot from the data owner ({@see SellerManager::getSellerSnapshot()}).

private resolveSellerSnapshot() : SellerSnapshot|null

null means no seller is set, or none exists for the set id; for checkout that is a hard failure.

Return values
SellerSnapshot|null

resolveUserTypeId()

Resolves the customer type from the two checkout checkboxes: private person, company non-payer or company VAT payer. The code list `cms_system_user_types` carries exactly these two axes (`requires_company_data`, `requires_vat_id`), so the type is derived without a select the customer would not understand. Without a matching row it falls back to the setting `4/invoicer.userTypeId`, then `7/invoice.default.userTypeId`.

private resolveUserTypeId(bool $isCompany, bool $isVatPayer) : int|null
Parameters
$isCompany : bool
$isVatPayer : bool
Return values
int|null

scalarStr()

private scalarStr(mixed $value) : string
Parameters
$value : mixed
Return values
string

serializeOrder()

private serializeOrder(Order $order) : array<string, mixed>
Parameters
$order : Order
Return values
array<string, mixed>

settingFlag()

Reads a setting through {@see SettingContext} (a framework service a manager may hold). The context is filled by `SettingInitTrait` in the startup of every base presenter (Api, Front, Admin, Cron, Script); a CLI harness must fill it itself.

private settingFlag(int $module, string $key) : bool
Parameters
$module : int
$key : string
Return values
bool

statusIdByKey()

private statusIdByKey(string $key) : int|null
Parameters
$key : string
Return values
int|null

str()

private str(array<string|int, mixed> $payload, string $key) : string|null
Parameters
$payload : array<string|int, mixed>
$key : string
Return values
string|null

targetStatusKey()

Returns the target state after the order is created: - a gateway or a method sending a proforma (bank transfer) -> `WAITING-ON-PAYMENT` (issues the proforma and sends an e-mail, `allow_cancelling = 0`), - otherwise (cash on delivery, cash) `APPROVED` when `4/order.approval.auto` is on, - otherwise the order stays in `CREATED` (confirmed manually by staff).

private targetStatusKey(int|null $paymentMethodId, bool $requiresGateway) : string
Parameters
$paymentMethodId : int|null
$requiresGateway : bool
Return values
string

tariffCountryCodes()

Stored delivery coverage of the tariff's region (null = no restriction).

private tariffCountryCodes(int $tariffId) : string|null
Parameters
$tariffId : int
Return values
string|null

widgetConfigFor()

Returns the carrier widget configuration for a single `tariffRows` row from {@see buildOptions()}.

private widgetConfigFor(array<string, mixed> $row, array{lang?: string, currency?: string, country?: string, weight?: float} $context) : array{scriptUrl: string, apiKey: ?string, mechanism: string, options: array, elementTag: ?string, eventName: ?string}|null

A carrier without script_name or without a driver in the registry behaves as if it had no pickup point support and must not crash: null at any step (missing script_name, driver not in CarrierRegistry, or the driver itself returning null for a missing API key) is a valid result, not an exception.

Parameters
$row : array<string, mixed>

tariffRows row (carries shipper_id, script_name)

$context : array{lang?: string, currency?: string, country?: string, weight?: float}

see CarrierInterface::getWidgetConfig()

Return values
array{scriptUrl: string, apiKey: ?string, mechanism: string, options: array, elementTag: ?string, eventName: ?string}|null

withdrawUncoveredOrder()

Cancels an order whose stock could not be reserved after commit through the regular state machine (stock remnant released, voucher usage returned), silently: the customer sees the checkout error right away, a "cancelled" e-mail would only confuse.

private withdrawUncoveredOrder(int $orderId) : void

The record stays for the operator (note in status_informations, order number consumed). Fail-soft — when the transition fails, the order stays in CREATED without any payment (logged for the admin); the customer still gets the error and nothing to pay.

Parameters
$orderId : int
On this page

Search results