docs(custom-fields) : corrige la source de verite (table custom_fields unique)
L'investigation initiale supposait des customFields JSON dans les skeleton_*_requirements ; en realite SkeletonStructureService traduit les customFields du payload ModelType en entites CustomField stockees dans la table custom_fields. Le SQL est donc un simple SELECT DISTINCT. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,10 @@
|
||||
## Contexte et problème
|
||||
|
||||
Aujourd'hui dans Inventory, on définit des "champs personnalisés" (custom fields) à plusieurs endroits :
|
||||
- Au niveau d'une machine (entité `CustomField` avec FK `machineId`)
|
||||
- Au niveau d'un ModelType (entité `CustomField` avec FK `typeComposantId` / `typePieceId` / `typeProductId`)
|
||||
- Au niveau des skeleton requirements d'un ModelType (JSON `customFields` dans `SkeletonPieceRequirement`, `SkeletonSubcomponentRequirement`, `SkeletonProductRequirement`)
|
||||
- Au niveau d'une **machine** (entité `CustomField` avec FK `machineId`)
|
||||
- Au niveau d'un **ModelType**, dans 3 contextes (composant / pièce / produit) : entité `CustomField` avec respectivement `typeComposantId`, `typePieceId`, `typeProductId`.
|
||||
|
||||
Côté frontend, l'éditeur de structure d'un ModelType expose des `customFields` array sur chaque node, mais lors du save le backend (`SkeletonStructureService::updateCustomFields`) traduit ça en entités `CustomField` persistées dans la table unique `custom_fields`. La table `custom_fields` est donc **l'unique source de vérité** pour tous les noms de champs perso de l'application.
|
||||
|
||||
À chaque création/modification, l'utilisateur saisit librement un **nom** dans un `<input>` texte. Conséquence : les mêmes concepts métier finissent écrits différemment (« Numéro de série », « N° série », « Num serie »), ce qui empêche toute uniformisation et complique les rapports/recherches.
|
||||
|
||||
@@ -33,20 +34,21 @@ GET /api/custom-fields/names ◄── useCustomFieldNameSuggestions()
|
||||
│ │ (cache module-level)
|
||||
│ returns: ["Numéro...", ...] │
|
||||
▼ ▼
|
||||
Union SQL : CustomFieldNameInput.vue (wrapper)
|
||||
custom_fields │
|
||||
+ skeleton_piece_requirements │ utilise
|
||||
+ skeleton_subcomponent_requirements│
|
||||
+ skeleton_product_requirements ▼
|
||||
SELECT DISTINCT name CustomFieldNameInput.vue (wrapper)
|
||||
FROM custom_fields │
|
||||
│ utilise
|
||||
▼
|
||||
SearchSelect.vue (creatable=true)
|
||||
▲
|
||||
│ utilisé par
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
│ │ │
|
||||
MachineCustomFieldDefEditor│ StructureNodeEditor
|
||||
│
|
||||
PieceModelStructureEditor
|
||||
┌───────────────┼─────────────────────┐
|
||||
│ │ │
|
||||
MachineCustomFieldDef- StructureNodeEditor PieceModelStructure-
|
||||
Editor (composants) Editor (pièces)
|
||||
│
|
||||
MachineCustomFieldsCard
|
||||
(édition inline d'une machine)
|
||||
```
|
||||
|
||||
## Backend
|
||||
@@ -70,29 +72,12 @@ Union SQL : CustomFieldNameInput.vue (wrapper)
|
||||
Le controller exécute une seule requête SQL brute via `Doctrine\DBAL\Connection` :
|
||||
|
||||
```sql
|
||||
SELECT DISTINCT name FROM (
|
||||
SELECT name FROM custom_fields
|
||||
UNION
|
||||
SELECT jsonb_array_elements(customfields)->>'name' AS name
|
||||
FROM skeleton_piece_requirements
|
||||
WHERE customfields IS NOT NULL
|
||||
UNION
|
||||
SELECT jsonb_array_elements(customfields)->>'name' AS name
|
||||
FROM skeleton_subcomponent_requirements
|
||||
WHERE customfields IS NOT NULL
|
||||
UNION
|
||||
SELECT jsonb_array_elements(customfields)->>'name' AS name
|
||||
FROM skeleton_product_requirements
|
||||
WHERE customfields IS NOT NULL
|
||||
) AS all_names
|
||||
SELECT DISTINCT name FROM custom_fields
|
||||
WHERE name IS NOT NULL AND name <> ''
|
||||
ORDER BY name ASC
|
||||
```
|
||||
|
||||
**À vérifier au moment de l'implémentation** :
|
||||
- Le nom exact de la colonne JSON `customfields` en lowercase dans PostgreSQL (Doctrine = camelCase, PG = lowercase).
|
||||
- Le nom exact des tables `skeleton_*_requirements` (à confirmer dans les migrations).
|
||||
- Le type de la colonne (JSON vs JSONB) — `jsonb_array_elements` ne fonctionne que sur JSONB ; pour JSON utiliser `json_array_elements`.
|
||||
> Toutes les sources de noms (machines, ModelType×composant/pièce/produit) convergent dans la même table `custom_fields` via les FKs `machineId`/`typeComposantId`/`typePieceId`/`typeProductId`. Pas de jointure ni de parsing JSON nécessaire — un simple `SELECT DISTINCT` suffit.
|
||||
|
||||
### Pas de cache HTTP
|
||||
|
||||
|
||||
Reference in New Issue
Block a user