Vue d'ensemble
L'éligibilité est le mécanisme central qui détermine, pour une commande donnée, quels transporteurs sont disponibles et capables de la prendre en charge. Elle répond à la question : "Pour ce retailer, ce magasin, avec ces colis à envoyer à cette adresse, quels transporteurs puis-je proposer ?"
1. La hiérarchie d'éligibilité
Les règles d'éligibilité sont organisées en 4 niveaux imbriqués, du plus général au plus spécifique :
Chaque niveau hérite du niveau supérieur. Un enfant ne stocke que les différences par rapport à son parent. Lors de la résolution, la plateforme fusionne les niveaux pour obtenir l'éligibilité effective.
Exemple : si un transporteur accepte des colis jusqu'à 30 kg au niveau carrier, mais qu'un retailer spécifique a négocié 50 kg, seul le champ maxKilogramCapacity: 50 est stocké au niveau retailer. Tous les autres champs sont hérités du carrier.
2. Les champs de configuration d'une éligibilité
Limites physiques des colis
| Champ | Description |
|---|---|
| minKilogramCapacity / maxKilogramCapacity | Poids total de la commande (min / max) |
| packageMinWeight / packageMaxWeight | Poids par colis individuel |
| minLength / maxLength | Longueur du plus grand côté d'un colis |
| minCombinedLength / maxCombinedLength | Longueur combinée (L + 2H + 2l) |
| maxDevelopedDimensions | Somme des 3 dimensions d'un colis |
| maxHeight | Hauteur maximale |
| minVolumetricWeight / maxVolumetricWeight | Poids volumétrique (volume × facteur) |
| volumetricWeightFactor | Facteur de conversion volume → poids volumétrique |
| minVolume / maxVolume | Volume total de la commande |
| minPackageVolume / maxPackageVolume | Volume par colis individuel |
| maxPackageQuantity | Nombre maximal de colis |
Couverture géographique
| Champ | Description |
|---|---|
| minKilometricDistance / maxKilometricDistance | Distance entre picking et delivery |
| deliveryDepartments | Codes de départements livrables (ex. { FR: ["75", "69"] }) |
Disponibilités temporelles
| Champ | Description |
|---|---|
| deliveryPromise | Règles de promesse de livraison |
| deliveryNoticePeriod | Délai de préavis avant enlèvement |
| minDeliveryTime | Délai minimum de livraison |
| deliveryCutOffs | Heures limites de prise en charge |
| workSchedule | Horaires de travail du transporteur |
| pickingSchedule | Horaires d'enlèvement |
| closingSchedules | Périodes de fermeture exceptionnelle |
| sameDay / nextDay / standard / scheduled | Indicateurs de type de livraison supporté |
Services proposés
| Champ | Description |
|---|---|
| services | Types de livraison disponibles (ex. HOME_DELIVERY, PICKUP_POINT) |
| typologies | Types de produits acceptés |
| pickupPointTypes | Catégories de points relais (ex. locker, agence, relais commerçant) |
| specifications | Fonctionnalités spéciales (ex. quote pour activer les devis) |
| options | Options supplémentaires proposées |
| tags | Tags de filtrage pour l'orchestration |
| commitments | Engagements de volume avec scoring |
Informations de contact et adresse
| Champ | Description |
|---|---|
| contact | Contact du transporteur |
| address | Adresse principale |
| trackingPageUrl | URL de suivi |
| claimUrl | URL de réclamation |
Activation
| Champ | Description |
|---|---|
| isActive | Active ou désactive le transporteur à ce niveau |
3. Les Delivery Methods
Un Delivery Method est une sous-variante d'un transporteur — par exemple, un même carrier peut proposer une livraison "Express" et une livraison "Économique" avec des règles différentes.
Quand withDeliveryMethods: true est activé, chaque entrée d'éligibilité peut être associée à un deliveryMethodId. Cela permet de retourner plusieurs lignes par carrier, une par méthode de livraison, chacune avec ses propres contraintes et sa propre promesse de livraison.
Sans delivery methods, un carrier n'a qu'une seule ligne d'éligibilité par niveau hiérarchique. Avec, il peut en avoir autant qu'il a de méthodes configurées.
La requête SQL sous-jacente utilise des fonctions PostgreSQL dédiées (get_merged_eligibilities_unified_v5 / get_merged_eligibilities_v7) selon que les delivery methods sont activés ou non.
4. Le flux de vérification d'éligibilité
Quand un retailer appelle l'API d'éligibilité, voici ce qui se passe dans l'ordre :
Étape 1 — Résolution du contexte
- Validation et récupération du magasin (storeId)
- Géocodage des adresses de picking et de livraison si nécessaire
- Résolution de l'exchangePlace à partir de l'adresse de picking
- Calcul des paramètres physiques des colis (poids total, dimensions max, volume, etc.)
- Récupération des delivery promises via le service dédié
Étape 2 — Récupération des éligibilités candidates
Les éligibilités actives (isActive: true) sont récupérées en base pour le contexte (retailerId, storeId, exchangePlaceId), avec fusion des niveaux hiérarchiques. Le résultat est mis en cache et invalidé uniquement si le header pragma: no-cache est présent.
Étape 3 — Application des filtres séquentiels
Les filtres sont appliqués dans cet ordre et éliminent les transporteurs non éligibles à chaque étape :
| Filtre | Condition d'activation |
|---|---|
filterByInitialized |
Transporteur correctement configuré |
filterByPromise |
Intervalle de picking ou livraison fourni |
filterBySchedule |
Intervalle de picking ou livraison fourni |
filterByMinKilogram / filterByMaxKilogram
|
Colis fournis |
filterByPackageWeight (min/max) |
Colis fournis |
filterByCombinedLength (min/max) |
Colis fournis |
filterByLength (min/max) |
Colis fournis |
filterByMaxDevelopedDimensions |
Colis fournis |
filterByMaxHeight |
Colis fournis |
filterByPackageQuantity |
Colis fournis |
filterByVolumetricWeight (min/max) |
Colis fournis |
filterByVolume (min/max) |
Colis fournis |
filterByPackageVolume (min/max) |
Colis fournis |
filterByCountry (delivery) |
Adresse de livraison fournie |
filterByCode (delivery) |
Adresse de livraison fournie |
filterByCountry (picking) |
Adresse de picking de type "address" |
filterByDistance (min/max) |
Option distance activée + adresse de livraison |
filterByZone (delivery) |
Option zoning activée |
filterByZone (picking) |
Option zoning activée + picking de type "address" |
filterByPostalCode (delivery/picking) |
Option zoning désactivée |
filterByTags |
Tags fournis dans la requête |
Étape 4 — Enrichissement des résultats
Selon les options activées dans la requête :
| Option | Enrichissement apporté |
|---|---|
| price | Ajout des prix/devis par transporteur (avec timeout configurable) |
| carrierScore | Satisfaction, NPS, score de ponctualité |
| impact | Émissions CO₂ estimées |
| slot | Créneaux de livraison disponibles |
| deliveryPromise | Intervalles de picking et livraison calculés |
| distance | Distance en km entre picking et delivery |
| ineligibleCarriers | Liste des transporteurs exclus avec leurs raisons |
Étape 5 — Construction de la réponse
Chaque transporteur éligible est retourné avec :
- Son code et son nom
- Le delivery method associé (si applicable)
- Les services disponibles (avec types de points relais si PICKUP_POINT)
- Les créneaux (si option slot)
- Le prix (si option price)
- Les promesses de livraison (si option deliveryPromise)
- Le score carbone (si option impact)
- Les horaires de travail
- Les tags
5. Gestion de l'activation / désactivation
L'activation d'un transporteur fonctionne en cascade :
- Désactiver un carrier → propage la désactivation à tous ses niveaux enfants (retailers, stores, exchange places). Si un enfant n'a pas d'autres champs personnalisés, sa ligne est supprimée en base.
- Activer un store → active automatiquement les exchange places associés (exchangePlaceIds configurés).
- Désactiver un retailer → désactive tous les stores et exchange places rattachés.
Les lignes d'éligibilité enfants sans champs surchargés sont nettoyées automatiquement (cleanupChildEligibilities).
6. La logique de sélection de l'impact CO₂
L'impact carbone est résolu selon la même logique de hiérarchie que l'éligibilité elle-même : le système cherche d'abord un impact au niveau exchangePlace, puis store, puis retailer, puis carrier. En l'absence de données, un facteur par défaut est utilisé (VEHICLE_TYPE_VAN_MEDIUM).