feat(baserow): add formulas pass + related field naming to seed
Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
- schema.json : 17 formulas (rollups + heures_restantes) ajoutees + related_field_name explicite sur les 10 liens - seed.py : 3 nouveaux methodes (create_formula_field, rename_field, create_link_field returns dict) - seed.py : pass 5/6 renomme automatiquement les related fields apres link creation - seed.py : pass 6/6 cree les formulas (idempotent) - README.md : section formulas updated Iteration 2 du plan Fast-App couverte. Apres seed, les rollups (formation_heures_attribuees, personne_heures_restantes_total, etc.) sont automatiques.
This commit is contained in:
parent
6724be6c85
commit
a0266b886c
3 changed files with 71 additions and 15 deletions
|
|
@ -69,7 +69,9 @@ Pour reset complet : drop la database via l'UI Baserow, puis relancer.
|
|||
|
||||
`schema.json` decrit les 9 tables + 10 liens FK. Format JSON declaratif, modifiable.
|
||||
|
||||
Les **formulas** (rollups, heures_restantes, etc.) ne sont **pas** crees par ce seed (Phase 1 = structure seule). Elles seront ajoutees en iteration 2 du plan Fast-App via un seed-formulas.py separe.
|
||||
Les **formulas** (rollups, heures_restantes, etc.) sont creees au pass 6/6. Le schema declaratif inclut 17 formulas dans `schema.json` (section `formulas`).
|
||||
|
||||
Si une formula echoue (syntaxe Baserow strict), le seed s'arrete et affiche l'erreur — corrige le `schema.json` et re-run.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -187,16 +187,34 @@
|
|||
}
|
||||
],
|
||||
"links": [
|
||||
{"from_table": "bloc", "from_field": "bloc_formation", "to_table": "formation"},
|
||||
{"from_table": "module", "from_field": "module_bloc", "to_table": "bloc"},
|
||||
{"from_table": "attribution", "from_field": "attribution_module", "to_table": "module"},
|
||||
{"from_table": "attribution", "from_field": "attribution_personne", "to_table": "personne"},
|
||||
{"from_table": "projet", "from_field": "projet_client", "to_table": "client"},
|
||||
{"from_table": "projet", "from_field": "projet_formation_pedagogique", "to_table": "formation"},
|
||||
{"from_table": "tache", "from_field": "tache_projet", "to_table": "projet"},
|
||||
{"from_table": "tache", "from_field": "tache_assignee", "to_table": "personne"},
|
||||
{"from_table": "intervention", "from_field": "intervention_tache", "to_table": "tache"},
|
||||
{"from_table": "intervention", "from_field": "intervention_personne", "to_table": "personne"}
|
||||
{"from_table": "bloc", "from_field": "bloc_formation", "to_table": "formation", "related_field_name": "formation_blocs"},
|
||||
{"from_table": "module", "from_field": "module_bloc", "to_table": "bloc", "related_field_name": "bloc_modules"},
|
||||
{"from_table": "attribution", "from_field": "attribution_module", "to_table": "module", "related_field_name": "module_attributions"},
|
||||
{"from_table": "attribution", "from_field": "attribution_personne", "to_table": "personne", "related_field_name": "personne_attributions"},
|
||||
{"from_table": "projet", "from_field": "projet_client", "to_table": "client", "related_field_name": "client_projets"},
|
||||
{"from_table": "projet", "from_field": "projet_formation_pedagogique", "to_table": "formation", "related_field_name": "formation_projets_pedagogiques"},
|
||||
{"from_table": "tache", "from_field": "tache_projet", "to_table": "projet", "related_field_name": "projet_taches"},
|
||||
{"from_table": "tache", "from_field": "tache_assignee", "to_table": "personne", "related_field_name": "personne_taches_assignees"},
|
||||
{"from_table": "intervention", "from_field": "intervention_tache", "to_table": "tache", "related_field_name": "tache_interventions"},
|
||||
{"from_table": "intervention", "from_field": "intervention_personne", "to_table": "personne", "related_field_name": "personne_interventions"}
|
||||
],
|
||||
"_note_phase_2": "Les formulas (rollups, heures_restantes) seront ajoutees en iteration 2 du plan Fast-App. Phase 1 = structure + liens seuls."
|
||||
"formulas": [
|
||||
{"table": "module", "name": "module_heures_prevues_active", "expression": "if(field('module_statut') = 'annule', 0, field('module_heures_prevues'))"},
|
||||
{"table": "attribution", "name": "attribution_heures_attribuees_active", "expression": "if(field('attribution_statut') = 'annule', 0, field('attribution_heures_attribuees'))"},
|
||||
{"table": "intervention", "name": "intervention_heures_active", "expression": "if(field('intervention_statut') = 'annule', 0, field('intervention_heures'))"},
|
||||
{"table": "bloc", "name": "bloc_heures_attribuees", "expression": "sum(lookup('bloc_modules', 'module_heures_prevues_active'))"},
|
||||
{"table": "bloc", "name": "bloc_heures_restantes", "expression": "field('bloc_heures_prevues') - field('bloc_heures_attribuees')"},
|
||||
{"table": "module", "name": "module_heures_attribuees", "expression": "sum(lookup('module_attributions', 'attribution_heures_attribuees_active'))"},
|
||||
{"table": "module", "name": "module_heures_realisees", "expression": "sum(lookup('module_attributions', 'attribution_heures_realisees'))"},
|
||||
{"table": "formation", "name": "formation_heures_attribuees", "expression": "sum(lookup('formation_blocs', 'bloc_heures_prevues'))"},
|
||||
{"table": "formation", "name": "formation_heures_restantes", "expression": "field('formation_heures_totales') - field('formation_heures_attribuees')"},
|
||||
{"table": "personne", "name": "personne_heures_attribuees_formation", "expression": "sum(lookup('personne_attributions', 'attribution_heures_attribuees_active'))"},
|
||||
{"table": "personne", "name": "personne_heures_attribuees_agence", "expression": "sum(lookup('personne_interventions', 'intervention_heures_active'))"},
|
||||
{"table": "personne", "name": "personne_heures_restantes_formation", "expression": "(field('personne_capacite_annuelle') * field('personne_split_formation_pct') / 100) - field('personne_heures_attribuees_formation')"},
|
||||
{"table": "personne", "name": "personne_heures_restantes_agence", "expression": "(field('personne_capacite_annuelle') * field('personne_split_agence_pct') / 100) - field('personne_heures_attribuees_agence')"},
|
||||
{"table": "personne", "name": "personne_heures_restantes_total", "expression": "field('personne_capacite_annuelle') - field('personne_heures_attribuees_formation') - field('personne_heures_attribuees_agence')"},
|
||||
{"table": "tache", "name": "tache_heures_realisees", "expression": "sum(lookup('tache_interventions', 'intervention_heures_active'))"},
|
||||
{"table": "projet", "name": "projet_heures_realisees", "expression": "sum(lookup('projet_taches', 'tache_heures_realisees'))"},
|
||||
{"table": "projet", "name": "projet_heures_restantes", "expression": "field('projet_charge_heures') - field('projet_heures_realisees')"}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class BaserowSeed:
|
|||
payload["long_text_enable_rich_text"] = True
|
||||
return payload
|
||||
|
||||
def create_link_field(self, from_table_id: int, name: str, to_table_id: int) -> int:
|
||||
def create_link_field(self, from_table_id: int, name: str, to_table_id: int) -> dict[str, Any]:
|
||||
r = self.session.post(
|
||||
f"{self.base_url}/api/database/fields/table/{from_table_id}/",
|
||||
headers=self._headers(),
|
||||
|
|
@ -158,6 +158,25 @@ class BaserowSeed:
|
|||
if r.status_code >= 300:
|
||||
print(f" [ERROR] link {name} resp={r.text}")
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def rename_field(self, field_id: int, new_name: str) -> None:
|
||||
r = self.session.patch(
|
||||
f"{self.base_url}/api/database/fields/{field_id}/",
|
||||
headers=self._headers(),
|
||||
json={"name": new_name},
|
||||
)
|
||||
r.raise_for_status()
|
||||
|
||||
def create_formula_field(self, table_id: int, name: str, expression: str) -> int:
|
||||
r = self.session.post(
|
||||
f"{self.base_url}/api/database/fields/table/{table_id}/",
|
||||
headers=self._headers(),
|
||||
json={"name": name, "type": "formula", "formula": expression},
|
||||
)
|
||||
if r.status_code >= 300:
|
||||
print(f" [ERROR] formula {name} expr={expression} resp={r.text}")
|
||||
r.raise_for_status()
|
||||
return r.json()["id"]
|
||||
|
||||
def seed(self, schema: dict[str, Any]) -> None:
|
||||
|
|
@ -183,7 +202,7 @@ class BaserowSeed:
|
|||
table_ids[tname] = tid
|
||||
self._sync_fields(tid, table)
|
||||
|
||||
print(f"\n[5/5] Link fields (2nd pass)")
|
||||
print(f"\n[5/6] Link fields (2nd pass)")
|
||||
for link in schema["links"]:
|
||||
from_id = table_ids[link["from_table"]]
|
||||
to_id = table_ids[link["to_table"]]
|
||||
|
|
@ -191,14 +210,31 @@ class BaserowSeed:
|
|||
if link["from_field"] in existing_fields:
|
||||
print(f" [link] Reuse {link['from_table']}.{link['from_field']} -> {link['to_table']}")
|
||||
continue
|
||||
self.create_link_field(from_id, link["from_field"], to_id)
|
||||
link_field = self.create_link_field(from_id, link["from_field"], to_id)
|
||||
print(f" [link] Created {link['from_table']}.{link['from_field']} -> {link['to_table']}")
|
||||
related_id = link_field.get("link_row_related_field_id") or link_field.get("link_row_related_field")
|
||||
related_name = link.get("related_field_name")
|
||||
if related_name and related_id:
|
||||
self.rename_field(related_id, related_name)
|
||||
print(f" [link] Renamed related field id={related_id} -> '{related_name}'")
|
||||
|
||||
print(f"\n[6/6] Formula fields (3rd pass)")
|
||||
for f in schema.get("formulas", []):
|
||||
tname = f["table"]
|
||||
tid = table_ids[tname]
|
||||
existing_fields = {x["name"]: x for x in self.list_fields(tid)}
|
||||
if f["name"] in existing_fields:
|
||||
print(f" [formula] Reuse {tname}.{f['name']}")
|
||||
continue
|
||||
self.create_formula_field(tid, f["name"], f["expression"])
|
||||
print(f" [formula] Created {tname}.{f['name']}")
|
||||
|
||||
print("\n=== Seed OK ===")
|
||||
print(f" Workspace: {schema['workspace_name']}")
|
||||
print(f" Database : {schema['database_name']}")
|
||||
print(f" Tables : {len(table_ids)}")
|
||||
print(f" Links : {len(schema['links'])}")
|
||||
print(f" Formulas : {len(schema.get('formulas', []))}")
|
||||
|
||||
def _sync_fields(self, table_id: int, table_def: dict[str, Any]) -> None:
|
||||
existing = {f["name"]: f for f in self.list_fields(table_id)}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue