312c119c06
Entité WeighingTicket - Entité métier complète (#[Auditable], TimestampableBlamableTrait, relations ORM Client/Supplier/Site) + contrat de sérialisation à 3 maillons (weighing_ticket:read / :item:read + contextes par opération). - Getters calculés displayDate et plateFreeFormat (#[SerializedName]), sécurité view/manage, pas de Delete/archive. - Validation #[Assert\*] messages FR + #[Assert\Callback] RG-5.03 (->atPath()), libellé i18n audit.entity.logistique_weighingticket. - Repository : interface Domain + DoctrineWeighingTicketRepository (recherche + tri number DESC, deletedAt IS NULL). Dette site.code - Site.code mappé VARCHAR(8) (groupes read/write), dérivation auto au PrePersist (2 premiers chiffres du CP), UniqueConstraint uq_site_code. - Migration Version20260617160000 : ALTER COLUMN code SET NOT NULL + COMMENT. - Fixtures (codes 86/17/82) et SiteApiTest ajustés. Câblage - doctrine.yaml : mapping ORM du module Logistique (absent du scaffold ERP-181). - ColumnCommentsCatalog : site.code + table weighing_ticket. Specs M5 versionnées (spec-back / spec-front / prompts).
39 lines
2.6 KiB
Markdown
39 lines
2.6 KiB
Markdown
# Prompt d'implémentation — M5 · ERP-181 (1.1) — Scaffolder le module Logistique + RBAC
|
|
|
|
Projet **Starseed** (modular monolith DDD). Tâche **back**. Lis d'abord `CLAUDE.md` + `.claude/rules/architecture.md` + `.claude/rules/backend.md`, puis la spec : `docs/specs/M5-tickets-pesee/spec-back.md` (§ 2.1, § 5).
|
|
|
|
## Mission
|
|
Créer le **nouveau module `Logistique`** et poser son socle RBAC, **avant toute entité**. Aucun écran fonctionnel ici, juste le squelette + permissions + sidebar + 3 miroirs RBAC.
|
|
|
|
## Étapes
|
|
1. Scaffolder via le skill projet **`create-module`** : `src/Module/Logistique/` avec `Domain/ Application/ Infrastructure/` et `LogistiqueModule.php` :
|
|
- `const string ID = 'logistique'` ; `const string LABEL = 'Logistique'` ; `const bool REQUIRED = false`.
|
|
- `permissions()` retourne :
|
|
- `['code' => 'logistique.weighing_tickets.view', 'label' => 'Voir les tickets de pesée']`
|
|
- `['code' => 'logistique.weighing_tickets.manage', 'label' => 'Créer / modifier les tickets de pesée']`
|
|
2. Enregistrer `LogistiqueModule::class` dans `config/modules.php`.
|
|
3. Créer le layer front minimal `frontend/modules/logistique/nuxt.config.ts` (kebab-case, auto-détecté).
|
|
4. Ajouter à `config/sidebar.php` une section/item « Logistique » :
|
|
```php
|
|
['label' => 'sidebar.logistique.weighing_tickets', 'to' => '/weighing-tickets',
|
|
'icon' => 'mdi-scale', 'module' => 'logistique', 'permission' => 'logistique.weighing_tickets.view'],
|
|
```
|
|
+ la clé i18n `sidebar.logistique.*` dans `frontend/i18n/locales/fr.json`.
|
|
5. **Règle ABSOLUE n°8 — 3 miroirs RBAC alignés ensemble** :
|
|
- `config/sidebar.php` (item + permission ci-dessus),
|
|
- `frontend/tests/e2e/_fixtures/personas.ts` (persona **Usine** gagne `weighing_tickets.view` + `manage` et `expectedAdminLinks` ; **Compta/Commerciale** : aucun accès),
|
|
- `src/Module/Core/Infrastructure/Console/SeedE2ECommand.php` (miroir back du même persona).
|
|
6. `make shell` → `php bin/console app:sync-permissions`.
|
|
|
|
## Garde-fous (règles ABSOLUES)
|
|
- `declare(strict_types=1);` partout ; commentaires **en français**, code en anglais.
|
|
- Permission au format `module.resource.action` snake_case.
|
|
- Ne PAS créer d'entité ni de migration ici (ticket 1.2).
|
|
- Pas de hardcode sidebar côté front : elle vient de `/api/sidebar`.
|
|
|
|
## Vérification
|
|
- `make test` (les tests Architecture ne cassent pas).
|
|
- `make php-cs-fixer-allow-risky`.
|
|
- `GET /api/modules` retourne `logistique` ; `GET /api/sidebar` : item présent pour Admin/Bureau/Usine, **absent** pour Compta/Commerciale.
|
|
- Les 3 miroirs RBAC sont cohérents (sinon test E2E faux positif).
|