Compare commits
10 Commits
fca3104a39
...
1a751927fa
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a751927fa | |||
| 987aa5c15f | |||
| d2a1cd0cc4 | |||
| 5222a6bbf9 | |||
| 15e0b23f15 | |||
| fab1d25871 | |||
| 037ed782a7 | |||
| de8b05a553 | |||
| 6f9e1ec626 | |||
| 8430e9baef |
6
.env
6
.env
@@ -39,3 +39,9 @@ DEFAULT_URI=http://localhost
|
||||
###> nelmio/cors-bundle ###
|
||||
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
||||
###< nelmio/cors-bundle ###
|
||||
|
||||
###> lexik/jwt-authentication-bundle ###
|
||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
JWT_PASSPHRASE=281e2cd303ed9ba4a4a4074e19eac9cea505cc9d82ce79a448bb8eb00c636ebe
|
||||
###< lexik/jwt-authentication-bundle ###
|
||||
|
||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -23,3 +23,18 @@
|
||||
###> docker ###
|
||||
docker/.env.docker.local
|
||||
###< docker ###
|
||||
|
||||
###> lexik/jwt-authentication-bundle ###
|
||||
/config/jwt/*.pem
|
||||
###< lexik/jwt-authentication-bundle ###
|
||||
|
||||
###> migration archives ###
|
||||
/_archives/
|
||||
###< migration archives ###
|
||||
|
||||
###> frontend ###
|
||||
/frontend/node_modules/
|
||||
/frontend/.nuxt/
|
||||
/frontend/.output/
|
||||
/frontend/dist/
|
||||
###< frontend ###
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "Inventory_frontend"]
|
||||
path = Inventory_frontend
|
||||
url = gitea@gitea.malio.fr:MALIO-DEV/Inventory_frontend.git
|
||||
416
CARNET_DE_BORD.md
Normal file
416
CARNET_DE_BORD.md
Normal file
@@ -0,0 +1,416 @@
|
||||
# 📔 Carnet de Bord - Migration Inventory → Symfony
|
||||
|
||||
**Projet** : Migration backend NestJS/Prisma → Symfony/API Platform
|
||||
**Début** : 2026-01-10
|
||||
**Objectif** : Migrer vers Symfony + JWT + API Platform propre et maintenable
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Convention de liaison des commits (INV)
|
||||
|
||||
- **Format** : `[INV-YYYYMMDD-XX]`
|
||||
- **Usage** : même code dans les commits du backend **et** du frontend + ajout ici pour retrouver le duo rapidement.
|
||||
|
||||
## 🧾 Journal des liaisons INV
|
||||
|
||||
- INV-20260111-01 : ajout du lien submodule `Inventory_frontend` (commit backend : `987aa5c`, commit frontend : `936a73f`)
|
||||
|
||||
## 🎯 Contexte
|
||||
|
||||
- **Situation initiale** :
|
||||
- `Inventory_backend/` : NestJS + Prisma (fonctionnel, ~11k lignes)
|
||||
- `Inventory_frontend/` : Nuxt 3 (fonctionnel, 105 fichiers)
|
||||
- Base de données PostgreSQL avec données en production
|
||||
|
||||
- **Objectif** :
|
||||
- Backend Symfony 8 + API Platform + JWT
|
||||
- Garder les données existantes (migration Prisma → Doctrine)
|
||||
- Frontend Nuxt connecté au nouveau backend
|
||||
- Docker : 2 backends en parallèle pendant transition
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 1 : Préparation (TERMINÉE - 10/01/2026)
|
||||
|
||||
### Ce qui a été fait
|
||||
|
||||
#### 1. Docker & Infrastructure ✅
|
||||
- **pgAdmin ajouté** au docker-compose.yml
|
||||
- Port : 5050
|
||||
- Login : admin@admin.com / admin
|
||||
- Container : `pgadmin-inventory`
|
||||
- Volume persistant : `pgadmin_data`
|
||||
- **Serveur PostgreSQL pré-configuré** :
|
||||
- Fichier `docker/pgadmin/servers.json` monté automatiquement
|
||||
- Fichier `docker/pgadmin/pgpass` pour authentification sans mot de passe
|
||||
- Connexion automatique à `db:5432/inventory` au démarrage
|
||||
- Nom du serveur : "Inventory PostgreSQL"
|
||||
|
||||
#### 2. Bundles Symfony installés ✅
|
||||
```bash
|
||||
# Versions installées
|
||||
- lexik/jwt-authentication-bundle: v3.2.0
|
||||
- vich/uploader-bundle: v2.9.1
|
||||
- symfony/uid: 8.0.*
|
||||
```
|
||||
|
||||
#### 3. JWT Configuration ✅
|
||||
- **Clés RSA générées** : `config/jwt/private.pem` + `public.pem`
|
||||
- **security.yaml configuré** :
|
||||
- Firewall `login` : pattern `^/api/login_check` avec `json_login`
|
||||
- Firewall `api` : pattern `^/api` avec `jwt` authenticator
|
||||
- Provider : `app_user_provider` (entité Profile via email)
|
||||
- Password hasher : bcrypt auto
|
||||
|
||||
#### 4. Entité Profile créée ✅
|
||||
**Fichier** : `src/Entity/Profile.php`
|
||||
|
||||
**Caractéristiques** :
|
||||
- Implémente `UserInterface` + `PasswordAuthenticatedUserInterface`
|
||||
- Champs :
|
||||
- `id` : string (30 chars, CUID-compatible pour Prisma)
|
||||
- `email` : string unique (username pour JWT)
|
||||
- `password` : string (hashed)
|
||||
- `roles` : array JSON (ROLE_USER par défaut)
|
||||
- `firstName`, `lastName` : string
|
||||
- `isActive` : boolean
|
||||
- `createdAt`, `updatedAt` : DateTimeImmutable
|
||||
- Repository : `ProfileRepository` avec `PasswordUpgraderInterface`
|
||||
- API Platform : endpoints CRUD auto-générés
|
||||
|
||||
#### 5. Base de Données ✅
|
||||
- **Migration créée** : `Version20260110175413`
|
||||
- **Table** : `profiles` créée avec succès
|
||||
- **Utilisateur test créé** :
|
||||
```
|
||||
Email: admin@admin.com
|
||||
Password: admin123
|
||||
Roles: ['ROLE_USER', 'ROLE_ADMIN']
|
||||
```
|
||||
|
||||
#### 6. API Platform ✅
|
||||
- **Endpoint racine** : http://localhost:8081/api/
|
||||
- **Réponse** :
|
||||
```json
|
||||
{
|
||||
"@context": "/api/contexts/Entrypoint",
|
||||
"@id": "/api/",
|
||||
"@type": "Entrypoint",
|
||||
"profile": "/api/profiles"
|
||||
}
|
||||
```
|
||||
- **OpenAPI Docs** : Configurées (à tester)
|
||||
|
||||
#### 7. Configuration Apache ✅
|
||||
- **VirtualHost** : `docker/php/config/vhost.conf`
|
||||
- **DocumentRoot** : `/var/www/html/public`
|
||||
- **AllowOverride** : All (pour `.htaccess`)
|
||||
- **Port** : 8081 (Apache) → accessible depuis l'hôte
|
||||
|
||||
#### 8. Routing Symfony ✅
|
||||
- **Routes définies** :
|
||||
- `/api/login_check` : Login JWT
|
||||
- `/api/test` : Test endpoint (TestController)
|
||||
- `/api/*` : API Platform auto-routes
|
||||
- **Vérification** :
|
||||
```bash
|
||||
php bin/console debug:router api_test
|
||||
php bin/console router:match /api/test --method=GET
|
||||
# ✅ Route found and matches
|
||||
```
|
||||
|
||||
#### 9. .htaccess créé ✅
|
||||
**Fichier** : `public/.htaccess`
|
||||
|
||||
**Contenu** : Symfony standard avec mod_rewrite
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Problèmes identifiés
|
||||
|
||||
#### 1. Routes inaccessibles via Apache (404)
|
||||
|
||||
**Symptôme** :
|
||||
```bash
|
||||
curl http://localhost:8081/api/test
|
||||
# → 404 Not Found
|
||||
```
|
||||
|
||||
**Tests effectués** :
|
||||
- ✅ Route existe : `php bin/console debug:router api_test`
|
||||
- ✅ Route match : `php bin/console router:match /api/test`
|
||||
- ✅ Symfony fonctionne : `curl http://localhost:8081/api/` → JSON OK
|
||||
- ✅ PHP built-in server OK :
|
||||
```bash
|
||||
php -S localhost:9000
|
||||
curl http://localhost:9000/api/test
|
||||
# → {"status":"ok","message":"Test endpoint works!"}
|
||||
```
|
||||
- ❌ Apache 404 : Depuis l'hôte via port 8081
|
||||
|
||||
**Diagnostic** :
|
||||
- Le problème est **Apache-spécifique**
|
||||
- Symfony/PHP fonctionnent correctement
|
||||
- Le `.htaccess` n'est probablement **PAS lu par Apache**
|
||||
- Hypothèses :
|
||||
1. `AllowOverride All` non pris en compte
|
||||
2. `mod_rewrite` mal configuré
|
||||
3. Ordre des directives Apache incorrect
|
||||
4. Problème de permissions sur `.htaccess`
|
||||
|
||||
**Actions à faire** :
|
||||
- [ ] Vérifier permissions `.htaccess` dans container
|
||||
- [ ] Tester `apache2ctl configtest`
|
||||
- [ ] Activer logs de rewrite : `LogLevel alert rewrite:trace3`
|
||||
- [ ] Tester FallbackResource dans vhost au lieu de `.htaccess`
|
||||
|
||||
#### 2. JWT Login non testé
|
||||
|
||||
**Raison** : Bloqué par problème #1 (routes inaccessibles)
|
||||
|
||||
**Actions à faire** :
|
||||
- [ ] Résoudre problème Apache
|
||||
- [ ] Tester `POST /api/login_check` avec credentials
|
||||
- [ ] Vérifier génération du token JWT
|
||||
- [ ] Tester route protégée avec token
|
||||
|
||||
---
|
||||
|
||||
## 📝 Configuration Actuelle
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
ports:
|
||||
- "8081:80" # Symfony API
|
||||
- "3001:3000" # (prévu pour Nuxt)
|
||||
|
||||
db:
|
||||
ports:
|
||||
- "5433:5432" # PostgreSQL
|
||||
|
||||
pgadmin:
|
||||
ports:
|
||||
- "5050:80" # pgAdmin
|
||||
```
|
||||
|
||||
### Variables d'Environnement
|
||||
|
||||
**Fichier** : `docker/.env.docker.local`
|
||||
|
||||
```env
|
||||
# PostgreSQL
|
||||
POSTGRES_DB=inventory
|
||||
POSTGRES_USER=root
|
||||
POSTGRES_PASSWORD=root
|
||||
POSTGRES_PORT=5433
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 2 : Migration DB + Frontend (TERMINÉE - 10/01/2026)
|
||||
|
||||
### Ce qui a été fait
|
||||
|
||||
#### 1. Entités Doctrine alignées Prisma ✅
|
||||
- **Toutes les entités manquantes** créées (Machine, ModelType, Composant, Piece, Product, Links, Requirements, CustomField, Document, etc.)
|
||||
- **IDs en string(36)** pour compatibilité CUID/UUID
|
||||
- **Colonnes Prisma en camelCase** conservées via `name="..."` (ex: `machineId`, `createdAt`, `supplierPrice`)
|
||||
- **Corrections** :
|
||||
- `Document.path` passé en `TEXT`
|
||||
- `CustomField.options` nullable
|
||||
- `TypeMachineComponentRequirement.required` corrigé
|
||||
|
||||
#### 2. Migration DB inventory-data → inventory ✅
|
||||
- **Dump data-only + normalisation** (conversion des identifiants quoted vers lowercase)
|
||||
- **Mapping table Prisma** : `"ModelType"` → `model_types`
|
||||
- **Exclusions** : `profiles`, `_prisma_migrations`
|
||||
- **Import validé** : `Counts match for all tables.`
|
||||
|
||||
Scripts utiles :
|
||||
```bash
|
||||
scripts/normalize-dump.py
|
||||
scripts/validate-migration.php
|
||||
```
|
||||
|
||||
#### 3. Frontend basculé sur Inventory_frontend ✅
|
||||
- `make dev-nuxt` pointe vers `Inventory_frontend/`
|
||||
- `README.md` mis à jour
|
||||
- **Base API** ajustée : `http://localhost:8081/api`
|
||||
|
||||
Fichiers modifiés :
|
||||
```
|
||||
makefile
|
||||
README.md
|
||||
Inventory_frontend/.env
|
||||
Inventory_frontend/nuxt.config.ts
|
||||
Inventory_frontend/app/services/modelTypes.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# pgAdmin
|
||||
PGADMIN_EMAIL=admin@admin.com
|
||||
PGADMIN_PASSWORD=admin
|
||||
PGADMIN_PORT=5050
|
||||
|
||||
# Symfony
|
||||
APP_ENV=dev
|
||||
APP_SECRET=changeme_super_secret_key_123456789
|
||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
JWT_PASSPHRASE=your_jwt_passphrase_change_me
|
||||
|
||||
# NestJS (pour futur parallèle)
|
||||
NESTJS_PORT=3000
|
||||
SESSION_SECRET=changeme_session_secret
|
||||
CORS_ORIGIN=http://localhost:3001
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚧 Phase 2 : Debugging & Tests (EN COURS)
|
||||
|
||||
### Objectifs
|
||||
- [x] Résoudre problème Apache `.htaccess`
|
||||
- [ ] Tester authentification JWT complète
|
||||
- [ ] Créer endpoint de test public fonctionnel
|
||||
- [ ] Documenter la solution Apache
|
||||
|
||||
### Prochaines étapes
|
||||
1. **Fix Apache** : Logs de debug + test FallbackResource
|
||||
2. **Test JWT** : Login + génération token + route protégée
|
||||
3. **Documentation** : Documenter la config Apache qui fonctionne
|
||||
|
||||
---
|
||||
|
||||
## 📊 Métriques
|
||||
|
||||
### Temps passé
|
||||
- **Phase 1** : ~3h (exploration + setup + debugging)
|
||||
- **Problème Apache** : ~1h30 (en cours)
|
||||
|
||||
### Fichiers créés/modifiés
|
||||
|
||||
**Nouveaux fichiers** :
|
||||
- `src/Entity/Profile.php`
|
||||
- `src/Repository/ProfileRepository.php`
|
||||
- `src/Controller/TestController.php`
|
||||
- `public/.htaccess`
|
||||
- `config/routes/routing.controllers.yaml`
|
||||
- `create_test_user.php` (script utilitaire)
|
||||
- `migrations/Version20260110175413.php`
|
||||
- `docker/pgadmin/servers.json` (config serveur PostgreSQL)
|
||||
- `docker/pgadmin/pgpass` (credentials PostgreSQL)
|
||||
- `CARNET_DE_BORD.md` (ce fichier)
|
||||
|
||||
**Fichiers modifiés** :
|
||||
- `docker-compose.yml` (+ pgAdmin)
|
||||
- `docker/.env.docker.local` (+ variables Symfony/JWT/pgAdmin)
|
||||
- `docker/php/config/vhost.conf` (DocumentRoot → public/)
|
||||
- `config/packages/security.yaml` (JWT firewalls)
|
||||
- `config/routes.yaml` (+ api_login_check)
|
||||
- `composer.json` (+ lexik JWT, vich uploader)
|
||||
|
||||
---
|
||||
|
||||
## 🎓 Leçons Apprises
|
||||
|
||||
### 1. Symfony 8 + API Platform
|
||||
- **Attributs PHP 8** : `use Symfony\Component\Routing\Attribute\Route;` (pas `Annotation`)
|
||||
- **Routes controllers** : Nécessite `config/routes/routing.controllers.yaml` avec `type: attribute`
|
||||
- **API Platform** : Auto-génère les endpoints CRUD avec `#[ApiResource]`
|
||||
|
||||
### 2. JWT Authentication
|
||||
- **3 composants** :
|
||||
1. Firewall `login` : `json_login` intercepte `/api/login_check`
|
||||
2. Firewall `api` : `jwt` vérifie le token sur `/api/*`
|
||||
3. Access control : `PUBLIC_ACCESS` vs `IS_AUTHENTICATED_FULLY`
|
||||
- **username_path** : Permet de mapper `email` au lieu de `username`
|
||||
- **Provider** : Doit être défini dans le firewall `login`
|
||||
|
||||
### 3. Doctrine Migrations
|
||||
- **ID Prisma CUID** : Garder en `string(30)` pour compatibilité
|
||||
- **Lifecycle callbacks** : `#[ORM\PrePersist]` pour `createdAt`/`updatedAt`
|
||||
- **UserInterface** : Nécessite `getUserIdentifier()`, `getRoles()`, `eraseCredentials()`
|
||||
|
||||
### 4. Docker & Apache
|
||||
- **`.htaccess` vs VirtualHost** : Le vhost peut override le `.htaccess`
|
||||
- **AllowOverride All** : Indispensable pour que `.htaccess` fonctionne
|
||||
- **FallbackResource** : Alternative au mod_rewrite dans `.htaccess`
|
||||
- **Debugging** : Tester avec PHP built-in server pour isoler le problème
|
||||
|
||||
---
|
||||
|
||||
## 📚 Ressources Utiles
|
||||
|
||||
### Accès aux Services
|
||||
|
||||
```
|
||||
🌐 pgAdmin: http://localhost:5050
|
||||
└─ Login: admin@admin.com / admin
|
||||
└─ Serveur: "Inventory PostgreSQL" (pré-configuré)
|
||||
└─ Database: inventory
|
||||
└─ Note: Le serveur PostgreSQL est automatiquement connecté au démarrage
|
||||
|
||||
🌐 API Platform: http://localhost:8081/api/
|
||||
└─ Docs: http://localhost:8081/api/docs (à venir)
|
||||
|
||||
🗄️ PostgreSQL: localhost:5433
|
||||
└─ User: root / root
|
||||
└─ Database: inventory
|
||||
```
|
||||
|
||||
### Commandes fréquentes
|
||||
|
||||
```bash
|
||||
# Symfony
|
||||
make shell # Entrer dans le container
|
||||
php bin/console cache:clear # Clear cache
|
||||
php bin/console debug:router # Lister routes
|
||||
php bin/console debug:firewall # Lister firewalls
|
||||
php bin/console doctrine:migrations:migrate # Exécuter migrations
|
||||
|
||||
# Docker
|
||||
make start # Démarrer containers
|
||||
make stop # Arrêter containers
|
||||
docker logs -f php-inventory-apache # Logs Apache
|
||||
docker logs -f pgadmin-inventory # Logs pgAdmin
|
||||
docker exec php-inventory-apache bash # Shell root
|
||||
|
||||
# Tests API
|
||||
curl http://localhost:8081/api/ # Test API Platform
|
||||
curl -X POST http://localhost:8081/api/login_check \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"admin@admin.com","password":"admin123"}'
|
||||
```
|
||||
|
||||
### Documentation
|
||||
- [Lexik JWT Bundle](https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/Resources/doc/index.rst)
|
||||
- [API Platform Security](https://api-platform.com/docs/core/security/)
|
||||
- [Symfony Security](https://symfony.com/doc/current/security.html)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Historique des Changements
|
||||
|
||||
### 2026-01-10 - Session 2 (20h30)
|
||||
- ✅ Problème Apache résolu (routes fonctionnelles)
|
||||
- ✅ Phase 2 complète (JWT 100% opérationnel)
|
||||
- ✅ Authentification testée avec succès
|
||||
- ✅ Réorganisation projet (frontend/ + _archives/)
|
||||
- ✅ État des lieux dans MIGRATION_PLAN.md
|
||||
- ✅ 5 commits conventionnels créés
|
||||
- 📊 Base inventory-data analysée (673 lignes)
|
||||
|
||||
### 2026-01-10 - Session 1 (19h00)
|
||||
- ✅ Création projet migration
|
||||
- ✅ Phase 1 complète (pgAdmin, JWT, Profile, migrations)
|
||||
- ⚠️ Problème Apache identifié (routes 404)
|
||||
- 📝 Carnet de bord créé
|
||||
|
||||
---
|
||||
|
||||
**Dernière mise à jour** : 2026-01-10 20:40
|
||||
**Statut** : Phase 2 TERMINÉE ✅ - Prêt pour Phase 3 (Création entités)
|
||||
1
Inventory_frontend
Submodule
1
Inventory_frontend
Submodule
Submodule Inventory_frontend added at 936a73fde3
1418
MIGRATION_PLAN.md
Normal file
1418
MIGRATION_PLAN.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@ Vous pouvez modifier le port si nécessaire.
|
||||
La bdd est déja pré-configuré dans PhpStorm, il suffit de rentrer les infos du .env.docker.local pour se connecter.
|
||||
C'est un bdd local dans le docker.
|
||||
### Frontend
|
||||
Le frontend utilise le dossier `Inventory_frontend/`.
|
||||
Pour le frontend, il suffit de taper la commande suivante qui va lancer le serveur de dev
|
||||
```bash
|
||||
make dev-nuxt
|
||||
|
||||
2
TODO.md
Normal file
2
TODO.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- Doc: ne pas oublier de mettre `make` dans la documentation.
|
||||
- Note: le probleme d'IP sous WSL, a ajouter dans la doc.
|
||||
@@ -12,6 +12,7 @@
|
||||
"doctrine/doctrine-bundle": "^3.2",
|
||||
"doctrine/doctrine-migrations-bundle": "^4.0",
|
||||
"doctrine/orm": "^3.6",
|
||||
"lexik/jwt-authentication-bundle": "^3.2",
|
||||
"nelmio/cors-bundle": "^2.6",
|
||||
"phpdocumentor/reflection-docblock": "^5.6",
|
||||
"phpstan/phpdoc-parser": "^2.3",
|
||||
@@ -27,8 +28,10 @@
|
||||
"symfony/security-bundle": "8.0.*",
|
||||
"symfony/serializer": "8.0.*",
|
||||
"symfony/twig-bundle": "8.0.*",
|
||||
"symfony/uid": "8.0.*",
|
||||
"symfony/validator": "8.0.*",
|
||||
"symfony/yaml": "8.0.*"
|
||||
"symfony/yaml": "8.0.*",
|
||||
"vich/uploader-bundle": "^2.9"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
|
||||
540
composer.lock
generated
540
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "bab4560dec1d36eec0b0aa2284bd8559",
|
||||
"content-hash": "9e0e35659f9b6ef5c0a60262a36b61f2",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/doctrine-common",
|
||||
@@ -2361,6 +2361,259 @@
|
||||
},
|
||||
"time": "2025-10-26T09:35:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jms/metadata",
|
||||
"version": "2.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/schmittjoh/metadata.git",
|
||||
"reference": "554319d2e5f0c5d8ccaeffe755eac924e14da330"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/schmittjoh/metadata/zipball/554319d2e5f0c5d8ccaeffe755eac924e14da330",
|
||||
"reference": "554319d2e5f0c5d8ccaeffe755eac924e14da330",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "^1.0|^2.0",
|
||||
"doctrine/coding-standard": "^8.0",
|
||||
"mikey179/vfsstream": "^1.6.7",
|
||||
"phpunit/phpunit": "^8.5.42|^9.6.23",
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/cache": "^3.1|^4.0|^5.0|^6.0|^7.0|^8.0",
|
||||
"symfony/dependency-injection": "^3.1|^4.0|^5.0|^6.0|^7.0|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Metadata\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Johannes M. Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Class/method/property metadata management in PHP",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"metadata",
|
||||
"xml",
|
||||
"yaml"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/schmittjoh/metadata/issues",
|
||||
"source": "https://github.com/schmittjoh/metadata/tree/2.9.0"
|
||||
},
|
||||
"time": "2025-11-30T20:12:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "5.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lcobucci/jwt.git",
|
||||
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/bb3e9f21e4196e8afc41def81ef649c164bca25e",
|
||||
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-sodium": "*",
|
||||
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
|
||||
"psr/clock": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.29",
|
||||
"lcobucci/clock": "^3.2",
|
||||
"lcobucci/coding-standard": "^11.0",
|
||||
"phpbench/phpbench": "^1.2",
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan": "^1.10.7",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1.3",
|
||||
"phpstan/phpstan-phpunit": "^1.3.10",
|
||||
"phpstan/phpstan-strict-rules": "^1.5.0",
|
||||
"phpunit/phpunit": "^11.1"
|
||||
},
|
||||
"suggest": {
|
||||
"lcobucci/clock": ">= 3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lcobucci\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Luís Cobucci",
|
||||
"email": "lcobucci@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
|
||||
"keywords": [
|
||||
"JWS",
|
||||
"jwt"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/lcobucci/jwt/issues",
|
||||
"source": "https://github.com/lcobucci/jwt/tree/5.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/lcobucci",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/lcobucci",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2025-10-17T11:30:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lexik/jwt-authentication-bundle",
|
||||
"version": "v3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lexik/LexikJWTAuthenticationBundle.git",
|
||||
"reference": "60df75dc70ee6f597929cb2f0812adda591dfa4b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lexik/LexikJWTAuthenticationBundle/zipball/60df75dc70ee6f597929cb2f0812adda591dfa4b",
|
||||
"reference": "60df75dc70ee6f597929cb2f0812adda591dfa4b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"lcobucci/jwt": "^5.0",
|
||||
"php": ">=8.2",
|
||||
"symfony/clock": "^6.4|^7.0|^8.0",
|
||||
"symfony/config": "^6.4|^7.0|^8.0",
|
||||
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||
"symfony/deprecation-contracts": "^2.4|^3.0",
|
||||
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||
"symfony/http-foundation": "^6.4|^7.0|^8.0",
|
||||
"symfony/http-kernel": "^6.4|^7.0|^8.0",
|
||||
"symfony/property-access": "^6.4|^7.0|^8.0",
|
||||
"symfony/security-bundle": "^6.4|^7.0|^8.0",
|
||||
"symfony/translation-contracts": "^1.0|^2.0|^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"api-platform/core": "^3.0|^4.0",
|
||||
"rector/rector": "^1.2",
|
||||
"symfony/browser-kit": "^6.4|^7.0|^8.0",
|
||||
"symfony/console": "^6.4|^7.0|^8.0",
|
||||
"symfony/dom-crawler": "^6.4|^7.0|^8.0",
|
||||
"symfony/filesystem": "^6.4|^7.0|^8.0",
|
||||
"symfony/framework-bundle": "^6.4|^7.0|^8.0",
|
||||
"symfony/phpunit-bridge": "^6.4|^7.0|^8.0",
|
||||
"symfony/var-dumper": "^6.4|^7.0|^8.0",
|
||||
"symfony/yaml": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"gesdinet/jwt-refresh-token-bundle": "Implements a refresh token system over Json Web Tokens in Symfony",
|
||||
"spomky-labs/lexik-jose-bridge": "Provides a JWT Token encoder with encryption support"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lexik\\Bundle\\JWTAuthenticationBundle\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeremy Barthe",
|
||||
"email": "j.barthe@lexik.fr",
|
||||
"homepage": "https://github.com/jeremyb"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Cabot",
|
||||
"email": "n.cabot@lexik.fr",
|
||||
"homepage": "https://github.com/slashfan"
|
||||
},
|
||||
{
|
||||
"name": "Cedric Girard",
|
||||
"email": "c.girard@lexik.fr",
|
||||
"homepage": "https://github.com/cedric-g"
|
||||
},
|
||||
{
|
||||
"name": "Dev Lexik",
|
||||
"email": "dev@lexik.fr",
|
||||
"homepage": "https://github.com/lexik"
|
||||
},
|
||||
{
|
||||
"name": "Robin Chalas",
|
||||
"email": "robin.chalas@gmail.com",
|
||||
"homepage": "https://github.com/chalasr"
|
||||
},
|
||||
{
|
||||
"name": "Lexik Community",
|
||||
"homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "This bundle provides JWT authentication for your Symfony REST API",
|
||||
"homepage": "https://github.com/lexik/LexikJWTAuthenticationBundle",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"JWS",
|
||||
"api",
|
||||
"bundle",
|
||||
"jwt",
|
||||
"rest",
|
||||
"symfony"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/lexik/LexikJWTAuthenticationBundle/issues",
|
||||
"source": "https://github.com/lexik/LexikJWTAuthenticationBundle/tree/v3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/chalasr",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/lexik/jwt-authentication-bundle",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-20T17:47:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nelmio/cors-bundle",
|
||||
"version": "2.6.0",
|
||||
@@ -4613,6 +4866,92 @@
|
||||
],
|
||||
"time": "2025-12-31T09:29:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40",
|
||||
"reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.4",
|
||||
"symfony/polyfill-intl-idn": "^1.10",
|
||||
"symfony/polyfill-mbstring": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"egulias/email-validator": "~3.0.0",
|
||||
"phpdocumentor/reflection-docblock": "<3.2.2",
|
||||
"phpdocumentor/type-resolver": "<1.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"egulias/email-validator": "^2.1.10|^3.1|^4",
|
||||
"league/html-to-markdown": "^5.0",
|
||||
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
|
||||
"symfony/dependency-injection": "^7.4|^8.0",
|
||||
"symfony/process": "^7.4|^8.0",
|
||||
"symfony/property-access": "^7.4|^8.0",
|
||||
"symfony/property-info": "^7.4|^8.0",
|
||||
"symfony/serializer": "^7.4|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Mime\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Allows manipulating MIME messages",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"mime",
|
||||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v8.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-16T10:17:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/password-hasher",
|
||||
"version": "v8.0.0",
|
||||
@@ -4768,6 +5107,93 @@
|
||||
],
|
||||
"time": "2025-06-27T09:58:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
|
||||
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"symfony/polyfill-intl-normalizer": "^1.10"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Idn\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Laurent Bassin",
|
||||
"email": "laurent@bassin.info"
|
||||
},
|
||||
{
|
||||
"name": "Trevor Rowbotham",
|
||||
"email": "trevor.rowbotham@pm.me"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"idn",
|
||||
"intl",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-10T14:38:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.33.0",
|
||||
@@ -7040,6 +7466,114 @@
|
||||
],
|
||||
"time": "2025-12-14T11:28:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "vich/uploader-bundle",
|
||||
"version": "v2.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dustin10/VichUploaderBundle.git",
|
||||
"reference": "945939a04a33c0b78c5fbb7ead31533d85112df5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/945939a04a33c0b78c5fbb7ead31533d85112df5",
|
||||
"reference": "945939a04a33c0b78c5fbb7ead31533d85112df5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/persistence": "^3.0 || ^4.0",
|
||||
"ext-simplexml": "*",
|
||||
"jms/metadata": "^2.4",
|
||||
"php": "^8.1",
|
||||
"symfony/config": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/event-dispatcher-contracts": "^3.1",
|
||||
"symfony/http-foundation": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/mime": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/property-access": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/string": "^5.4 || ^6.0 || ^7.0 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/annotations": "<1.12",
|
||||
"league/flysystem": "<2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dg/bypass-finals": "^1.9",
|
||||
"doctrine/common": "^3.0",
|
||||
"doctrine/doctrine-bundle": "^2.7 || ^3.0",
|
||||
"doctrine/mongodb-odm": "^2.4",
|
||||
"doctrine/orm": "^2.13 || ^3.0",
|
||||
"ext-sqlite3": "*",
|
||||
"knplabs/knp-gaufrette-bundle": "dev-master",
|
||||
"league/flysystem-bundle": "^2.4 || ^3.0",
|
||||
"league/flysystem-memory": "^2.0 || ^3.0",
|
||||
"matthiasnoback/symfony-dependency-injection-test": "^5.1 || ^6.0",
|
||||
"mikey179/vfsstream": "^1.6.11",
|
||||
"phpunit/phpunit": "^10.5 || ^11.5 || ^12.2",
|
||||
"symfony/asset": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/browser-kit": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/doctrine-bridge": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/form": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/phpunit-bridge": "^7.3",
|
||||
"symfony/security-csrf": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/translation": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/twig-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/validator": "^5.4.22 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/var-dumper": "^5.4 || ^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/doctrine-bundle": "For integration with Doctrine",
|
||||
"doctrine/mongodb-odm-bundle": "For integration with Doctrine ODM",
|
||||
"doctrine/orm": "For integration with Doctrine ORM",
|
||||
"doctrine/phpcr-odm": "For integration with Doctrine PHPCR",
|
||||
"knplabs/knp-gaufrette-bundle": "For integration with Gaufrette",
|
||||
"league/flysystem-bundle": "For integration with Flysystem",
|
||||
"liip/imagine-bundle": "To generate image thumbnails",
|
||||
"oneup/flysystem-bundle": "For integration with Flysystem",
|
||||
"symfony/asset": "To generate better links",
|
||||
"symfony/form": "To handle uploads in forms",
|
||||
"symfony/yaml": "To use YAML mapping"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Vich\\UploaderBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dustin Dobervich",
|
||||
"email": "ddobervich@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Ease file uploads attached to entities",
|
||||
"homepage": "https://github.com/dustin10/VichUploaderBundle",
|
||||
"keywords": [
|
||||
"file uploads",
|
||||
"upload"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dustin10/VichUploaderBundle/issues",
|
||||
"source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.9.1"
|
||||
},
|
||||
"time": "2025-12-10T08:23:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "2.0.0",
|
||||
@@ -10208,7 +10742,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
@@ -10216,6 +10750,6 @@
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
|
||||
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
|
||||
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle;
|
||||
use Nelmio\CorsBundle\NelmioCorsBundle;
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
use Symfony\Bundle\TwigBundle\TwigBundle;
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||
FrameworkBundle::class => ['all' => true],
|
||||
TwigBundle::class => ['all' => true],
|
||||
SecurityBundle::class => ['all' => true],
|
||||
DoctrineBundle::class => ['all' => true],
|
||||
DoctrineMigrationsBundle::class => ['all' => true],
|
||||
NelmioCorsBundle::class => ['all' => true],
|
||||
ApiPlatformBundle::class => ['all' => true],
|
||||
LexikJWTAuthenticationBundle::class => ['all' => true],
|
||||
];
|
||||
|
||||
@@ -2,6 +2,6 @@ api_platform:
|
||||
title: Hello API Platform
|
||||
version: 1.0.0
|
||||
defaults:
|
||||
stateless: true
|
||||
stateless: false
|
||||
cache_headers:
|
||||
vary: ['Content-Type', 'Authorization', 'Origin']
|
||||
|
||||
4
config/packages/lexik_jwt_authentication.yaml
Normal file
4
config/packages/lexik_jwt_authentication.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
lexik_jwt_authentication:
|
||||
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
|
||||
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
|
||||
pass_phrase: '%env(JWT_PASSPHRASE)%'
|
||||
@@ -4,7 +4,8 @@ nelmio_cors:
|
||||
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
allow_headers: ['Content-Type', 'Authorization']
|
||||
allow_credentials: true
|
||||
expose_headers: ['Link']
|
||||
max_age: 3600
|
||||
paths:
|
||||
'^/': null
|
||||
'^/api/': ~
|
||||
|
||||
@@ -29,10 +29,17 @@ security:
|
||||
success_handler: lexik_jwt_authentication.handler.authentication_success
|
||||
failure_handler: lexik_jwt_authentication.handler.authentication_failure
|
||||
|
||||
session_profile:
|
||||
pattern: ^/api/session
|
||||
stateless: false
|
||||
|
||||
session_api:
|
||||
pattern: ^/api/(sites|machines|documents|profiles)
|
||||
stateless: false
|
||||
|
||||
api:
|
||||
pattern: ^/api
|
||||
stateless: true
|
||||
jwt: ~
|
||||
stateless: false
|
||||
|
||||
main:
|
||||
lazy: true
|
||||
@@ -40,7 +47,9 @@ security:
|
||||
|
||||
# Note: Only the *first* matching rule is applied
|
||||
access_control:
|
||||
- { path: ^/api/login, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/api/session/profile, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/api/session/profiles, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/api, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/api/test, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/docs, roles: PUBLIC_ACCESS }
|
||||
|
||||
@@ -768,6 +768,9 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* property?: scalar|null|Param, // Default: null
|
||||
* manager_name?: scalar|null|Param, // Default: null
|
||||
* },
|
||||
* lexik_jwt?: array{
|
||||
* class?: scalar|null|Param, // Default: "Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\User\\JWTUser"
|
||||
* },
|
||||
* }>,
|
||||
* firewalls: array<string, array{ // Default: []
|
||||
* pattern?: scalar|null|Param,
|
||||
@@ -826,6 +829,10 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* provider?: scalar|null|Param,
|
||||
* user?: scalar|null|Param, // Default: "REMOTE_USER"
|
||||
* },
|
||||
* jwt?: array{
|
||||
* provider?: scalar|null|Param, // Default: null
|
||||
* authenticator?: scalar|null|Param, // Default: "lexik_jwt_authentication.security.jwt_authenticator"
|
||||
* },
|
||||
* login_link?: array{
|
||||
* check_route: scalar|null|Param, // Route that will validate the login link - e.g. "app_login_link_verify".
|
||||
* check_post_only?: scalar|null|Param, // If true, only HTTP POST requests to "check_route" will be handled by the authenticator. // Default: false
|
||||
@@ -1514,6 +1521,91 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* ...<mixed>
|
||||
* },
|
||||
* }
|
||||
* @psalm-type LexikJwtAuthenticationConfig = array{
|
||||
* public_key?: scalar|null|Param, // The key used to sign tokens (useless for HMAC). If not set, the key will be automatically computed from the secret key. // Default: null
|
||||
* additional_public_keys?: list<scalar|null|Param>,
|
||||
* secret_key?: scalar|null|Param, // The key used to sign tokens. It can be a raw secret (for HMAC), a raw RSA/ECDSA key or the path to a file itself being plaintext or PEM. // Default: null
|
||||
* pass_phrase?: scalar|null|Param, // The key passphrase (useless for HMAC) // Default: ""
|
||||
* token_ttl?: scalar|null|Param, // Default: 3600
|
||||
* allow_no_expiration?: bool|Param, // Allow tokens without "exp" claim (i.e. indefinitely valid, no lifetime) to be considered valid. Caution: usage of this should be rare. // Default: false
|
||||
* clock_skew?: scalar|null|Param, // Default: 0
|
||||
* encoder?: array{
|
||||
* service?: scalar|null|Param, // Default: "lexik_jwt_authentication.encoder.lcobucci"
|
||||
* signature_algorithm?: scalar|null|Param, // Default: "RS256"
|
||||
* },
|
||||
* user_id_claim?: scalar|null|Param, // Default: "username"
|
||||
* token_extractors?: array{
|
||||
* authorization_header?: bool|array{
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* prefix?: scalar|null|Param, // Default: "Bearer"
|
||||
* name?: scalar|null|Param, // Default: "Authorization"
|
||||
* },
|
||||
* cookie?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* name?: scalar|null|Param, // Default: "BEARER"
|
||||
* },
|
||||
* query_parameter?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* name?: scalar|null|Param, // Default: "bearer"
|
||||
* },
|
||||
* split_cookie?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* cookies?: list<scalar|null|Param>,
|
||||
* },
|
||||
* },
|
||||
* remove_token_from_body_when_cookies_used?: scalar|null|Param, // Default: true
|
||||
* set_cookies?: array<string, array{ // Default: []
|
||||
* lifetime?: scalar|null|Param, // The cookie lifetime. If null, the "token_ttl" option value will be used // Default: null
|
||||
* samesite?: "none"|"lax"|"strict"|Param, // Default: "lax"
|
||||
* path?: scalar|null|Param, // Default: "/"
|
||||
* domain?: scalar|null|Param, // Default: null
|
||||
* secure?: scalar|null|Param, // Default: true
|
||||
* httpOnly?: scalar|null|Param, // Default: true
|
||||
* partitioned?: scalar|null|Param, // Default: false
|
||||
* split?: list<scalar|null|Param>,
|
||||
* }>,
|
||||
* api_platform?: bool|array{ // API Platform compatibility: add check_path in OpenAPI documentation.
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* check_path?: scalar|null|Param, // The login check path to add in OpenAPI. // Default: null
|
||||
* username_path?: scalar|null|Param, // The path to the username in the JSON body. // Default: null
|
||||
* password_path?: scalar|null|Param, // The path to the password in the JSON body. // Default: null
|
||||
* },
|
||||
* access_token_issuance?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* signature?: array{
|
||||
* algorithm: scalar|null|Param, // The algorithm use to sign the access tokens.
|
||||
* key: scalar|null|Param, // The signature key. It shall be JWK encoded.
|
||||
* },
|
||||
* encryption?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* key_encryption_algorithm: scalar|null|Param, // The key encryption algorithm is used to encrypt the token.
|
||||
* content_encryption_algorithm: scalar|null|Param, // The key encryption algorithm is used to encrypt the token.
|
||||
* key: scalar|null|Param, // The encryption key. It shall be JWK encoded.
|
||||
* },
|
||||
* },
|
||||
* access_token_verification?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* signature?: array{
|
||||
* header_checkers?: list<scalar|null|Param>,
|
||||
* claim_checkers?: list<scalar|null|Param>,
|
||||
* mandatory_claims?: list<scalar|null|Param>,
|
||||
* allowed_algorithms?: list<scalar|null|Param>,
|
||||
* keyset: scalar|null|Param, // The signature keyset. It shall be JWKSet encoded.
|
||||
* },
|
||||
* encryption?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* continue_on_decryption_failure?: bool|Param, // If enable, non-encrypted tokens or tokens that failed during decryption or verification processes are accepted. // Default: false
|
||||
* header_checkers?: list<scalar|null|Param>,
|
||||
* allowed_key_encryption_algorithms?: list<scalar|null|Param>,
|
||||
* allowed_content_encryption_algorithms?: list<scalar|null|Param>,
|
||||
* keyset: scalar|null|Param, // The encryption keyset. It shall be JWKSet encoded.
|
||||
* },
|
||||
* },
|
||||
* blocklist_token?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* cache?: scalar|null|Param, // Storage to track blocked tokens // Default: "cache.app"
|
||||
* },
|
||||
* }
|
||||
* @psalm-type ConfigType = array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
@@ -1525,6 +1617,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* doctrine_migrations?: DoctrineMigrationsConfig,
|
||||
* nelmio_cors?: NelmioCorsConfig,
|
||||
* api_platform?: ApiPlatformConfig,
|
||||
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
|
||||
* "when@dev"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
@@ -1536,6 +1629,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* doctrine_migrations?: DoctrineMigrationsConfig,
|
||||
* nelmio_cors?: NelmioCorsConfig,
|
||||
* api_platform?: ApiPlatformConfig,
|
||||
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
|
||||
* },
|
||||
* "when@prod"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
@@ -1548,6 +1642,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* doctrine_migrations?: DoctrineMigrationsConfig,
|
||||
* nelmio_cors?: NelmioCorsConfig,
|
||||
* api_platform?: ApiPlatformConfig,
|
||||
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
|
||||
* },
|
||||
* "when@test"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
@@ -1560,6 +1655,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* doctrine_migrations?: DoctrineMigrationsConfig,
|
||||
* nelmio_cors?: NelmioCorsConfig,
|
||||
* api_platform?: ApiPlatformConfig,
|
||||
* lexik_jwt_authentication?: LexikJwtAuthenticationConfig,
|
||||
* },
|
||||
* ...<string, ExtensionType|array{ // extra keys must follow the when@%env% pattern or match an extension alias
|
||||
* imports?: ImportsConfig,
|
||||
|
||||
@@ -14,6 +14,7 @@ services:
|
||||
XDEBUG_CLIENT_HOST: ${XDEBUG_CLIENT_HOST:-host.docker.internal}
|
||||
XDEBUG_CONFIG: client_host=${XDEBUG_CLIENT_HOST:-host.docker.internal} client_port=9003
|
||||
DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?serverVersion=16&charset=utf8"
|
||||
CORS_ALLOW_ORIGIN: ${CORS_ALLOW_ORIGIN}
|
||||
volumes:
|
||||
- ./:/var/www/html
|
||||
- ~/.cache:/var/www/.cache # Pour la cache de composer
|
||||
@@ -43,5 +44,35 @@ services:
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5433}:5432"
|
||||
restart: unless-stopped
|
||||
|
||||
pgadmin:
|
||||
container_name: pgadmin-${DOCKER_APP_NAME}
|
||||
image: dpage/pgadmin4:latest
|
||||
user: root
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@admin.com}
|
||||
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-admin}
|
||||
PGADMIN_CONFIG_SERVER_MODE: 'False'
|
||||
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False'
|
||||
PGADMIN_SERVER_JSON_FILE: '/pgadmin4/servers.json'
|
||||
volumes:
|
||||
- pgadmin_data:/var/lib/pgadmin
|
||||
- ./docker/pgadmin/servers.json:/pgadmin4/servers.json:ro
|
||||
- ./docker/pgadmin/pgpass:/pgadmin4/pgpass:ro
|
||||
ports:
|
||||
- "${PGADMIN_PORT:-5050}:80"
|
||||
depends_on:
|
||||
- db
|
||||
restart: unless-stopped
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
mkdir -p /var/lib/pgadmin &&
|
||||
cp /pgadmin4/pgpass /var/lib/pgadmin/pgpass &&
|
||||
chmod 600 /var/lib/pgadmin/pgpass &&
|
||||
chown 5050:5050 /var/lib/pgadmin/pgpass &&
|
||||
/entrypoint.sh
|
||||
"
|
||||
|
||||
volumes:
|
||||
pg_data:
|
||||
pgadmin_data:
|
||||
|
||||
@@ -2,8 +2,34 @@ DOCKER_APP_NAME=inventory
|
||||
DOCKER_PHP_VERSION=8.4.6
|
||||
DOCKER_NODE_VERSION=24.12.0
|
||||
APP_USER=www-data
|
||||
CURRENT_UID=1000
|
||||
CURRENT_GID=1000
|
||||
|
||||
# PostgreSQL
|
||||
POSTGRES_DB=inventory
|
||||
POSTGRES_USER=root
|
||||
POSTGRES_PASSWORD=root
|
||||
#
|
||||
# CORS
|
||||
CORS_ALLOW_ORIGIN=^https?://(localhost|127\\.0\\.0\\.1)(:[0-9]+)?$
|
||||
POSTGRES_PORT=5433
|
||||
|
||||
# pgAdmin
|
||||
PGADMIN_EMAIL=admin@admin.com
|
||||
PGADMIN_PASSWORD=admin
|
||||
PGADMIN_PORT=5050
|
||||
|
||||
# XDebug
|
||||
XDEBUG_CLIENT_HOST=host.docker.internal
|
||||
|
||||
# Symfony (pour future migration)
|
||||
APP_ENV=dev
|
||||
APP_SECRET=changeme_super_secret_key_123456789
|
||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||
JWT_PASSPHRASE=your_jwt_passphrase_change_me
|
||||
|
||||
# NestJS
|
||||
NESTJS_PORT=3000
|
||||
SESSION_SECRET=changeme_session_secret
|
||||
CORS_ORIGIN=http://localhost:3001
|
||||
|
||||
2
docker/pgadmin/pgpass
Normal file
2
docker/pgadmin/pgpass
Normal file
@@ -0,0 +1,2 @@
|
||||
db:5432:inventory:root:root
|
||||
db:5432:*:root:root
|
||||
15
docker/pgadmin/servers.json
Normal file
15
docker/pgadmin/servers.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "Inventory PostgreSQL",
|
||||
"Group": "Servers",
|
||||
"Host": "db",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "inventory",
|
||||
"Username": "root",
|
||||
"SSLMode": "prefer",
|
||||
"PassFile": "/var/lib/pgadmin/pgpass",
|
||||
"Comment": "Serveur PostgreSQL du projet Inventory"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,15 @@
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot /var/www/html
|
||||
ServerName localhost
|
||||
DocumentRoot /var/www/html/public
|
||||
|
||||
AliasMatch "^/api(/.*)?" "/var/www/html/public$1"
|
||||
# API Symfony
|
||||
<Directory /var/www/html/public>
|
||||
Options FollowSymLinks
|
||||
Options +FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
AliasMatch "^(/.*)?" "/var/www/html/frontend/dist$1"
|
||||
<Directory /var/www/html/frontend/dist>
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
Allow from All
|
||||
|
||||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
RewriteRule ^ index.html [L]
|
||||
</Directory>
|
||||
|
||||
ErrorLog "${APACHE_LOG_DIR}/error.log"
|
||||
CustomLog "${APACHE_LOG_DIR}/access.log" combined
|
||||
# Logs
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
</VirtualHost>
|
||||
|
||||
13
makefile
13
makefile
@@ -31,6 +31,11 @@ start: env-init
|
||||
@echo "**** START CONTAINERS ****"
|
||||
@cp --update=none docker/.env.docker docker/.env.docker.local
|
||||
CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d
|
||||
@echo ""
|
||||
@echo "URLs disponibles:"
|
||||
@echo "- Symfony API: http://localhost:8081/api"
|
||||
@echo "- Nuxt (Inventory_frontend): http://localhost:3001"
|
||||
@echo "- pgAdmin: http://localhost:5050"
|
||||
|
||||
# Éteint le container
|
||||
stop:
|
||||
@@ -49,16 +54,16 @@ composer-install:
|
||||
$(EXEC_PHP) composer install
|
||||
|
||||
build-nuxtJS:
|
||||
# $(EXEC_PHP) cp -n frontend/.env.dist frontend/.env.local
|
||||
$(EXEC_PHP) sh -lc "cd frontend && npm install && npm run build:dist"
|
||||
# $(EXEC_PHP) cp -n Inventory_frontend/.env.dist Inventory_frontend/.env.local
|
||||
$(EXEC_PHP) sh -lc "cd Inventory_frontend && npm install && npm run build:dist"
|
||||
|
||||
dev-nuxt:
|
||||
$(EXEC_PHP) sh -c "cd frontend && npm run dev"
|
||||
$(EXEC_PHP) sh -c "cd Inventory_frontend && npm run dev"
|
||||
|
||||
delete_built_dir:
|
||||
CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d
|
||||
$(DOCKER) exec -u root $(PHP_CONTAINER) rm -rf vendor/
|
||||
$(DOCKER) exec -u root $(PHP_CONTAINER) rm -rf frontend/node_modules
|
||||
$(DOCKER) exec -u root $(PHP_CONTAINER) rm -rf Inventory_frontend/node_modules
|
||||
|
||||
remove_orphans:
|
||||
$(DOCKER_COMPOSE) kill
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20260110175413 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE profiles (id VARCHAR(30) NOT NULL, email VARCHAR(180) NOT NULL, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, is_active BOOLEAN DEFAULT true NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_email ON profiles (email)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE profiles');
|
||||
}
|
||||
}
|
||||
229
migrations/Version20260110202855.php
Normal file
229
migrations/Version20260110202855.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20260110202855 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE composants (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, reference VARCHAR(255) DEFAULT NULL, prix NUMERIC(10, 2) DEFAULT NULL, structure JSON DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeComposantId VARCHAR(36) DEFAULT NULL, productId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_F95A31995E237E06 ON composants (name)');
|
||||
$this->addSql('CREATE INDEX IDX_F95A3199CC8A4CEE ON composants (typeComposantId)');
|
||||
$this->addSql('CREATE INDEX IDX_F95A319936799605 ON composants (productId)');
|
||||
$this->addSql('CREATE TABLE _ComposantConstructeurs (A VARCHAR(36) NOT NULL, B VARCHAR(36) NOT NULL, PRIMARY KEY (A, B))');
|
||||
$this->addSql('CREATE INDEX IDX_60760125D3D99E8B ON _ComposantConstructeurs (A)');
|
||||
$this->addSql('CREATE INDEX IDX_607601254AD0CF31 ON _ComposantConstructeurs (B)');
|
||||
$this->addSql('CREATE TABLE constructeurs (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(255) DEFAULT NULL, phone VARCHAR(255) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_CC8D6F55E237E06 ON constructeurs (name)');
|
||||
$this->addSql('CREATE TABLE custom_field_values (id VARCHAR(36) NOT NULL, value VARCHAR(255) NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, customFieldId VARCHAR(36) NOT NULL, machineId VARCHAR(36) DEFAULT NULL, composantId VARCHAR(36) DEFAULT NULL, pieceId VARCHAR(36) DEFAULT NULL, productId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_6B64D7FF5C4A705F ON custom_field_values (customFieldId)');
|
||||
$this->addSql('CREATE INDEX IDX_6B64D7FF633EC4FD ON custom_field_values (machineId)');
|
||||
$this->addSql('CREATE INDEX IDX_6B64D7FF345EE564 ON custom_field_values (composantId)');
|
||||
$this->addSql('CREATE INDEX IDX_6B64D7FF3C6A9D1 ON custom_field_values (pieceId)');
|
||||
$this->addSql('CREATE INDEX IDX_6B64D7FF36799605 ON custom_field_values (productId)');
|
||||
$this->addSql('CREATE TABLE custom_fields (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(50) NOT NULL, required BOOLEAN DEFAULT false NOT NULL, defaultValue VARCHAR(255) DEFAULT NULL, options JSON NOT NULL, orderIndex INT DEFAULT 0 NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeMachineId VARCHAR(36) DEFAULT NULL, typeComposantId VARCHAR(36) DEFAULT NULL, typePieceId VARCHAR(36) DEFAULT NULL, typeProductId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_4A48378C2F024C2 ON custom_fields (typeMachineId)');
|
||||
$this->addSql('CREATE INDEX IDX_4A48378CCC8A4CEE ON custom_fields (typeComposantId)');
|
||||
$this->addSql('CREATE INDEX IDX_4A48378C169F1CF6 ON custom_fields (typePieceId)');
|
||||
$this->addSql('CREATE INDEX IDX_4A48378C57B7763A ON custom_fields (typeProductId)');
|
||||
$this->addSql('CREATE TABLE documents (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, filename VARCHAR(255) NOT NULL, path VARCHAR(500) NOT NULL, mimeType VARCHAR(100) NOT NULL, size INT NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, machineId VARCHAR(36) DEFAULT NULL, composantId VARCHAR(36) DEFAULT NULL, pieceId VARCHAR(36) DEFAULT NULL, productId VARCHAR(36) DEFAULT NULL, siteId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_A2B07288633EC4FD ON documents (machineId)');
|
||||
$this->addSql('CREATE INDEX IDX_A2B07288345EE564 ON documents (composantId)');
|
||||
$this->addSql('CREATE INDEX IDX_A2B072883C6A9D1 ON documents (pieceId)');
|
||||
$this->addSql('CREATE INDEX IDX_A2B0728836799605 ON documents (productId)');
|
||||
$this->addSql('CREATE INDEX IDX_A2B072886973A4FD ON documents (siteId)');
|
||||
$this->addSql('CREATE TABLE machine_component_links (id VARCHAR(36) NOT NULL, nameOverride VARCHAR(255) DEFAULT NULL, referenceOverride VARCHAR(255) DEFAULT NULL, prixOverride NUMERIC(10, 2) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, machineId VARCHAR(36) NOT NULL, composantId VARCHAR(36) NOT NULL, parentLinkId VARCHAR(36) DEFAULT NULL, typeMachineComponentRequirementId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_528EFE19633EC4FD ON machine_component_links (machineId)');
|
||||
$this->addSql('CREATE INDEX IDX_528EFE19345EE564 ON machine_component_links (composantId)');
|
||||
$this->addSql('CREATE INDEX IDX_528EFE19EF6CF34B ON machine_component_links (parentLinkId)');
|
||||
$this->addSql('CREATE INDEX IDX_528EFE19C44B383C ON machine_component_links (typeMachineComponentRequirementId)');
|
||||
$this->addSql('CREATE TABLE machine_piece_links (id VARCHAR(36) NOT NULL, nameOverride VARCHAR(255) DEFAULT NULL, referenceOverride VARCHAR(255) DEFAULT NULL, prixOverride NUMERIC(10, 2) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, machineId VARCHAR(36) NOT NULL, pieceId VARCHAR(36) NOT NULL, parentLinkId VARCHAR(36) DEFAULT NULL, typeMachinePieceRequirementId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_62941615633EC4FD ON machine_piece_links (machineId)');
|
||||
$this->addSql('CREATE INDEX IDX_629416153C6A9D1 ON machine_piece_links (pieceId)');
|
||||
$this->addSql('CREATE INDEX IDX_62941615EF6CF34B ON machine_piece_links (parentLinkId)');
|
||||
$this->addSql('CREATE INDEX IDX_62941615F957D314 ON machine_piece_links (typeMachinePieceRequirementId)');
|
||||
$this->addSql('CREATE TABLE machine_product_links (id VARCHAR(36) NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, machineId VARCHAR(36) NOT NULL, productId VARCHAR(36) NOT NULL, typeMachineProductRequirementId VARCHAR(36) DEFAULT NULL, parentLinkId VARCHAR(36) DEFAULT NULL, parentComponentLinkId VARCHAR(36) DEFAULT NULL, parentPieceLinkId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_8CC32259633EC4FD ON machine_product_links (machineId)');
|
||||
$this->addSql('CREATE INDEX IDX_8CC3225936799605 ON machine_product_links (productId)');
|
||||
$this->addSql('CREATE INDEX IDX_8CC32259B590B209 ON machine_product_links (typeMachineProductRequirementId)');
|
||||
$this->addSql('CREATE INDEX IDX_8CC32259EF6CF34B ON machine_product_links (parentLinkId)');
|
||||
$this->addSql('CREATE INDEX IDX_8CC32259A63AC5DC ON machine_product_links (parentComponentLinkId)');
|
||||
$this->addSql('CREATE INDEX IDX_8CC32259937A1D7C ON machine_product_links (parentPieceLinkId)');
|
||||
$this->addSql('CREATE TABLE machines (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, reference VARCHAR(255) DEFAULT NULL, prix NUMERIC(10, 2) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, siteId VARCHAR(36) NOT NULL, typeMachineId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_F1CE8DED5E237E06 ON machines (name)');
|
||||
$this->addSql('CREATE INDEX IDX_F1CE8DED6973A4FD ON machines (siteId)');
|
||||
$this->addSql('CREATE INDEX IDX_F1CE8DED2F024C2 ON machines (typeMachineId)');
|
||||
$this->addSql('CREATE TABLE _MachineConstructeurs (A VARCHAR(36) NOT NULL, B VARCHAR(36) NOT NULL, PRIMARY KEY (A, B))');
|
||||
$this->addSql('CREATE INDEX IDX_E6A040CCD3D99E8B ON _MachineConstructeurs (A)');
|
||||
$this->addSql('CREATE INDEX IDX_E6A040CC4AD0CF31 ON _MachineConstructeurs (B)');
|
||||
$this->addSql('CREATE TABLE model_types (id VARCHAR(36) NOT NULL, name VARCHAR(120) NOT NULL, code VARCHAR(60) NOT NULL, category VARCHAR(255) NOT NULL, notes TEXT DEFAULT NULL, description TEXT DEFAULT NULL, componentSkeleton JSON DEFAULT NULL, pieceSkeleton JSON DEFAULT NULL, productSkeleton JSON DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_6773A9C777153098 ON model_types (code)');
|
||||
$this->addSql('CREATE UNIQUE INDEX unique_category_name ON model_types (category, name)');
|
||||
$this->addSql('CREATE TABLE pieces (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, reference VARCHAR(255) DEFAULT NULL, prix NUMERIC(10, 2) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typePieceId VARCHAR(36) DEFAULT NULL, productId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_B92D74725E237E06 ON pieces (name)');
|
||||
$this->addSql('CREATE INDEX IDX_B92D7472169F1CF6 ON pieces (typePieceId)');
|
||||
$this->addSql('CREATE INDEX IDX_B92D747236799605 ON pieces (productId)');
|
||||
$this->addSql('CREATE TABLE _PieceConstructeurs (A VARCHAR(36) NOT NULL, B VARCHAR(36) NOT NULL, PRIMARY KEY (A, B))');
|
||||
$this->addSql('CREATE INDEX IDX_E94732E5D3D99E8B ON _PieceConstructeurs (A)');
|
||||
$this->addSql('CREATE INDEX IDX_E94732E54AD0CF31 ON _PieceConstructeurs (B)');
|
||||
$this->addSql('CREATE TABLE products (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, reference VARCHAR(255) DEFAULT NULL, supplierPrice NUMERIC(10, 2) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeProductId VARCHAR(36) DEFAULT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_B3BA5A5A5E237E06 ON products (name)');
|
||||
$this->addSql('CREATE INDEX IDX_B3BA5A5A57B7763A ON products (typeProductId)');
|
||||
$this->addSql('CREATE TABLE _ProductConstructeurs (A VARCHAR(36) NOT NULL, B VARCHAR(36) NOT NULL, PRIMARY KEY (A, B))');
|
||||
$this->addSql('CREATE INDEX IDX_CF7403FCD3D99E8B ON _ProductConstructeurs (A)');
|
||||
$this->addSql('CREATE INDEX IDX_CF7403FC4AD0CF31 ON _ProductConstructeurs (B)');
|
||||
$this->addSql('CREATE TABLE profiles (id VARCHAR(36) NOT NULL, email VARCHAR(180) DEFAULT NULL, firstName VARCHAR(100) NOT NULL, lastName VARCHAR(100) NOT NULL, isActive BOOLEAN DEFAULT true NOT NULL, roles JSON DEFAULT \'["ROLE_USER"]\' NOT NULL, password VARCHAR(255) DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_email ON profiles (email)');
|
||||
$this->addSql('CREATE TABLE sites (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, contactName VARCHAR(255) DEFAULT \'\' NOT NULL, contactPhone VARCHAR(20) DEFAULT \'\' NOT NULL, contactAddress VARCHAR(500) DEFAULT \'\' NOT NULL, contactPostalCode VARCHAR(10) DEFAULT \'\' NOT NULL, contactCity VARCHAR(100) DEFAULT \'\' NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE TABLE type_machine_component_requirements (id VARCHAR(36) NOT NULL, label VARCHAR(255) DEFAULT NULL, minCount INT DEFAULT 1 NOT NULL, maxCount INT DEFAULT NULL, allowNewModels BOOLEAN DEFAULT true NOT NULL, allow_new_models BOOLEAN DEFAULT true NOT NULL, orderIndex INT DEFAULT 0 NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeMachineId VARCHAR(36) NOT NULL, typeComposantId VARCHAR(36) NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_969587902F024C2 ON type_machine_component_requirements (typeMachineId)');
|
||||
$this->addSql('CREATE INDEX IDX_96958790CC8A4CEE ON type_machine_component_requirements (typeComposantId)');
|
||||
$this->addSql('CREATE TABLE type_machine_piece_requirements (id VARCHAR(36) NOT NULL, label VARCHAR(255) DEFAULT NULL, minCount INT DEFAULT 0 NOT NULL, maxCount INT DEFAULT NULL, required BOOLEAN DEFAULT false NOT NULL, allowNewModels BOOLEAN DEFAULT true NOT NULL, orderIndex INT DEFAULT 0 NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeMachineId VARCHAR(36) NOT NULL, typePieceId VARCHAR(36) NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_F609E59E2F024C2 ON type_machine_piece_requirements (typeMachineId)');
|
||||
$this->addSql('CREATE INDEX IDX_F609E59E169F1CF6 ON type_machine_piece_requirements (typePieceId)');
|
||||
$this->addSql('CREATE TABLE type_machine_product_requirements (id VARCHAR(36) NOT NULL, label VARCHAR(255) DEFAULT NULL, minCount INT DEFAULT 0 NOT NULL, maxCount INT DEFAULT NULL, required BOOLEAN DEFAULT false NOT NULL, allowNewModels BOOLEAN DEFAULT true NOT NULL, orderIndex INT DEFAULT 0 NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, typeMachineId VARCHAR(36) NOT NULL, typeProductId VARCHAR(36) NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE INDEX IDX_29A51F982F024C2 ON type_machine_product_requirements (typeMachineId)');
|
||||
$this->addSql('CREATE INDEX IDX_29A51F9857B7763A ON type_machine_product_requirements (typeProductId)');
|
||||
$this->addSql('CREATE TABLE type_machines (id VARCHAR(36) NOT NULL, name VARCHAR(255) NOT NULL, description TEXT DEFAULT NULL, maintenanceFrequency VARCHAR(255) DEFAULT NULL, maintenance_frequency VARCHAR(255) DEFAULT NULL, criticalParts JSON DEFAULT NULL, machinePieces JSON DEFAULT NULL, machine_pieces JSON DEFAULT NULL, specifications JSON DEFAULT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY (id))');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_3C31AA115E237E06 ON type_machines (name)');
|
||||
$this->addSql('ALTER TABLE composants ADD CONSTRAINT FK_F95A3199CC8A4CEE FOREIGN KEY (typeComposantId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE composants ADD CONSTRAINT FK_F95A319936799605 FOREIGN KEY (productId) REFERENCES products (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _ComposantConstructeurs ADD CONSTRAINT FK_60760125D3D99E8B FOREIGN KEY (A) REFERENCES composants (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _ComposantConstructeurs ADD CONSTRAINT FK_607601254AD0CF31 FOREIGN KEY (B) REFERENCES constructeurs (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_field_values ADD CONSTRAINT FK_6B64D7FF5C4A705F FOREIGN KEY (customFieldId) REFERENCES custom_fields (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_field_values ADD CONSTRAINT FK_6B64D7FF633EC4FD FOREIGN KEY (machineId) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_field_values ADD CONSTRAINT FK_6B64D7FF345EE564 FOREIGN KEY (composantId) REFERENCES composants (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_field_values ADD CONSTRAINT FK_6B64D7FF3C6A9D1 FOREIGN KEY (pieceId) REFERENCES pieces (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_field_values ADD CONSTRAINT FK_6B64D7FF36799605 FOREIGN KEY (productId) REFERENCES products (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_fields ADD CONSTRAINT FK_4A48378C2F024C2 FOREIGN KEY (typeMachineId) REFERENCES type_machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_fields ADD CONSTRAINT FK_4A48378CCC8A4CEE FOREIGN KEY (typeComposantId) REFERENCES model_types (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_fields ADD CONSTRAINT FK_4A48378C169F1CF6 FOREIGN KEY (typePieceId) REFERENCES model_types (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE custom_fields ADD CONSTRAINT FK_4A48378C57B7763A FOREIGN KEY (typeProductId) REFERENCES model_types (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE documents ADD CONSTRAINT FK_A2B07288633EC4FD FOREIGN KEY (machineId) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE documents ADD CONSTRAINT FK_A2B07288345EE564 FOREIGN KEY (composantId) REFERENCES composants (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE documents ADD CONSTRAINT FK_A2B072883C6A9D1 FOREIGN KEY (pieceId) REFERENCES pieces (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE documents ADD CONSTRAINT FK_A2B0728836799605 FOREIGN KEY (productId) REFERENCES products (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE documents ADD CONSTRAINT FK_A2B072886973A4FD FOREIGN KEY (siteId) REFERENCES sites (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_component_links ADD CONSTRAINT FK_528EFE19633EC4FD FOREIGN KEY (machineId) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_component_links ADD CONSTRAINT FK_528EFE19345EE564 FOREIGN KEY (composantId) REFERENCES composants (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_component_links ADD CONSTRAINT FK_528EFE19EF6CF34B FOREIGN KEY (parentLinkId) REFERENCES machine_component_links (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_component_links ADD CONSTRAINT FK_528EFE19C44B383C FOREIGN KEY (typeMachineComponentRequirementId) REFERENCES type_machine_component_requirements (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_piece_links ADD CONSTRAINT FK_62941615633EC4FD FOREIGN KEY (machineId) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_piece_links ADD CONSTRAINT FK_629416153C6A9D1 FOREIGN KEY (pieceId) REFERENCES pieces (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_piece_links ADD CONSTRAINT FK_62941615EF6CF34B FOREIGN KEY (parentLinkId) REFERENCES machine_component_links (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_piece_links ADD CONSTRAINT FK_62941615F957D314 FOREIGN KEY (typeMachinePieceRequirementId) REFERENCES type_machine_piece_requirements (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC32259633EC4FD FOREIGN KEY (machineId) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC3225936799605 FOREIGN KEY (productId) REFERENCES products (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC32259B590B209 FOREIGN KEY (typeMachineProductRequirementId) REFERENCES type_machine_product_requirements (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC32259EF6CF34B FOREIGN KEY (parentLinkId) REFERENCES machine_product_links (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC32259A63AC5DC FOREIGN KEY (parentComponentLinkId) REFERENCES machine_component_links (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machine_product_links ADD CONSTRAINT FK_8CC32259937A1D7C FOREIGN KEY (parentPieceLinkId) REFERENCES machine_piece_links (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machines ADD CONSTRAINT FK_F1CE8DED6973A4FD FOREIGN KEY (siteId) REFERENCES sites (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE machines ADD CONSTRAINT FK_F1CE8DED2F024C2 FOREIGN KEY (typeMachineId) REFERENCES type_machines (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _MachineConstructeurs ADD CONSTRAINT FK_E6A040CCD3D99E8B FOREIGN KEY (A) REFERENCES machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _MachineConstructeurs ADD CONSTRAINT FK_E6A040CC4AD0CF31 FOREIGN KEY (B) REFERENCES constructeurs (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE pieces ADD CONSTRAINT FK_B92D7472169F1CF6 FOREIGN KEY (typePieceId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE pieces ADD CONSTRAINT FK_B92D747236799605 FOREIGN KEY (productId) REFERENCES products (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _PieceConstructeurs ADD CONSTRAINT FK_E94732E5D3D99E8B FOREIGN KEY (A) REFERENCES pieces (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _PieceConstructeurs ADD CONSTRAINT FK_E94732E54AD0CF31 FOREIGN KEY (B) REFERENCES constructeurs (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE products ADD CONSTRAINT FK_B3BA5A5A57B7763A FOREIGN KEY (typeProductId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _ProductConstructeurs ADD CONSTRAINT FK_CF7403FCD3D99E8B FOREIGN KEY (A) REFERENCES products (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE _ProductConstructeurs ADD CONSTRAINT FK_CF7403FC4AD0CF31 FOREIGN KEY (B) REFERENCES constructeurs (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_component_requirements ADD CONSTRAINT FK_969587902F024C2 FOREIGN KEY (typeMachineId) REFERENCES type_machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_component_requirements ADD CONSTRAINT FK_96958790CC8A4CEE FOREIGN KEY (typeComposantId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_piece_requirements ADD CONSTRAINT FK_F609E59E2F024C2 FOREIGN KEY (typeMachineId) REFERENCES type_machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_piece_requirements ADD CONSTRAINT FK_F609E59E169F1CF6 FOREIGN KEY (typePieceId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_product_requirements ADD CONSTRAINT FK_29A51F982F024C2 FOREIGN KEY (typeMachineId) REFERENCES type_machines (id) ON DELETE CASCADE NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE type_machine_product_requirements ADD CONSTRAINT FK_29A51F9857B7763A FOREIGN KEY (typeProductId) REFERENCES model_types (id) NOT DEFERRABLE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE composants DROP CONSTRAINT FK_F95A3199CC8A4CEE');
|
||||
$this->addSql('ALTER TABLE composants DROP CONSTRAINT FK_F95A319936799605');
|
||||
$this->addSql('ALTER TABLE _ComposantConstructeurs DROP CONSTRAINT FK_60760125D3D99E8B');
|
||||
$this->addSql('ALTER TABLE _ComposantConstructeurs DROP CONSTRAINT FK_607601254AD0CF31');
|
||||
$this->addSql('ALTER TABLE custom_field_values DROP CONSTRAINT FK_6B64D7FF5C4A705F');
|
||||
$this->addSql('ALTER TABLE custom_field_values DROP CONSTRAINT FK_6B64D7FF633EC4FD');
|
||||
$this->addSql('ALTER TABLE custom_field_values DROP CONSTRAINT FK_6B64D7FF345EE564');
|
||||
$this->addSql('ALTER TABLE custom_field_values DROP CONSTRAINT FK_6B64D7FF3C6A9D1');
|
||||
$this->addSql('ALTER TABLE custom_field_values DROP CONSTRAINT FK_6B64D7FF36799605');
|
||||
$this->addSql('ALTER TABLE custom_fields DROP CONSTRAINT FK_4A48378C2F024C2');
|
||||
$this->addSql('ALTER TABLE custom_fields DROP CONSTRAINT FK_4A48378CCC8A4CEE');
|
||||
$this->addSql('ALTER TABLE custom_fields DROP CONSTRAINT FK_4A48378C169F1CF6');
|
||||
$this->addSql('ALTER TABLE custom_fields DROP CONSTRAINT FK_4A48378C57B7763A');
|
||||
$this->addSql('ALTER TABLE documents DROP CONSTRAINT FK_A2B07288633EC4FD');
|
||||
$this->addSql('ALTER TABLE documents DROP CONSTRAINT FK_A2B07288345EE564');
|
||||
$this->addSql('ALTER TABLE documents DROP CONSTRAINT FK_A2B072883C6A9D1');
|
||||
$this->addSql('ALTER TABLE documents DROP CONSTRAINT FK_A2B0728836799605');
|
||||
$this->addSql('ALTER TABLE documents DROP CONSTRAINT FK_A2B072886973A4FD');
|
||||
$this->addSql('ALTER TABLE machine_component_links DROP CONSTRAINT FK_528EFE19633EC4FD');
|
||||
$this->addSql('ALTER TABLE machine_component_links DROP CONSTRAINT FK_528EFE19345EE564');
|
||||
$this->addSql('ALTER TABLE machine_component_links DROP CONSTRAINT FK_528EFE19EF6CF34B');
|
||||
$this->addSql('ALTER TABLE machine_component_links DROP CONSTRAINT FK_528EFE19C44B383C');
|
||||
$this->addSql('ALTER TABLE machine_piece_links DROP CONSTRAINT FK_62941615633EC4FD');
|
||||
$this->addSql('ALTER TABLE machine_piece_links DROP CONSTRAINT FK_629416153C6A9D1');
|
||||
$this->addSql('ALTER TABLE machine_piece_links DROP CONSTRAINT FK_62941615EF6CF34B');
|
||||
$this->addSql('ALTER TABLE machine_piece_links DROP CONSTRAINT FK_62941615F957D314');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC32259633EC4FD');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC3225936799605');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC32259B590B209');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC32259EF6CF34B');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC32259A63AC5DC');
|
||||
$this->addSql('ALTER TABLE machine_product_links DROP CONSTRAINT FK_8CC32259937A1D7C');
|
||||
$this->addSql('ALTER TABLE machines DROP CONSTRAINT FK_F1CE8DED6973A4FD');
|
||||
$this->addSql('ALTER TABLE machines DROP CONSTRAINT FK_F1CE8DED2F024C2');
|
||||
$this->addSql('ALTER TABLE _MachineConstructeurs DROP CONSTRAINT FK_E6A040CCD3D99E8B');
|
||||
$this->addSql('ALTER TABLE _MachineConstructeurs DROP CONSTRAINT FK_E6A040CC4AD0CF31');
|
||||
$this->addSql('ALTER TABLE pieces DROP CONSTRAINT FK_B92D7472169F1CF6');
|
||||
$this->addSql('ALTER TABLE pieces DROP CONSTRAINT FK_B92D747236799605');
|
||||
$this->addSql('ALTER TABLE _PieceConstructeurs DROP CONSTRAINT FK_E94732E5D3D99E8B');
|
||||
$this->addSql('ALTER TABLE _PieceConstructeurs DROP CONSTRAINT FK_E94732E54AD0CF31');
|
||||
$this->addSql('ALTER TABLE products DROP CONSTRAINT FK_B3BA5A5A57B7763A');
|
||||
$this->addSql('ALTER TABLE _ProductConstructeurs DROP CONSTRAINT FK_CF7403FCD3D99E8B');
|
||||
$this->addSql('ALTER TABLE _ProductConstructeurs DROP CONSTRAINT FK_CF7403FC4AD0CF31');
|
||||
$this->addSql('ALTER TABLE type_machine_component_requirements DROP CONSTRAINT FK_969587902F024C2');
|
||||
$this->addSql('ALTER TABLE type_machine_component_requirements DROP CONSTRAINT FK_96958790CC8A4CEE');
|
||||
$this->addSql('ALTER TABLE type_machine_piece_requirements DROP CONSTRAINT FK_F609E59E2F024C2');
|
||||
$this->addSql('ALTER TABLE type_machine_piece_requirements DROP CONSTRAINT FK_F609E59E169F1CF6');
|
||||
$this->addSql('ALTER TABLE type_machine_product_requirements DROP CONSTRAINT FK_29A51F982F024C2');
|
||||
$this->addSql('ALTER TABLE type_machine_product_requirements DROP CONSTRAINT FK_29A51F9857B7763A');
|
||||
$this->addSql('DROP TABLE composants');
|
||||
$this->addSql('DROP TABLE _ComposantConstructeurs');
|
||||
$this->addSql('DROP TABLE constructeurs');
|
||||
$this->addSql('DROP TABLE custom_field_values');
|
||||
$this->addSql('DROP TABLE custom_fields');
|
||||
$this->addSql('DROP TABLE documents');
|
||||
$this->addSql('DROP TABLE machine_component_links');
|
||||
$this->addSql('DROP TABLE machine_piece_links');
|
||||
$this->addSql('DROP TABLE machine_product_links');
|
||||
$this->addSql('DROP TABLE machines');
|
||||
$this->addSql('DROP TABLE _MachineConstructeurs');
|
||||
$this->addSql('DROP TABLE model_types');
|
||||
$this->addSql('DROP TABLE pieces');
|
||||
$this->addSql('DROP TABLE _PieceConstructeurs');
|
||||
$this->addSql('DROP TABLE products');
|
||||
$this->addSql('DROP TABLE _ProductConstructeurs');
|
||||
$this->addSql('DROP TABLE profiles');
|
||||
$this->addSql('DROP TABLE sites');
|
||||
$this->addSql('DROP TABLE type_machine_component_requirements');
|
||||
$this->addSql('DROP TABLE type_machine_piece_requirements');
|
||||
$this->addSql('DROP TABLE type_machine_product_requirements');
|
||||
$this->addSql('DROP TABLE type_machines');
|
||||
}
|
||||
}
|
||||
5
scripts/insert_profiles.sql
Normal file
5
scripts/insert_profiles.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
INSERT INTO public.profiles (id, firstname, lastname, isactive, createdat, updatedat)
|
||||
VALUES
|
||||
('admin-default-profile', 'Admin', 'General', true, '2025-09-23 13:09:47.804', '2025-09-23 13:09:47.804'),
|
||||
('cmhab2j3x003g47v77xhnm1ff', 'Elodie', 'Souriau', true, '2025-10-28 08:29:25.437', '2025-10-28 08:29:25.437')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
45
scripts/migrate-inventory-data.sh
Executable file
45
scripts/migrate-inventory-data.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SOURCE_DB="${SOURCE_DB:-inventory_data}"
|
||||
TARGET_DB="${TARGET_DB:-inventory}"
|
||||
PGHOST="${PGHOST:-localhost}"
|
||||
PGPORT="${PGPORT:-5433}"
|
||||
PGUSER="${PGUSER:-postgres}"
|
||||
PGPASSWORD="${PGPASSWORD:-postgres}"
|
||||
DUMP_FILE="${DUMP_FILE:-/tmp/inventory_data_dump.sql}"
|
||||
|
||||
export PGPASSWORD
|
||||
|
||||
EXCLUDE_TABLES=(
|
||||
"doctrine_migration_versions"
|
||||
"migration_versions"
|
||||
"_prisma_migrations"
|
||||
"profiles"
|
||||
)
|
||||
|
||||
EXCLUDE_ARGS=()
|
||||
for table in "${EXCLUDE_TABLES[@]}"; do
|
||||
EXCLUDE_ARGS+=(--exclude-table-data="$table")
|
||||
done
|
||||
|
||||
echo "Dumping data from ${SOURCE_DB}..."
|
||||
pg_dump \
|
||||
--data-only \
|
||||
--inserts \
|
||||
--no-owner \
|
||||
--no-privileges \
|
||||
"${EXCLUDE_ARGS[@]}" \
|
||||
-h "${PGHOST}" \
|
||||
-p "${PGPORT}" \
|
||||
-U "${PGUSER}" \
|
||||
"${SOURCE_DB}" > "${DUMP_FILE}"
|
||||
|
||||
echo "Restoring data into ${TARGET_DB}..."
|
||||
psql \
|
||||
-h "${PGHOST}" \
|
||||
-p "${PGPORT}" \
|
||||
-U "${PGUSER}" \
|
||||
"${TARGET_DB}" < "${DUMP_FILE}"
|
||||
|
||||
echo "Done. Data copied from ${SOURCE_DB} to ${TARGET_DB}."
|
||||
80
scripts/normalize-dump.py
Normal file
80
scripts/normalize-dump.py
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
|
||||
TABLE_NAME_MAP = {
|
||||
"ModelType": "model_types",
|
||||
}
|
||||
|
||||
|
||||
def normalize_identifiers(sql: str) -> str:
|
||||
out = []
|
||||
i = 0
|
||||
in_single = False
|
||||
length = len(sql)
|
||||
|
||||
while i < length:
|
||||
ch = sql[i]
|
||||
|
||||
if in_single:
|
||||
if ch == "'":
|
||||
if i + 1 < length and sql[i + 1] == "'":
|
||||
out.append("''")
|
||||
i += 2
|
||||
continue
|
||||
in_single = False
|
||||
out.append(ch)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if ch == "'":
|
||||
in_single = True
|
||||
out.append(ch)
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if ch == '"':
|
||||
i += 1
|
||||
ident = []
|
||||
while i < length:
|
||||
if sql[i] == '"':
|
||||
break
|
||||
ident.append(sql[i])
|
||||
i += 1
|
||||
ident_str = ''.join(ident)
|
||||
mapped = TABLE_NAME_MAP.get(ident_str)
|
||||
if mapped is not None:
|
||||
out.append(mapped)
|
||||
else:
|
||||
out.append(ident_str.lower())
|
||||
if i < length and sql[i] == '"':
|
||||
i += 1
|
||||
continue
|
||||
|
||||
out.append(ch)
|
||||
i += 1
|
||||
|
||||
return ''.join(out)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: scripts/normalize-dump.py <input.sql> <output.sql>", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
src = sys.argv[1]
|
||||
dst = sys.argv[2]
|
||||
|
||||
with open(src, "r", encoding="utf-8") as f:
|
||||
data = f.read()
|
||||
|
||||
normalized = normalize_identifiers(data)
|
||||
|
||||
with open(dst, "w", encoding="utf-8") as f:
|
||||
f.write(normalized)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
139
scripts/validate-migration.php
Normal file
139
scripts/validate-migration.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
function parseDatabaseUrl(string $url): array
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
if ($parts === false) {
|
||||
throw new RuntimeException('Invalid database URL.');
|
||||
}
|
||||
|
||||
$host = $parts['host'] ?? 'localhost';
|
||||
$port = isset($parts['port']) ? (int) $parts['port'] : 5432;
|
||||
$user = $parts['user'] ?? '';
|
||||
$pass = $parts['pass'] ?? '';
|
||||
$db = ltrim($parts['path'] ?? '', '/');
|
||||
|
||||
return [
|
||||
'dsn' => sprintf('pgsql:host=%s;port=%d;dbname=%s', $host, $port, $db),
|
||||
'user' => $user,
|
||||
'pass' => $pass,
|
||||
];
|
||||
}
|
||||
|
||||
function connect(string $url): PDO
|
||||
{
|
||||
$config = parseDatabaseUrl($url);
|
||||
$pdo = new PDO($config['dsn'], $config['user'], $config['pass'], [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
]);
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
$sourceUrl = getenv('SOURCE_DATABASE_URL') ?: '';
|
||||
$targetUrl = getenv('TARGET_DATABASE_URL') ?: '';
|
||||
|
||||
if ($sourceUrl === '' || $targetUrl === '') {
|
||||
fwrite(STDERR, "Usage: SOURCE_DATABASE_URL=... TARGET_DATABASE_URL=... php scripts/validate-migration.php\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$tables = [
|
||||
'sites',
|
||||
'type_machines',
|
||||
'machines',
|
||||
'model_types',
|
||||
'composants',
|
||||
'pieces',
|
||||
'products',
|
||||
'constructeurs',
|
||||
'documents',
|
||||
'custom_fields',
|
||||
'custom_field_values',
|
||||
'machine_component_links',
|
||||
'machine_piece_links',
|
||||
'machine_product_links',
|
||||
'type_machine_component_requirements',
|
||||
'type_machine_piece_requirements',
|
||||
'type_machine_product_requirements',
|
||||
'_machineconstructeurs',
|
||||
'_composantconstructeurs',
|
||||
'_piececonstructeurs',
|
||||
'_productconstructeurs',
|
||||
'profiles',
|
||||
];
|
||||
|
||||
$skipTables = array_filter(array_map('trim', explode(',', getenv('SKIP_TABLES') ?: 'profiles')));
|
||||
|
||||
$sourceTableMap = [
|
||||
'model_types' => ['ModelType', 'model_types'],
|
||||
'_machineconstructeurs' => ['_MachineConstructeurs', '_machineconstructeurs'],
|
||||
'_composantconstructeurs' => ['_ComposantConstructeurs', '_composantconstructeurs'],
|
||||
'_piececonstructeurs' => ['_PieceConstructeurs', '_piececonstructeurs'],
|
||||
'_productconstructeurs' => ['_ProductConstructeurs', '_productconstructeurs'],
|
||||
];
|
||||
|
||||
function resolveTable(PDO $db, array $candidates): ?string
|
||||
{
|
||||
foreach ($candidates as $candidate) {
|
||||
$exists = (bool) $db
|
||||
->query(sprintf("SELECT to_regclass('public.%s')", $candidate))
|
||||
->fetchColumn();
|
||||
if ($exists) {
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
$quoted = (bool) $db
|
||||
->query(sprintf("SELECT to_regclass('public.\"%s\"')", $candidate))
|
||||
->fetchColumn();
|
||||
if ($quoted) {
|
||||
return sprintf('"%s"', $candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$source = connect($sourceUrl);
|
||||
$target = connect($targetUrl);
|
||||
|
||||
$hasDifferences = false;
|
||||
|
||||
foreach ($tables as $table) {
|
||||
if (in_array($table, $skipTables, true)) {
|
||||
continue;
|
||||
}
|
||||
$sourceCandidates = $sourceTableMap[$table] ?? [$table];
|
||||
$sourceTable = resolveTable($source, $sourceCandidates);
|
||||
$sourceExists = $sourceTable !== null;
|
||||
$targetExists = (bool) $target
|
||||
->query(sprintf("SELECT to_regclass('public.%s')", $table))
|
||||
->fetchColumn();
|
||||
|
||||
if (!$sourceExists || !$targetExists) {
|
||||
$hasDifferences = true;
|
||||
printf(
|
||||
"%s: source=%s target=%s\n",
|
||||
$table,
|
||||
$sourceExists ? 'exists' : 'missing',
|
||||
$targetExists ? 'exists' : 'missing'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceCount = (int) $source->query(sprintf('SELECT COUNT(*) FROM public.%s', $sourceTable))->fetchColumn();
|
||||
$targetCount = (int) $target->query(sprintf('SELECT COUNT(*) FROM public.%s', $table))->fetchColumn();
|
||||
|
||||
if ($sourceCount !== $targetCount) {
|
||||
$hasDifferences = true;
|
||||
printf("%s: source=%d target=%d\n", $table, $sourceCount, $targetCount);
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasDifferences) {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
echo "Counts match for all tables.\n";
|
||||
287
src/Controller/CustomFieldValueController.php
Normal file
287
src/Controller/CustomFieldValueController.php
Normal file
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\CustomField;
|
||||
use App\Entity\CustomFieldValue;
|
||||
use App\Repository\ComposantRepository;
|
||||
use App\Repository\CustomFieldRepository;
|
||||
use App\Repository\CustomFieldValueRepository;
|
||||
use App\Repository\MachineRepository;
|
||||
use App\Repository\PieceRepository;
|
||||
use App\Repository\ProductRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/custom-fields/values')]
|
||||
class CustomFieldValueController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly CustomFieldRepository $customFieldRepository,
|
||||
private readonly CustomFieldValueRepository $customFieldValueRepository,
|
||||
private readonly MachineRepository $machineRepository,
|
||||
private readonly ComposantRepository $composantRepository,
|
||||
private readonly PieceRepository $pieceRepository,
|
||||
private readonly ProductRepository $productRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('', name: 'custom_field_values_create', methods: ['POST'])]
|
||||
public function create(Request $request): JsonResponse
|
||||
{
|
||||
$payload = $this->decodePayload($request);
|
||||
if ($payload instanceof JsonResponse) {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
$customField = $this->resolveCustomField($payload);
|
||||
if ($customField instanceof JsonResponse) {
|
||||
return $customField;
|
||||
}
|
||||
|
||||
$target = $this->resolveTarget($payload);
|
||||
if ($target instanceof JsonResponse) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$value = new CustomFieldValue();
|
||||
$value->setCustomField($customField);
|
||||
$value->setValue((string) ($payload['value'] ?? ''));
|
||||
$this->applyTarget($value, $target['type'], $target['entity']);
|
||||
|
||||
$this->entityManager->persist($value);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json($this->normalizeCustomFieldValue($value));
|
||||
}
|
||||
|
||||
#[Route('/upsert', name: 'custom_field_values_upsert', methods: ['POST'])]
|
||||
public function upsert(Request $request): JsonResponse
|
||||
{
|
||||
$payload = $this->decodePayload($request);
|
||||
if ($payload instanceof JsonResponse) {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
$customField = $this->resolveCustomField($payload);
|
||||
if ($customField instanceof JsonResponse) {
|
||||
return $customField;
|
||||
}
|
||||
|
||||
$target = $this->resolveTarget($payload);
|
||||
if ($target instanceof JsonResponse) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$existing = $this->customFieldValueRepository->findOneBy([
|
||||
'customField' => $customField,
|
||||
$target['type'] => $target['entity'],
|
||||
]);
|
||||
|
||||
if ($existing instanceof CustomFieldValue) {
|
||||
$existing->setValue((string) ($payload['value'] ?? ''));
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json($this->normalizeCustomFieldValue($existing));
|
||||
}
|
||||
|
||||
$value = new CustomFieldValue();
|
||||
$value->setCustomField($customField);
|
||||
$value->setValue((string) ($payload['value'] ?? ''));
|
||||
$this->applyTarget($value, $target['type'], $target['entity']);
|
||||
|
||||
$this->entityManager->persist($value);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json($this->normalizeCustomFieldValue($value));
|
||||
}
|
||||
|
||||
#[Route('/{entityType}/{entityId}', name: 'custom_field_values_list', methods: ['GET'])]
|
||||
public function listByEntity(string $entityType, string $entityId): JsonResponse
|
||||
{
|
||||
$target = $this->resolveTarget([
|
||||
'entityType' => $entityType,
|
||||
'entityId' => $entityId,
|
||||
]);
|
||||
|
||||
if ($target instanceof JsonResponse) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$values = $this->customFieldValueRepository->findBy([
|
||||
$target['type'] => $target['entity'],
|
||||
]);
|
||||
|
||||
return $this->json(array_map(
|
||||
fn (CustomFieldValue $value) => $this->normalizeCustomFieldValue($value),
|
||||
$values
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'custom_field_values_update', methods: ['PATCH'])]
|
||||
public function update(string $id, Request $request): JsonResponse
|
||||
{
|
||||
$value = $this->customFieldValueRepository->find($id);
|
||||
if (!$value instanceof CustomFieldValue) {
|
||||
return $this->json(['success' => false, 'error' => 'Custom field value not found.'], 404);
|
||||
}
|
||||
|
||||
$payload = $this->decodePayload($request);
|
||||
if ($payload instanceof JsonResponse) {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
if (array_key_exists('value', $payload)) {
|
||||
$value->setValue((string) $payload['value']);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json($this->normalizeCustomFieldValue($value));
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'custom_field_values_delete', methods: ['DELETE'])]
|
||||
public function delete(string $id): JsonResponse
|
||||
{
|
||||
$value = $this->customFieldValueRepository->find($id);
|
||||
if (!$value instanceof CustomFieldValue) {
|
||||
return $this->json(['success' => false, 'error' => 'Custom field value not found.'], 404);
|
||||
}
|
||||
|
||||
$this->entityManager->remove($value);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json(['success' => true]);
|
||||
}
|
||||
|
||||
private function decodePayload(Request $request): array|JsonResponse
|
||||
{
|
||||
$payload = json_decode($request->getContent(), true);
|
||||
if (!is_array($payload)) {
|
||||
return $this->json(['success' => false, 'error' => 'Invalid JSON payload.'], 400);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private function resolveCustomField(array $payload): CustomField|JsonResponse
|
||||
{
|
||||
$customFieldId = isset($payload['customFieldId']) ? trim((string) $payload['customFieldId']) : '';
|
||||
if ($customFieldId !== '') {
|
||||
$customField = $this->customFieldRepository->find($customFieldId);
|
||||
if ($customField instanceof CustomField) {
|
||||
return $customField;
|
||||
}
|
||||
|
||||
return $this->json(['success' => false, 'error' => 'Custom field not found.'], 404);
|
||||
}
|
||||
|
||||
$customFieldName = isset($payload['customFieldName']) ? trim((string) $payload['customFieldName']) : '';
|
||||
if ($customFieldName === '') {
|
||||
return $this->json(['success' => false, 'error' => 'customFieldId or customFieldName is required.'], 400);
|
||||
}
|
||||
|
||||
$customField = new CustomField();
|
||||
$customField->setName($customFieldName);
|
||||
$customField->setType((string) ($payload['customFieldType'] ?? 'text'));
|
||||
$customField->setRequired((bool) ($payload['customFieldRequired'] ?? false));
|
||||
|
||||
$options = $payload['customFieldOptions'] ?? null;
|
||||
if (is_array($options)) {
|
||||
$customField->setOptions($options);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($customField);
|
||||
|
||||
return $customField;
|
||||
}
|
||||
|
||||
private function resolveTarget(array $payload): array|JsonResponse
|
||||
{
|
||||
$entityType = isset($payload['entityType']) ? strtolower((string) $payload['entityType']) : '';
|
||||
$entityId = isset($payload['entityId']) ? trim((string) $payload['entityId']) : '';
|
||||
|
||||
if ($entityType === '' || $entityId === '') {
|
||||
foreach (['machine', 'composant', 'piece', 'product'] as $candidate) {
|
||||
$key = $candidate . 'Id';
|
||||
if (!isset($payload[$key])) {
|
||||
continue;
|
||||
}
|
||||
$entityType = $candidate;
|
||||
$entityId = trim((string) $payload[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entityType === '' || $entityId === '') {
|
||||
return $this->json(['success' => false, 'error' => 'Entity target is missing.'], 400);
|
||||
}
|
||||
|
||||
return match ($entityType) {
|
||||
'machine' => $this->resolveEntity('machine', $entityId, $this->machineRepository),
|
||||
'composant' => $this->resolveEntity('composant', $entityId, $this->composantRepository),
|
||||
'piece' => $this->resolveEntity('piece', $entityId, $this->pieceRepository),
|
||||
'product' => $this->resolveEntity('product', $entityId, $this->productRepository),
|
||||
default => $this->json(['success' => false, 'error' => 'Unsupported entity type.'], 400),
|
||||
};
|
||||
}
|
||||
|
||||
private function resolveEntity(string $type, string $id, $repository): array|JsonResponse
|
||||
{
|
||||
$entity = $repository->find($id);
|
||||
if (!$entity) {
|
||||
return $this->json(['success' => false, 'error' => sprintf('%s not found.', $type)], 404);
|
||||
}
|
||||
|
||||
return ['type' => $type, 'entity' => $entity];
|
||||
}
|
||||
|
||||
private function applyTarget(CustomFieldValue $value, string $type, object $entity): void
|
||||
{
|
||||
switch ($type) {
|
||||
case 'machine':
|
||||
$value->setMachine($entity);
|
||||
break;
|
||||
case 'composant':
|
||||
$value->setComposant($entity);
|
||||
break;
|
||||
case 'piece':
|
||||
$value->setPiece($entity);
|
||||
break;
|
||||
case 'product':
|
||||
$value->setProduct($entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function normalizeCustomFieldValue(CustomFieldValue $value): array
|
||||
{
|
||||
$customField = $value->getCustomField();
|
||||
|
||||
return [
|
||||
'id' => $value->getId(),
|
||||
'value' => $value->getValue(),
|
||||
'customFieldId' => $customField->getId(),
|
||||
'customField' => [
|
||||
'id' => $customField->getId(),
|
||||
'name' => $customField->getName(),
|
||||
'type' => $customField->getType(),
|
||||
'required' => $customField->isRequired(),
|
||||
'options' => $customField->getOptions(),
|
||||
'orderIndex' => $customField->getOrderIndex(),
|
||||
],
|
||||
'machineId' => $value->getMachine()?->getId(),
|
||||
'composantId' => $value->getComposant()?->getId(),
|
||||
'pieceId' => $value->getPiece()?->getId(),
|
||||
'productId' => $value->getProduct()?->getId(),
|
||||
'createdAt' => $value->getCreatedAt()->format(DATE_ATOM),
|
||||
'updatedAt' => $value->getUpdatedAt()->format(DATE_ATOM),
|
||||
];
|
||||
}
|
||||
}
|
||||
119
src/Controller/DocumentQueryController.php
Normal file
119
src/Controller/DocumentQueryController.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Document;
|
||||
use App\Repository\ComposantRepository;
|
||||
use App\Repository\DocumentRepository;
|
||||
use App\Repository\MachineRepository;
|
||||
use App\Repository\PieceRepository;
|
||||
use App\Repository\ProductRepository;
|
||||
use App\Repository\SiteRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/documents')]
|
||||
class DocumentQueryController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DocumentRepository $documentRepository,
|
||||
private readonly SiteRepository $siteRepository,
|
||||
private readonly MachineRepository $machineRepository,
|
||||
private readonly ComposantRepository $composantRepository,
|
||||
private readonly PieceRepository $pieceRepository,
|
||||
private readonly ProductRepository $productRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/site/{id}', name: 'documents_by_site', methods: ['GET'])]
|
||||
public function listBySite(string $id): JsonResponse
|
||||
{
|
||||
$site = $this->siteRepository->find($id);
|
||||
if (!$site) {
|
||||
return $this->json(['success' => false, 'error' => 'Site not found.'], 404);
|
||||
}
|
||||
|
||||
$documents = $this->documentRepository->findBy(['site' => $site]);
|
||||
|
||||
return $this->json($this->normalizeDocuments($documents));
|
||||
}
|
||||
|
||||
#[Route('/machine/{id}', name: 'documents_by_machine', methods: ['GET'])]
|
||||
public function listByMachine(string $id): JsonResponse
|
||||
{
|
||||
$machine = $this->machineRepository->find($id);
|
||||
if (!$machine) {
|
||||
return $this->json(['success' => false, 'error' => 'Machine not found.'], 404);
|
||||
}
|
||||
|
||||
$documents = $this->documentRepository->findBy(['machine' => $machine]);
|
||||
|
||||
return $this->json($this->normalizeDocuments($documents));
|
||||
}
|
||||
|
||||
#[Route('/composant/{id}', name: 'documents_by_composant', methods: ['GET'])]
|
||||
public function listByComposant(string $id): JsonResponse
|
||||
{
|
||||
$composant = $this->composantRepository->find($id);
|
||||
if (!$composant) {
|
||||
return $this->json(['success' => false, 'error' => 'Composant not found.'], 404);
|
||||
}
|
||||
|
||||
$documents = $this->documentRepository->findBy(['composant' => $composant]);
|
||||
|
||||
return $this->json($this->normalizeDocuments($documents));
|
||||
}
|
||||
|
||||
#[Route('/piece/{id}', name: 'documents_by_piece', methods: ['GET'])]
|
||||
public function listByPiece(string $id): JsonResponse
|
||||
{
|
||||
$piece = $this->pieceRepository->find($id);
|
||||
if (!$piece) {
|
||||
return $this->json(['success' => false, 'error' => 'Piece not found.'], 404);
|
||||
}
|
||||
|
||||
$documents = $this->documentRepository->findBy(['piece' => $piece]);
|
||||
|
||||
return $this->json($this->normalizeDocuments($documents));
|
||||
}
|
||||
|
||||
#[Route('/product/{id}', name: 'documents_by_product', methods: ['GET'])]
|
||||
public function listByProduct(string $id): JsonResponse
|
||||
{
|
||||
$product = $this->productRepository->find($id);
|
||||
if (!$product) {
|
||||
return $this->json(['success' => false, 'error' => 'Product not found.'], 404);
|
||||
}
|
||||
|
||||
$documents = $this->documentRepository->findBy(['product' => $product]);
|
||||
|
||||
return $this->json($this->normalizeDocuments($documents));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document[] $documents
|
||||
*/
|
||||
private function normalizeDocuments(array $documents): array
|
||||
{
|
||||
return array_map(static function (Document $document): array {
|
||||
return [
|
||||
'id' => $document->getId(),
|
||||
'name' => $document->getName(),
|
||||
'filename' => $document->getFilename(),
|
||||
'path' => $document->getPath(),
|
||||
'mimeType' => $document->getMimeType(),
|
||||
'size' => $document->getSize(),
|
||||
'siteId' => $document->getSite()?->getId(),
|
||||
'machineId' => $document->getMachine()?->getId(),
|
||||
'composantId' => $document->getComposant()?->getId(),
|
||||
'pieceId' => $document->getPiece()?->getId(),
|
||||
'productId' => $document->getProduct()?->getId(),
|
||||
'createdAt' => $document->getCreatedAt()->format(DATE_ATOM),
|
||||
'updatedAt' => $document->getUpdatedAt()->format(DATE_ATOM),
|
||||
];
|
||||
}, $documents);
|
||||
}
|
||||
}
|
||||
76
src/Controller/MachineCustomFieldsController.php
Normal file
76
src/Controller/MachineCustomFieldsController.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\CustomField;
|
||||
use App\Entity\CustomFieldValue;
|
||||
use App\Entity\Machine;
|
||||
use App\Repository\CustomFieldValueRepository;
|
||||
use App\Repository\MachineRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/machines')]
|
||||
class MachineCustomFieldsController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly MachineRepository $machineRepository,
|
||||
private readonly CustomFieldValueRepository $customFieldValueRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/{id}/add-custom-fields', name: 'machine_add_custom_fields', methods: ['POST'])]
|
||||
public function addMissingCustomFields(string $id): JsonResponse
|
||||
{
|
||||
$machine = $this->machineRepository->find($id);
|
||||
if (!$machine instanceof Machine) {
|
||||
return $this->json(['success' => false, 'error' => 'Machine not found.'], 404);
|
||||
}
|
||||
|
||||
$typeMachine = $machine->getTypeMachine();
|
||||
if (!$typeMachine) {
|
||||
return $this->json(['success' => true, 'machineId' => $machine->getId(), 'customFieldValues' => []]);
|
||||
}
|
||||
|
||||
foreach ($typeMachine->getCustomFields() as $customField) {
|
||||
if (!$customField instanceof CustomField) {
|
||||
continue;
|
||||
}
|
||||
$existing = $this->customFieldValueRepository->findOneBy([
|
||||
'machine' => $machine,
|
||||
'customField' => $customField,
|
||||
]);
|
||||
if ($existing instanceof CustomFieldValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = new CustomFieldValue();
|
||||
$value->setMachine($machine);
|
||||
$value->setCustomField($customField);
|
||||
$value->setValue($customField->getDefaultValue() ?? '');
|
||||
$this->entityManager->persist($value);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$values = $this->customFieldValueRepository->findBy(['machine' => $machine]);
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'machineId' => $machine->getId(),
|
||||
'customFieldValues' => array_map(
|
||||
static fn (CustomFieldValue $value) => [
|
||||
'id' => $value->getId(),
|
||||
'value' => $value->getValue(),
|
||||
'customFieldId' => $value->getCustomField()->getId(),
|
||||
],
|
||||
$values
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
657
src/Controller/MachineSkeletonController.php
Normal file
657
src/Controller/MachineSkeletonController.php
Normal file
@@ -0,0 +1,657 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Composant;
|
||||
use App\Entity\Machine;
|
||||
use App\Entity\MachineComponentLink;
|
||||
use App\Entity\MachinePieceLink;
|
||||
use App\Entity\MachineProductLink;
|
||||
use App\Entity\ModelType;
|
||||
use App\Entity\Piece;
|
||||
use App\Entity\Product;
|
||||
use App\Entity\TypeMachineComponentRequirement;
|
||||
use App\Entity\TypeMachinePieceRequirement;
|
||||
use App\Entity\TypeMachineProductRequirement;
|
||||
use App\Repository\ComposantRepository;
|
||||
use App\Repository\MachineComponentLinkRepository;
|
||||
use App\Repository\MachinePieceLinkRepository;
|
||||
use App\Repository\MachineProductLinkRepository;
|
||||
use App\Repository\MachineRepository;
|
||||
use App\Repository\PieceRepository;
|
||||
use App\Repository\ProductRepository;
|
||||
use App\Repository\TypeMachineComponentRequirementRepository;
|
||||
use App\Repository\TypeMachinePieceRequirementRepository;
|
||||
use App\Repository\TypeMachineProductRequirementRepository;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/machines')]
|
||||
class MachineSkeletonController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly MachineRepository $machineRepository,
|
||||
private readonly MachineComponentLinkRepository $machineComponentLinkRepository,
|
||||
private readonly MachinePieceLinkRepository $machinePieceLinkRepository,
|
||||
private readonly MachineProductLinkRepository $machineProductLinkRepository,
|
||||
private readonly ComposantRepository $composantRepository,
|
||||
private readonly PieceRepository $pieceRepository,
|
||||
private readonly ProductRepository $productRepository,
|
||||
private readonly TypeMachineComponentRequirementRepository $componentRequirementRepository,
|
||||
private readonly TypeMachinePieceRequirementRepository $pieceRequirementRepository,
|
||||
private readonly TypeMachineProductRequirementRepository $productRequirementRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/{id}/skeleton', name: 'machine_skeleton_update', methods: ['PATCH'])]
|
||||
public function updateSkeleton(string $id, Request $request): JsonResponse
|
||||
{
|
||||
$machine = $this->machineRepository->find($id);
|
||||
if (!$machine instanceof Machine) {
|
||||
return $this->json(['success' => false, 'error' => 'Machine not found.'], 404);
|
||||
}
|
||||
|
||||
$payload = json_decode($request->getContent(), true);
|
||||
if (!is_array($payload)) {
|
||||
return $this->json(['success' => false, 'error' => 'Invalid JSON payload.'], 400);
|
||||
}
|
||||
|
||||
$componentLinksPayload = $this->normalizePayloadList($payload['componentLinks'] ?? []);
|
||||
$pieceLinksPayload = $this->normalizePayloadList($payload['pieceLinks'] ?? []);
|
||||
$productLinksPayload = $this->normalizePayloadList($payload['productLinks'] ?? []);
|
||||
|
||||
$componentLinks = $this->applyComponentLinks($machine, $componentLinksPayload);
|
||||
if ($componentLinks instanceof JsonResponse) {
|
||||
return $componentLinks;
|
||||
}
|
||||
|
||||
$pieceLinks = $this->applyPieceLinks($machine, $pieceLinksPayload, $componentLinks);
|
||||
if ($pieceLinks instanceof JsonResponse) {
|
||||
return $pieceLinks;
|
||||
}
|
||||
|
||||
$productLinks = $this->applyProductLinks($machine, $productLinksPayload, $componentLinks, $pieceLinks);
|
||||
if ($productLinks instanceof JsonResponse) {
|
||||
return $productLinks;
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json($this->normalizeMachineSkeletonResponse(
|
||||
$machine,
|
||||
$componentLinks,
|
||||
$pieceLinks,
|
||||
$productLinks
|
||||
));
|
||||
}
|
||||
|
||||
private function normalizePayloadList(mixed $value): array
|
||||
{
|
||||
if (!is_array($value)) {
|
||||
return [];
|
||||
}
|
||||
return array_values(array_filter($value, static fn ($item) => is_array($item)));
|
||||
}
|
||||
|
||||
private function applyComponentLinks(Machine $machine, array $payload): array|JsonResponse
|
||||
{
|
||||
$existing = $this->indexLinksById($this->machineComponentLinkRepository->findBy(['machine' => $machine]));
|
||||
$keepIds = [];
|
||||
$pendingParents = [];
|
||||
$links = [];
|
||||
|
||||
foreach ($payload as $entry) {
|
||||
$linkId = $this->resolveIdentifier($entry, ['id', 'linkId']);
|
||||
$link = $linkId && isset($existing[$linkId]) ? $existing[$linkId] : new MachineComponentLink();
|
||||
if (!$linkId) {
|
||||
$linkId = $this->generateCuid();
|
||||
}
|
||||
if (!$link->getId()) {
|
||||
$link->setId($linkId);
|
||||
}
|
||||
|
||||
$composantId = $this->resolveIdentifier($entry, ['composantId', 'componentId', 'idComposant']);
|
||||
if (!$composantId) {
|
||||
return $this->json(['success' => false, 'error' => 'Composant requis pour le squelette.'], 400);
|
||||
}
|
||||
$composant = $this->composantRepository->find($composantId);
|
||||
if (!$composant instanceof Composant) {
|
||||
return $this->json(['success' => false, 'error' => 'Composant introuvable.'], 404);
|
||||
}
|
||||
|
||||
$link->setMachine($machine);
|
||||
$link->setComposant($composant);
|
||||
|
||||
$requirementId = $this->resolveIdentifier($entry, ['requirementId', 'typeMachineComponentRequirementId']);
|
||||
if ($requirementId) {
|
||||
$requirement = $this->componentRequirementRepository->find($requirementId);
|
||||
if ($requirement instanceof TypeMachineComponentRequirement) {
|
||||
$link->setTypeMachineComponentRequirement($requirement);
|
||||
}
|
||||
}
|
||||
|
||||
$this->applyOverrides($link, $entry['overrides'] ?? null);
|
||||
|
||||
$pendingParents[$linkId] = $this->resolveIdentifier($entry, [
|
||||
'parentComponentLinkId',
|
||||
'parentLinkId',
|
||||
'parentMachineComponentLinkId',
|
||||
]);
|
||||
|
||||
$this->entityManager->persist($link);
|
||||
$links[$linkId] = $link;
|
||||
$keepIds[] = $linkId;
|
||||
}
|
||||
|
||||
foreach ($pendingParents as $linkId => $parentId) {
|
||||
if (!$parentId) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($links[$linkId])) {
|
||||
continue;
|
||||
}
|
||||
$parent = $links[$parentId] ?? $existing[$parentId] ?? null;
|
||||
if ($parent instanceof MachineComponentLink) {
|
||||
$links[$linkId]->setParentLink($parent);
|
||||
}
|
||||
}
|
||||
|
||||
$this->removeMissingLinks($existing, $keepIds);
|
||||
|
||||
return array_values($links);
|
||||
}
|
||||
|
||||
private function applyPieceLinks(Machine $machine, array $payload, array $componentLinks): array|JsonResponse
|
||||
{
|
||||
$existing = $this->indexLinksById($this->machinePieceLinkRepository->findBy(['machine' => $machine]));
|
||||
$componentIndex = $this->indexLinksById($componentLinks);
|
||||
$keepIds = [];
|
||||
$pendingParents = [];
|
||||
$links = [];
|
||||
|
||||
foreach ($payload as $entry) {
|
||||
$linkId = $this->resolveIdentifier($entry, ['id', 'linkId']);
|
||||
$link = $linkId && isset($existing[$linkId]) ? $existing[$linkId] : new MachinePieceLink();
|
||||
if (!$linkId) {
|
||||
$linkId = $this->generateCuid();
|
||||
}
|
||||
if (!$link->getId()) {
|
||||
$link->setId($linkId);
|
||||
}
|
||||
|
||||
$pieceId = $this->resolveIdentifier($entry, ['pieceId']);
|
||||
if (!$pieceId) {
|
||||
return $this->json(['success' => false, 'error' => 'Pièce requise pour le squelette.'], 400);
|
||||
}
|
||||
$piece = $this->pieceRepository->find($pieceId);
|
||||
if (!$piece instanceof Piece) {
|
||||
return $this->json(['success' => false, 'error' => 'Pièce introuvable.'], 404);
|
||||
}
|
||||
|
||||
$link->setMachine($machine);
|
||||
$link->setPiece($piece);
|
||||
|
||||
$requirementId = $this->resolveIdentifier($entry, ['requirementId', 'typeMachinePieceRequirementId']);
|
||||
if ($requirementId) {
|
||||
$requirement = $this->pieceRequirementRepository->find($requirementId);
|
||||
if ($requirement instanceof TypeMachinePieceRequirement) {
|
||||
$link->setTypeMachinePieceRequirement($requirement);
|
||||
}
|
||||
}
|
||||
|
||||
$this->applyOverrides($link, $entry['overrides'] ?? null);
|
||||
|
||||
$pendingParents[$linkId] = $this->resolveIdentifier($entry, [
|
||||
'parentComponentLinkId',
|
||||
'parentLinkId',
|
||||
'parentMachineComponentLinkId',
|
||||
]);
|
||||
|
||||
$this->entityManager->persist($link);
|
||||
$links[$linkId] = $link;
|
||||
$keepIds[] = $linkId;
|
||||
}
|
||||
|
||||
foreach ($pendingParents as $linkId => $parentId) {
|
||||
if (!$parentId) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($links[$linkId])) {
|
||||
continue;
|
||||
}
|
||||
$parent = $componentIndex[$parentId] ?? null;
|
||||
if ($parent instanceof MachineComponentLink) {
|
||||
$links[$linkId]->setParentLink($parent);
|
||||
}
|
||||
}
|
||||
|
||||
$this->removeMissingLinks($existing, $keepIds);
|
||||
|
||||
return array_values($links);
|
||||
}
|
||||
|
||||
private function applyProductLinks(
|
||||
Machine $machine,
|
||||
array $payload,
|
||||
array $componentLinks,
|
||||
array $pieceLinks,
|
||||
): array|JsonResponse {
|
||||
$existing = $this->indexLinksById($this->machineProductLinkRepository->findBy(['machine' => $machine]));
|
||||
$componentIndex = $this->indexLinksById($componentLinks);
|
||||
$pieceIndex = $this->indexLinksById($pieceLinks);
|
||||
$keepIds = [];
|
||||
$pendingParents = [];
|
||||
$links = [];
|
||||
|
||||
foreach ($payload as $entry) {
|
||||
$linkId = $this->resolveIdentifier($entry, ['id', 'linkId']);
|
||||
$link = $linkId && isset($existing[$linkId]) ? $existing[$linkId] : new MachineProductLink();
|
||||
if (!$linkId) {
|
||||
$linkId = $this->generateCuid();
|
||||
}
|
||||
if (!$link->getId()) {
|
||||
$link->setId($linkId);
|
||||
}
|
||||
|
||||
$productId = $this->resolveIdentifier($entry, ['productId']);
|
||||
if (!$productId) {
|
||||
return $this->json(['success' => false, 'error' => 'Produit requis pour le squelette.'], 400);
|
||||
}
|
||||
$product = $this->productRepository->find($productId);
|
||||
if (!$product instanceof Product) {
|
||||
return $this->json(['success' => false, 'error' => 'Produit introuvable.'], 404);
|
||||
}
|
||||
|
||||
$link->setMachine($machine);
|
||||
$link->setProduct($product);
|
||||
|
||||
$requirementId = $this->resolveIdentifier($entry, ['requirementId', 'typeMachineProductRequirementId']);
|
||||
if ($requirementId) {
|
||||
$requirement = $this->productRequirementRepository->find($requirementId);
|
||||
if ($requirement instanceof TypeMachineProductRequirement) {
|
||||
$link->setTypeMachineProductRequirement($requirement);
|
||||
}
|
||||
}
|
||||
|
||||
$pendingParents[$linkId] = [
|
||||
'parentComponentLinkId' => $this->resolveIdentifier($entry, ['parentComponentLinkId']),
|
||||
'parentPieceLinkId' => $this->resolveIdentifier($entry, ['parentPieceLinkId']),
|
||||
'parentLinkId' => $this->resolveIdentifier($entry, ['parentLinkId']),
|
||||
];
|
||||
|
||||
$this->entityManager->persist($link);
|
||||
$links[$linkId] = $link;
|
||||
$keepIds[] = $linkId;
|
||||
}
|
||||
|
||||
foreach ($pendingParents as $linkId => $parentIds) {
|
||||
if (!isset($links[$linkId])) {
|
||||
continue;
|
||||
}
|
||||
if (!empty($parentIds['parentComponentLinkId']) && isset($componentIndex[$parentIds['parentComponentLinkId']])) {
|
||||
$links[$linkId]->setParentComponentLink($componentIndex[$parentIds['parentComponentLinkId']]);
|
||||
}
|
||||
if (!empty($parentIds['parentPieceLinkId']) && isset($pieceIndex[$parentIds['parentPieceLinkId']])) {
|
||||
$links[$linkId]->setParentPieceLink($pieceIndex[$parentIds['parentPieceLinkId']]);
|
||||
}
|
||||
if (!empty($parentIds['parentLinkId']) && isset($links[$parentIds['parentLinkId']])) {
|
||||
$links[$linkId]->setParentLink($links[$parentIds['parentLinkId']]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->removeMissingLinks($existing, $keepIds);
|
||||
|
||||
return array_values($links);
|
||||
}
|
||||
|
||||
private function normalizeMachineSkeletonResponse(
|
||||
Machine $machine,
|
||||
array $componentLinks,
|
||||
array $pieceLinks,
|
||||
array $productLinks,
|
||||
): array {
|
||||
$normalizedComponentLinks = $this->normalizeComponentLinks($componentLinks);
|
||||
$componentIndex = $this->indexNormalizedLinks($normalizedComponentLinks);
|
||||
$normalizedPieceLinks = $this->normalizePieceLinks($pieceLinks);
|
||||
|
||||
foreach ($normalizedComponentLinks as &$link) {
|
||||
$parentId = $link['parentComponentLinkId'] ?? null;
|
||||
if ($parentId && isset($componentIndex[$parentId])) {
|
||||
$componentIndex[$parentId]['childLinks'][] = $link;
|
||||
}
|
||||
}
|
||||
unset($link);
|
||||
|
||||
foreach ($normalizedPieceLinks as $pieceLink) {
|
||||
$parentId = $pieceLink['parentComponentLinkId'] ?? null;
|
||||
if ($parentId && isset($componentIndex[$parentId])) {
|
||||
$componentIndex[$parentId]['pieceLinks'][] = $pieceLink;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'machine' => $this->normalizeMachine($machine),
|
||||
'componentLinks' => array_values($componentIndex),
|
||||
'pieceLinks' => $normalizedPieceLinks,
|
||||
'productLinks' => $this->normalizeProductLinks($productLinks),
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeMachine(Machine $machine): array
|
||||
{
|
||||
return [
|
||||
'id' => $machine->getId(),
|
||||
'name' => $machine->getName(),
|
||||
'reference' => $machine->getReference(),
|
||||
'prix' => $machine->getPrix(),
|
||||
'siteId' => $machine->getSite()->getId(),
|
||||
'typeMachineId' => $machine->getTypeMachine()?->getId(),
|
||||
'documents' => null,
|
||||
'customFieldValues' => null,
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeComponentLinks(array $links): array
|
||||
{
|
||||
return array_map(function (MachineComponentLink $link): array {
|
||||
$composant = $link->getComposant();
|
||||
$requirement = $link->getTypeMachineComponentRequirement();
|
||||
$parentLink = $link->getParentLink();
|
||||
$parentRequirementId = $parentLink?->getTypeMachineComponentRequirement()?->getId();
|
||||
|
||||
return [
|
||||
'id' => $link->getId(),
|
||||
'linkId' => $link->getId(),
|
||||
'machineId' => $link->getMachine()->getId(),
|
||||
'composantId' => $composant->getId(),
|
||||
'composant' => $this->normalizeComposant($composant),
|
||||
'typeMachineComponentRequirementId' => $requirement?->getId(),
|
||||
'typeMachineComponentRequirement' => $requirement ? $this->normalizeComponentRequirement($requirement) : null,
|
||||
'parentLinkId' => $parentLink?->getId(),
|
||||
'parentComponentLinkId' => $parentLink?->getId(),
|
||||
'parentComponentId' => $parentLink?->getComposant()->getId(),
|
||||
'parentMachineComponentRequirementId' => $parentRequirementId,
|
||||
'overrides' => $this->normalizeOverrides($link),
|
||||
'childLinks' => [],
|
||||
'pieceLinks' => [],
|
||||
];
|
||||
}, $links);
|
||||
}
|
||||
|
||||
private function normalizePieceLinks(array $links): array
|
||||
{
|
||||
return array_map(function (MachinePieceLink $link): array {
|
||||
$piece = $link->getPiece();
|
||||
$requirement = $link->getTypeMachinePieceRequirement();
|
||||
$parentLink = $link->getParentLink();
|
||||
$parentRequirementId = $parentLink?->getTypeMachineComponentRequirement()?->getId();
|
||||
|
||||
return [
|
||||
'id' => $link->getId(),
|
||||
'linkId' => $link->getId(),
|
||||
'machineId' => $link->getMachine()->getId(),
|
||||
'pieceId' => $piece->getId(),
|
||||
'piece' => $this->normalizePiece($piece),
|
||||
'typeMachinePieceRequirementId' => $requirement?->getId(),
|
||||
'typeMachinePieceRequirement' => $requirement ? $this->normalizePieceRequirement($requirement) : null,
|
||||
'parentLinkId' => $parentLink?->getId(),
|
||||
'parentComponentLinkId' => $parentLink?->getId(),
|
||||
'parentComponentId' => $parentLink?->getComposant()->getId(),
|
||||
'parentMachineComponentRequirementId' => $parentRequirementId,
|
||||
'overrides' => $this->normalizeOverrides($link),
|
||||
];
|
||||
}, $links);
|
||||
}
|
||||
|
||||
private function normalizeProductLinks(array $links): array
|
||||
{
|
||||
return array_map(function (MachineProductLink $link): array {
|
||||
$product = $link->getProduct();
|
||||
$requirement = $link->getTypeMachineProductRequirement();
|
||||
|
||||
return [
|
||||
'id' => $link->getId(),
|
||||
'linkId' => $link->getId(),
|
||||
'machineId' => $link->getMachine()->getId(),
|
||||
'productId' => $product->getId(),
|
||||
'product' => $this->normalizeProduct($product),
|
||||
'typeMachineProductRequirementId' => $requirement?->getId(),
|
||||
'typeMachineProductRequirement' => $requirement ? $this->normalizeProductRequirement($requirement) : null,
|
||||
'parentLinkId' => $link->getParentLink()?->getId(),
|
||||
'parentComponentLinkId' => $link->getParentComponentLink()?->getId(),
|
||||
'parentPieceLinkId' => $link->getParentPieceLink()?->getId(),
|
||||
];
|
||||
}, $links);
|
||||
}
|
||||
|
||||
private function normalizeComposant(Composant $composant): array
|
||||
{
|
||||
return [
|
||||
'id' => $composant->getId(),
|
||||
'name' => $composant->getName(),
|
||||
'reference' => $composant->getReference(),
|
||||
'prix' => $composant->getPrix(),
|
||||
'typeComposantId' => $composant->getTypeComposant()?->getId(),
|
||||
'typeComposant' => $this->normalizeModelType($composant->getTypeComposant()),
|
||||
'productId' => $composant->getProduct()?->getId(),
|
||||
'product' => $composant->getProduct() ? $this->normalizeProduct($composant->getProduct()) : null,
|
||||
'constructeurs' => $this->normalizeConstructeurs($composant->getConstructeurs()),
|
||||
'documents' => [],
|
||||
'customFields' => [],
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizePiece(Piece $piece): array
|
||||
{
|
||||
return [
|
||||
'id' => $piece->getId(),
|
||||
'name' => $piece->getName(),
|
||||
'reference' => $piece->getReference(),
|
||||
'prix' => $piece->getPrix(),
|
||||
'typePieceId' => $piece->getTypePiece()?->getId(),
|
||||
'typePiece' => $this->normalizeModelType($piece->getTypePiece()),
|
||||
'productId' => $piece->getProduct()?->getId(),
|
||||
'product' => $piece->getProduct() ? $this->normalizeProduct($piece->getProduct()) : null,
|
||||
'constructeurs' => $this->normalizeConstructeurs($piece->getConstructeurs()),
|
||||
'documents' => [],
|
||||
'customFields' => [],
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeProduct(Product $product): array
|
||||
{
|
||||
return [
|
||||
'id' => $product->getId(),
|
||||
'name' => $product->getName(),
|
||||
'reference' => $product->getReference(),
|
||||
'supplierPrice' => $product->getSupplierPrice(),
|
||||
'typeProductId' => $product->getTypeProduct()?->getId(),
|
||||
'typeProduct' => $this->normalizeModelType($product->getTypeProduct()),
|
||||
'constructeurs' => $this->normalizeConstructeurs($product->getConstructeurs()),
|
||||
'documents' => [],
|
||||
'customFields' => [],
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeModelType(?ModelType $type): ?array
|
||||
{
|
||||
if (!$type instanceof ModelType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $type->getId(),
|
||||
'name' => $type->getName(),
|
||||
'code' => $type->getCode(),
|
||||
'category' => $type->getCategory()->value,
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeComponentRequirement(TypeMachineComponentRequirement $requirement): array
|
||||
{
|
||||
return [
|
||||
'id' => $requirement->getId(),
|
||||
'label' => $requirement->getLabel(),
|
||||
'minCount' => $requirement->getMinCount(),
|
||||
'maxCount' => $requirement->getMaxCount(),
|
||||
'required' => $requirement->isRequired(),
|
||||
'typeComposantId' => $requirement->getTypeComposant()->getId(),
|
||||
'typeComposant' => $this->normalizeModelType($requirement->getTypeComposant()),
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizePieceRequirement(TypeMachinePieceRequirement $requirement): array
|
||||
{
|
||||
return [
|
||||
'id' => $requirement->getId(),
|
||||
'label' => $requirement->getLabel(),
|
||||
'minCount' => $requirement->getMinCount(),
|
||||
'maxCount' => $requirement->getMaxCount(),
|
||||
'required' => $requirement->isRequired(),
|
||||
'typePieceId' => $requirement->getTypePiece()->getId(),
|
||||
'typePiece' => $this->normalizeModelType($requirement->getTypePiece()),
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeProductRequirement(TypeMachineProductRequirement $requirement): array
|
||||
{
|
||||
return [
|
||||
'id' => $requirement->getId(),
|
||||
'label' => $requirement->getLabel(),
|
||||
'minCount' => $requirement->getMinCount(),
|
||||
'maxCount' => $requirement->getMaxCount(),
|
||||
'required' => $requirement->isRequired(),
|
||||
'typeProductId' => $requirement->getTypeProduct()->getId(),
|
||||
'typeProduct' => $this->normalizeModelType($requirement->getTypeProduct()),
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeConstructeurs(Collection $constructeurs): array
|
||||
{
|
||||
$items = [];
|
||||
foreach ($constructeurs as $constructeur) {
|
||||
$items[] = [
|
||||
'id' => $constructeur->getId(),
|
||||
'name' => $constructeur->getName(),
|
||||
'email' => $constructeur->getEmail(),
|
||||
'phone' => $constructeur->getPhone(),
|
||||
];
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
private function normalizeOverrides(object $link): ?array
|
||||
{
|
||||
$name = method_exists($link, 'getNameOverride') ? $link->getNameOverride() : null;
|
||||
$reference = method_exists($link, 'getReferenceOverride') ? $link->getReferenceOverride() : null;
|
||||
$prix = method_exists($link, 'getPrixOverride') ? $link->getPrixOverride() : null;
|
||||
|
||||
if ($name === null && $reference === null && $prix === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $name,
|
||||
'reference' => $reference,
|
||||
'prix' => $prix,
|
||||
];
|
||||
}
|
||||
|
||||
private function applyOverrides(object $link, mixed $overrides): void
|
||||
{
|
||||
if (!is_array($overrides)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_key_exists('name', $overrides) && method_exists($link, 'setNameOverride')) {
|
||||
$link->setNameOverride($this->stringOrNull($overrides['name']));
|
||||
}
|
||||
if (array_key_exists('reference', $overrides) && method_exists($link, 'setReferenceOverride')) {
|
||||
$link->setReferenceOverride($this->stringOrNull($overrides['reference']));
|
||||
}
|
||||
if (array_key_exists('prix', $overrides) && method_exists($link, 'setPrixOverride')) {
|
||||
$link->setPrixOverride($this->stringOrNull($overrides['prix']));
|
||||
}
|
||||
}
|
||||
|
||||
private function stringOrNull(mixed $value): ?string
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
$string = trim((string) $value);
|
||||
|
||||
return $string === '' ? null : $string;
|
||||
}
|
||||
|
||||
private function resolveIdentifier(array $entry, array $keys): ?string
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
if (!array_key_exists($key, $entry)) {
|
||||
continue;
|
||||
}
|
||||
$value = $entry[$key];
|
||||
if ($value === null || $value === '') {
|
||||
continue;
|
||||
}
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<array-key, object> $links
|
||||
* @return array<string, object>
|
||||
*/
|
||||
private function indexLinksById(array $links): array
|
||||
{
|
||||
$indexed = [];
|
||||
foreach ($links as $link) {
|
||||
if (method_exists($link, 'getId') && $link->getId()) {
|
||||
$indexed[$link->getId()] = $link;
|
||||
}
|
||||
}
|
||||
|
||||
return $indexed;
|
||||
}
|
||||
|
||||
private function indexNormalizedLinks(array $links): array
|
||||
{
|
||||
$indexed = [];
|
||||
foreach ($links as $link) {
|
||||
if (is_array($link) && isset($link['id'])) {
|
||||
$indexed[$link['id']] = $link;
|
||||
}
|
||||
}
|
||||
|
||||
return $indexed;
|
||||
}
|
||||
|
||||
private function removeMissingLinks(array $existing, array $keepIds): void
|
||||
{
|
||||
$keep = array_flip($keepIds);
|
||||
foreach ($existing as $link) {
|
||||
if (!method_exists($link, 'getId')) {
|
||||
continue;
|
||||
}
|
||||
$id = $link->getId();
|
||||
if ($id && !isset($keep[$id])) {
|
||||
$this->entityManager->remove($link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
}
|
||||
90
src/Controller/SessionProfileController.php
Normal file
90
src/Controller/SessionProfileController.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Repository\ProfileRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class SessionProfileController
|
||||
{
|
||||
public function __construct(private readonly ProfileRepository $profiles)
|
||||
{
|
||||
}
|
||||
|
||||
#[Route('/api/session/profile', name: 'api_session_profile_get', methods: ['GET'])]
|
||||
public function getActiveProfile(Request $request): JsonResponse
|
||||
{
|
||||
$session = $request->getSession();
|
||||
if (!$session instanceof SessionInterface) {
|
||||
return new JsonResponse(['message' => 'Session indisponible.'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$profileId = $session->get('profileId');
|
||||
if (!$profileId) {
|
||||
return new JsonResponse(['message' => 'Aucun profil actif.'], JsonResponse::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$profile = $this->profiles->find($profileId);
|
||||
if (!$profile || !$profile->isActive()) {
|
||||
$session->remove('profileId');
|
||||
return new JsonResponse(['message' => 'Profil introuvable ou inactif.'], JsonResponse::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
return new JsonResponse([
|
||||
'id' => $profile->getId(),
|
||||
'firstName' => $profile->getFirstName(),
|
||||
'lastName' => $profile->getLastName(),
|
||||
'email' => $profile->getEmail(),
|
||||
'isActive' => $profile->isActive(),
|
||||
'roles' => $profile->getRoles(),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/session/profile', name: 'api_session_profile_post', methods: ['POST'])]
|
||||
public function activateProfile(Request $request): JsonResponse
|
||||
{
|
||||
$session = $request->getSession();
|
||||
if (!$session instanceof SessionInterface) {
|
||||
return new JsonResponse(['message' => 'Session indisponible.'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$payload = $request->toArray();
|
||||
$profileId = $payload['profileId'] ?? null;
|
||||
|
||||
if (!$profileId) {
|
||||
return new JsonResponse(['message' => 'profileId est requis.'], JsonResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$profile = $this->profiles->find($profileId);
|
||||
if (!$profile || !$profile->isActive()) {
|
||||
return new JsonResponse(['message' => 'Profil introuvable ou inactif.'], JsonResponse::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$session->set('profileId', $profile->getId());
|
||||
|
||||
return new JsonResponse([
|
||||
'id' => $profile->getId(),
|
||||
'firstName' => $profile->getFirstName(),
|
||||
'lastName' => $profile->getLastName(),
|
||||
'email' => $profile->getEmail(),
|
||||
'isActive' => $profile->isActive(),
|
||||
'roles' => $profile->getRoles(),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/session/profile', name: 'api_session_profile_delete', methods: ['DELETE'])]
|
||||
public function logout(Request $request): JsonResponse
|
||||
{
|
||||
$session = $request->getSession();
|
||||
if ($session instanceof SessionInterface) {
|
||||
$session->invalidate();
|
||||
}
|
||||
|
||||
return new JsonResponse(['success' => true]);
|
||||
}
|
||||
}
|
||||
80
src/Controller/SessionProfilesController.php
Normal file
80
src/Controller/SessionProfilesController.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Profile;
|
||||
use App\Repository\ProfileRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class SessionProfilesController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ProfileRepository $profiles,
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/api/session/profiles', name: 'api_session_profiles_list', methods: ['GET'])]
|
||||
public function list(): JsonResponse
|
||||
{
|
||||
$items = $this->profiles->createQueryBuilder('p')
|
||||
->andWhere('p.isActive = :active')
|
||||
->setParameter('active', true)
|
||||
->orderBy('p.firstName', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
return new JsonResponse(array_map([$this, 'serializeProfile'], $items));
|
||||
}
|
||||
|
||||
#[Route('/api/session/profiles', name: 'api_session_profiles_create', methods: ['POST'])]
|
||||
public function create(Request $request): JsonResponse
|
||||
{
|
||||
$payload = $request->toArray();
|
||||
$firstName = trim((string) ($payload['firstName'] ?? ''));
|
||||
$lastName = trim((string) ($payload['lastName'] ?? ''));
|
||||
|
||||
if ($firstName === '' || $lastName === '') {
|
||||
return new JsonResponse(['message' => 'firstName et lastName sont requis.'], JsonResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$profile = new Profile();
|
||||
$profile->setFirstName($firstName);
|
||||
$profile->setLastName($lastName);
|
||||
$profile->setIsActive(true);
|
||||
|
||||
$this->entityManager->persist($profile);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse($this->serializeProfile($profile), JsonResponse::HTTP_CREATED);
|
||||
}
|
||||
|
||||
#[Route('/api/session/profiles/{id}', name: 'api_session_profiles_delete', methods: ['DELETE'])]
|
||||
public function delete(string $id): JsonResponse
|
||||
{
|
||||
$profile = $this->profiles->find($id);
|
||||
if (!$profile) {
|
||||
return new JsonResponse(['message' => 'Profil introuvable.'], JsonResponse::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$profile->setIsActive(false);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(['success' => true]);
|
||||
}
|
||||
|
||||
private function serializeProfile(Profile $profile): array
|
||||
{
|
||||
return [
|
||||
'id' => $profile->getId(),
|
||||
'firstName' => $profile->getFirstName(),
|
||||
'lastName' => $profile->getLastName(),
|
||||
'isActive' => $profile->isActive(),
|
||||
];
|
||||
}
|
||||
}
|
||||
227
src/Entity/Composant.php
Normal file
227
src/Entity/Composant.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\ComposantRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ComposantRepository::class)]
|
||||
#[ORM\Table(name: 'composants')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Composant
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $reference = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true)]
|
||||
private ?string $prix = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
private ?array $structure = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'composants')]
|
||||
#[ORM\JoinColumn(name: 'typeComposantId', referencedColumnName: 'id', nullable: true)]
|
||||
private ?ModelType $typeComposant = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'composants')]
|
||||
#[ORM\JoinColumn(name: 'productId', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?Product $product = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Constructeur>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Constructeur::class, inversedBy: 'composants')]
|
||||
#[ORM\JoinTable(
|
||||
name: '_ComposantConstructeurs',
|
||||
joinColumns: [new ORM\JoinColumn(name: 'A', referencedColumnName: 'id', onDelete: 'CASCADE')],
|
||||
inverseJoinColumns: [new ORM\InverseJoinColumn(name: 'B', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
)]
|
||||
private Collection $constructeurs;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Document>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'composant', targetEntity: Document::class)]
|
||||
private Collection $documents;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomFieldValue>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'composant', targetEntity: CustomFieldValue::class)]
|
||||
private Collection $customFieldValues;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineComponentLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'composant', targetEntity: MachineComponentLink::class)]
|
||||
private Collection $machineLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructeurs = new ArrayCollection();
|
||||
$this->documents = new ArrayCollection();
|
||||
$this->customFieldValues = new ArrayCollection();
|
||||
$this->machineLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReference(): ?string
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(?string $reference): static
|
||||
{
|
||||
$this->reference = $reference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrix(): ?string
|
||||
{
|
||||
return $this->prix;
|
||||
}
|
||||
|
||||
public function setPrix(?string $prix): static
|
||||
{
|
||||
$this->prix = $prix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStructure(): ?array
|
||||
{
|
||||
return $this->structure;
|
||||
}
|
||||
|
||||
public function setStructure(?array $structure): static
|
||||
{
|
||||
$this->structure = $structure;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeComposant(): ?ModelType
|
||||
{
|
||||
return $this->typeComposant;
|
||||
}
|
||||
|
||||
public function setTypeComposant(?ModelType $typeComposant): static
|
||||
{
|
||||
$this->typeComposant = $typeComposant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): static
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Constructeur>
|
||||
*/
|
||||
public function getConstructeurs(): Collection
|
||||
{
|
||||
return $this->constructeurs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Document>
|
||||
*/
|
||||
public function getDocuments(): Collection
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, CustomFieldValue>
|
||||
*/
|
||||
public function getCustomFieldValues(): Collection
|
||||
{
|
||||
return $this->customFieldValues;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
151
src/Entity/Constructeur.php
Normal file
151
src/Entity/Constructeur.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\ConstructeurRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ConstructeurRepository::class)]
|
||||
#[ORM\Table(name: 'constructeurs')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Constructeur
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $email = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $phone = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Machine>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Machine::class, mappedBy: 'constructeurs')]
|
||||
private Collection $machines;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Composant>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Composant::class, mappedBy: 'constructeurs')]
|
||||
private Collection $composants;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Piece>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Piece::class, mappedBy: 'constructeurs')]
|
||||
private Collection $pieces;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Product>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Product::class, mappedBy: 'constructeurs')]
|
||||
private Collection $products;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->machines = new ArrayCollection();
|
||||
$this->composants = new ArrayCollection();
|
||||
$this->pieces = new ArrayCollection();
|
||||
$this->products = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(?string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPhone(): ?string
|
||||
{
|
||||
return $this->phone;
|
||||
}
|
||||
|
||||
public function setPhone(?string $phone): static
|
||||
{
|
||||
$this->phone = $phone;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
191
src/Entity/CustomField.php
Normal file
191
src/Entity/CustomField.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\CustomFieldRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: CustomFieldRepository::class)]
|
||||
#[ORM\Table(name: 'custom_fields')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class CustomField
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 50)]
|
||||
private string $type;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
||||
private bool $required = false;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'defaultValue')]
|
||||
private ?string $defaultValue = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
private ?array $options = null;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'orderIndex')]
|
||||
private int $orderIndex = 0;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachine::class, inversedBy: 'customFields')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?TypeMachine $typeMachine = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'customFields')]
|
||||
#[ORM\JoinColumn(name: 'typeComposantId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?ModelType $typeComposant = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'pieceCustomFields')]
|
||||
#[ORM\JoinColumn(name: 'typePieceId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?ModelType $typePiece = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'productCustomFields')]
|
||||
#[ORM\JoinColumn(name: 'typeProductId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?ModelType $typeProduct = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomFieldValue>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'customField', targetEntity: CustomFieldValue::class)]
|
||||
private Collection $customFieldValues;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->customFieldValues = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setRequired(bool $required): static
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultValue(): ?string
|
||||
{
|
||||
return $this->defaultValue;
|
||||
}
|
||||
|
||||
public function setDefaultValue(?string $defaultValue): static
|
||||
{
|
||||
$this->defaultValue = $defaultValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOptions(): ?array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function setOptions(?array $options): static
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderIndex(): int
|
||||
{
|
||||
return $this->orderIndex;
|
||||
}
|
||||
|
||||
public function setOrderIndex(int $orderIndex): static
|
||||
{
|
||||
$this->orderIndex = $orderIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
167
src/Entity/CustomFieldValue.php
Normal file
167
src/Entity/CustomFieldValue.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\CustomFieldValueRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: CustomFieldValueRepository::class)]
|
||||
#[ORM\Table(name: 'custom_field_values')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class CustomFieldValue
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||
private string $value;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: CustomField::class, inversedBy: 'customFieldValues')]
|
||||
#[ORM\JoinColumn(name: 'customFieldId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private CustomField $customField;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Machine::class, inversedBy: 'customFieldValues')]
|
||||
#[ORM\JoinColumn(name: 'machineId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Machine $machine = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Composant::class, inversedBy: 'customFieldValues')]
|
||||
#[ORM\JoinColumn(name: 'composantId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Composant $composant = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Piece::class, inversedBy: 'customFieldValues')]
|
||||
#[ORM\JoinColumn(name: 'pieceId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Piece $piece = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'customFieldValues')]
|
||||
#[ORM\JoinColumn(name: 'productId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Product $product = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue(string $value): static
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomField(): CustomField
|
||||
{
|
||||
return $this->customField;
|
||||
}
|
||||
|
||||
public function setCustomField(CustomField $customField): static
|
||||
{
|
||||
$this->customField = $customField;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachine(): ?Machine
|
||||
{
|
||||
return $this->machine;
|
||||
}
|
||||
|
||||
public function setMachine(?Machine $machine): static
|
||||
{
|
||||
$this->machine = $machine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComposant(): ?Composant
|
||||
{
|
||||
return $this->composant;
|
||||
}
|
||||
|
||||
public function setComposant(?Composant $composant): static
|
||||
{
|
||||
$this->composant = $composant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPiece(): ?Piece
|
||||
{
|
||||
return $this->piece;
|
||||
}
|
||||
|
||||
public function setPiece(?Piece $piece): static
|
||||
{
|
||||
$this->piece = $piece;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): static
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
227
src/Entity/Document.php
Normal file
227
src/Entity/Document.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\DocumentRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: DocumentRepository::class)]
|
||||
#[ORM\Table(name: 'documents')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Document
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||
private string $filename;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT)]
|
||||
private string $path;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 100, name: 'mimeType')]
|
||||
private string $mimeType;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER)]
|
||||
private int $size;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Machine::class, inversedBy: 'documents')]
|
||||
#[ORM\JoinColumn(name: 'machineId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Machine $machine = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Composant::class, inversedBy: 'documents')]
|
||||
#[ORM\JoinColumn(name: 'composantId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Composant $composant = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Piece::class, inversedBy: 'documents')]
|
||||
#[ORM\JoinColumn(name: 'pieceId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Piece $piece = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'documents')]
|
||||
#[ORM\JoinColumn(name: 'productId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Product $product = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Site::class, inversedBy: 'documents')]
|
||||
#[ORM\JoinColumn(name: 'siteId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?Site $site = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
public function setFilename(string $filename): static
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function setPath(string $path): static
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMimeType(): string
|
||||
{
|
||||
return $this->mimeType;
|
||||
}
|
||||
|
||||
public function setMimeType(string $mimeType): static
|
||||
{
|
||||
$this->mimeType = $mimeType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSize(): int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
public function setSize(int $size): static
|
||||
{
|
||||
$this->size = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachine(): ?Machine
|
||||
{
|
||||
return $this->machine;
|
||||
}
|
||||
|
||||
public function setMachine(?Machine $machine): static
|
||||
{
|
||||
$this->machine = $machine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComposant(): ?Composant
|
||||
{
|
||||
return $this->composant;
|
||||
}
|
||||
|
||||
public function setComposant(?Composant $composant): static
|
||||
{
|
||||
$this->composant = $composant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPiece(): ?Piece
|
||||
{
|
||||
return $this->piece;
|
||||
}
|
||||
|
||||
public function setPiece(?Piece $piece): static
|
||||
{
|
||||
$this->piece = $piece;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): static
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSite(): ?Site
|
||||
{
|
||||
return $this->site;
|
||||
}
|
||||
|
||||
public function setSite(?Site $site): static
|
||||
{
|
||||
$this->site = $site;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
250
src/Entity/Machine.php
Normal file
250
src/Entity/Machine.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\MachineRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MachineRepository::class)]
|
||||
#[ORM\Table(name: 'machines')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Machine
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $reference = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true)]
|
||||
private ?string $prix = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Site::class, inversedBy: 'machines')]
|
||||
#[ORM\JoinColumn(name: 'siteId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Site $site;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachine::class, inversedBy: 'machines')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineId', referencedColumnName: 'id', nullable: true)]
|
||||
private ?TypeMachine $typeMachine = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Constructeur>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Constructeur::class, inversedBy: 'machines')]
|
||||
#[ORM\JoinTable(
|
||||
name: '_MachineConstructeurs',
|
||||
joinColumns: [new ORM\JoinColumn(name: 'A', referencedColumnName: 'id', onDelete: 'CASCADE')],
|
||||
inverseJoinColumns: [new ORM\InverseJoinColumn(name: 'B', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
)]
|
||||
private Collection $constructeurs;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineComponentLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'machine', targetEntity: MachineComponentLink::class)]
|
||||
private Collection $componentLinks;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachinePieceLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'machine', targetEntity: MachinePieceLink::class)]
|
||||
private Collection $pieceLinks;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'machine', targetEntity: MachineProductLink::class)]
|
||||
private Collection $productLinks;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Document>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'machine', targetEntity: Document::class)]
|
||||
private Collection $documents;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomFieldValue>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'machine', targetEntity: CustomFieldValue::class)]
|
||||
private Collection $customFieldValues;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructeurs = new ArrayCollection();
|
||||
$this->componentLinks = new ArrayCollection();
|
||||
$this->pieceLinks = new ArrayCollection();
|
||||
$this->productLinks = new ArrayCollection();
|
||||
$this->documents = new ArrayCollection();
|
||||
$this->customFieldValues = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReference(): ?string
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(?string $reference): static
|
||||
{
|
||||
$this->reference = $reference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrix(): ?string
|
||||
{
|
||||
return $this->prix;
|
||||
}
|
||||
|
||||
public function setPrix(?string $prix): static
|
||||
{
|
||||
$this->prix = $prix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSite(): Site
|
||||
{
|
||||
return $this->site;
|
||||
}
|
||||
|
||||
public function setSite(Site $site): static
|
||||
{
|
||||
$this->site = $site;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachine(): ?TypeMachine
|
||||
{
|
||||
return $this->typeMachine;
|
||||
}
|
||||
|
||||
public function setTypeMachine(?TypeMachine $typeMachine): static
|
||||
{
|
||||
$this->typeMachine = $typeMachine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Constructeur>
|
||||
*/
|
||||
public function getConstructeurs(): Collection
|
||||
{
|
||||
return $this->constructeurs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, MachineComponentLink>
|
||||
*/
|
||||
public function getComponentLinks(): Collection
|
||||
{
|
||||
return $this->componentLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, MachinePieceLink>
|
||||
*/
|
||||
public function getPieceLinks(): Collection
|
||||
{
|
||||
return $this->pieceLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, MachineProductLink>
|
||||
*/
|
||||
public function getProductLinks(): Collection
|
||||
{
|
||||
return $this->productLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Document>
|
||||
*/
|
||||
public function getDocuments(): Collection
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, CustomFieldValue>
|
||||
*/
|
||||
public function getCustomFieldValues(): Collection
|
||||
{
|
||||
return $this->customFieldValues;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
198
src/Entity/MachineComponentLink.php
Normal file
198
src/Entity/MachineComponentLink.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\MachineComponentLinkRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MachineComponentLinkRepository::class)]
|
||||
#[ORM\Table(name: 'machine_component_links')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class MachineComponentLink
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Machine::class, inversedBy: 'componentLinks')]
|
||||
#[ORM\JoinColumn(name: 'machineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Machine $machine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Composant::class, inversedBy: 'machineLinks')]
|
||||
#[ORM\JoinColumn(name: 'composantId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Composant $composant;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MachineComponentLink::class, inversedBy: 'childLinks')]
|
||||
#[ORM\JoinColumn(name: 'parentLinkId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?MachineComponentLink $parentLink = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineComponentLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'parentLink', targetEntity: MachineComponentLink::class)]
|
||||
private Collection $childLinks;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachineComponentRequirement::class, inversedBy: 'machineComponentLinks')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineComponentRequirementId', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?TypeMachineComponentRequirement $typeMachineComponentRequirement = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachinePieceLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'parentLink', targetEntity: MachinePieceLink::class)]
|
||||
private Collection $pieceLinks;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'parentComponentLink', targetEntity: MachineProductLink::class)]
|
||||
private Collection $productLinks;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'nameOverride')]
|
||||
private ?string $nameOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'referenceOverride')]
|
||||
private ?string $referenceOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true, name: 'prixOverride')]
|
||||
private ?string $prixOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->childLinks = new ArrayCollection();
|
||||
$this->pieceLinks = new ArrayCollection();
|
||||
$this->productLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachine(): Machine
|
||||
{
|
||||
return $this->machine;
|
||||
}
|
||||
|
||||
public function setMachine(Machine $machine): static
|
||||
{
|
||||
$this->machine = $machine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComposant(): Composant
|
||||
{
|
||||
return $this->composant;
|
||||
}
|
||||
|
||||
public function setComposant(Composant $composant): static
|
||||
{
|
||||
$this->composant = $composant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParentLink(): ?MachineComponentLink
|
||||
{
|
||||
return $this->parentLink;
|
||||
}
|
||||
|
||||
public function setParentLink(?MachineComponentLink $parentLink): static
|
||||
{
|
||||
$this->parentLink = $parentLink;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachineComponentRequirement(): ?TypeMachineComponentRequirement
|
||||
{
|
||||
return $this->typeMachineComponentRequirement;
|
||||
}
|
||||
|
||||
public function setTypeMachineComponentRequirement(?TypeMachineComponentRequirement $requirement): static
|
||||
{
|
||||
$this->typeMachineComponentRequirement = $requirement;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNameOverride(): ?string
|
||||
{
|
||||
return $this->nameOverride;
|
||||
}
|
||||
|
||||
public function setNameOverride(?string $nameOverride): static
|
||||
{
|
||||
$this->nameOverride = $nameOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReferenceOverride(): ?string
|
||||
{
|
||||
return $this->referenceOverride;
|
||||
}
|
||||
|
||||
public function setReferenceOverride(?string $referenceOverride): static
|
||||
{
|
||||
$this->referenceOverride = $referenceOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrixOverride(): ?string
|
||||
{
|
||||
return $this->prixOverride;
|
||||
}
|
||||
|
||||
public function setPrixOverride(?string $prixOverride): static
|
||||
{
|
||||
$this->prixOverride = $prixOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
184
src/Entity/MachinePieceLink.php
Normal file
184
src/Entity/MachinePieceLink.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\MachinePieceLinkRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MachinePieceLinkRepository::class)]
|
||||
#[ORM\Table(name: 'machine_piece_links')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class MachinePieceLink
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Machine::class, inversedBy: 'pieceLinks')]
|
||||
#[ORM\JoinColumn(name: 'machineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Machine $machine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Piece::class, inversedBy: 'machineLinks')]
|
||||
#[ORM\JoinColumn(name: 'pieceId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Piece $piece;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MachineComponentLink::class, inversedBy: 'pieceLinks')]
|
||||
#[ORM\JoinColumn(name: 'parentLinkId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?MachineComponentLink $parentLink = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachinePieceRequirement::class, inversedBy: 'machinePieceLinks')]
|
||||
#[ORM\JoinColumn(name: 'typeMachinePieceRequirementId', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?TypeMachinePieceRequirement $typeMachinePieceRequirement = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'parentPieceLink', targetEntity: MachineProductLink::class)]
|
||||
private Collection $productLinks;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'nameOverride')]
|
||||
private ?string $nameOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'referenceOverride')]
|
||||
private ?string $referenceOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true, name: 'prixOverride')]
|
||||
private ?string $prixOverride = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->productLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachine(): Machine
|
||||
{
|
||||
return $this->machine;
|
||||
}
|
||||
|
||||
public function setMachine(Machine $machine): static
|
||||
{
|
||||
$this->machine = $machine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPiece(): Piece
|
||||
{
|
||||
return $this->piece;
|
||||
}
|
||||
|
||||
public function setPiece(Piece $piece): static
|
||||
{
|
||||
$this->piece = $piece;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParentLink(): ?MachineComponentLink
|
||||
{
|
||||
return $this->parentLink;
|
||||
}
|
||||
|
||||
public function setParentLink(?MachineComponentLink $parentLink): static
|
||||
{
|
||||
$this->parentLink = $parentLink;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachinePieceRequirement(): ?TypeMachinePieceRequirement
|
||||
{
|
||||
return $this->typeMachinePieceRequirement;
|
||||
}
|
||||
|
||||
public function setTypeMachinePieceRequirement(?TypeMachinePieceRequirement $requirement): static
|
||||
{
|
||||
$this->typeMachinePieceRequirement = $requirement;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNameOverride(): ?string
|
||||
{
|
||||
return $this->nameOverride;
|
||||
}
|
||||
|
||||
public function setNameOverride(?string $nameOverride): static
|
||||
{
|
||||
$this->nameOverride = $nameOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReferenceOverride(): ?string
|
||||
{
|
||||
return $this->referenceOverride;
|
||||
}
|
||||
|
||||
public function setReferenceOverride(?string $referenceOverride): static
|
||||
{
|
||||
$this->referenceOverride = $referenceOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrixOverride(): ?string
|
||||
{
|
||||
return $this->prixOverride;
|
||||
}
|
||||
|
||||
public function setPrixOverride(?string $prixOverride): static
|
||||
{
|
||||
$this->prixOverride = $prixOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
171
src/Entity/MachineProductLink.php
Normal file
171
src/Entity/MachineProductLink.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\MachineProductLinkRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MachineProductLinkRepository::class)]
|
||||
#[ORM\Table(name: 'machine_product_links')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class MachineProductLink
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Machine::class, inversedBy: 'productLinks')]
|
||||
#[ORM\JoinColumn(name: 'machineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Machine $machine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'machineLinks')]
|
||||
#[ORM\JoinColumn(name: 'productId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Product $product;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachineProductRequirement::class, inversedBy: 'machineProductLinks')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineProductRequirementId', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?TypeMachineProductRequirement $typeMachineProductRequirement = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MachineProductLink::class, inversedBy: 'childLinks')]
|
||||
#[ORM\JoinColumn(name: 'parentLinkId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?MachineProductLink $parentLink = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'parentLink', targetEntity: MachineProductLink::class)]
|
||||
private Collection $childLinks;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MachineComponentLink::class, inversedBy: 'productLinks')]
|
||||
#[ORM\JoinColumn(name: 'parentComponentLinkId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?MachineComponentLink $parentComponentLink = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MachinePieceLink::class, inversedBy: 'productLinks')]
|
||||
#[ORM\JoinColumn(name: 'parentPieceLinkId', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
|
||||
private ?MachinePieceLink $parentPieceLink = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->childLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachine(): Machine
|
||||
{
|
||||
return $this->machine;
|
||||
}
|
||||
|
||||
public function setMachine(Machine $machine): static
|
||||
{
|
||||
$this->machine = $machine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProduct(): Product
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(Product $product): static
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachineProductRequirement(): ?TypeMachineProductRequirement
|
||||
{
|
||||
return $this->typeMachineProductRequirement;
|
||||
}
|
||||
|
||||
public function setTypeMachineProductRequirement(?TypeMachineProductRequirement $requirement): static
|
||||
{
|
||||
$this->typeMachineProductRequirement = $requirement;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParentLink(): ?MachineProductLink
|
||||
{
|
||||
return $this->parentLink;
|
||||
}
|
||||
|
||||
public function setParentLink(?MachineProductLink $parentLink): static
|
||||
{
|
||||
$this->parentLink = $parentLink;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParentComponentLink(): ?MachineComponentLink
|
||||
{
|
||||
return $this->parentComponentLink;
|
||||
}
|
||||
|
||||
public function setParentComponentLink(?MachineComponentLink $parentComponentLink): static
|
||||
{
|
||||
$this->parentComponentLink = $parentComponentLink;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParentPieceLink(): ?MachinePieceLink
|
||||
{
|
||||
return $this->parentPieceLink;
|
||||
}
|
||||
|
||||
public function setParentPieceLink(?MachinePieceLink $parentPieceLink): static
|
||||
{
|
||||
$this->parentPieceLink = $parentPieceLink;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
263
src/Entity/ModelType.php
Normal file
263
src/Entity/ModelType.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Enum\ModelCategory;
|
||||
use App\Repository\ModelTypeRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ModelTypeRepository::class)]
|
||||
#[ORM\Table(name: 'model_types')]
|
||||
#[ORM\UniqueConstraint(name: 'unique_category_name', columns: ['category', 'name'])]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class ModelType
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 120)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 60, unique: true)]
|
||||
private string $code;
|
||||
|
||||
#[ORM\Column(enumType: ModelCategory::class)]
|
||||
private ModelCategory $category;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $notes = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true, name: 'componentSkeleton')]
|
||||
private ?array $componentSkeleton = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true, name: 'pieceSkeleton')]
|
||||
private ?array $pieceSkeleton = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true, name: 'productSkeleton')]
|
||||
private ?array $productSkeleton = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Composant>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeComposant', targetEntity: Composant::class)]
|
||||
private Collection $composants;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Piece>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typePiece', targetEntity: Piece::class)]
|
||||
private Collection $pieces;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Product>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeProduct', targetEntity: Product::class)]
|
||||
private Collection $products;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachineComponentRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeComposant', targetEntity: TypeMachineComponentRequirement::class)]
|
||||
private Collection $componentRequirements;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachinePieceRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typePiece', targetEntity: TypeMachinePieceRequirement::class)]
|
||||
private Collection $pieceRequirements;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachineProductRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeProduct', targetEntity: TypeMachineProductRequirement::class)]
|
||||
private Collection $productRequirements;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomField>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeComposant', targetEntity: CustomField::class)]
|
||||
private Collection $customFields;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomField>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typePiece', targetEntity: CustomField::class)]
|
||||
private Collection $pieceCustomFields;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomField>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeProduct', targetEntity: CustomField::class)]
|
||||
private Collection $productCustomFields;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->composants = new ArrayCollection();
|
||||
$this->pieces = new ArrayCollection();
|
||||
$this->products = new ArrayCollection();
|
||||
$this->componentRequirements = new ArrayCollection();
|
||||
$this->pieceRequirements = new ArrayCollection();
|
||||
$this->productRequirements = new ArrayCollection();
|
||||
$this->customFields = new ArrayCollection();
|
||||
$this->pieceCustomFields = new ArrayCollection();
|
||||
$this->productCustomFields = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode(): string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(string $code): static
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCategory(): ModelCategory
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory(ModelCategory $category): static
|
||||
{
|
||||
$this->category = $category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotes(): ?string
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
public function setNotes(?string $notes): static
|
||||
{
|
||||
$this->notes = $notes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComponentSkeleton(): ?array
|
||||
{
|
||||
return $this->componentSkeleton;
|
||||
}
|
||||
|
||||
public function setComponentSkeleton(?array $componentSkeleton): static
|
||||
{
|
||||
$this->componentSkeleton = $componentSkeleton;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPieceSkeleton(): ?array
|
||||
{
|
||||
return $this->pieceSkeleton;
|
||||
}
|
||||
|
||||
public function setPieceSkeleton(?array $pieceSkeleton): static
|
||||
{
|
||||
$this->pieceSkeleton = $pieceSkeleton;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProductSkeleton(): ?array
|
||||
{
|
||||
return $this->productSkeleton;
|
||||
}
|
||||
|
||||
public function setProductSkeleton(?array $productSkeleton): static
|
||||
{
|
||||
$this->productSkeleton = $productSkeleton;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
212
src/Entity/Piece.php
Normal file
212
src/Entity/Piece.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\PieceRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: PieceRepository::class)]
|
||||
#[ORM\Table(name: 'pieces')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Piece
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $reference = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true)]
|
||||
private ?string $prix = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'pieces')]
|
||||
#[ORM\JoinColumn(name: 'typePieceId', referencedColumnName: 'id', nullable: true)]
|
||||
private ?ModelType $typePiece = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'pieces')]
|
||||
#[ORM\JoinColumn(name: 'productId', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
private ?Product $product = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Constructeur>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Constructeur::class, inversedBy: 'pieces')]
|
||||
#[ORM\JoinTable(
|
||||
name: '_PieceConstructeurs',
|
||||
joinColumns: [new ORM\JoinColumn(name: 'A', referencedColumnName: 'id', onDelete: 'CASCADE')],
|
||||
inverseJoinColumns: [new ORM\InverseJoinColumn(name: 'B', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
)]
|
||||
private Collection $constructeurs;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Document>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'piece', targetEntity: Document::class)]
|
||||
private Collection $documents;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomFieldValue>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'piece', targetEntity: CustomFieldValue::class)]
|
||||
private Collection $customFieldValues;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachinePieceLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'piece', targetEntity: MachinePieceLink::class)]
|
||||
private Collection $machineLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructeurs = new ArrayCollection();
|
||||
$this->documents = new ArrayCollection();
|
||||
$this->customFieldValues = new ArrayCollection();
|
||||
$this->machineLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReference(): ?string
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(?string $reference): static
|
||||
{
|
||||
$this->reference = $reference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrix(): ?string
|
||||
{
|
||||
return $this->prix;
|
||||
}
|
||||
|
||||
public function setPrix(?string $prix): static
|
||||
{
|
||||
$this->prix = $prix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypePiece(): ?ModelType
|
||||
{
|
||||
return $this->typePiece;
|
||||
}
|
||||
|
||||
public function setTypePiece(?ModelType $typePiece): static
|
||||
{
|
||||
$this->typePiece = $typePiece;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProduct(): ?Product
|
||||
{
|
||||
return $this->product;
|
||||
}
|
||||
|
||||
public function setProduct(?Product $product): static
|
||||
{
|
||||
$this->product = $product;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Constructeur>
|
||||
*/
|
||||
public function getConstructeurs(): Collection
|
||||
{
|
||||
return $this->constructeurs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Document>
|
||||
*/
|
||||
public function getDocuments(): Collection
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, CustomFieldValue>
|
||||
*/
|
||||
public function getCustomFieldValues(): Collection
|
||||
{
|
||||
return $this->customFieldValues;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
210
src/Entity/Product.php
Normal file
210
src/Entity/Product.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\ProductRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ProductRepository::class)]
|
||||
#[ORM\Table(name: 'products')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class Product
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $reference = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2, nullable: true, name: 'supplierPrice')]
|
||||
private ?string $supplierPrice = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'products')]
|
||||
#[ORM\JoinColumn(name: 'typeProductId', referencedColumnName: 'id', nullable: true)]
|
||||
private ?ModelType $typeProduct = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Constructeur>
|
||||
*/
|
||||
#[ORM\ManyToMany(targetEntity: Constructeur::class, inversedBy: 'products')]
|
||||
#[ORM\JoinTable(
|
||||
name: '_ProductConstructeurs',
|
||||
joinColumns: [new ORM\JoinColumn(name: 'A', referencedColumnName: 'id', onDelete: 'CASCADE')],
|
||||
inverseJoinColumns: [new ORM\InverseJoinColumn(name: 'B', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||
)]
|
||||
private Collection $constructeurs;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Document>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'product', targetEntity: Document::class)]
|
||||
private Collection $documents;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomFieldValue>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'product', targetEntity: CustomFieldValue::class)]
|
||||
private Collection $customFieldValues;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Piece>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'product', targetEntity: Piece::class)]
|
||||
private Collection $pieces;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Composant>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'product', targetEntity: Composant::class)]
|
||||
private Collection $composants;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'product', targetEntity: MachineProductLink::class)]
|
||||
private Collection $machineLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->constructeurs = new ArrayCollection();
|
||||
$this->documents = new ArrayCollection();
|
||||
$this->customFieldValues = new ArrayCollection();
|
||||
$this->pieces = new ArrayCollection();
|
||||
$this->composants = new ArrayCollection();
|
||||
$this->machineLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReference(): ?string
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(?string $reference): static
|
||||
{
|
||||
$this->reference = $reference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSupplierPrice(): ?string
|
||||
{
|
||||
return $this->supplierPrice;
|
||||
}
|
||||
|
||||
public function setSupplierPrice(?string $supplierPrice): static
|
||||
{
|
||||
$this->supplierPrice = $supplierPrice;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeProduct(): ?ModelType
|
||||
{
|
||||
return $this->typeProduct;
|
||||
}
|
||||
|
||||
public function setTypeProduct(?ModelType $typeProduct): static
|
||||
{
|
||||
$this->typeProduct = $typeProduct;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Constructeur>
|
||||
*/
|
||||
public function getConstructeurs(): Collection
|
||||
{
|
||||
return $this->constructeurs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Document>
|
||||
*/
|
||||
public function getDocuments(): Collection
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, CustomFieldValue>
|
||||
*/
|
||||
public function getCustomFieldValues(): Collection
|
||||
{
|
||||
return $this->customFieldValues;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -36,49 +36,48 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
class Profile implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'string', length: 30)]
|
||||
#[ORM\Column(type: 'string', length: 36)]
|
||||
#[Groups(['profile:read'])]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 180, unique: true)]
|
||||
#[Assert\NotBlank]
|
||||
#[ORM\Column(type: 'string', length: 180, unique: true, nullable: true)]
|
||||
#[Assert\Email]
|
||||
#[Groups(['profile:read', 'profile:write'])]
|
||||
private string $email;
|
||||
private ?string $email = null;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 100)]
|
||||
#[ORM\Column(type: 'string', length: 100, name: 'firstName')]
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['profile:read', 'profile:write'])]
|
||||
private string $firstName;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 100)]
|
||||
#[ORM\Column(type: 'string', length: 100, name: 'lastName')]
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['profile:read', 'profile:write'])]
|
||||
private string $lastName;
|
||||
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => true])]
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => true], name: 'isActive')]
|
||||
#[Groups(['profile:read', 'profile:write'])]
|
||||
private bool $isActive = true;
|
||||
|
||||
/**
|
||||
* @var list<string> The user roles
|
||||
*/
|
||||
#[ORM\Column(type: 'json')]
|
||||
#[ORM\Column(type: 'json', options: ['default' => '["ROLE_USER"]'])]
|
||||
#[Groups(['profile:read', 'profile:write'])]
|
||||
private array $roles = ['ROLE_USER'];
|
||||
|
||||
/**
|
||||
* @var string The hashed password
|
||||
*/
|
||||
#[ORM\Column(type: 'string')]
|
||||
#[ORM\Column(type: 'string', nullable: true)]
|
||||
#[Groups(['profile:write'])]
|
||||
private ?string $password = null;
|
||||
|
||||
#[ORM\Column(type: 'datetime_immutable')]
|
||||
#[ORM\Column(type: 'datetime_immutable', name: 'createdAt')]
|
||||
#[Groups(['profile:read'])]
|
||||
private DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'datetime_immutable')]
|
||||
#[ORM\Column(type: 'datetime_immutable', name: 'updatedAt')]
|
||||
#[Groups(['profile:read'])]
|
||||
private DateTimeImmutable $updatedAt;
|
||||
|
||||
@@ -95,12 +94,12 @@ class Profile implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getEmail(): string
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
public function setEmail(?string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
@@ -148,7 +147,7 @@ class Profile implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
*/
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return $this->email;
|
||||
return (string) $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
260
src/Entity/Site.php
Normal file
260
src/Entity/Site.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use App\Repository\SiteRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: SiteRepository::class)]
|
||||
#[ORM\Table(name: 'sites')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(),
|
||||
new GetCollection(),
|
||||
new Post(),
|
||||
new Put(),
|
||||
new Delete(),
|
||||
]
|
||||
)]
|
||||
class Site
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255)]
|
||||
#[Assert\NotBlank]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, options: ['default' => ''], name: 'contactName')]
|
||||
private string $contactName = '';
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 20, options: ['default' => ''], name: 'contactPhone')]
|
||||
private string $contactPhone = '';
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 500, options: ['default' => ''], name: 'contactAddress')]
|
||||
private string $contactAddress = '';
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 10, options: ['default' => ''], name: 'contactPostalCode')]
|
||||
private string $contactPostalCode = '';
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 100, options: ['default' => ''], name: 'contactCity')]
|
||||
private string $contactCity = '';
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Machine>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Machine::class, mappedBy: 'site', cascade: ['persist', 'remove'], orphanRemoval: true)]
|
||||
private Collection $machines;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Document>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Document::class, mappedBy: 'site', cascade: ['remove'], orphanRemoval: true)]
|
||||
private Collection $documents;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->machines = new ArrayCollection();
|
||||
$this->documents = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$this->createdAt = new \DateTimeImmutable();
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
|
||||
// Générer un ID CUID-compatible si nécessaire
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
// Génération d'un ID compatible CUID (format: cl + 24 caractères)
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactName(): string
|
||||
{
|
||||
return $this->contactName;
|
||||
}
|
||||
|
||||
public function setContactName(string $contactName): static
|
||||
{
|
||||
$this->contactName = $contactName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactPhone(): string
|
||||
{
|
||||
return $this->contactPhone;
|
||||
}
|
||||
|
||||
public function setContactPhone(string $contactPhone): static
|
||||
{
|
||||
$this->contactPhone = $contactPhone;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactAddress(): string
|
||||
{
|
||||
return $this->contactAddress;
|
||||
}
|
||||
|
||||
public function setContactAddress(string $contactAddress): static
|
||||
{
|
||||
$this->contactAddress = $contactAddress;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactPostalCode(): string
|
||||
{
|
||||
return $this->contactPostalCode;
|
||||
}
|
||||
|
||||
public function setContactPostalCode(string $contactPostalCode): static
|
||||
{
|
||||
$this->contactPostalCode = $contactPostalCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContactCity(): string
|
||||
{
|
||||
return $this->contactCity;
|
||||
}
|
||||
|
||||
public function setContactCity(string $contactCity): static
|
||||
{
|
||||
$this->contactCity = $contactCity;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): \DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Machine>
|
||||
*/
|
||||
public function getMachines(): Collection
|
||||
{
|
||||
return $this->machines;
|
||||
}
|
||||
|
||||
public function addMachine(Machine $machine): static
|
||||
{
|
||||
if (!$this->machines->contains($machine)) {
|
||||
$this->machines->add($machine);
|
||||
$machine->setSite($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeMachine(Machine $machine): static
|
||||
{
|
||||
if ($this->machines->removeElement($machine)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($machine->getSite() === $this) {
|
||||
$machine->setSite(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Document>
|
||||
*/
|
||||
public function getDocuments(): Collection
|
||||
{
|
||||
return $this->documents;
|
||||
}
|
||||
|
||||
public function addDocument(Document $document): static
|
||||
{
|
||||
if (!$this->documents->contains($document)) {
|
||||
$this->documents->add($document);
|
||||
$document->setSite($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeDocument(Document $document): static
|
||||
{
|
||||
if ($this->documents->removeElement($document)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($document->getSite() === $this) {
|
||||
$document->setSite(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
396
src/Entity/TypeMachine.php
Normal file
396
src/Entity/TypeMachine.php
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use App\Repository\TypeMachineRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TypeMachineRepository::class)]
|
||||
#[ORM\Table(name: 'type_machines')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[UniqueEntity(fields: ['name'], message: 'Ce nom de type de machine existe déjà.')]
|
||||
#[ApiResource(
|
||||
operations: [
|
||||
new Get(),
|
||||
new GetCollection(),
|
||||
new Post(),
|
||||
new Put(),
|
||||
new Delete(),
|
||||
],
|
||||
normalizationContext: ['groups' => ['type_machine:read']],
|
||||
denormalizationContext: ['groups' => ['type_machine:write']]
|
||||
)]
|
||||
class TypeMachine
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
#[Groups(['type_machine:read'])]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, unique: true)]
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['type_machine:read', 'type_machine:write', 'machine:read'])]
|
||||
private string $name;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true, name: 'maintenanceFrequency')]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?string $category = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?string $maintenanceFrequency = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true, name: 'criticalParts')]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?array $components = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true, name: 'machinePieces')]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?array $criticalParts = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?array $machinePieces = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
#[Groups(['type_machine:read', 'type_machine:write'])]
|
||||
private ?array $specifications = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
#[Groups(['type_machine:read'])]
|
||||
private DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
#[Groups(['type_machine:read'])]
|
||||
private DateTimeImmutable $updatedAt;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Machine>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Machine::class, mappedBy: 'typeMachine')]
|
||||
private Collection $machines;
|
||||
|
||||
/**
|
||||
* @var Collection<int, CustomField>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: CustomField::class, mappedBy: 'typeMachine')]
|
||||
private Collection $customFields;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachineComponentRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: TypeMachineComponentRequirement::class, mappedBy: 'typeMachine', cascade: ['persist', 'remove'])]
|
||||
private Collection $componentRequirements;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachinePieceRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: TypeMachinePieceRequirement::class, mappedBy: 'typeMachine', cascade: ['persist', 'remove'])]
|
||||
private Collection $pieceRequirements;
|
||||
|
||||
/**
|
||||
* @var Collection<int, TypeMachineProductRequirement>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: TypeMachineProductRequirement::class, mappedBy: 'typeMachine', cascade: ['persist', 'remove'])]
|
||||
private Collection $productRequirements;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->id = 'cl' . bin2hex(random_bytes(12));
|
||||
$this->createdAt = new DateTimeImmutable();
|
||||
$this->updatedAt = new DateTimeImmutable();
|
||||
$this->machines = new ArrayCollection();
|
||||
$this->customFields = new ArrayCollection();
|
||||
$this->componentRequirements = new ArrayCollection();
|
||||
$this->pieceRequirements = new ArrayCollection();
|
||||
$this->productRequirements = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCategory(): ?string
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory(?string $category): static
|
||||
{
|
||||
$this->category = $category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaintenanceFrequency(): ?string
|
||||
{
|
||||
return $this->maintenanceFrequency;
|
||||
}
|
||||
|
||||
public function setMaintenanceFrequency(?string $maintenanceFrequency): static
|
||||
{
|
||||
$this->maintenanceFrequency = $maintenanceFrequency;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComponents(): ?array
|
||||
{
|
||||
return $this->components;
|
||||
}
|
||||
|
||||
public function setComponents(?array $components): static
|
||||
{
|
||||
$this->components = $components;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCriticalParts(): ?array
|
||||
{
|
||||
return $this->criticalParts;
|
||||
}
|
||||
|
||||
public function setCriticalParts(?array $criticalParts): static
|
||||
{
|
||||
$this->criticalParts = $criticalParts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMachinePieces(): ?array
|
||||
{
|
||||
return $this->machinePieces;
|
||||
}
|
||||
|
||||
public function setMachinePieces(?array $machinePieces): static
|
||||
{
|
||||
$this->machinePieces = $machinePieces;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSpecifications(): ?array
|
||||
{
|
||||
return $this->specifications;
|
||||
}
|
||||
|
||||
public function setSpecifications(?array $specifications): static
|
||||
{
|
||||
$this->specifications = $specifications;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Machine>
|
||||
*/
|
||||
public function getMachines(): Collection
|
||||
{
|
||||
return $this->machines;
|
||||
}
|
||||
|
||||
public function addMachine(Machine $machine): static
|
||||
{
|
||||
if (!$this->machines->contains($machine)) {
|
||||
$this->machines->add($machine);
|
||||
$machine->setTypeMachine($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeMachine(Machine $machine): static
|
||||
{
|
||||
if ($this->machines->removeElement($machine)) {
|
||||
if ($machine->getTypeMachine() === $this) {
|
||||
$machine->setTypeMachine(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, CustomField>
|
||||
*/
|
||||
public function getCustomFields(): Collection
|
||||
{
|
||||
return $this->customFields;
|
||||
}
|
||||
|
||||
public function addCustomField(CustomField $customField): static
|
||||
{
|
||||
if (!$this->customFields->contains($customField)) {
|
||||
$this->customFields->add($customField);
|
||||
$customField->setTypeMachine($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeCustomField(CustomField $customField): static
|
||||
{
|
||||
if ($this->customFields->removeElement($customField)) {
|
||||
if ($customField->getTypeMachine() === $this) {
|
||||
$customField->setTypeMachine(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, TypeMachineComponentRequirement>
|
||||
*/
|
||||
public function getComponentRequirements(): Collection
|
||||
{
|
||||
return $this->componentRequirements;
|
||||
}
|
||||
|
||||
public function addComponentRequirement(TypeMachineComponentRequirement $componentRequirement): static
|
||||
{
|
||||
if (!$this->componentRequirements->contains($componentRequirement)) {
|
||||
$this->componentRequirements->add($componentRequirement);
|
||||
$componentRequirement->setTypeMachine($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeComponentRequirement(TypeMachineComponentRequirement $componentRequirement): static
|
||||
{
|
||||
if ($this->componentRequirements->removeElement($componentRequirement)) {
|
||||
if ($componentRequirement->getTypeMachine() === $this) {
|
||||
$componentRequirement->setTypeMachine(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, TypeMachinePieceRequirement>
|
||||
*/
|
||||
public function getPieceRequirements(): Collection
|
||||
{
|
||||
return $this->pieceRequirements;
|
||||
}
|
||||
|
||||
public function addPieceRequirement(TypeMachinePieceRequirement $pieceRequirement): static
|
||||
{
|
||||
if (!$this->pieceRequirements->contains($pieceRequirement)) {
|
||||
$this->pieceRequirements->add($pieceRequirement);
|
||||
$pieceRequirement->setTypeMachine($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePieceRequirement(TypeMachinePieceRequirement $pieceRequirement): static
|
||||
{
|
||||
if ($this->pieceRequirements->removeElement($pieceRequirement)) {
|
||||
if ($pieceRequirement->getTypeMachine() === $this) {
|
||||
$pieceRequirement->setTypeMachine(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, TypeMachineProductRequirement>
|
||||
*/
|
||||
public function getProductRequirements(): Collection
|
||||
{
|
||||
return $this->productRequirements;
|
||||
}
|
||||
|
||||
public function addProductRequirement(TypeMachineProductRequirement $productRequirement): static
|
||||
{
|
||||
if (!$this->productRequirements->contains($productRequirement)) {
|
||||
$this->productRequirements->add($productRequirement);
|
||||
$productRequirement->setTypeMachine($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeProductRequirement(TypeMachineProductRequirement $productRequirement): static
|
||||
{
|
||||
if ($this->productRequirements->removeElement($productRequirement)) {
|
||||
if ($productRequirement->getTypeMachine() === $this) {
|
||||
$productRequirement->setTypeMachine(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$this->createdAt = new DateTimeImmutable();
|
||||
$this->updatedAt = new DateTimeImmutable();
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new DateTimeImmutable();
|
||||
}
|
||||
}
|
||||
197
src/Entity/TypeMachineComponentRequirement.php
Normal file
197
src/Entity/TypeMachineComponentRequirement.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\TypeMachineComponentRequirementRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TypeMachineComponentRequirementRepository::class)]
|
||||
#[ORM\Table(name: 'type_machine_component_requirements')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class TypeMachineComponentRequirement
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 1], name: 'minCount')]
|
||||
private int $minCount = 1;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, nullable: true, name: 'maxCount')]
|
||||
private ?int $maxCount = null;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => true], name: 'required')]
|
||||
private bool $required = true;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => true], name: 'allowNewModels')]
|
||||
private bool $allowNewModels = true;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'orderIndex')]
|
||||
private int $orderIndex = 0;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachine::class, inversedBy: 'componentRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private TypeMachine $typeMachine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'componentRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typeComposantId', referencedColumnName: 'id', nullable: false)]
|
||||
private ModelType $typeComposant;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineComponentLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeMachineComponentRequirement', targetEntity: MachineComponentLink::class)]
|
||||
private Collection $machineComponentLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->machineComponentLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setLabel(?string $label): static
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMinCount(): int
|
||||
{
|
||||
return $this->minCount;
|
||||
}
|
||||
|
||||
public function setMinCount(int $minCount): static
|
||||
{
|
||||
$this->minCount = $minCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaxCount(): ?int
|
||||
{
|
||||
return $this->maxCount;
|
||||
}
|
||||
|
||||
public function setMaxCount(?int $maxCount): static
|
||||
{
|
||||
$this->maxCount = $maxCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setRequired(bool $required): static
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAllowNewModels(): bool
|
||||
{
|
||||
return $this->allowNewModels;
|
||||
}
|
||||
|
||||
public function setAllowNewModels(bool $allowNewModels): static
|
||||
{
|
||||
$this->allowNewModels = $allowNewModels;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderIndex(): int
|
||||
{
|
||||
return $this->orderIndex;
|
||||
}
|
||||
|
||||
public function setOrderIndex(int $orderIndex): static
|
||||
{
|
||||
$this->orderIndex = $orderIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachine(): TypeMachine
|
||||
{
|
||||
return $this->typeMachine;
|
||||
}
|
||||
|
||||
public function setTypeMachine(TypeMachine $typeMachine): static
|
||||
{
|
||||
$this->typeMachine = $typeMachine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeComposant(): ModelType
|
||||
{
|
||||
return $this->typeComposant;
|
||||
}
|
||||
|
||||
public function setTypeComposant(ModelType $typeComposant): static
|
||||
{
|
||||
$this->typeComposant = $typeComposant;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
197
src/Entity/TypeMachinePieceRequirement.php
Normal file
197
src/Entity/TypeMachinePieceRequirement.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\TypeMachinePieceRequirementRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TypeMachinePieceRequirementRepository::class)]
|
||||
#[ORM\Table(name: 'type_machine_piece_requirements')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class TypeMachinePieceRequirement
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'minCount')]
|
||||
private int $minCount = 0;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, nullable: true, name: 'maxCount')]
|
||||
private ?int $maxCount = null;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
||||
private bool $required = false;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => true], name: 'allowNewModels')]
|
||||
private bool $allowNewModels = true;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'orderIndex')]
|
||||
private int $orderIndex = 0;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachine::class, inversedBy: 'pieceRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private TypeMachine $typeMachine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'pieceRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typePieceId', referencedColumnName: 'id', nullable: false)]
|
||||
private ModelType $typePiece;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachinePieceLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeMachinePieceRequirement', targetEntity: MachinePieceLink::class)]
|
||||
private Collection $machinePieceLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->machinePieceLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setLabel(?string $label): static
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMinCount(): int
|
||||
{
|
||||
return $this->minCount;
|
||||
}
|
||||
|
||||
public function setMinCount(int $minCount): static
|
||||
{
|
||||
$this->minCount = $minCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaxCount(): ?int
|
||||
{
|
||||
return $this->maxCount;
|
||||
}
|
||||
|
||||
public function setMaxCount(?int $maxCount): static
|
||||
{
|
||||
$this->maxCount = $maxCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setRequired(bool $required): static
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAllowNewModels(): bool
|
||||
{
|
||||
return $this->allowNewModels;
|
||||
}
|
||||
|
||||
public function setAllowNewModels(bool $allowNewModels): static
|
||||
{
|
||||
$this->allowNewModels = $allowNewModels;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderIndex(): int
|
||||
{
|
||||
return $this->orderIndex;
|
||||
}
|
||||
|
||||
public function setOrderIndex(int $orderIndex): static
|
||||
{
|
||||
$this->orderIndex = $orderIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachine(): TypeMachine
|
||||
{
|
||||
return $this->typeMachine;
|
||||
}
|
||||
|
||||
public function setTypeMachine(TypeMachine $typeMachine): static
|
||||
{
|
||||
$this->typeMachine = $typeMachine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypePiece(): ModelType
|
||||
{
|
||||
return $this->typePiece;
|
||||
}
|
||||
|
||||
public function setTypePiece(ModelType $typePiece): static
|
||||
{
|
||||
$this->typePiece = $typePiece;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
197
src/Entity/TypeMachineProductRequirement.php
Normal file
197
src/Entity/TypeMachineProductRequirement.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use App\Repository\TypeMachineProductRequirementRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TypeMachineProductRequirementRepository::class)]
|
||||
#[ORM\Table(name: 'type_machine_product_requirements')]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[ApiResource]
|
||||
class TypeMachineProductRequirement
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: Types::STRING, length: 36)]
|
||||
private ?string $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
private ?string $label = null;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'minCount')]
|
||||
private int $minCount = 0;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, nullable: true, name: 'maxCount')]
|
||||
private ?int $maxCount = null;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
||||
private bool $required = false;
|
||||
|
||||
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => true], name: 'allowNewModels')]
|
||||
private bool $allowNewModels = true;
|
||||
|
||||
#[ORM\Column(type: Types::INTEGER, options: ['default' => 0], name: 'orderIndex')]
|
||||
private int $orderIndex = 0;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: TypeMachine::class, inversedBy: 'productRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typeMachineId', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private TypeMachine $typeMachine;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ModelType::class, inversedBy: 'productRequirements')]
|
||||
#[ORM\JoinColumn(name: 'typeProductId', referencedColumnName: 'id', nullable: false)]
|
||||
private ModelType $typeProduct;
|
||||
|
||||
/**
|
||||
* @var Collection<int, MachineProductLink>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'typeMachineProductRequirement', targetEntity: MachineProductLink::class)]
|
||||
private Collection $machineProductLinks;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
private \DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'updatedAt')]
|
||||
private \DateTimeImmutable $updatedAt;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->machineProductLinks = new ArrayCollection();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setCreatedAtValue(): void
|
||||
{
|
||||
$now = new \DateTimeImmutable();
|
||||
$this->createdAt = $now;
|
||||
$this->updatedAt = $now;
|
||||
|
||||
if ($this->id === null) {
|
||||
$this->id = $this->generateCuid();
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\PreUpdate]
|
||||
public function setUpdatedAtValue(): void
|
||||
{
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
private function generateCuid(): string
|
||||
{
|
||||
return 'cl' . bin2hex(random_bytes(12));
|
||||
}
|
||||
|
||||
public function getId(): ?string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(string $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setLabel(?string $label): static
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMinCount(): int
|
||||
{
|
||||
return $this->minCount;
|
||||
}
|
||||
|
||||
public function setMinCount(int $minCount): static
|
||||
{
|
||||
$this->minCount = $minCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaxCount(): ?int
|
||||
{
|
||||
return $this->maxCount;
|
||||
}
|
||||
|
||||
public function setMaxCount(?int $maxCount): static
|
||||
{
|
||||
$this->maxCount = $maxCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequired(): bool
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setRequired(bool $required): static
|
||||
{
|
||||
$this->required = $required;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAllowNewModels(): bool
|
||||
{
|
||||
return $this->allowNewModels;
|
||||
}
|
||||
|
||||
public function setAllowNewModels(bool $allowNewModels): static
|
||||
{
|
||||
$this->allowNewModels = $allowNewModels;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderIndex(): int
|
||||
{
|
||||
return $this->orderIndex;
|
||||
}
|
||||
|
||||
public function setOrderIndex(int $orderIndex): static
|
||||
{
|
||||
$this->orderIndex = $orderIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeMachine(): TypeMachine
|
||||
{
|
||||
return $this->typeMachine;
|
||||
}
|
||||
|
||||
public function setTypeMachine(TypeMachine $typeMachine): static
|
||||
{
|
||||
$this->typeMachine = $typeMachine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTypeProduct(): ModelType
|
||||
{
|
||||
return $this->typeProduct;
|
||||
}
|
||||
|
||||
public function setTypeProduct(ModelType $typeProduct): static
|
||||
{
|
||||
$this->typeProduct = $typeProduct;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
12
src/Enum/ModelCategory.php
Normal file
12
src/Enum/ModelCategory.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
enum ModelCategory: string
|
||||
{
|
||||
case COMPONENT = 'COMPONENT';
|
||||
case PIECE = 'PIECE';
|
||||
case PRODUCT = 'PRODUCT';
|
||||
}
|
||||
20
src/Repository/ComposantRepository.php
Normal file
20
src/Repository/ComposantRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Composant;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Composant>
|
||||
*/
|
||||
class ComposantRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Composant::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/ConstructeurRepository.php
Normal file
20
src/Repository/ConstructeurRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Constructeur;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Constructeur>
|
||||
*/
|
||||
class ConstructeurRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Constructeur::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/CustomFieldRepository.php
Normal file
20
src/Repository/CustomFieldRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\CustomField;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<CustomField>
|
||||
*/
|
||||
class CustomFieldRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, CustomField::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/CustomFieldValueRepository.php
Normal file
20
src/Repository/CustomFieldValueRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\CustomFieldValue;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<CustomFieldValue>
|
||||
*/
|
||||
class CustomFieldValueRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, CustomFieldValue::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/DocumentRepository.php
Normal file
20
src/Repository/DocumentRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Document;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Document>
|
||||
*/
|
||||
class DocumentRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Document::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/MachineComponentLinkRepository.php
Normal file
20
src/Repository/MachineComponentLinkRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\MachineComponentLink;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MachineComponentLink>
|
||||
*/
|
||||
class MachineComponentLinkRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, MachineComponentLink::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/MachinePieceLinkRepository.php
Normal file
20
src/Repository/MachinePieceLinkRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\MachinePieceLink;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MachinePieceLink>
|
||||
*/
|
||||
class MachinePieceLinkRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, MachinePieceLink::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/MachineProductLinkRepository.php
Normal file
20
src/Repository/MachineProductLinkRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\MachineProductLink;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MachineProductLink>
|
||||
*/
|
||||
class MachineProductLinkRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, MachineProductLink::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/MachineRepository.php
Normal file
20
src/Repository/MachineRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Machine;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Machine>
|
||||
*/
|
||||
class MachineRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Machine::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/ModelTypeRepository.php
Normal file
20
src/Repository/ModelTypeRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\ModelType;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<ModelType>
|
||||
*/
|
||||
class ModelTypeRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ModelType::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/PieceRepository.php
Normal file
20
src/Repository/PieceRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Piece;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Piece>
|
||||
*/
|
||||
class PieceRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Piece::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/ProductRepository.php
Normal file
20
src/Repository/ProductRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Product;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Product>
|
||||
*/
|
||||
class ProductRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Product::class);
|
||||
}
|
||||
}
|
||||
45
src/Repository/SiteRepository.php
Normal file
45
src/Repository/SiteRepository.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Site;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Site>
|
||||
*/
|
||||
class SiteRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Site::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Site[] Returns an array of Site objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('s')
|
||||
// ->andWhere('s.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('s.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Site
|
||||
// {
|
||||
// return $this->createQueryBuilder('s')
|
||||
// ->andWhere('s.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
20
src/Repository/TypeMachineComponentRequirementRepository.php
Normal file
20
src/Repository/TypeMachineComponentRequirementRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\TypeMachineComponentRequirement;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TypeMachineComponentRequirement>
|
||||
*/
|
||||
class TypeMachineComponentRequirementRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TypeMachineComponentRequirement::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/TypeMachinePieceRequirementRepository.php
Normal file
20
src/Repository/TypeMachinePieceRequirementRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\TypeMachinePieceRequirement;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TypeMachinePieceRequirement>
|
||||
*/
|
||||
class TypeMachinePieceRequirementRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TypeMachinePieceRequirement::class);
|
||||
}
|
||||
}
|
||||
20
src/Repository/TypeMachineProductRequirementRepository.php
Normal file
20
src/Repository/TypeMachineProductRequirementRepository.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\TypeMachineProductRequirement;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TypeMachineProductRequirement>
|
||||
*/
|
||||
class TypeMachineProductRequirementRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TypeMachineProductRequirement::class);
|
||||
}
|
||||
}
|
||||
38
src/Repository/TypeMachineRepository.php
Normal file
38
src/Repository/TypeMachineRepository.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\TypeMachine;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TypeMachine>
|
||||
*/
|
||||
class TypeMachineRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, TypeMachine::class);
|
||||
}
|
||||
|
||||
public function save(TypeMachine $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(TypeMachine $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
21
symfony.lock
21
symfony.lock
@@ -61,6 +61,18 @@
|
||||
".php-cs-fixer.dist.php"
|
||||
]
|
||||
},
|
||||
"lexik/jwt-authentication-bundle": {
|
||||
"version": "3.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.5",
|
||||
"ref": "e9481b233a11ef7e15fe055a2b21fd3ac1aa2bb7"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/lexik_jwt_authentication.yaml"
|
||||
]
|
||||
},
|
||||
"nelmio/cors-bundle": {
|
||||
"version": "2.6",
|
||||
"recipe": {
|
||||
@@ -204,5 +216,14 @@
|
||||
"files": [
|
||||
"config/packages/validator.yaml"
|
||||
]
|
||||
},
|
||||
"vich/uploader-bundle": {
|
||||
"version": "2.9",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "main",
|
||||
"version": "1.13",
|
||||
"ref": "1b3064c2f6b255c2bc2f56461aaeb76b11e07e36"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user