Skip to main content
gold.decision_context est le socle de la couche décision. Il matérialise une ligne par (organization_id, variant_id, shop_id, snapshot_date), consolidant l’état du stock, la marge, la prévision et les clés de dimension en une forme unique que chaque scorer du vecteur de décision lit. On le construit une fois, on le score de trois façons.

Lignage — trois entrées gold

Le builder s’ancre sur gold.stock_snapshot (une position = une ligne de stock) et y joint en LEFT JOIN la marge et la prévision, après avoir agrégé chaque entrée sur size_taxonomy_id.
  • stock_snapshot est l’ancre : aucune position → rien à construire (skip_task_if_empty).
  • sales_kpis fournit gross_margin_pct (LEFT JOIN sur la clé de position).
  • sales_forecasts est best-effort — filtré à granularity = 'daily', sommé sur la fenêtre des 30 prochains jours ; une prévision manquante laisse la colonne NULL.

Référence des colonnes

Les colonnes d’audit (created_at, updated_at) sont omises. aged_stock_flag est la seule colonne hors position en NOT NULL.

État du stock

Ventes et marge

Prévision

Clés de dimension (matching de périmètre des règles)

Slots toujours-NULL en v1

Sept colonnes sont typées et réservées mais toujours NULL en v1target_stock, lead_time_days, sell_through_7d/30d/90d, category_id, supplier_id. Leur type et leur nullabilité sont stables pour que le writer puisse les remplir plus tard sans migration DDL.
Comme target_stock est toujours NULL en v1, les ratios surplus/déficit du rebalance s’effondrent à 0 sur tout le catalogue (une position sans cible ne peut véritablement pas être classée surplus ou déficit). C’est un comportement correct et déterministe — les vrais scores de rebalance arrivent le jour où target_stock est rempli. Voir la page vecteur de décision.
La couche de scoring traite NULL comme « ignorer ce signal pour cette position » en ramenant chaque entrée NULL à une valeur neutre avant les calculs (documenté par domaine sur la page suivante).

Validation

Les règles sont embarquées sur le schéma et appliquées par le writer :
  • Erreurs (échouent la tâche) : decision_context_not_empty, decision_context_required_fields (organization_id, snapshot_date, aged_stock_flag non-NULL), decision_context_pk_unique.
  • Avertissements : contrôles de non-négativité sur current_stock, days_of_cover, forecast_30d.
Un DecisionContextHealthTask lève des brèches [freshness] (pas de snapshot récent) ou [row-count-drift] (la tranche du jour diverge de celle de la veille) pour le triage on-call.

Source

  • Schéma : pipelines/shared/schemas/gold/decision_context.py
  • Writer : pipelines/layers/gold/tasks/build_decision_context/task.py
  • Doc repo : docs/gold/decision-context.md