Added

Djust 3.135.0 - Semaine du 21 Septembre 2026

Périmètre

🔗 Data Hub

📘

NEW

Email par défaut en cas d'échec d'exécution d'un import

Contexte

« Échec d'exécution d'un job d'intégration » était le seul modèle du catalogue d'e-mails livré sans version par défaut. Sur un tenant ne disposant pas de son propre modèle, l'éditeur du Back-Office affichait un canevas vide et la notification d'échec ne pouvait pas être envoyée : une exécution d'import en erreur passait donc inaperçue.

Fonctionnement

Un modèle par défaut est désormais fourni pour ce type de notification. Sans modèle personnalisé, l'e-mail part avec ce contenu par défaut et l'éditeur d'e-mails du Back-Office affiche son design, prêt à être adapté.

L'e-mail récapitule le nom et le type de l'import concerné, ses dates et heures de début et de fin, le destinataire, un lien direct vers l'exécution, ainsi que l'identifiant de l'exécution en échec — désormais transmis jusqu'au modèle et affiché dans le corps du message.

Comportement inchangé pour les tenants disposant déjà d'un modèle personnalisé : celui-ci reste prioritaire.

📄 Documentation :

👉 Côté métier : toute exécution d'import en échec déclenche désormais une notification lisible, sans configuration préalable, avec l'identifiant de l'exécution à communiquer au support pour accélérer le diagnostic.

👉 Côté technique : la variable jobExecutionId est disponible dans le modèle d'e-mail d'échec d'import ; l'ajout est rétrocompatible et ne modifie aucun modèle personnalisé existant.

🛠️ API

📘

NEW

Liste des stores de rattachement du customer user authentifié

Contexte

Une page de connexion unique placée devant plusieurs stores a besoin, juste après authentification, de connaître les stores auxquels le customer user est rattaché pour ouvrir la session sur le bon store — connexion directe s'il n'y en a qu'un, écran de sélection sinon. Aucune route StoreFront ne renvoyait cette information : la récupération de l'utilisateur authentifié exige un store valide et répond 403 sans ce contexte, et le détail d'un store ne renvoie qu'un store à la fois.

Fonctionnement

Une nouvelle route StoreFront liste les stores de rattachement du customer user authentifié. Elle est appelable sans header dj-store, donc avant tout choix de store ; un dj-store transmis est ignoré et n'altère pas la liste.

Seuls les stores auxquels le customer user est rattaché sont renvoyés, actifs comme inactifs : un store du tenant sur lequel il n'est pas rattaché n'apparaît jamais, même s'il est explicitement demandé par filtre. Un customer user rattaché à aucun store reçoit une liste vide avec un 200.

La liste se filtre sur le statut d'activation, les identifiants techniques ou les externalIds (ET entre critères différents, OU entre valeurs d'un même critère), se trie sur name, externalId ou active (défaut name:asc, entrées de tri invalides silencieusement ignorées) et se pagine via l'enveloppe standard.

Impact API

GET /v1/shop/stores (operationId : STORE-550)
Réservée à dj-client: ACCOUNT403 pour OPERATOR ou SUPPLIER.
Réponse paginée de StoreResponse, incluant storeViews[].
400 si la valeur du filtre d'activation ou les paramètres de pagination ne sont pas au bon format.

📄 Documentation : Stores

👉 Côté métier : un même front peut servir plusieurs stores derrière une seule page de connexion, avec une redirection automatique ou un écran de sélection selon les rattachements du customer user.

👉 Côté technique : nouvelle route de liste STORE-550, sans header dj-store requis, avec filtres, tri et pagination standards.

👍

UPDATE

Store views exposées sur le détail d'un store

Contexte

Le détail d'un store ne renvoyait pas ses store views. Un front ne pouvait donc pas positionner le contexte dj-store-view à partir des données du store, alors que les langues du store (storeLocales) étaient déjà disponibles.

Fonctionnement

La réponse d'un store contient désormais l'ensemble de ses store views, actives et inactives, chacune avec son identifiant, son externalId, son nom et son statut d'activation. Un store sans store view renvoie un tableau vide.

