OrderTaxManager
in package
Converts the unified tax engine result into the order VAT snapshot.
The only place where the e-shop deals with VAT: TaxManager decides the rate, treatment
and clause; this class writes them into the order snapshot (orders.tax_*, order_items.vat
with supply kind, shipping and payment). Consumers (checkout, state transition, invoice) only
read the snapshot and never branch on VAT elsewhere.
Checkout order: buildItems(), resolveForOrder() + applyItemTaxes() +
applyHeader(), buildShipper() (needs the cart value with VAT for free_from),
buildPaymentMethod(), applyAncillaryTaxes(), vouchers, recalculate().
Shipping (and a payment without its own supply kind) is an ancillary supply: it shares the main supply treatment and is allocated proportionally to item bases per rate by OrderCalculator::ancillaryShares(). The invoice and recap use the same split, so they never diverge.
IMPORTANT: TaxManager reads code lists via raw DBAL, so it can be called in the middle of
building the order graph. A find() there would call UoW::clear() and break the graph.
Tags
Table of Contents
Constants
- ERROR_CODE : string = 'taxUnavailable'
- Error for the caller: the engine gave no usable answer (missing seller status, rate or supply kind).
Properties
- $calculator : OrderCalculator
- $countryManager : CountryManager
- $em : EntityManagerInterface
- $settingContext : SettingContext
- $supplyKindManager : SupplyKindManager
- $taxManager : TaxManager
- $translator : Translator
- $vatIdCheckManager : VatIdCheckManager
Methods
- __construct() : mixed
- applyAncillaryTaxes() : void
- Sets shipping and payment rates. A payment with its own supply kind (`payment_methods.supply_kind_id`) is a separate supply with its own rate; otherwise (and always for shipping) it is an ancillary supply allocated proportionally to item rates.
- applyHeader() : void
- Writes the header snapshot: treatment code, rate date and country, clause in the order language (plus Czech), VAT id verification, flags and summary report code. `with_vat` is only derived from `chargeVat` (read by the calculator and the invoice).
- applyItemTaxes() : void
- Sets item (and fee) rates from the engine treatment: `vat` is the treatment rate (0 = no VAT charged), `price*WithVat*` are derived. Resolution lines are in the same order as order items.
- displayRate() : string
- Returns the rate for display and admin prefill: an anonymous consumer in the payment region country. An unknown supply kind or a seller without status gives `'0.00'` (never a silent default).
- findCountryText() : string|null
- Returns the country name from the code list for printing (the ISO code is the single source of truth).
- hasUnverifiedVatId() : bool
- Tells whether to show the customer the "VAT id not verified" notice in the order summary.
- normalizeCountryCode() : string|null
- Returns the ISO code from the code list (unknown gives `null`, never a silent default).
- reRateAtShipping() : bool
- Re-rates an order paid after dispatch (cash on delivery, invoice with due date): on the shipping day only the rate at the dispatch date is resolved again; customer class and treatment code stay from the order. Writes straight to the DB (runs inside a state transition, outside `save()`) and to the entity, so the e-mail and invoice show the new amount, and cash on delivery is collected in the new amount.
- resolveForOrder() : TaxResolution|null
- Resolves the VAT treatment of the whole order at the tax date. Returns `null` when the engine gave no usable answer; the caller must not finish the purchase with zero tax but show the customer an error ({@see ERROR_CODE}).
- resolveSellerId() : int|null
- Resolves the e-shop seller: order snapshot, then `4/invoicer.sellerId`, then `7/invoice.default.sellerId` (the same chain as the invoice created from an order).
- buildContext() : TaxContext
- Builds the engine context: billing and delivery country, company by buyer type, VAT id and company number. The order region is the country fallback.
- buildItemLines() : array<int, TaxLine>
- Builds engine lines from order items (base after discounts times quantity). The supply kind comes from the item snapshot; an item without one falls back to the default kind.
- isUsable() : bool
- itemBase() : string
- Returns the item base after both discounts times quantity, the same values {@see OrderCalculator::itemsTotals()} uses (ancillary allocation weights and main supply choice).
- money() : numeric-string
- Returns a decimal column value for bcmath (non-numeric or empty gives zero).
- persistReRate() : void
- Persists the dispatch re-rate with raw UPDATEs of the module tables. It runs inside a state transition, outside `OrderManager::save()`, which would trigger reservations and invoice issuing again.
- rateOf() : string
- Returns the treatment rate for the snapshot: `0.00` when no VAT is charged or the engine returned no line.
- resolveOwnTreatment() : TaxTreatment|null
- Resolves the treatment of one separate supply (a payment with its own kind) in the same context as the order. Always `CacheOnly`: the VAT id check already ran in the main resolution.
- translateNote() : string|null
- Returns the VAT clause in the order language (plus Czech).
- withFlag() : array<int, string>
Constants
ERROR_CODE
Error for the caller: the engine gave no usable answer (missing seller status, rate or supply kind).
public
string
ERROR_CODE
= 'taxUnavailable'
Properties
$calculator read-only
private
OrderCalculator
$calculator
$countryManager read-only
private
CountryManager
$countryManager
$em read-only
private
EntityManagerInterface
$em
$settingContext read-only
private
SettingContext
$settingContext
$supplyKindManager read-only
private
SupplyKindManager
$supplyKindManager
$taxManager read-only
private
TaxManager
$taxManager
$translator read-only
private
Translator
$translator
$vatIdCheckManager read-only
private
VatIdCheckManager
$vatIdCheckManager
Methods
__construct()
public
__construct(TaxManager $taxManager, SupplyKindManager $supplyKindManager, VatIdCheckManager $vatIdCheckManager, CountryManager $countryManager, OrderCalculator $calculator, Translator $translator, SettingContext $settingContext, EntityManagerInterface $em) : mixed
Parameters
- $taxManager : TaxManager
- $supplyKindManager : SupplyKindManager
- $vatIdCheckManager : VatIdCheckManager
- $countryManager : CountryManager
- $calculator : OrderCalculator
- $translator : Translator
- $settingContext : SettingContext
- $em : EntityManagerInterface
applyAncillaryTaxes()
Sets shipping and payment rates. A payment with its own supply kind (`payment_methods.supply_kind_id`) is a separate supply with its own rate; otherwise (and always for shipping) it is an ancillary supply allocated proportionally to item rates.
public
applyAncillaryTaxes(TOrderGraph $order, TaxResolution $resolution, int $sellerId) : void
Parameters
- $order : TOrderGraph
- $resolution : TaxResolution
- $sellerId : int
applyHeader()
Writes the header snapshot: treatment code, rate date and country, clause in the order language (plus Czech), VAT id verification, flags and summary report code. `with_vat` is only derived from `chargeVat` (read by the calculator and the invoice).
public
applyHeader(TOrderGraph $order, TaxResolution $resolution) : void
Parameters
- $order : TOrderGraph
- $resolution : TaxResolution
applyItemTaxes()
Sets item (and fee) rates from the engine treatment: `vat` is the treatment rate (0 = no VAT charged), `price*WithVat*` are derived. Resolution lines are in the same order as order items.
public
applyItemTaxes(TOrderGraph $order, TaxResolution $resolution) : void
Parameters
- $order : TOrderGraph
- $resolution : TaxResolution
displayRate()
Returns the rate for display and admin prefill: an anonymous consumer in the payment region country. An unknown supply kind or a seller without status gives `'0.00'` (never a silent default).
public
displayRate(int|null $paymentRegionId, int|null $supplyKindId[, int|null $sellerId = null ][, DateTimeInterface|null $at = null ]) : string
Parameters
- $paymentRegionId : int|null
- $supplyKindId : int|null
- $sellerId : int|null = null
- $at : DateTimeInterface|null = null
Return values
stringfindCountryText()
Returns the country name from the code list for printing (the ISO code is the single source of truth).
public
findCountryText(string|null $countryCode[, int|null $languageId = null ]) : string|null
Parameters
- $countryCode : string|null
- $languageId : int|null = null
Return values
string|nullhasUnverifiedVatId()
Tells whether to show the customer the "VAT id not verified" notice in the order summary.
public
hasUnverifiedVatId(TOrderGraph $order) : bool
Parameters
- $order : TOrderGraph
Return values
boolnormalizeCountryCode()
Returns the ISO code from the code list (unknown gives `null`, never a silent default).
public
normalizeCountryCode(string|null $countryCode) : string|null
Parameters
- $countryCode : string|null
Return values
string|nullreRateAtShipping()
Re-rates an order paid after dispatch (cash on delivery, invoice with due date): on the shipping day only the rate at the dispatch date is resolved again; customer class and treatment code stay from the order. Writes straight to the DB (runs inside a state transition, outside `save()`) and to the entity, so the e-mail and invoice show the new amount, and cash on delivery is collected in the new amount.
public
reRateAtShipping(TOrderGraph $order, DateTimeInterface $shippedAt) : bool
Parameters
- $order : TOrderGraph
- $shippedAt : DateTimeInterface
Return values
bool —true when the snapshot changed (rate, totals, tax_date, RESOLVED_AT_SHIPPING flag)
resolveForOrder()
Resolves the VAT treatment of the whole order at the tax date. Returns `null` when the engine gave no usable answer; the caller must not finish the purchase with zero tax but show the customer an error ({@see ERROR_CODE}).
public
resolveForOrder(TOrderGraph $order, int $sellerId, bool $binding[, string|null $ip = null ][, DateTimeInterface|null $taxDate = null ]) : TaxResolution|null
Parameters
- $order : TOrderGraph
- $sellerId : int
- $binding : bool
-
binding submit: the VAT id is verified online on the tax date (once a day per VAT id, IP rate-limited); a cart preview uses stored results only (
CacheOnly) - $ip : string|null = null
- $taxDate : DateTimeInterface|null = null
Return values
TaxResolution|nullresolveSellerId()
Resolves the e-shop seller: order snapshot, then `4/invoicer.sellerId`, then `7/invoice.default.sellerId` (the same chain as the invoice created from an order).
public
resolveSellerId([int|null $orderSellerId = null ]) : int|null
Parameters
- $orderSellerId : int|null = null
Return values
int|nullbuildContext()
Builds the engine context: billing and delivery country, company by buyer type, VAT id and company number. The order region is the country fallback.
private
buildContext(TOrderGraph $order, int $sellerId, bool $binding, string|null $ip, DateTimeInterface|null $taxDate) : TaxContext
Parameters
- $order : TOrderGraph
- $sellerId : int
- $binding : bool
- $ip : string|null
- $taxDate : DateTimeInterface|null
Return values
TaxContextbuildItemLines()
Builds engine lines from order items (base after discounts times quantity). The supply kind comes from the item snapshot; an item without one falls back to the default kind.
private
buildItemLines(TOrderGraph $order) : array<int, TaxLine>
Parameters
- $order : TOrderGraph
Return values
array<int, TaxLine>isUsable()
private
isUsable(TaxResolution $resolution) : bool
Parameters
- $resolution : TaxResolution
Return values
boolitemBase()
Returns the item base after both discounts times quantity, the same values {@see OrderCalculator::itemsTotals()} uses (ancillary allocation weights and main supply choice).
private
itemBase(TOrderGraph $order, OrderItem $item) : string
Parameters
- $order : TOrderGraph
- $item : OrderItem
Return values
stringmoney()
Returns a decimal column value for bcmath (non-numeric or empty gives zero).
private
money(string $value) : numeric-string
Parameters
- $value : string
Return values
numeric-stringpersistReRate()
Persists the dispatch re-rate with raw UPDATEs of the module tables. It runs inside a state transition, outside `OrderManager::save()`, which would trigger reservations and invoice issuing again.
private
persistReRate(TOrderGraph $order, int $orderId) : void
Parameters
- $order : TOrderGraph
- $orderId : int
rateOf()
Returns the treatment rate for the snapshot: `0.00` when no VAT is charged or the engine returned no line.
private
rateOf(TaxTreatment|null $treatment) : string
Parameters
- $treatment : TaxTreatment|null
Return values
stringresolveOwnTreatment()
Resolves the treatment of one separate supply (a payment with its own kind) in the same context as the order. Always `CacheOnly`: the VAT id check already ran in the main resolution.
private
resolveOwnTreatment(TOrderGraph $order, int $sellerId, int $supplyKindId, string $amount, TaxResolution $resolution) : TaxTreatment|null
Parameters
- $order : TOrderGraph
- $sellerId : int
- $supplyKindId : int
- $amount : string
- $resolution : TaxResolution
Return values
TaxTreatment|nulltranslateNote()
Returns the VAT clause in the order language (plus Czech).
private
translateNote(TOrderGraph $order, string|null $noteKey) : string|null
IMPORTANT: take the language from the order entity (a lazy proxy is enough, getAlias() is
only a SELECT), never via LanguageManager::find(): every Api read does UoW::clear(),
which would break the identity map in the middle of building the order graph.
Parameters
- $order : TOrderGraph
- $noteKey : string|null
Return values
string|nullwithFlag()
private
withFlag(array<int, string>|null $flags, TaxFlag $flag) : array<int, string>
Parameters
- $flags : array<int, string>|null
- $flag : TaxFlag