CoolCMS API

TaxManager
in package

FinalYes

VAT engine orchestrator.

Manager-tier (no entity of its own): loads the seller profile on the tax date (SellerTaxProfileManager), countries, supply kind natures, rates and the VAT id verification, classifies the customer and asks TaxRuleTable, the only place with rules. It never persists anything except VIES evidence (through VatIdCheckManager) and never touches amounts except the gross split and the ancillary allocation (TaxAmountCalculator).

IMPORTANT: all reads are raw DBAL (no UoW::clear()), because consumers call it while building an order / payment graph. Lookups are cached per request (rates per kind, country and day, natures, regions).

Consumers: the bridge api/system/tax/resolve (payment form), InvoiceGenerator (legacy payments without a snapshot, rate on the payment date), InvoiceTaxManager (manual invoices) and the e-shop (OrderTaxManager, ProductSetManager).

Table of Contents

Properties

$countryManager  : CountryManager
$natures  : array<int, SupplyNature|false>
$paymentRegionManager  : PaymentRegionManager
$rates  : array<string, numeric-string|null>
$regionCountryCodes  : array<int, string|null>
$sellerTaxProfileManager  : SellerTaxProfileManager
$supplyKindManager  : SupplyKindManager
$taxAmountCalculator  : TaxAmountCalculator
$taxRuleTable  : TaxRuleTable
$vatIdCheckManager  : VatIdCheckManager
$vatRateManager  : VatRateManager

Methods

__construct()  : mixed
allocateAncillary()  : array<int, TaxAncillaryShare>
proportionally to their bases; the rounding remainder goes to the largest group.
findNoteKey()  : string|null
Note key (`tax.note.<CODE>[.<status>]`) of a snapshotted treatment code: the invoice from a payment copies the code and re-translates the note in the document language. An unknown or `DOMESTIC` code gives null.
rate()  : numeric-string|null
Rate of a supply kind in a country on a date ('21.00'); null means `RATE_MISSING` (never a default).
resetCache()  : void
Drops request caches (long-running CLI after an admin change of rates / kinds).
resolve()  : TaxResolution
resolveDisplay()  : array<int, TaxTreatment>
Catalog / detail display: anonymous consumer in the country of the display region (region without a country gives the seller country + `COUNTRY_ASSUMED`). Never calls VIES.
sellerStatusAt()  : SellerVatStatus|null
verifyVatId()  : VatIdVerification
Verification outside a resolution (profile save, admin "verify in VIES" action).
buildAmounts()  : array{0: numeric-string, 1: numeric-string|null}
buildHeader()  : TaxTreatment|null
Header = main supply (highest base, first on a tie), `chargeVat` = any line charges VAT, all flags.
buildTreatment()  : TaxTreatment
classifyCustomer()  : CustomerClass
Customer class C. The VAT id is verified lazily: at most once per resolution and only when a line goes to another EU member state; its flags are collected in `$state`.
findCountryOrPlaceholder()  : TaxCountry
findNatures()  : array<int, SupplyNature>
isEuB2cThresholdExceeded()  : bool
Hook: limit `EU_B2C_DISTANCE` of the seller (sum of the period + this document). Until the limits exist there is no active limit, so the result is no.
mergeFlags()  : array<int, TaxFlag>
resolveCustomerCountry()  : TaxCountry
Customer country, then payment region country, then seller country; the fallbacks flag `COUNTRY_ASSUMED`.

Properties

$rates

private array<string, numeric-string|null> $rates = []

$regionCountryCodes

private array<int, string|null> $regionCountryCodes = []

Methods

__construct()

public __construct(SellerTaxProfileManager $sellerTaxProfileManager, SupplyKindManager $supplyKindManager, CountryManager $countryManager, VatRateManager $vatRateManager, PaymentRegionManager $paymentRegionManager, VatIdCheckManager $vatIdCheckManager, TaxRuleTable $taxRuleTable, TaxAmountCalculator $taxAmountCalculator) : mixed
Parameters
$sellerTaxProfileManager : SellerTaxProfileManager
$supplyKindManager : SupplyKindManager
$countryManager : CountryManager
$vatRateManager : VatRateManager
$paymentRegionManager : PaymentRegionManager
$vatIdCheckManager : VatIdCheckManager
$taxRuleTable : TaxRuleTable
$taxAmountCalculator : TaxAmountCalculator

allocateAncillary()

proportionally to their bases; the rounding remainder goes to the largest group.

public allocateAncillary(TaxResolution $resolution, numeric-string $amount[, bool $grossPrice = false ]) : array<int, TaxAncillaryShare>

Lines with an error are ignored. $grossPrice means the amount includes VAT (split from the top per group).

Parameters
$resolution : TaxResolution
$amount : numeric-string
$grossPrice : bool = false
Return values
array<int, TaxAncillaryShare>

findNoteKey()

