Brief développeur — Power App Prio Réfs

Solution PowerRange 1.0.0.3 · préfixe cr568_ · orgdbdf3046.crm12.dynamics.com
Destinataires : équipe Power App / Dataverse (Perfect Store + DXI).
Ne pas réutiliser l’app Saisie e890ef64-b48f-43ad-9a7e-e2454e283e82.
Dataset Power BI : 612ef347-d29a-40a4-9073-11a699847590

1. Contrat — même mécanique que Saisie

Une phrase. Power BI calcule une proposition (Hero / Strat / rang / DV). L’humain confirme ou force. Dataverse mémorise. Après refresh, les colonnes « actuel » du rapport suivent la décision, pas la proposition.

Chaîne à implémenter, dans cet ordre :

  1. Page Prio (Power BI) — clic ligne EAN + slicers (Hero / Strat / Liste prio / Objectifs).
  2. Canvas Prio (nouvelle app) — lecture de PowerBIIntegration.Data, Patch sur clé alternative.
  3. Dataverse — tables cr568_prio_decision et cr568_prio_objectif.
  4. Flux + dataset — On Create/Update puis refresh 612ef347-…
  5. Retour Power BI — PRIO actuel, PL actuel, DV Objectif Prio (plus seulement Excel).
Saisie des accordsPrio Réfs (à construire)
App canvase890ef64-b48f-43ad-9a7e-e2454e283e82Nouvelle app. Interdit de l’embarquer dans le slot Prio.
Visuel PBIPowerApps_PBI_CV_C29F1DCC_81F5_4973_94AD_0517D44CC06AMême type de visuel, autre appId.
Table Dataversecr568_negotiation_current (ledger négo)Deux tables neuves. Pas une colonne de plus sur le ledger.
Grain d’écritureEAN × enseigne × PeriodKey (ScaKey)Décision : EAN × circuit × année. Objectif : EAN × enseigne × PeriodKey.
Contexte reçuColonnes de negotiation_current (ean, Année, DV, dates…)Mesures et colonnes Prio (section Embed).
Après PatchFlux PPC / refresh datasetMême hop refresh. Pointer ensuite PRIO actuel / PL actuel / DV Objectif Prio sur Dataverse.
Sécurité CDCÉquipe négoRestricted Perfect Store + DXI uniquement.

cr568_prio_ref n’est pas la cible. Ce champ (et cr568_priority_list, entier) existe déjà sur cr568_negotiation_current : étiquette recopiée sur le ledger d’accords. Une écriture Prio dedans casserait la négo et ne nourrirait pas PRIO actuel, qui lit Spec_Produit_Wide via TREATAS. Créer des tables dédiées.

Rôles figés côté Power BI (déjà livrés)

Le rapport ne persiste rien. Il affiche une proposition DAX et un « actuel » Excel. L’app est le seul endroit où un humain verrouille.

Pattern Saisie : visuel 0aebe2b2f8c11bb0fa9f, table cr568_negotiation_current2. Pages Prio : Hero b2be14e97edc42e38e63, Strat a7c4e91b50d2486f3e21, Liste prio b8d5fa2c61e359704f32, Objectifs c9e60b3d72f46a815043.

2. Dataverse — cr568_prio_decision

Publisher DataLift, préfixe cr568_, table non managée, audit on. Une ligne = une décision d’assortiment pour un circuit et une année typo. CDC : unitaires, pas de refs HD. Alternate key obligatoire : cr568_ak_prio_decision sur cr568_ean + cr568_circuit + cr568_annee.

Attribut logiqueTypeOblig.Règle
cr568_prio_decisioniduniqueidentifierPKGUID système
cr568_namenvarchar 200autoFormule : ean & "|" & circuit & "|" & annee
cr568_eannvarchar 20ouiTexte, pas Int64. Pad interdit.
cr568_circuitchoiceouiHM / SM / PROXI seulement. Pas HD, pas ECOM.
cr568_anneenvarchar 4ouiAnnée typo spec 2023…2026 = slicer Spec_Produit_Wide[annee].
cr568_conditionnementchoiceouiDéfaut UNITAIRE. DP / BOX hors scope Prio (Supply).
cr568_refs_hdchoiceouiDéfaut HORS HD. Les jumeaux HD de Spec_Produit_Wide cassent SELECTEDVALUE.
cr568_priochoiceouiHERO / STRAT / INNO / OTHER — valeur lue ensuite par PRIO actuel.
cr568_prio_proposenvarchar 20nonCopie de Hero proposé / Strat proposé au Patch (audit).
cr568_ranking_plintnonRang liste prio (1…n), unique par (circuit, annee).
cr568_ranking_pl_proposeintnonCopie de PL proposé au Patch.
cr568_sourcechoiceouiPROPOSE (accepté tel quel) / FORCE (surcharge humaine).
cr568_host_screenchoiceouiHERO / STRAT / LISTE_PRIO.
cr568_commentairenvarchar 500nonMotif si FORCE.
ownerid / createdon / modifiedonstdouiAudit PS + DXI.

Patch idempotent. LookUp sur la clé alternative, puis Patch du record. Ne pas Create en doublon si l’EAN est déjà tranché pour ce circuit-année.

3. Dataverse — cr568_prio_objectif et sécurité

Grain plus fin que la décision prio : EAN × enseigne nvx2 × PeriodKey (2025Q1, 2025Q3…), identique à Objectifs.xlsx (14 267 lignes, ScaKey = ProductKey|enseigne|PeriodKey, ProductKey = ean & "0"). Périmètre CDC : HMSM + CRF City/Contact + Franprix. Pas HD, pas e-com.

Attribut logiqueTypeOblig.Règle
cr568_prio_objectifidGUIDPK
cr568_scakeynvarchar 120oui uniqueean & "0|" & label_enseigne_nvx2 & "|" & periodkey
cr568_eannvarchar 20oui
cr568_label_enseigne_nvx2nvarchar 100ouiLibellé enseigne référentiel, pas le circuit.
cr568_periodkeynvarchar 8ouiYYYYQ1 ou YYYYQ3 uniquement (CDC négo).
cr568_anneeintouiDérivé de PeriodKey.
cr568_negochoice Q1/Q3oui
cr568_dv_objectifdecimal (2)ouiSaisie humaine. DV brute enseigne, pas un %.
cr568_dn_objectifdecimal (2)nonSi le métier le saisit ; sinon vide.
cr568_sourcechoiceouiEXCEL_IMPORT / SAISIE_APP.

Sécurité

RôleTables Prionegotiation_current
Perfect StoreCRUD prio_decision + prio_objectiflecture seule recommandée
DXICRUD + publier solutioninchangé
Autres (négo, field)aucuninchangé

Valeurs de choice — identiques au modèle PBI

4. Console Hero

Une app, quatre écrans. StartScreen selon host_screen (section Embed). Pas de menu interne qui duplique les onglets PBI.

OnVisible commun : Set(varRow; First(PowerBIIntegration.Data)). Si ean blank → « Sélectionnez une ligne dans le tableau ». Tous les Patch lisent varRow, jamais une galerie interne non filtrée.

ContrôleSourceComportement
LblRefvarRow.reference & " · " & varRow.eanlecture
LblCircuitAnneevarRow.circuit & " · " & varRow.anneecircuit vient du slicer PBI
LblActuelvarRow.PRIO_actuelspec Excel / Dataverse après bascule
LblProposevarRow.Hero_proposeHERO ou OTHER
LblCumulvarRow.Poids_NR_Cumulewarning 50 %
CmbPrioHERO / OTHER (pas INNO/STRAT ici)défaut = Hero_propose
TglForceboolsi choix ≠ proposé → source = FORCE, commentaire obligatoire
BtnEnregistrerPatch prio_decisionhost_screen = HERO

Avertissement (pas un blocage) si CmbPrio = HERO et Poids_NR_Cumule déjà ≥ 50 % hors de cette SKU : le métier a le droit de forcer.

Patch(
  cr568_prio_decisions;
  LookUp(cr568_prio_decisions;
    cr568_ean = varRow.ean And cr568_circuit = varRow.circuit And cr568_annee = Text(varRow.annee)
  );
  {
    cr568_ean: varRow.ean;
    cr568_circuit: varRow.circuit;
    cr568_annee: Text(varRow.annee);
    cr568_conditionnement: "UNITAIRE";
    cr568_refs_hd: "HORS HD";
    cr568_prio: CmbPrio.Selected.Value;
    cr568_prio_propose: varRow.Hero_propose;
    cr568_source: If(CmbPrio.Selected.Value = varRow.Hero_propose; "PROPOSE"; "FORCE");
    cr568_host_screen: "HERO";
    cr568_commentaire: TxtMotif.Text
  }
)

5. Consoles Strat, Liste prio, Objectifs

Strat

CmbPrio : STRAT / OTHER. HERO désactivé — renvoyer vers l’onglet Hero. Si Hero_propose = HERO : « déjà Hero, ne pas retrancher ici ». Le scoring Perfect Store (croissance, marge, DN) vit ici : formule CDC absente du PBIX. Tant que le score n’existe pas, préremplir avec Strat_propose (bande 50–80 %).

