77 lines
3.1 KiB
Python
77 lines
3.1 KiB
Python
import db
|
|
|
|
|
|
def apply_data_action(slug, action):
|
|
"""Exécute au moment du clic (mode jouable) une action "modifier_donnee" :
|
|
lit l'objet/la ligne/le champ visés dans l'action, calcule la nouvelle
|
|
valeur selon l'opération choisie, et l'enregistre — un vrai UPDATE SQL,
|
|
limité à cette seule colonne (les autres champs de la ligne ne sont pas
|
|
touchés)."""
|
|
definition_id = action.get("target_definition_id")
|
|
row_id = action.get("target_row_id")
|
|
field_name = action.get("target_field")
|
|
operation = action.get("data_operation")
|
|
raw_value = action.get("data_value")
|
|
if not (definition_id and row_id and field_name and operation):
|
|
return False
|
|
definition = db.get_definition(slug, definition_id)
|
|
if not definition:
|
|
return False
|
|
field_def = next((f for f in definition["fields"] if f["name"] == field_name), None)
|
|
if not field_def:
|
|
return False
|
|
row = db.get_row(slug, definition, row_id)
|
|
if not row:
|
|
return False
|
|
col = db.slugify(field_def["name"]).replace("-", "_")
|
|
if field_def["type"] == "relation":
|
|
col = col + "_id"
|
|
current = row.get(col)
|
|
|
|
if operation == "definir_texte":
|
|
new_value = raw_value or ""
|
|
elif operation == "definir_nombre":
|
|
try:
|
|
new_value = float(raw_value) if field_def["type"] == "nombre_decimal" else int(float(raw_value))
|
|
except (TypeError, ValueError):
|
|
new_value = 0
|
|
elif operation == "definir_bool_vrai":
|
|
new_value = 1
|
|
elif operation == "definir_bool_faux":
|
|
new_value = 0
|
|
elif operation == "basculer_bool":
|
|
new_value = 0 if current else 1
|
|
elif operation in ("incrementer", "decrementer"):
|
|
try:
|
|
amount = float(raw_value) if raw_value not in (None, "") else 0
|
|
except (TypeError, ValueError):
|
|
amount = 0
|
|
if operation == "decrementer":
|
|
amount = -amount
|
|
result = (current or 0) + amount
|
|
new_value = result if field_def["type"] == "nombre_decimal" else int(result)
|
|
else:
|
|
return False
|
|
|
|
new_value = _clamp_to_field_bounds(new_value, field_def)
|
|
db.update_row_field(slug, definition, row_id, field_def, new_value)
|
|
return True
|
|
|
|
|
|
def _clamp_to_field_bounds(value, field_def):
|
|
"""2.2 — bornage automatique : ramène la valeur dans [min_value,
|
|
max_value] si l'un ou l'autre est réglé sur ce champ, pour qu'une
|
|
jauge (voir render_jauge.py) ne puisse jamais dépasser 100 % ni
|
|
descendre sous 0 % (ou toute autre borne définie), quel que soit le
|
|
nombre d'actions "Augmenter de..."/"Diminuer de..." posées dans le
|
|
graphe de logique. Ne s'applique qu'aux champs numériques — un champ
|
|
non numérique n'a pas de min_value/max_value (voir create_definition)."""
|
|
if field_def["type"] not in ("nombre_entier", "nombre_decimal"):
|
|
return value
|
|
min_v, max_v = field_def.get("min_value"), field_def.get("max_value")
|
|
if min_v is not None and value < min_v:
|
|
value = min_v
|
|
if max_v is not None and value > max_v:
|
|
value = max_v
|
|
return value if field_def["type"] == "nombre_decimal" else int(value)
|