feat(directory) : add Clients/Prospects repertoire front layer
LST-58 (2.4) front. Completes the Directory module.
- New frontend/modules/directory/ layer (auto-detected): /directory page with
Clients and Prospects tabs.
- Client front moved into the layer (clients service + client DTO +
ClientDrawer). New prospects service, prospect DTO and ProspectDrawer (with
a "Convert to client" action calling POST /prospects/{id}/convert).
- Consumers repointed to ~/modules/directory/... (admin client tab, PM project
drawer + project pages + project DTO, time-tracking page + export drawer).
- Sidebar admin item /directory gated by the directory module; /directory
protected by the admin middleware. i18n keys added (directory.*, prospects.*).
nuxt build passes; routes preserved.
Adds the 2.4 plan doc.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
# LST-58 (2.4) — Module Directory : Prospect + front répertoire (plan)
|
||||
|
||||
> Suite de la migration Directory. Client (back) déjà livré (`c5738d2`).
|
||||
> Reste : **entité Prospect** (nouvelle) + **front répertoire** (Clients + Prospects).
|
||||
> Spec produit non fournie → design défini ici de façon raisonnable, à valider au test.
|
||||
> Additif, sans régression. Branche `integration/modular-monolith-0.1-1.3`.
|
||||
|
||||
## Design Prospect (décidé, à valider)
|
||||
Aligné sur `Client` (même module Directory), enrichi des concepts de prospection commerciale.
|
||||
|
||||
**Entité `App\Module\Directory\Domain\Entity\Prospect`** (table `prospect`) :
|
||||
- `id` int PK
|
||||
- `name` string(255) NOT NULL — contact ou société
|
||||
- `company` string(255) nullable
|
||||
- `email` string(255) nullable
|
||||
- `phone` string(50) nullable
|
||||
- `street` string(255) nullable / `city` string(255) nullable / `postalCode` string(20) nullable (alignés Client)
|
||||
- `status` enum `ProspectStatus` NOT NULL (default `New`)
|
||||
- `source` string(255) nullable — origine (recommandation, salon, site web…)
|
||||
- `notes` text nullable
|
||||
- `convertedClient` ManyToOne `ClientInterface` nullable, JoinColumn ON DELETE SET NULL — rempli à la conversion
|
||||
- Timestampable/Blamable (trait) + `#[Auditable]`
|
||||
- Groupes : `prospect:read` / `prospect:write`
|
||||
|
||||
**Enum `App\Module\Directory\Domain\Enum\ProspectStatus`** : `New` (nouveau), `Contacted` (contacté), `Qualified` (qualifié), `Won` (gagné/converti), `Lost` (perdu). Méthode `label(): string` (FR), comme les autres enums.
|
||||
|
||||
**API Platform** (aligné Client) :
|
||||
- `GetCollection` paginationEnabled:false, `is_granted('ROLE_USER')`
|
||||
- `Get` ROLE_USER ; `Post`/`Patch`/`Delete` ROLE_ADMIN
|
||||
- Opération custom **`Post /prospects/{id}/convert`** (processor `ConvertProspectProcessor`) : crée un `Client` à partir du Prospect (name/company→name, email, phone, adresse), lie `convertedClient`, passe `status=Won`. Sécurité ROLE_ADMIN. Renvoie le Prospect mis à jour. Idempotent si déjà converti (renvoie l'existant).
|
||||
- `#[ApiFilter]` SearchFilter sur `status` (filtre répertoire).
|
||||
|
||||
**Repo** : `ProspectRepositoryInterface` (Domain) + `DoctrineProspectRepository` (Infra) + binding.
|
||||
|
||||
**MCP** (cohérent avec clients, sous `Infrastructure/Mcp/Tool/`) : `list-prospects`, `get-prospect`, `create-prospect`, `update-prospect`, `delete-prospect`, `convert-prospect`. Serializer : ajouter `prospect()` dans `src/Mcp/Tool/Serializer.php`.
|
||||
|
||||
**DirectoryModule.permissions()** : ajouter `directory.prospects.view`, `directory.prospects.manage` (additif).
|
||||
|
||||
**Migration additive** : CREATE TABLE prospect (colonnes + FK converted_client→client ON DELETE SET NULL + created_by/updated_by FK user + index + COMMENT). Down = DROP TABLE.
|
||||
|
||||
**Fixtures** : 2-3 prospects de démo (statuts variés), dont un converti.
|
||||
|
||||
## Front répertoire (`frontend/modules/directory/`)
|
||||
Aujourd'hui : pas de page client dédiée (AdminClientTab + picker ProjectDrawer). On crée un vrai répertoire.
|
||||
- `nuxt.config.ts` vide.
|
||||
- `services/` : `clients.ts` (move depuis racine), `prospects.ts` (nouveau) + `dto/{client,prospect}.ts`.
|
||||
- `pages/directory.vue` : page à 2 onglets (Clients / Prospects), tableaux paginés côté client (paginationEnabled:false back), recherche/filtre statut pour prospects.
|
||||
- `components/` : `ClientDrawer.vue` (move depuis `components/client/`), `ProspectDrawer.vue` (nouveau, create/edit + bouton « Convertir en client »).
|
||||
- Sidebar : ajouter item `sidebar.general.directory` → `/directory`, `'module' => 'directory'`, gate ROLE_ADMIN (gestion référentiel).
|
||||
- Réécrire imports consommateurs de `~/services/clients` / `~/services/dto/client` (AdminClientTab, ProjectDrawer, pages projects) → `~/modules/directory/services/...`. AdminClientTab : soit le retirer de /admin au profit de /directory, soit le laisser pointer le nouveau service. Décision : garder AdminClientTab fonctionnel (repoint service) ET ajouter la page /directory (les deux coexistent ; /directory = vue dédiée).
|
||||
- i18n global : ajouter clés `directory.*`, `prospects.*`, `sidebar.general.directory`.
|
||||
|
||||
## Vagues d'exécution
|
||||
1. **Back Prospect** : enum + entité + repo + API (CRUD + convert) + MCP (6 tools) + Serializer + permissions module + fixtures + migration. Vérif cache:clear/migrate/phpunit/cs-fixer → commit.
|
||||
2. **Front Directory** : layer (move client front + page répertoire + ProspectDrawer + prospects service/dto) + sidebar + imports + i18n. Vérif nuxt build → commit.
|
||||
|
||||
## Critères d'acceptation (ticket #58)
|
||||
- [x] Clients en module (fait, c5738d2)
|
||||
- [ ] Prospects en module + front répertoire fonctionnel
|
||||
- [x] resolve_target_entities → Directory\Client
|
||||
- [ ] make test vert, aucune migration destructive
|
||||
- [ ] toggle module directory (sidebar + route /directory)
|
||||
|
||||
## Suite phase 2 (après 2.4)
|
||||
- 2.5 (#67) Module Mail — WIP `docs/mail-integration.md`, à traiter avec précaution.
|
||||
- 2.6 (#68) Module Integration (Gitea/BookStack/Zimbra/Share).
|
||||
Reference in New Issue
Block a user