Quand le score arriveraOù le coderImpact PBI
Règle chiffrée PS (score ≥ seuil)App : cr568_score + calcul OnVisibleRemplacer la mesure Strat proposé DAX, ou la laisser en suggestion
EAN déjà STRAT dans specPrécocher CmbPrio = PRIO_actuel si STRATComparer actuel vs proposé dans le tableau

Liste prio

TxtRang entier ≥ 1. Unicité de cr568_ranking_pl par (circuit, annee). Collision : décaler les rangs suivants (ForAll Update) ou refuser. Préremplir avec PL_propose. Afficher PL_actuel (spec) en lecture.

Objectifs — le grain change

Une ligne PBI (EAN) peut cacher N enseignes. Soit le tableEx de la page Objectifs expose label_enseigne_nvx2 + PeriodKey (recommandé), soit l’app charge une galerie Filter(cr568_prio_objectifs; cr568_ean = varRow.ean).

Champ galeriePatch
Enseigne (lecture)cr568_label_enseigne_nvx2
PeriodKey (slicer Q1/Q3 ou combo)cr568_periodkey — 2025Q1 / 2025Q3
DV objectif (saisie)cr568_dv_objectif — nombre, pas %
DN objectif (optionnel)cr568_dn_objectif

Périmètre Objectifs. Patch seulement si l’enseigne est HMSM, Carrefour City, Carrefour Contact ou Franprix. Refuser HD / Drive / e-com / enseigne saisie à la main. Alignement Dim_Enseignes[Enseigne_MAG] et circuit HM/SM/PROXI.

Messages et états

CasUI
PowerBIIntegration.Data videPas de Patch. Texte d’aide.
Circuit ou année = ToutBloquer. SELECTEDVALUE prio / annee est blank.
Patch OKNotify succès + déclencher le flux refresh.
Patch KO (clé / sécurité)Notify erreur Dataverse brute, ne pas avaler.

6. Embed Power BI

Remplacer la card « Console Prio — à brancher » (acedc191357f4eac992b) par le visuel Power Apps, même emplacement que Saisie : x ≈ 987, y ≈ 223, width ≈ 279, height ≈ 477, dans le rectangle arrondi console.

Propriété visuelValeur
visualTypePowerApps_PBI_CV_C29F1DCC_81F5_4973_94AD_0517D44CC06A
objects.general.appId/providers/Microsoft.PowerApps/apps/<GUID-NOUVELLE-APP>
query.queryState.table.projectionsRôle table (pas Values) — liste ci-dessous
Table Prio drillFilterOtherVisualsRepasser à true (false aujourd’hui à cause du crash isMeasure sans app).

Champs PowerBIIntegration.Data (nativeQueryRef)

Noms sans slash ni accent : l’app les lit en identifiants. Le tableau PBI peut garder les libellés FR.

nativeQueryRefChamp PBIPages
eanDim_Produit_EAN[ean]toutes
referenceDim_Produit_EAN[reference]toutes
circuitDim_Enseignes[circuit] — slicer, pas une mesuretoutes
anneeSpec_Produit_Wide[annee]toutes
conditionnementDim_Produit_EAN[conditionnement]toutes
NR_FinanceMesures[NR_Finance]toutes
Poids_NRMesures[Poids NR/Circuit]Hero, Strat, PL
Poids_NR_CumuleMesures[Poids NR Cumulé]Hero, Strat
PRIO_actuelMesures[PRIO actuel]toutes
Hero_proposeMesures[Hero proposé]Hero, Strat, PL
Strat_proposeMesures[Strat proposé]Strat, PL
PL_actuelMesures[PL actuel]Liste prio
PL_proposeMesures[PL proposé]Liste prio
DV_ObjectifMesures[DV Objectif Prio]Objectifs
label_enseigne_nvx2à ajouter sur la page ObjectifsObjectifs
PeriodKeyObjectifs[PeriodKey]Objectifs
host_screenmesure constante HERO / STRAT / LISTE_PRIO / OBJECTIFStoutes

Mesure host_screen par page pour StartScreen = Switch(First(PowerBIIntegration.Data).host_screen; …). Évite un Param() fragile dans l’embed Desktop.

Interactions visuelles

Table → console : remettre DataFilter (aujourd’hui NoFilter), sinon le clic EAN n’envoie pas la ligne. Table → cartes KPI : garder NoFilter (un Hero unique ferait chuter % NR à ~2 %).

Slicers obligatoires avant saisie

