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:
+5
-2
@@ -145,14 +145,17 @@ final class CounterpartyValidationTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste des propertyPath des violations de l'entite.
|
||||
* Liste des propertyPath des violations de l'entite, validee dans le groupe
|
||||
* `finalize` (la coherence contrepartie ne joue qu'a la validation depuis
|
||||
* ERP-193 ; un brouillon peut ne pas porter de contrepartie). Miroir du
|
||||
* validationContext de l'operation `validate` (['Default', 'finalize']).
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function violationPaths(WeighingTicket $ticket): array
|
||||
{
|
||||
$paths = [];
|
||||
foreach ($this->validator->validate($ticket) as $violation) {
|
||||
foreach ($this->validator->validate($ticket, null, ['Default', 'finalize']) as $violation) {
|
||||
$paths[] = $violation->getPropertyPath();
|
||||
}
|
||||
|
||||
|
||||
+11
-28
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace App\Tests\Module\Logistique\Infrastructure\ApiPlatform\State\Processor;
|
||||
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use App\Module\Logistique\Application\Service\DsdAllocatorInterface;
|
||||
use App\Module\Logistique\Domain\Contract\WeighbridgeReaderInterface;
|
||||
use App\Module\Logistique\Domain\Exception\WeighbridgeUnavailableException;
|
||||
use App\Module\Logistique\Domain\Weighbridge\WeighbridgeReading;
|
||||
@@ -21,8 +20,8 @@ use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
|
||||
* Processor de l'action `POST /api/weighbridge_readings` (§ 4.2).
|
||||
*
|
||||
* Couvre les 4 chemins sans BDD ni HTTP (stubs purs) : AUTO (lecture pont),
|
||||
* MANUAL (allocation DSD seule), indisponibilite → 503 (RG-5.06) et absence de
|
||||
* site courant → 400.
|
||||
* MANUAL (poids ET DSD saisis conserves tels quels, ERP-193), indisponibilite →
|
||||
* 503 (RG-5.06) et absence de site courant → 400.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
@@ -30,8 +29,7 @@ final class WeighbridgeReadingProcessorTest extends TestCase
|
||||
{
|
||||
private function site(): Site
|
||||
{
|
||||
// getId() reste null (non persiste) — sans incidence : reader et allocator
|
||||
// sont stubbes dans ces tests unitaires.
|
||||
// getId() reste null (non persiste) — sans incidence : reader stubbe.
|
||||
return new Site('Châtellerault', 'Rue du Pont', null, '86000', 'Châtellerault', '#112233');
|
||||
}
|
||||
|
||||
@@ -43,11 +41,7 @@ final class WeighbridgeReadingProcessorTest extends TestCase
|
||||
$reader = $this->createStub(WeighbridgeReaderInterface::class);
|
||||
$reader->method('read')->willReturn(new WeighbridgeReading(23000, 42));
|
||||
|
||||
$processor = new WeighbridgeReadingProcessor(
|
||||
$siteProvider,
|
||||
$reader,
|
||||
$this->createStub(DsdAllocatorInterface::class),
|
||||
);
|
||||
$processor = new WeighbridgeReadingProcessor($siteProvider, $reader);
|
||||
|
||||
$resource = new WeighbridgeReadingResource();
|
||||
$resource->mode = 'AUTO';
|
||||
@@ -56,34 +50,28 @@ final class WeighbridgeReadingProcessorTest extends TestCase
|
||||
|
||||
self::assertSame(23000, $result->weight);
|
||||
self::assertSame(42, $result->dsd);
|
||||
self::assertNull($result->manualNumber);
|
||||
self::assertSame('AUTO', $result->mode);
|
||||
}
|
||||
|
||||
public function testManualModeKeepsWeightAndAllocatesDsd(): void
|
||||
public function testManualModeKeepsWeightAndDsdAsEntered(): void
|
||||
{
|
||||
$siteProvider = $this->createStub(CurrentSiteProviderInterface::class);
|
||||
$siteProvider->method('get')->willReturn($this->site());
|
||||
|
||||
$allocator = $this->createStub(DsdAllocatorInterface::class);
|
||||
$allocator->method('next')->willReturn(43);
|
||||
|
||||
$processor = new WeighbridgeReadingProcessor(
|
||||
$siteProvider,
|
||||
$this->createStub(WeighbridgeReaderInterface::class),
|
||||
$allocator,
|
||||
);
|
||||
|
||||
$resource = new WeighbridgeReadingResource();
|
||||
$resource->mode = 'MANUAL';
|
||||
$resource->weight = 23187;
|
||||
$resource->manualNumber = 'PAP-555';
|
||||
$resource = new WeighbridgeReadingResource();
|
||||
$resource->mode = 'MANUAL';
|
||||
$resource->weight = 23187;
|
||||
$resource->dsd = 16619; // DSD saisi par l'operateur
|
||||
|
||||
$result = $processor->process($resource, new Post());
|
||||
|
||||
self::assertSame(23187, $result->weight, 'Le poids saisi est conserve en manuel.');
|
||||
self::assertSame(43, $result->dsd);
|
||||
self::assertSame('PAP-555', $result->manualNumber);
|
||||
self::assertSame(16619, $result->dsd, 'Le DSD saisi est conserve tel quel — pas d\'auto-increment (ERP-193).');
|
||||
self::assertSame('MANUAL', $result->mode);
|
||||
}
|
||||
|
||||
@@ -95,11 +83,7 @@ final class WeighbridgeReadingProcessorTest extends TestCase
|
||||
$reader = $this->createStub(WeighbridgeReaderInterface::class);
|
||||
$reader->method('read')->willThrowException(new WeighbridgeUnavailableException());
|
||||
|
||||
$processor = new WeighbridgeReadingProcessor(
|
||||
$siteProvider,
|
||||
$reader,
|
||||
$this->createStub(DsdAllocatorInterface::class),
|
||||
);
|
||||
$processor = new WeighbridgeReadingProcessor($siteProvider, $reader);
|
||||
|
||||
$resource = new WeighbridgeReadingResource();
|
||||
$resource->mode = 'AUTO';
|
||||
@@ -121,7 +105,6 @@ final class WeighbridgeReadingProcessorTest extends TestCase
|
||||
$processor = new WeighbridgeReadingProcessor(
|
||||
$siteProvider,
|
||||
$this->createStub(WeighbridgeReaderInterface::class),
|
||||
$this->createStub(DsdAllocatorInterface::class),
|
||||
);
|
||||
|
||||
$resource = new WeighbridgeReadingResource();
|
||||
|
||||
Reference in New Issue
Block a user