Note key (`tax.note.<CODE>[.<status>]`) of a snapshotted treatment code: the invoice from a payment copies the code and re-translates the note in the document language. An unknown or `DOMESTIC` code gives null.

public findNoteKey(string $code, int $sellerId, DateTimeInterface $at) : string|null
Parameters
$code : string
$sellerId : int
$at : DateTimeInterface
Return values
string|null

rate()

Rate of a supply kind in a country on a date ('21.00'); null means `RATE_MISSING` (never a default).

public rate(int $supplyKindId, string $countryCode, DateTimeInterface $at) : numeric-string|null
Parameters
$supplyKindId : int
$countryCode : string
$at : DateTimeInterface
Return values
numeric-string|null

resetCache()

Drops request caches (long-running CLI after an admin change of rates / kinds).

public resetCache() : void

resolveDisplay()

Catalog / detail display: anonymous consumer in the country of the display region (region without a country gives the seller country + `COUNTRY_ASSUMED`). Never calls VIES.

public resolveDisplay(int $sellerId, int|null $paymentRegionId, array<int, int> $supplyKindIds, DateTimeInterface $at) : array<int, TaxTreatment>
Parameters
$sellerId : int
$paymentRegionId : int|null
$supplyKindIds : array<int, int>
$at : DateTimeInterface
Return values
array<int, TaxTreatment> —

keyed by supply kind id; unknown kinds are left out

verifyVatId()

Verification outside a resolution (profile save, admin "verify in VIES" action).

public verifyVatId(string $vatId[, bool $forceOnline = false ][, int|null $sellerId = null ][, string|null $fallbackCountryCode = null ][, VatIdCheckLimit|null $limit = null ]) : VatIdVerification

$sellerId supplies the requester VAT id for the VIES consultation number. $limit is the rate limit of the online call (VatIdCheckManager::buildUserCheckLimit()); null means unlimited.

Parameters
$vatId : string
$forceOnline : bool = false
$sellerId : int|null = null
$fallbackCountryCode : string|null = null
$limit : VatIdCheckLimit|null = null
Return values
VatIdVerification

buildTreatment()

private buildTreatment(int $supplyKindId, SupplyNature $nature, SellerVatStatus $sellerStatus, SellerTaxProfile|null $profile, TaxCountry $sellerCountry, CustomerClass $customerClass, bool|null $placeDomestic, DateTimeInterface $taxDate, VatIdVerification|null $verification) : TaxTreatment
Parameters
$supplyKindId : int
$nature : SupplyNature
$sellerStatus : SellerVatStatus
$profile : SellerTaxProfile|null
$sellerCountry : TaxCountry
$customerClass : CustomerClass
$placeDomestic : bool|null
$taxDate : DateTimeInterface
$verification : VatIdVerification|null
Return values
TaxTreatment

classifyCustomer()

Customer class C. The VAT id is verified lazily: at most once per resolution and only when a line goes to another EU member state; its flags are collected in `$state`.

private classifyCustomer(TaxCountry $country, TaxCountry $sellerCountry, DateTimeInterface $taxDate, bool $isBusiness, bool $hasVatId, callable(): VatIdVerification $verify, callable(TaxCountry): Array $findEvidence, TaxFlag>, evidenceLooked: bool} &$state) : CustomerClass

A non-EU business stays declared (BUSINESS_STATUS_DECLARED); its manual evidence ("prove company") is only attached as the verification (snapshot customer_vat_id_check_id), looked up once per resolution.

Parameters
$country : TaxCountry
$sellerCountry : TaxCountry
$taxDate : DateTimeInterface
$isBusiness : bool
$hasVatId : bool
$verify : callable(): VatIdVerification
$findEvidence : callable(TaxCountry): Array
$state : TaxFlag>, evidenceLooked: bool}
Return values
CustomerClass

findCountryOrPlaceholder()

private findCountryOrPlaceholder(string $countryCode) : TaxCountry
Parameters
$countryCode : string
Return values
TaxCountry

findNatures()

private findNatures(array<int, int> $supplyKindIds) : array<int, SupplyNature>
Parameters
$supplyKindIds : array<int, int>
Return values
array<int, SupplyNature>

isEuB2cThresholdExceeded()

Hook: limit `EU_B2C_DISTANCE` of the seller (sum of the period + this document). Until the limits exist there is no active limit, so the result is no.

private isEuB2cThresholdExceeded() : bool
Return values
bool

resolveCustomerCountry()

Customer country, then payment region country, then seller country; the fallbacks flag `COUNTRY_ASSUMED`.

private resolveCustomerCountry(string|null $customerCountryCode, int|null $paymentRegionId, TaxCountry $sellerCountry, array<int, TaxFlag> &$flags) : TaxCountry

An unknown ISO code from the client counts as missing.

Parameters
$customerCountryCode : string|null
$paymentRegionId : int|null
$sellerCountry : TaxCountry
$flags : array<int, TaxFlag>
Return values
TaxCountry
On this page

Search results