feat: update version to 0.7.5 and enhance maturity model binding logic
Some checks failed
Deploy Development / deploy (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 5s
Test Suite / playwright-tests (push) Failing after 1m55s

- Incremented application version to 0.7.5 and updated maturity model version to 1.3.1.
- Improved binding logic to ensure that only relevant entries are considered based on the presence of context bindings.
- Updated documentation to clarify the behavior of binding resolution and its impact on legacy model resolution.
- Documented changes in the changelog for version 0.7.5, detailing the new binding resolution rules.
This commit is contained in:
Lars 2026-04-27 13:05:18 +02:00
parent f2c007cc68
commit 863535aa26
3 changed files with 54 additions and 9 deletions

View File

@ -260,7 +260,18 @@ def _binding_matches_query_dims(
b_style: Any,
b_tt: Any,
) -> bool:
"""Zeile passt zur Abfrage, wenn gesetzte Dimensionswerte der Zeile mit der Anfrage übereinstimmen."""
"""
Prüft, ob eine Binding-Zeile zur Anfrage passt.
Nicht gesetzte Spalten der Zeile gelten als egal (Wildcard):
- Nur Fokus: Stilrichtung und Trainingsstil NULL gilt für alle Stile/Trainingsstile unter diesem Fokus.
- Fokus + Stilrichtung: Trainingsstil NULL gilt nur für diese Stilrichtung, für jeden Trainingsstil.
- Fokus + Trainingsstil: Stilrichtung NULL gilt nur für diesen Trainingsstil, für jede Stilrichtung.
- Alle drei gesetzt ausschließlich diese Kombination.
In der Anfrage fehlende Dimensionen schließen Zeilen aus, die diese Dimension festgelegt haben
(z. B. Fokus+Trainingsstil-Binding zählt nicht, wenn kein Trainingsstil angefragt wird).
"""
if b_style is not None:
if style_direction_id is None or int(b_style) != int(style_direction_id):
return False
@ -279,6 +290,18 @@ def _binding_dim_count(b_style: Any, b_tt: Any) -> int:
return n
def _focus_has_any_bindings(cur, focus_area_id: int) -> bool:
cur.execute(
"""
SELECT 1 FROM maturity_model_context_bindings
WHERE focus_area_id = %s
LIMIT 1
""",
(focus_area_id,),
)
return cur.fetchone() is not None
def _resolve_binding_model_ids(
cur,
focus_area_id: int,
@ -449,6 +472,8 @@ def resolve_maturity_model(
Zuordnungen überschreiben Zelltexte gleicher Fähigkeit/Stufe.
**Priorität 2 (Legacy):** Ein aktives Modell per M:N am Modell (Zielgruppe unverändert).
Nur wenn für den Fokusbereich **keine** Einträge in `maturity_model_context_bindings` existieren
sonst würde Legacy den Trainingsstil ignorieren und Kontext-Bindings unterlaufen.
"""
with get_db() as conn:
cur = get_cursor(conn)
@ -462,6 +487,8 @@ def resolve_maturity_model(
if chain:
loaded = [_load_full_model(cur, mid) for mid in chain]
return _merge_loaded_models(loaded)
if _focus_has_any_bindings(cur, int(focus_area_id)):
return None
mid = _legacy_resolve_pick_model_id(
cur, focus_area_id, style_direction_id, target_group_id
@ -1188,13 +1215,19 @@ def export_resolved_maturity_bundle(
loaded = [_load_full_model(cur, mid) for mid in chain]
merged = _merge_loaded_models(loaded)
else:
if _focus_has_any_bindings(cur, int(focus_area_id)):
raise HTTPException(
404,
"Kein Reifegradmodell für diese Kontext-Kombination (es gibt Bindings für diesen Fokus, "
"aber keine passende Zeile).",
)
mid = _legacy_resolve_pick_model_id(
cur, focus_area_id, style_direction_id, None
)
if mid is None:
raise HTTPException(
404,
"Kein Modell für diesen Kontext (keine Bindings und kein Legacy-Treffer)",
"Kein Modell für diesen Kontext (keine Bindings für den Fokus und kein Legacy-Treffer).",
)
merged = _load_full_model(cur, mid)

View File

@ -1,6 +1,6 @@
# Shinkan Jinkendo Version Information
APP_VERSION = "0.7.4"
APP_VERSION = "0.7.5"
BUILD_DATE = "2026-04-27"
DB_SCHEMA_VERSION = "20260427027"
@ -19,10 +19,17 @@ MODULE_VERSIONS = {
"admin": "1.0.0",
"membership": "1.0.0",
"catalogs": "1.5.0", # Updated: Trainer Contexts API (Migration 012)
"maturity_models": "1.3.0", # 027: Fokus+Trainingsstil; Export/Import; resolve-Merge
"maturity_models": "1.3.1", # Resolve: kein Legacy, wenn Fokus bereits Bindings hat
}
CHANGELOG = [
{
"version": "0.7.5",
"date": "2026-04-27",
"changes": [
"Resolve/Export: Legacy M:N nur noch, wenn für den Fokus keine Kontext-Bindings existieren (korrekte Striktheit für Fokus+Trainingsstil / Teil-Kontexte)",
],
},
{
"version": "0.7.4",
"date": "2026-04-27",

View File

@ -132,11 +132,16 @@ export default function MaturityModelBindingsAdmin() {
<div className="admin-bindings">
<p className="admin-bindings__intro muted">
<strong>Zusammenführung:</strong> Zu einem Fokus können mehrere Zeilen existieren (nur Fokus, Fokus +
Stilrichtung, Fokus + Trainingsstil ohne Stil, oder alle drei). Beim Aufruf von{' '}
<code className="admin-bindings__code">/maturity-models/resolve</code> werden alle zur Anfrage passenden
Zeilen ermittelt, nach Spezifität sortiert (weniger zuerst) und zu einer Matrix verbunden: spezifischere
Zuordnungen überschreiben Zelltexte gleicher Fähigkeit und Stufe. Stufen (Spalten) stammen vom{' '}
<strong>ersten</strong> (am wenigsten spezifischen) Modell in dieser Kette.
Stilrichtung, Fokus + Trainingsstil ohne Stil, oder alle drei). Eine Zeile gilt nur, wenn alle von ihr
gesetzten Dimensionen mit der Anfrage übereinstimmen; fehlende Spalten in der Zeile bedeuten alle
(z.B. Fokus+Trainingsstil gilt unter jeder Stilrichtung, aber nur für genau diesen Trainingsstil).
Sobald für einen Fokusbereich mindestens eine Zuordnung in dieser Tabelle existiert, wird{' '}
<strong>kein</strong> älteres Legacy-Resolve (nur M:N am Modell) mehr verwendet fehlende Treffer
liefern dann keine Matrix. Beim Aufruf von{' '}
<code className="admin-bindings__code">/maturity-models/resolve</code> werden alle passenden Zeilen nach
Spezifität sortiert (weniger zuerst) gemerged; spezifischere Zuordnungen überschreiben Zelltexte gleicher
Fähigkeit und Stufe. Stufen (Spalten) stammen vom <strong>ersten</strong> (am wenigsten spezifischen)
Modell in dieser Kette.
</p>
{error ? (