feat : M5 — Tickets de pesée (ERP-188 → ERP-193) (#144)
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:
2026-06-24 14:38:01 +00:00
committed by Autin
parent a4158d4e37
commit faafd99ef8
47 changed files with 4121 additions and 254 deletions
@@ -0,0 +1,58 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { useWeighingTicketsRepository, type WeighingTicket } from '../useWeighingTicketsRepository'
const mockApiGet = vi.hoisted(() => vi.fn())
vi.stubGlobal('useApi', () => ({ get: mockApiGet }))
/**
* Tests du repertoire des tickets de pesee (M5, ERP-188).
*
* `useWeighingTicketsRepository` est une fine enveloppe de
* `usePaginatedList<WeighingTicket>` sur `/weighing_tickets`. Les invariants
* generiques de pagination sont deja couverts par `usePaginatedList.test.ts` ;
* on verifie ici le CONTRAT propre au repertoire :
* - la ressource ciblee est bien `/weighing_tickets` ;
* - le header `Accept: application/ld+json` est envoye (sinon API Platform 4
* renvoie un tableau plat sans pagination) ;
* - DEFAUT 25 ITEMS/PAGE : la liste etant consultee en volume, le premier
* fetch demande 25 items (et non le defaut 10) — l'utilisateur peut toujours
* rebasculer via le selecteur.
*/
describe('useWeighingTicketsRepository', () => {
beforeEach(() => {
mockApiGet.mockReset()
})
/** Une page de tickets Hydra minimale. */
const PAGE: WeighingTicket[] = [
{
id: 1,
status: 'VALIDATED',
number: '86-TP-0001',
client: { id: 7, companyName: 'ACME' },
supplier: null,
otherLabel: null,
displayDate: '2026-06-17T09:12:00+02:00',
netWeight: 7150,
},
]
it('cible /weighing_tickets en Hydra avec 25 items/page par defaut', async () => {
mockApiGet.mockResolvedValueOnce({ member: PAGE, totalItems: 1 })
const repo = useWeighingTicketsRepository()
await repo.fetch()
expect(mockApiGet).toHaveBeenCalledTimes(1)
const [url, query, opts] = mockApiGet.mock.calls[0]
expect(url).toBe('/weighing_tickets')
expect(query).toMatchObject({ page: 1, itemsPerPage: 25 })
expect(opts).toMatchObject({
toast: false,
headers: { Accept: 'application/ld+json' },
})
expect(repo.itemsPerPage.value).toBe(25)
expect(repo.items.value).toEqual(PAGE)
expect(repo.totalItems.value).toBe(1)
})
})