feat : M5 — Tickets de pesée (ERP-188 → ERP-193) (#144)
Auto Tag Develop / tag (push) Successful in 8s
Auto Tag Develop / tag (push) Successful in 8s
MR unique regroupant tout le module M5 « Tickets de pesée » (remplace les MR empilées #140/#141/#142/#143).
## Périmètre
- **ERP-188** — Page liste des tickets de pesée + export XLSX (colonnes Fournisseur/Client/Autre + Statut).
- **ERP-189** — Écran « Ajouter » (4 champs en haut, 2 blocs de pesée, pesée bascule/manuelle, date+heure horodatée à la validation).
- **ERP-190** — Écran « Modifier » + bouton Imprimer.
- **ERP-191** — i18n + libellés + branchement site courant.
- **ERP-192** — Bon de pesée PDF généré côté back (template Twig → Dompdf), endpoint `GET /api/weighing_tickets/{id}/print.pdf`.
- **ERP-193** — Cycle de vie brouillon/validé (status DRAFT/VALIDATED, numéro attribué à la validation), DSD saisi conservé en pesée manuelle, retours métier design.
## Vérifications
- Back : tests Logistique + architecture verts, php-cs-fixer propre, migrations appliquées (dev + test).
- Front : suite Vitest complète verte, ESLint propre.
Base : `develop` — contient les 16 commits du M5 (rien d'autre).
Reviewed-on: #144
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #144.
This commit is contained in:
@@ -220,7 +220,8 @@ abstract class AbstractWeighingTicketApiTestCase extends AbstractApiTestCase
|
||||
|
||||
/**
|
||||
* POST un ticket et renvoie la reponse (assertions de statut a la charge de
|
||||
* l'appelant).
|
||||
* l'appelant). Cree un BROUILLON (status DRAFT, sans numero, ERP-193) — la
|
||||
* validation est portee par validateTicket().
|
||||
*/
|
||||
protected function postTicket(Client $http, array $payload): ResponseInterface
|
||||
{
|
||||
@@ -230,6 +231,32 @@ abstract class AbstractWeighingTicketApiTestCase extends AbstractApiTestCase
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* « Valider » un ticket : PATCH /weighing_tickets/{id}/validate (ERP-193).
|
||||
* Declenche la validation stricte (groupe finalize) + attribution du numero +
|
||||
* passage en VALIDATED. Body vide par defaut = on valide l'etat deja persiste.
|
||||
*/
|
||||
protected function validateTicket(Client $http, int $id, array $payload = []): ResponseInterface
|
||||
{
|
||||
return $http->request('PATCH', '/api/weighing_tickets/'.$id.'/validate', [
|
||||
'headers' => ['Content-Type' => self::MERGE],
|
||||
'json' => [] === $payload ? new \stdClass() : $payload,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST un brouillon complet puis le valide ; renvoie le ticket VALIDE (numero
|
||||
* attribue). Le payload doit porter contrepartie + immatriculation + 2 pesees.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function createValidatedTicket(Client $http, array $payload): array
|
||||
{
|
||||
$id = (int) $this->postTicket($http, $payload)->toArray()['id'];
|
||||
|
||||
return $this->validateTicket($http, $id)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrouve un membre d'une collection Hydra par son id.
|
||||
*
|
||||
|
||||
@@ -56,18 +56,16 @@ final class WeighbridgeReadingApiTest extends AbstractApiTestCase
|
||||
self::assertLessThanOrEqual(50000, $data['weight']);
|
||||
self::assertIsInt($data['dsd']);
|
||||
self::assertGreaterThanOrEqual(1, $data['dsd']);
|
||||
// manualNumber est null en mode bascule (cle potentiellement omise si
|
||||
// skip_null_values est actif — tolerant aux deux cas).
|
||||
self::assertNull($data['manualNumber'] ?? null);
|
||||
}
|
||||
|
||||
public function testManualWeighingKeepsWeightAndAllocatesDsd(): void
|
||||
public function testManualWeighingKeepsWeightAndEnteredDsd(): void
|
||||
{
|
||||
$client = $this->manageClientWithCurrentSite();
|
||||
|
||||
$response = $client->request('POST', '/api/weighbridge_readings', [
|
||||
'headers' => ['Content-Type' => 'application/ld+json'],
|
||||
'json' => ['mode' => 'MANUAL', 'weight' => 23187, 'manualNumber' => 'PAP-555'],
|
||||
// Le DSD est SAISI par l'operateur et conserve tel quel (ERP-193).
|
||||
'json' => ['mode' => 'MANUAL', 'weight' => 23187, 'dsd' => 16619],
|
||||
]);
|
||||
|
||||
self::assertResponseStatusCodeSame(200);
|
||||
@@ -75,8 +73,7 @@ final class WeighbridgeReadingApiTest extends AbstractApiTestCase
|
||||
|
||||
self::assertSame('MANUAL', $data['mode']);
|
||||
self::assertSame(23187, $data['weight']);
|
||||
self::assertSame('PAP-555', $data['manualNumber']);
|
||||
self::assertGreaterThanOrEqual(1, $data['dsd']);
|
||||
self::assertSame(16619, $data['dsd'], 'Le DSD saisi est conserve, pas d\'auto-increment.');
|
||||
}
|
||||
|
||||
public function testManagePermissionIsRequired(): void
|
||||
@@ -117,11 +114,25 @@ final class WeighbridgeReadingApiTest extends AbstractApiTestCase
|
||||
'json' => ['mode' => 'MANUAL'],
|
||||
]);
|
||||
|
||||
// Garde-fou ERP-101 : la 422 doit cibler `weight` (Callback validateManualWeight).
|
||||
// Garde-fou ERP-101 : la 422 doit cibler `weight` (Callback validateManualFields).
|
||||
self::assertResponseStatusCodeSame(422);
|
||||
self::assertViolationOnPath($response, 'weight');
|
||||
}
|
||||
|
||||
public function testManualWeighingRequiresDsd(): void
|
||||
{
|
||||
$client = $this->manageClientWithCurrentSite();
|
||||
|
||||
$response = $client->request('POST', '/api/weighbridge_readings', [
|
||||
'headers' => ['Content-Type' => 'application/ld+json'],
|
||||
'json' => ['mode' => 'MANUAL', 'weight' => 23187],
|
||||
]);
|
||||
|
||||
// En manuel, le DSD est saisi → obligatoire (Callback validateManualFields).
|
||||
self::assertResponseStatusCodeSame(422);
|
||||
self::assertViolationOnPath($response, 'dsd');
|
||||
}
|
||||
|
||||
/**
|
||||
* Garde-fou ERP-101 (miroir AbstractWeighingTicketApiTestCase) : une 422 doit
|
||||
* porter une violation sur le `propertyPath` attendu, consommable inline par
|
||||
|
||||
@@ -72,8 +72,10 @@ final class WeighingTicketExportControllerTest extends AbstractApiTestCase
|
||||
// 1re ligne = en-tetes attendus (ordre des colonnes § 4.5).
|
||||
$header = $this->gridFromResponse($response->getContent())[0];
|
||||
self::assertSame('Numéro', $header[0]);
|
||||
self::assertContains('Type contrepartie', $header);
|
||||
self::assertContains('Contrepartie', $header);
|
||||
// Contrepartie eclatee en 3 colonnes (miroir liste, ERP-193).
|
||||
self::assertContains('Fournisseur', $header);
|
||||
self::assertContains('Client', $header);
|
||||
self::assertContains('Autre', $header);
|
||||
self::assertContains('Date', $header);
|
||||
self::assertContains('Immatriculation', $header);
|
||||
self::assertContains('Poids vide (kg)', $header);
|
||||
@@ -81,6 +83,7 @@ final class WeighingTicketExportControllerTest extends AbstractApiTestCase
|
||||
self::assertContains('Poids net (kg)', $header);
|
||||
self::assertContains('DSD vide', $header);
|
||||
self::assertContains('DSD plein', $header);
|
||||
self::assertContains('Statut', $header);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,8 +102,11 @@ final class WeighingTicketExportControllerTest extends AbstractApiTestCase
|
||||
|
||||
$cell = static fn (string $label) => $row[array_search($label, $header, true)] ?? null;
|
||||
|
||||
self::assertSame('Client', $cell('Type contrepartie'));
|
||||
self::assertStringContainsString('BÉTON SA', (string) $cell('Contrepartie'));
|
||||
// Contrepartie Client → colonne « Client » renseignée, « Fournisseur » / « Autre » vides.
|
||||
self::assertStringContainsString('BÉTON SA', (string) $cell('Client'));
|
||||
self::assertSame('', (string) $cell('Fournisseur'));
|
||||
self::assertSame('', (string) $cell('Autre'));
|
||||
self::assertSame('Terminée', $cell('Statut'));
|
||||
self::assertSame('AB-123-CD', $cell('Immatriculation'));
|
||||
self::assertSame(7150, (int) $cell('Poids vide (kg)'));
|
||||
self::assertSame(14300, (int) $cell('Poids plein (kg)'));
|
||||
@@ -184,6 +190,7 @@ final class WeighingTicketExportControllerTest extends AbstractApiTestCase
|
||||
$ticket->setFullDsd(42);
|
||||
$ticket->setFullMode('AUTO');
|
||||
$ticket->setNetWeight(7150);
|
||||
$ticket->setStatus(WeighingTicket::STATUS_VALIDATED);
|
||||
|
||||
$em->persist($ticket);
|
||||
$em->flush();
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Logistique\Api;
|
||||
|
||||
/**
|
||||
* Cycle de vie brouillon -> valide du ticket de pesee (ERP-193, spec-back § 2.14).
|
||||
*
|
||||
* Couvre :
|
||||
* - une pesee peut etre enregistree SANS contrepartie ni immatriculation : le POST
|
||||
* cree un BROUILLON (status DRAFT, pas de numero) ;
|
||||
* - la validation (PATCH /validate) exige les 3 champs du haut (type + champ
|
||||
* contrepartie + immatriculation) ET les 2 pesees (groupe `finalize`) ;
|
||||
* - une validation complete attribue le numero {siteCode}-TP-{NNNN} et passe le
|
||||
* ticket en VALIDATED.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class WeighingTicketLifecycleTest extends AbstractWeighingTicketApiTestCase
|
||||
{
|
||||
public function testWeighingOnlyCreatesDraftWithoutNumber(): void
|
||||
{
|
||||
$http = $this->authManageOnSite($this->siteByCode('86'));
|
||||
|
||||
// Pesee a vide seule : ni contrepartie, ni immatriculation.
|
||||
$body = $this->postTicket($http, [
|
||||
'emptyDate' => '2026-06-17T09:00:00+02:00',
|
||||
'emptyWeight' => 7150,
|
||||
'emptyMode' => 'AUTO',
|
||||
])->toArray();
|
||||
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
self::assertSame('DRAFT', $body['status']);
|
||||
self::assertArrayNotHasKey('number', $body, 'Un brouillon n\'a pas encore de numero (skip_null_values).');
|
||||
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'));
|
||||
|
||||
// Brouillon complet cote pesees + immatriculation, mais SANS contrepartie.
|
||||
$id = (int) $this->postTicket($http, [
|
||||
'immatriculation' => 'AB-123-CD',
|
||||
'emptyDate' => '2026-06-17T09:00:00+02:00',
|
||||
'emptyWeight' => 7150,
|
||||
'emptyMode' => 'AUTO',
|
||||
'fullDate' => '2026-06-17T09:12:00+02:00',
|
||||
'fullWeight' => 14300,
|
||||
'fullMode' => 'AUTO',
|
||||
])->toArray()['id'];
|
||||
|
||||
$response = $this->validateTicket($http, $id);
|
||||
|
||||
self::assertResponseStatusCodeSame(422);
|
||||
self::assertViolationOnPath($response, 'counterpartyType');
|
||||
}
|
||||
|
||||
public function testValidateRequiresBothWeighings(): void
|
||||
{
|
||||
$http = $this->authManageOnSite($this->siteByCode('86'));
|
||||
$client = $this->seedTestClient('Lifecycle');
|
||||
|
||||
// Brouillon avec contrepartie + immat + UNE seule pesee (a vide).
|
||||
$id = (int) $this->postTicket($http, [
|
||||
'counterpartyType' => 'CLIENT',
|
||||
'client' => $this->clientIri($client),
|
||||
'immatriculation' => 'AB-123-CD',
|
||||
'emptyDate' => '2026-06-17T09:00:00+02:00',
|
||||
'emptyWeight' => 7150,
|
||||
'emptyMode' => 'AUTO',
|
||||
])->toArray()['id'];
|
||||
|
||||
$response = $this->validateTicket($http, $id);
|
||||
|
||||
self::assertResponseStatusCodeSame(422);
|
||||
self::assertViolationOnPath($response, 'fullWeight');
|
||||
}
|
||||
|
||||
public function testValidateAssignsNumberAndStatus(): void
|
||||
{
|
||||
$http = $this->authManageOnSite($this->siteByCode('86'));
|
||||
$client = $this->seedTestClient('LifecycleOk');
|
||||
|
||||
$validated = $this->createValidatedTicket($http, $this->validClientTicketPayload($client));
|
||||
|
||||
self::assertSame('VALIDATED', $validated['status']);
|
||||
self::assertMatchesRegularExpression('/^86-TP-\d{4}$/', (string) $validated['number']);
|
||||
self::assertSame(7150, $validated['netWeight']);
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,12 @@ final class WeighingTicketNumberingTest extends AbstractWeighingTicketApiTestCas
|
||||
$http = $this->authManageOnSite($site);
|
||||
$client = $this->seedTestClient('Num');
|
||||
|
||||
$first = $this->postTicket($http, $this->validClientTicketPayload($client));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$second = $this->postTicket($http, $this->validClientTicketPayload($client));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
// Le numero est attribue a la VALIDATION (brouillon -> valide, ERP-193).
|
||||
$first = $this->createValidatedTicket($http, $this->validClientTicketPayload($client));
|
||||
$second = $this->createValidatedTicket($http, $this->validClientTicketPayload($client));
|
||||
|
||||
$n1 = (string) $first->toArray()['number'];
|
||||
$n2 = (string) $second->toArray()['number'];
|
||||
$n1 = (string) $first['number'];
|
||||
$n2 = (string) $second['number'];
|
||||
|
||||
self::assertMatchesRegularExpression('/^86-TP-\d{4}$/', $n1);
|
||||
self::assertMatchesRegularExpression('/^86-TP-\d{4}$/', $n2);
|
||||
@@ -49,8 +48,8 @@ final class WeighingTicketNumberingTest extends AbstractWeighingTicketApiTestCas
|
||||
$http86 = $this->authManageOnSite($this->siteByCode('86'));
|
||||
$http17 = $this->authManageOnSite($this->siteByCode('17'));
|
||||
|
||||
$n86 = (string) $this->postTicket($http86, $this->validClientTicketPayload($client))->toArray()['number'];
|
||||
$n17 = (string) $this->postTicket($http17, $this->validClientTicketPayload($client))->toArray()['number'];
|
||||
$n86 = (string) $this->createValidatedTicket($http86, $this->validClientTicketPayload($client))['number'];
|
||||
$n17 = (string) $this->createValidatedTicket($http17, $this->validClientTicketPayload($client))['number'];
|
||||
|
||||
// Chaque site encode son propre code dans le numero ; sequences disjointes.
|
||||
self::assertStringStartsWith('86-TP-', $n86);
|
||||
@@ -63,7 +62,8 @@ final class WeighingTicketNumberingTest extends AbstractWeighingTicketApiTestCas
|
||||
$http = $this->authManageOnSite($site);
|
||||
$client = $this->seedTestClient('Immutable');
|
||||
|
||||
$created = $this->postTicket($http, $this->validClientTicketPayload($client))->toArray();
|
||||
// Ticket valide (numero attribue) puis tentative de re-ecriture.
|
||||
$created = $this->createValidatedTicket($http, $this->validClientTicketPayload($client));
|
||||
$id = (int) $created['id'];
|
||||
$number = (string) $created['number'];
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Logistique\Api;
|
||||
|
||||
/**
|
||||
* Tests fonctionnels de l'impression du bon de pesee PDF (M5, spec-back § 2.12 /
|
||||
* § 4.6 — RG-5.08, ERP-192) : operation `GET /api/weighing_tickets/{id}/print.pdf`.
|
||||
*
|
||||
* Couvre la verification du ticket :
|
||||
* - 200 + PDF non vide (Content-Type application/pdf, disposition inline,
|
||||
* signature %PDF) pour un ticket existant et visible ;
|
||||
* - 403 sans la permission `logistique.weighing_tickets.view` ;
|
||||
* - 404 pour un ticket inexistant.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class WeighingTicketPrintApiTest extends AbstractWeighingTicketApiTestCase
|
||||
{
|
||||
public function testPrintReturnsNonEmptyPdfForExistingTicket(): void
|
||||
{
|
||||
$site = $this->firstSite();
|
||||
$http = $this->authManageOnSite($site);
|
||||
$client = $this->seedTestClient('Print');
|
||||
|
||||
$created = $this->postTicket($http, $this->validClientTicketPayload($client));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$ticketId = $created->toArray()['id'];
|
||||
|
||||
$response = $http->request('GET', sprintf('/api/weighing_tickets/%d/print.pdf', $ticketId));
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
|
||||
$headers = $response->getHeaders(false);
|
||||
self::assertStringContainsString('application/pdf', $headers['content-type'][0] ?? '');
|
||||
self::assertStringContainsString('inline', $headers['content-disposition'][0] ?? '');
|
||||
|
||||
// PDF non vide + signature de fichier PDF (« %PDF-1.x »).
|
||||
$binary = $response->getContent(false);
|
||||
self::assertNotSame('', $binary, 'Le PDF du bon de pesée ne doit pas être vide.');
|
||||
self::assertStringStartsWith('%PDF', $binary);
|
||||
}
|
||||
|
||||
public function testForbiddenWithoutViewPermission(): void
|
||||
{
|
||||
// On seede un ticket reel via un user habilite, puis on tente l'impression
|
||||
// avec un user depourvu de `logistique.weighing_tickets.view`.
|
||||
$site = $this->firstSite();
|
||||
$manager = $this->authManageOnSite($site);
|
||||
$client = $this->seedTestClient('Forbidden');
|
||||
|
||||
$created = $this->postTicket($manager, $this->validClientTicketPayload($client));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$ticketId = $created->toArray()['id'];
|
||||
|
||||
$creds = $this->createUserWithPermission('core.users.view');
|
||||
$intrus = $this->authenticatedClient($creds['username'], $creds['password']);
|
||||
|
||||
$intrus->request('GET', sprintf('/api/weighing_tickets/%d/print.pdf', $ticketId));
|
||||
|
||||
self::assertResponseStatusCodeSame(403);
|
||||
}
|
||||
|
||||
public function testNotFoundForUnknownTicket(): void
|
||||
{
|
||||
$http = $this->authManageOnSite($this->firstSite());
|
||||
|
||||
$http->request('GET', '/api/weighing_tickets/99999999/print.pdf');
|
||||
|
||||
self::assertResponseStatusCodeSame(404);
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,12 @@ final class WeighingTicketSerializationContractTest extends AbstractWeighingTick
|
||||
$http = $this->authManageOnSite($site);
|
||||
$clientEntity = $this->seedTestClient('Negoce');
|
||||
|
||||
$created = $this->postTicket($http, $this->validClientTicketPayload($clientEntity));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$createdBody = $created->toArray();
|
||||
// Brouillon cree puis valide (numero attribue a la validation, ERP-193).
|
||||
$createdBody = $this->createValidatedTicket($http, $this->validClientTicketPayload($clientEntity));
|
||||
|
||||
$id = (int) $createdBody['id'];
|
||||
$number = (string) $createdBody['number'];
|
||||
self::assertSame('VALIDATED', $createdBody['status']);
|
||||
|
||||
$detail = $http->request('GET', '/api/weighing_tickets/'.$id, ['headers' => ['Accept' => self::LD]])->toArray();
|
||||
$list = $http->request('GET', '/api/weighing_tickets?search='.$number, ['headers' => ['Accept' => self::LD]])->toArray();
|
||||
@@ -69,6 +69,9 @@ final class WeighingTicketSerializationContractTest extends AbstractWeighingTick
|
||||
// displayDate (date du ticket = fullDate ?? emptyDate) expose en liste.
|
||||
self::assertArrayHasKey('displayDate', $row);
|
||||
|
||||
// Statut du cycle de vie expose en liste (colonne « En attente / Terminée »).
|
||||
self::assertSame('VALIDATED', $row['status']);
|
||||
|
||||
// === DETAIL : site embarque (avec code), immatriculation, les 2 pesees ===
|
||||
self::assertIsArray($detail['site']);
|
||||
self::assertSame('86', $detail['site']['code']);
|
||||
@@ -95,9 +98,7 @@ final class WeighingTicketSerializationContractTest extends AbstractWeighingTick
|
||||
$http = $this->authManageOnSite($site);
|
||||
$supplierEntity = $this->seedTestSupplier('Ferraille');
|
||||
|
||||
$created = $this->postTicket($http, $this->validSupplierTicketPayload($supplierEntity));
|
||||
self::assertResponseStatusCodeSame(201);
|
||||
$createdBody = $created->toArray();
|
||||
$createdBody = $this->createValidatedTicket($http, $this->validSupplierTicketPayload($supplierEntity));
|
||||
|
||||
$id = (int) $createdBody['id'];
|
||||
$number = (string) $createdBody['number'];
|
||||
|
||||
Reference in New Issue
Block a user