Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Backend: Domain/Application/Infrastructure/Api layers per bounded context.
Frontend: domains/{context}/ modules with isolated components/services/stores.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
189 lines
8.8 KiB
Markdown
189 lines
8.8 KiB
Markdown
# Coltura
|
|
|
|
CRM/ERP. Monorepo Symfony 8 (API Platform 4) + Nuxt 4. **Architecture DDD (Domain-Driven Design).**
|
|
|
|
## Architecture DDD
|
|
|
|
Le projet suit une architecture DDD cote backend ET frontend. Le code est organise par **domaine metier** (Bounded Context), pas par type technique.
|
|
|
|
### Backend — Organisation par domaine
|
|
|
|
```
|
|
src/
|
|
Domain/ # Couche domaine (logique metier pure, aucune dependance framework)
|
|
{BoundedContext}/ # Ex: Customer, Sales, Catalog, Invoice...
|
|
Entity/ # Entites et Aggregates du domaine
|
|
ValueObject/ # Value Objects (Money, Address, Email...)
|
|
Repository/ # Interfaces des repositories (ports)
|
|
Service/ # Services domaine (logique metier)
|
|
Event/ # Domain Events
|
|
Exception/ # Exceptions metier
|
|
Application/ # Couche application (cas d'usage, orchestration)
|
|
{BoundedContext}/
|
|
Command/ # Commands (write) + Handlers
|
|
Query/ # Queries (read) + Handlers
|
|
DTO/ # Data Transfer Objects
|
|
Infrastructure/ # Couche infrastructure (implementations techniques)
|
|
{BoundedContext}/
|
|
Repository/ # Implementations Doctrine des repositories
|
|
Persistence/ # Mapping Doctrine (si XML/YAML)
|
|
Shared/ # Services techniques partages (mail, storage, etc.)
|
|
Api/ # Couche API (exposition HTTP)
|
|
{BoundedContext}/
|
|
Resource/ # ApiResource API Platform
|
|
State/ # Providers & Processors API Platform
|
|
```
|
|
|
|
**Regles DDD backend :**
|
|
- Le domaine (`Domain/`) ne depend de RIEN (pas de Doctrine, pas de Symfony, pas d'API Platform)
|
|
- Les repositories dans `Domain/` sont des **interfaces** ; les implementations Doctrine sont dans `Infrastructure/`
|
|
- Les entites API Platform (`Api/Resource/`) sont decouples des entites domaine si necessaire
|
|
- Chaque Bounded Context est autonome — pas d'import croise entre contextes (communiquer via events ou services application)
|
|
- `User` et `Auth` restent dans `src/` (hors DDD) car c'est du framework pur (Security Bundle)
|
|
|
|
### Frontend — Organisation par domaine
|
|
|
|
```
|
|
frontend/
|
|
domains/ # Modules metier
|
|
{bounded-context}/ # Ex: customer, sales, catalog, invoice...
|
|
components/ # Composants Vue specifiques au domaine
|
|
composables/ # Composables specifiques au domaine
|
|
services/ # Services API du domaine
|
|
dto/ # Types TypeScript du domaine
|
|
pages/ # Pages du domaine (optionnel, ou dans pages/)
|
|
stores/ # Store Pinia du domaine (si necessaire)
|
|
components/ # Composants UI partages (non lies a un domaine)
|
|
composables/ # Composables partages (useApi, useAppVersion)
|
|
stores/ # Stores globaux (auth, ui)
|
|
services/ # Services partages
|
|
```
|
|
|
|
**Regles DDD frontend :**
|
|
- Chaque domaine est un dossier autonome dans `frontend/domains/`
|
|
- Un domaine ne doit pas importer depuis un autre domaine — utiliser les composables/stores partages
|
|
- Les composants, services et types partages restent a la racine (`components/`, `composables/`, etc.)
|
|
- Les pages peuvent etre dans `frontend/pages/` (routing Nuxt) et importer les composants du domaine
|
|
|
|
## Stack
|
|
|
|
- **Backend** : PHP 8.4, Symfony 8.0, API Platform 4, Doctrine ORM, PostgreSQL 16
|
|
- **Frontend** : Nuxt 4 (SSR off / SPA), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui, nuxt-toast, @nuxtjs/i18n, @nuxt/icon
|
|
- **Auth** : JWT HTTP-only cookie (lexik/jwt-authentication-bundle), login a `/login_check`, cookie `BEARER`
|
|
- **Docker** : PHP-FPM + Node 24, Nginx (port 8083), PostgreSQL (port 5436)
|
|
|
|
## Structure
|
|
|
|
```
|
|
src/
|
|
Domain/{Context}/Entity/ # Entites domaine
|
|
Domain/{Context}/ValueObject/ # Value Objects
|
|
Domain/{Context}/Repository/ # Interfaces repositories
|
|
Domain/{Context}/Service/ # Services domaine
|
|
Domain/{Context}/Event/ # Domain Events
|
|
Application/{Context}/Command/ # Commands + Handlers
|
|
Application/{Context}/Query/ # Queries + Handlers
|
|
Application/{Context}/DTO/ # Data Transfer Objects
|
|
Infrastructure/{Context}/Repository/ # Implementations Doctrine
|
|
Api/{Context}/Resource/ # ApiResource API Platform
|
|
Api/{Context}/State/ # Providers & Processors
|
|
Entity/ # Entites framework (User)
|
|
DataFixtures/ # Fixtures
|
|
config/ # Config Symfony
|
|
config/jwt/ # Cles JWT
|
|
migrations/ # Migrations Doctrine
|
|
infra/dev/ # Docker dev
|
|
infra/prod/ # Docker prod (multi-stage)
|
|
frontend/
|
|
domains/{context}/components/ # Composants du domaine
|
|
domains/{context}/composables/ # Composables du domaine
|
|
domains/{context}/services/ # Services API du domaine
|
|
domains/{context}/dto/ # Types TS du domaine
|
|
domains/{context}/stores/ # Store Pinia du domaine
|
|
components/ # Composants UI partages
|
|
composables/ # Composables partages (useApi, useAppVersion)
|
|
stores/ # Stores globaux (auth, ui)
|
|
pages/ # Pages (routing Nuxt)
|
|
layouts/ # Layouts
|
|
i18n/locales/ # Traductions
|
|
```
|
|
|
|
## Commandes
|
|
|
|
```bash
|
|
make start # Demarrer les containers
|
|
make stop # Arreter les containers
|
|
make restart # Redemarrer les containers
|
|
make install # Install complet (composer, migrations, fixtures, build Nuxt)
|
|
make reset # Tout supprimer et reinstaller (supprime la BDD)
|
|
make dev-nuxt # Dev server Nuxt (hot reload, port 3003)
|
|
make shell # Shell dans le container PHP
|
|
make shell-root # Shell root dans le container PHP
|
|
make cache-clear # Vider le cache Symfony
|
|
make migration-migrate # Lancer les migrations
|
|
make fixtures # Charger les fixtures
|
|
make db-reset # Reset BDD + migrations + fixtures
|
|
make test # PHPUnit
|
|
make php-cs-fixer-allow-risky # Fix code style PHP
|
|
make logs-dev # Tail logs Symfony
|
|
```
|
|
|
|
## Conventions
|
|
|
|
### Commits
|
|
|
|
Format : `<type>(<scope optionnel>) : <message>` (espace avant et apres `:`)
|
|
|
|
Types autorises (minuscules) : `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`
|
|
|
|
Exemples : `feat : add login page`, `fix(auth) : prevent null token crash`
|
|
|
|
### Tags & Versioning
|
|
|
|
- La version de l'app est dans `config/version.yaml` (parametre `app.version`)
|
|
- A chaque creation de tag, **toujours** mettre a jour `config/version.yaml` avec la meme version
|
|
- Faire un commit separe de bump : `chore : bump version to v<X.Y.Z>`
|
|
- Puis creer le tag et pusher : `git tag v<X.Y.Z> && git push origin develop --tags`
|
|
|
|
### Backend
|
|
|
|
- Toujours `declare(strict_types=1)` en haut des fichiers PHP
|
|
- API Platform : utiliser ApiResource, Providers (`src/State/`), Processors — pas de controllers
|
|
- Routes API prefixees `/api` (via `config/routes/api_platform.yaml`)
|
|
- Le login (`/login_check`) est hors prefix `/api`, nginx reecrit `REQUEST_URI` vers `/login_check`
|
|
- PHP CS Fixer : regles Symfony + PSR-12 + strict types
|
|
- Roles : `ROLE_ADMIN`, `ROLE_USER` — hierarchie dans `security.yaml`
|
|
- PostgreSQL : noms de colonnes toujours en **minuscules** dans le SQL brut
|
|
- Controllers custom sous `/api/` : ajouter `priority: 1` sur `#[Route]` pour eviter le conflit avec API Platform `{id}`
|
|
- Serialization : pour embarquer une relation (pas IRI), ajouter le groupe du parent aux proprietes de l'entite cible
|
|
- Upload fichiers : utiliser `$file->getMimeType()` (pas `getClientMimeType()`) pour valider cote serveur
|
|
|
|
### Frontend
|
|
|
|
- TypeScript strict
|
|
- Composable `useApi()` pour tous les appels API (gere cookies, erreurs, toasts, i18n)
|
|
- Stores Pinia : `useAuthStore` (auth), `useUiStore` (ui)
|
|
- Middleware global `auth.global.ts` protege les routes
|
|
- Traductions dans `frontend/i18n/locales/`
|
|
- 4 espaces d'indentation
|
|
|
|
### Nginx
|
|
|
|
- `/api/*` -> Symfony (via try_files + index.php)
|
|
- `/api/login_check` -> location exact match, fastcgi direct avec REQUEST_URI reecrit en `/login_check`
|
|
- `/` -> SPA frontend (`frontend/dist/`)
|
|
|
|
## Docker
|
|
|
|
- Container PHP : `php-coltura-fpm`
|
|
- Container Nginx : `nginx-coltura`
|
|
- Container DB : PostgreSQL sur port **5436** (interne et externe)
|
|
- Config Docker dev : `infra/dev/.env.docker` (override local : `infra/dev/.env.docker.local`)
|
|
- Config Docker prod : `infra/prod/` (Dockerfile multi-stage, docker-compose.prod.yml)
|
|
- Apres modif nginx : `docker restart nginx-coltura`
|
|
|
|
## Fixtures
|
|
|
|
- User admin : `admin` / `admin` (ROLE_ADMIN)
|
|
- Users internes : `alice` / `alice`, `bob` / `bob` (ROLE_USER)
|