Laravel SISP 2.1 separa o comprador do cliente
A fatura pertence a uma entidade fiscal, o checkout fala com uma pessoa. A versão 2.1 deixa de tratar as duas como o mesmo campo.
Uma fatura em Cabo Verde não vale pelo nome que aparece no topo. Vale pelo NIF. É esse número que liga o documento a uma entidade, e é por ele que a contabilidade o aceita ou o devolve.
O Laravel SISP não tinha onde guardar esse número. Tinha nome, email, telefone, morada, tudo aquilo que serve para contactar quem pagou. Nada disso identifica quem deve.
A versão 2.1 arruma essa diferença: o comprador da fatura é uma identidade fiscal, o cliente do checkout é um contacto, e a partir de agora o pacote guarda os dois.
A saída barata não resolve
A tentação é reaproveitar o que já existe. Passar a tratar customer_name como nome fiscal, pedir ao comerciante que envie sempre a empresa, e poupar quatro colunas.
Isso parte no primeiro pedido de suporte. Quem atende precisa do gerente que pagou. Quem fatura precisa da empresa. Uma coluna só responde a metade e mente na outra metade, e a mentira aparece no pior momento possível, que é quando alguém tenta reconciliar um pagamento que não encontra.
Quatro campos, nenhum substitui outro
src/ValueObjects/CustomerData.php
final readonly class CustomerData
{
public function __construct(
public string $name,
public ?string $email = null,
// ...
public ?string $vat = null,
public ?string $taxName = null,
public ?string $taxEntityType = null,
public ?string $taxAddress = null,
) {}
}
Os campos de contacto continuam a significar o que significavam. Os quatro novos descrevem a entidade que deve o dinheiro. O pedido de pagamento valida-os como sometimes|nullable, e tanto a transação como a fatura guardam ambos os conjuntos.
Guardar a identidade fiscal duas vezes é uma decisão, não um descuido. Uma fatura é um documento e tem de continuar verdadeira depois de a transação mudar. Copiar os campos no momento em que a fatura é gerada é o preço dessa garantia.
O PDF decide tarde
O código que interessa não é o esquema da base de dados. É o instante em que o documento tem de escolher que nome imprimir.
src/Actions/GenerateInvoicePdfAction.php
$taxName = $invoice->customer_tax_name ?? $transaction->customer_tax_name;
$taxAddress = $invoice->customer_tax_address ?? $transaction->customer_tax_address;
$buyer = EntityBuilder::make()
->name($taxName ?? $invoice->customer_name ?? $transaction->customer_name ?? '')
->address($taxAddress ?? $invoice->customer_address ?? $transaction->customer_address ?? '')
->vat($invoice->customer_vat ?? $transaction->customer_vat ?? '')
O bloco do comprador prefere a identidade fiscal e recua para o contacto quando ela não existe. Duas cadeias, ambas resolvidas na altura de gerar o ficheiro.
Esse recuo é também o caminho de atualização. Um comerciante que não envie nada de novo recebe o mesmo PDF de antes. Um comerciante que envie customer_tax_name e customer_vat recebe um documento que a contabilidade arquiva sem perguntas. Sem flag para ligar, sem migração de dados a correr atrás.
Quem carrega no botão de pagar e quem responde pelo imposto raramente são a mesma entidade. O pacote passou a saber disso.