SlicerPourquoi l’app l’exige
Circuit = HM ou SM ou PROXIPRIO actuel / PL actuel sont circuit-spécifiques. Tout = SELECTEDVALUE blank.
Année typo = une annéeSpec_Produit_Wide a 4 années ; sans filtre SELECTEDVALUE prio_ref_* est blank (doublons).
Contour / ConditionnementFiltrent la proposition NR ; UNITAIRE recommandé (CDC).
Set(varRow; First(PowerBIIntegration.Data));;
Set(varCircuit; Coalesce(varRow.circuit; Blank()));;
If(
  IsBlank(varRow.ean) Or IsBlank(varCircuit) Or IsBlank(varRow.annee);
  Notify("Sélectionnez un circuit, une année, puis une ligne EAN"; NotificationType.Warning);
  Navigate(EcrHero; ScreenTransition.None)
)

7. Flux et colonnes actuel

Sans ce hop, le Patch est invisible dans Power BI. Aujourd’hui PRIO actuel lit Spec_Produit_Wide (Excel SharePoint Specifications_produits.xlsx). Objectifs lit Objectifs.xlsx. Dataverse n’est importé que pour cr568_negotiation_current.

OptionMécaniqueQuand
A — recommandée (proche Saisie)Flux cloud « Power Range Prio writeback » : On Create/Update de cr568_prio_decision et cr568_prio_objectif, import des deux tables (Import, pas DirectQuery), relation ean → Dim_Produit_EAN, refresh dataset 612ef347-…. COALESCE(Dataverse ; spec Excel).Même contrat que Saisie.
B — ExcelLe flux upsert prio_ref_* et ranking_PL_* dans Specifications_produits.xlsx, et DV Objectif dans Objectifs.xlsx. Aucun changement DAX.Uniquement si l’import Dataverse est refusé. Fragile (lock fichier, HD vs HORS HD).
Mesure PBI à rebrancherLecture actuelleAprès option A
PRIO actuelTREATAS EAN → Spec_Produit_Wide[prio_ref_HM/SM/Proxi]SELECTEDVALUE(cr568_prio_decision[cr568_prio]) filtré circuit+année ; fallback spec si pas de ligne
PL actuelranking_PL_* speccr568_ranking_pl ; fallback spec
DV Objectif PrioSUM(Objectifs[DV Objectif])SUM Dataverse si source = SAISIE_APP, sinon Excel (union Power Query)

Fallback spec. COALESCE(décision Dataverse ; spec Excel) : une SKU jamais touchée dans l’app continue d’afficher l’Excel. C’est le comportement attendu au go-live.

Refresh à la demande. Bouton app « Publier vers le rapport » = déclenchement du flux Power Automate, pas un refresh Desktop. Ne rafraîchir que si le Patch a réussi. Pas toutes les 5 min (le PPC négo garde son cadencement).

8. Recette

#DonnéAttendu
1Slicer Tout / clic EAN / Enregistrer HeroApp refuse. Message circuit + année.
2HM + 2025 + FOOD + UNITAIRE, ligne Hero proposé = HERO, accepterLigne Dataverse source=PROPOSE, prio=HERO. Après refresh, PRIO actuel = HERO sur cet EAN × HM.
3Même filtre, forcer OTHER sur un Hero DAXsource=FORCE, commentaire obligatoire. PRIO actuel devient OTHER. Hero proposé reste HERO (DAX).
4Même EAN, passer slicer SMAutre ligne Dataverse (clé ean|SM|année). HM inchangé. CDC : un EAN peut être Hero HM et Other Proxi.
5Onglet Strat, SKU déjà Hero proposéPas de Patch STRAT. Message renvoyer vers Hero.
6Liste prio : deux EAN rang 1Refus ou décalage. Jamais deux rangs identiques actifs.
7Objectifs : enseigne DrivePatch refusé.
8Utilisateur hors PS/DXIApp en lecture ou accès Dataverse refusé.
9Embarquer l’app Saisie e890ef64 dans le slot PrioHors recette — interdit. Champs dates/DV négo, mauvais grain.
10Doublon spec HD vs HORS HD même EAN 2025App n’écrit que HORS HD. PRIO actuel PBI ne doit plus rester blank après bascule Dataverse.

9. Checklist de livraison

LivrableOwner
Tables + choices + alternate keys + security roles dans PowerRangeDataverse / DXI
Canvas app 4 écrans + Patch + Notify + bouton refreshPower App
Visuel Power Apps × 4 pages Prio, bindings, drillFilter true, host_screenPower BI
Mesures fallback Dataverse / spec pour PRIO actuel, PL actuel, DV Objectif PrioPower BI
Flux On Create/Update → refresh dataset 612ef347-…Power Automate
Remplacer Strat proposé DAX quand le score PS est codé dans l’appPower App + PBI

Hors scope de ce sprint

Aligné sur le CDC module Priorisation des refs, le visuel Saisie, le ledger cr568_negotiation_current, et les mesures dossier Prio Réfs du PBIP Power_Range_Undynamic.