hasVerifiedVatId()) { return new self($domestic, false); } // Asked of the recorded type, not of the number. Somebody who has said // they are a private person is a private person, and a VAT ID on their // record — a former sole trader's, a colleague's, a mistake — must not // be able to turn that answer over. Only an explicit "consumer" refuses // here; an unrecorded type falls through and is treated exactly as it // was before this check existed (see the class comment). if ($customer->hasRecordedType() && ! $customer->isBusiness()) { return new self($domestic, false); } $vatId = $customer->normalisedVatId(); $country = substr($vatId, 0, 2); $seller = strtoupper((string) config('provisioning.tax.seller_country', 'AT')); // Reverse charge is an intra-EU business rule: it needs a member state // that is not ours, and a number that at least looks like one. $eligible = in_array($country, self::EU_MEMBER_STATES, true) && $country !== $seller && preg_match('/^[A-Z]{2}[0-9A-Z]{8,12}$/', $vatId) === 1; return $eligible ? new self(0.0, true) : new self($domestic, false); } public function grossCents(int $netCents): int { return (int) round($netCents * (1 + $this->rate)); } public function percentLabel(): string { return rtrim(rtrim(number_format($this->rate * 100, 1, ',', '.'), '0'), ','); } }