storeLocales (langues du store) et storeViews restent deux notions distinctes et sont toutes les deux renvoyées. L'ajout est non cassant : les champs existants sont inchangés.

Impact API

GET /v1/shop/stores/{storeId} (operationId : STORE-500)
Nouveau champ storeViews[] (id, externalId, name, active) dans StoreResponse, également renvoyé par la nouvelle route de liste.

📄 Documentation : Stores

👉 Côté métier : la configuration complète d'un store, langues et store views comprises, est accessible en une seule requête.

👉 Côté technique : enrichissement non cassant de StoreResponse, partagé par le détail et la liste des stores.


Filtre « commandes en attente de mon approbation »

Contexte

La recherche de commandes logistiques d'un storefront permettait de distinguer « mes commandes » de « toutes les commandes du compte », sans jamais isoler celles que l'utilisateur connecté doit approuver. Un storefront devait charger toutes les commandes en attente d'approbation puis trier côté navigateur, ce qui est incompatible avec une pagination serveur.

Fonctionnement

Un nouveau critère booléen pendingMyApproval permet de ne conserver que les commandes dont l'approbation est attribuée au customer user connecté et toujours en attente. Les commandes qu'il a déjà approuvées, comme celles attendant l'approbation d'un autre utilisateur, sont exclues.

À false ou absent, le comportement est strictement inchangé. Le critère se combine avec tous les autres filtres et tris, et le périmètre de sécurité habituel (comptes clients autorisés et store view) reste appliqué d'office.

Ce critère est disponible sur le storefront uniquement, l'utilisateur connecté au Back-Office n'étant pas un approbateur.

Impact API

POST /v1/shop/logistic-orders (operationId : ORDER-550)
Nouveau champ optionnel pendingMyApproval (boolean) dans le corps de la requête. Ajout non cassant.

📄 Documentation : Search, Filter & Sort Logistic Orders

👉 Côté métier : un approbateur accède directement à sa file d'approbation, sans parcourir toutes les commandes de son compte.

👉 Côté technique : filtre serveur sur les approbations en attente de l'utilisateur connecté, compatible avec la pagination et les tris existants.

⚠️

IMPORTANT UPDATE

Suppression d'un groupe d'utilisateurs refusée si elle laisserait des membres sans groupe

Contexte

La suppression d'un groupe ne tenait pas compte de ses membres : un utilisateur dont c'était le seul groupe se retrouvait sans aucun groupe, donc sans droits, sans aucun signal. C'était le dernier chemin permettant de créer des utilisateurs orphelins de groupe.

Fonctionnement

La suppression d'un groupe est désormais refusée dès qu'au moins un de ses membres n'appartient à aucun autre groupe du même périmètre. Le refus est actionnable : la réponse identifie les utilisateurs bloquants, afin de les réaffecter vers un groupe de remplacement avant de relancer la suppression.

La règle et le code d'erreur sont alignés sur ceux du retrait de membres d'un groupe. Lorsqu'aucun utilisateur ne serait orphelin, la suppression s'effectue comme avant.

Impact API

DELETE /v2/user-groups/{groupId} (operationId : ADM-USER-GROUP-300)
Nouvelle réponse 400 avec le code d'erreur UV0008 ; le détail porte le nombre d'utilisateurs concernés, la liste de leurs identifiants (plafonnée à 100) et un indicateur de troncature.
Réponse inchangée (204 No Content) lorsque la suppression est autorisée.
Les intégrations appelant cette route doivent désormais traiter le cas 400.
Référence complète des codes : Error / Warning codes

📄 Documentation : Back-end users (Operators)

👉 Côté métier : plus aucun utilisateur ne peut perdre tous ses droits à la suite de la suppression d'un groupe, et les utilisateurs à réaffecter sont identifiés immédiatement.

👉 Côté technique : nouveau cas d'erreur 400 UV0008 sur la suppression de groupe, avec la liste des utilisateurs bloquants pour permettre leur réaffectation.

Autre :

Activation du module de shipping par défaut à la création d'un nouveau tenant.