CluPilotCloud/app/Services/Tax/FakeVatIdVerifier.php

61 lines
1.8 KiB
PHP

<?php
namespace App\Services\Tax;
use App\Models\Customer;
/**
* The register, for tests.
*
* Answers UNAVAILABLE for anything it was not told about, which is deliberately
* the awkward default: a test that forgets to arm a number finds out, instead of
* quietly proving that an unchecked number earns a reverse charge.
*/
final class FakeVatIdVerifier implements VatIdVerifier
{
/** @var array<string, VatIdCheck> */
private array $answers = [];
/** @var array<int, string> every number that was asked about, in order */
public array $asked = [];
public function registered(string $vatId, ?string $name = null): self
{
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::valid($name);
return $this;
}
public function notRegistered(string $vatId): self
{
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::invalid();
return $this;
}
/** The register is down — the case that must never clear a verification. */
public function down(string $vatId): self
{
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::unavailable('test');
return $this;
}
public function check(string $vatId): VatIdCheck
{
$normalised = Customer::normaliseVatId($vatId);
// Refused before it is recorded as asked, exactly as the real verifier
// refuses before it spends a request. Without this the fake would answer
// where VIES would never have been consulted, and a test could prove the
// opposite of what the product does.
if (! VatIdShape::verifiable($normalised)) {
return VatIdCheck::invalid();
}
$this->asked[] = $normalised;
return $this->answers[$normalised] ?? VatIdCheck::unavailable('not armed in this test');
}
}