fix : brouillon à contrepartie incomplète enregistrable sans erreur 500 (ERP-193)

Un brouillon dont le type de contrepartie est choisi sans son champ associé
(client/fournisseur null, ou libellé « Autre » vide) violait chk_wt_*_branch
et levait une 500 : le callback de cohérence RG-5.03 ne joue qu'au groupe
finalize, laissant passer l'incohérence à l'enregistrement du brouillon.

- back : WeighingTicketProcessor retire la contrepartie entière quand le champ
  de branche est absent (clearCounterparty) au lieu de persister un état
  incohérent. N'affecte que le brouillon (à la validation, le callback finalize
  lève déjà une 422 avant le processor).
- front : buildDraftPayload n'émet le type que si son champ associé est rempli ;
  la validation continue d'envoyer toujours le type pour la 422 métier.
- tests : 2 cas back (CLIENT sans client, AUTRE libellé vide) + 2 cas front.
This commit is contained in:
2026-06-24 16:12:40 +02:00
parent 9e2206a7d6
commit 391f383c4b
4 changed files with 134 additions and 8 deletions
@@ -36,6 +36,49 @@ final class WeighingTicketLifecycleTest extends AbstractWeighingTicketApiTestCas
self::assertSame(7150, $body['emptyWeight']);
}
public function testDraftWithIncompleteCounterpartyIsPersistedWithoutBranch(): void
{
$http = $this->authManageOnSite($this->siteByCode('86'));
// Brouillon « contrepartie incomplete » : type CLIENT choisi mais client pas
// encore selectionne (cas reel : l'operateur ouvre le menu puis pese). Le
// Callback de coherence ne joue qu'a la validation (groupe finalize) ->
// SANS normalisation cote Processor, le persist violerait chk_wt_client_branch
// (counterparty_type='CLIENT' + client_id NULL) et leverait une 500.
$body = $this->postTicket($http, [
'counterpartyType' => 'CLIENT',
'emptyDate' => '2026-06-17T09:00:00+02:00',
'emptyWeight' => 7150,
'emptyMode' => 'AUTO',
])->toArray();
self::assertResponseStatusCodeSame(201);
self::assertSame('DRAFT', $body['status']);
// La contrepartie incoherente est retiree (pas persistee a moitie) : le
// brouillon reste enregistrable, la coherence est exigee a la validation.
self::assertNull($body['counterpartyType'] ?? null);
self::assertSame(7150, $body['emptyWeight']);
}
public function testDraftWithEmptyOtherLabelIsPersistedWithoutBranch(): void
{
$http = $this->authManageOnSite($this->siteByCode('86'));
// Meme piege en branche AUTRE : type AUTRE mais libelle vide -> le normalizer
// ramene otherLabel a NULL, ce qui violait chk_wt_other_branch (500).
$body = $this->postTicket($http, [
'counterpartyType' => 'AUTRE',
'otherLabel' => ' ',
'emptyDate' => '2026-06-17T09:00:00+02:00',
'emptyWeight' => 7150,
'emptyMode' => 'AUTO',
])->toArray();
self::assertResponseStatusCodeSame(201);
self::assertSame('DRAFT', $body['status']);
self::assertNull($body['counterpartyType'] ?? null);
}
public function testValidateRequiresCounterparty(): void
{
$http = $this->authManageOnSite($this->siteByCode('86'));