# LIM-84 — Algorithme de séquençage des palettes (TK → PS) ## Ordonnancement des tâches de picking avant sortie de l'ASRS > **Version 1.1** — 11 mai 2026 > > Ce document décrit l'algorithme de séquençage qui définit **dans quel ordre** les palettes sources doivent sortir de l'ASRS (TK) à destination du poste de sortie (PS). Il s'exécute **en amont** de l'algorithme de placement PS → table PK [[Logique combinatoire picking - PS vers PK - V1.0]]. > > Le résultat de cet algorithme est l'écriture des numéros de séquence `Line.CstAtt` sur chaque tâche de picking, et le positionnement de `OS.CstAtt = true` pour autoriser le stacker_crane à consommer les tâches. ### Changelog V1.1 (11/05/2026) Modifications issues de la réunion Arthur + Justine (MECALUX) — Olivier (LIMAGRAIN), croisées avec l'AF et le DevOps #64854. - **Hiérarchie des règles** : nouvel ordre de priorité validé (§3). La complétude palette et l'anti-split de lignes de stock sont désormais des contraintes amont prioritaires sur les règles de tri. - **Picking négatif** : ajout d'une condition cumulative de poids ≥ 7 kg (§3.1 + §6.3). - **Traitement commercial** : critère de regroupement par TC **supprimé** (`CONTROLE_TRAITEMENT_COMMERCIAL = false`). Le critère 3 de la V1.0 est retiré du tri. - **Calcul de remplissage** : méthode pro rata Bag/pal validée, remplace la logique DevOps "Bag/pal max" (§3 — contrainte amont C1). - **Poids max palette** : 1 250 kg (l'AF fait foi, corrige les 1 200 kg du DevOps). - **Règles confirmées** : mélange d'espèces OK, pas de gerbage, hauteur max 1,90 m, séparateurs inter-lots hors WMS. --- ## 0. Glossaire rapide |Terme|Définition| |---|---| |**TK**|Transtockeur / sortie ASRS (origine physique de la palette)| |**PS**|Poste de sortie (point d'arrivée de la palette, avant placement sur table PK)| |**OS**|Ordre de sortie (commande)| |**OS.CstAtt**|Flag booléen sur l'OS. `false` = séquences non calculées, stacker_crane ignore. `true` = séquences prêtes, stacker_crane peut consommer.| |**Line.CstAtt**|Numéro de séquence (entier) sur chaque tâche de picking. Définit l'ordre de sortie ASRS. Plusieurs tâches peuvent partager la même valeur (ex-aequo).| |~~**TC**~~|~~Traitement commercial — attribut article.~~ **Supprimé V1.1** : `CONTROLE_TRAITEMENT_COMMERCIAL = false`. L'entrepôt ne fait pas de bio. Paramètre réactivable si besoin futur.| |**Bag/pal**|Nombre de sacs par palette pour un lot donné. Sert au calcul de remplissage pro rata.| --- ## 1. Déclenchement L'algorithme est déclenché sur **deux événements** : ### 1.1. `TaskCreatedEvent` Une nouvelle tâche de picking vient d'être créée (par le MINI JOB Picking LIM-75, ou suite à une réassignation de stock). ``` SI événement.type == TaskCreatedEvent : SI tâche.type == PICKING ET tâche.OS.statut == Released : traiter_séquençage(tâche.OS) ``` ### 1.2. `OutboundOrderReleasedEvent` Un OS passe au statut Released (première mise en service, ou relance après un arrêt). ``` SI événement.type == OutboundOrderReleasedEvent : traiter_séquençage(OS) ``` --- ## 2. Process principal ``` FONCTION traiter_séquençage(OS) : // ─── Étape 1 : verrouiller l'OS ─── OS.CstAtt ← false // ─── Étape 2 : récupérer les tâches ─── toutes_tâches ← récupérer_tâches_picking(OS) // ─── Étape 3 : filtrer ─── tâches_à_séquencer ← [t POUR t DANS toutes_tâches SI t.statut == EN_ATTENTE] SI tâches_à_séquencer est vide : OS.CstAtt ← true RETOURNER // ─── Étape 4 : trier ─── tâches_triées ← trier_tâches(tâches_à_séquencer) // cf. §3 // ─── Étape 5 : écrire les séquences ─── écrire_séquences(tâches_triées) // cf. §4 // ─── Étape 6 : libérer l'OS ─── OS.CstAtt ← true ``` --- ## 3. Contraintes amont et règles de tri > **V1.1** — La hiérarchie ci-dessous remplace toute hiérarchie antérieure. Elle distingue les **contraintes amont** (appliquées avant/pendant la constitution des palettes filles) et les **règles de tri** (appliquées au séquençage des tâches de picking). ### Contraintes amont (constitution des palettes filles) Ces contraintes orientent le regroupement des lignes sur les palettes filles **avant** que l'algorithme de tri ne séquence les sorties ASRS. Elles ne sont pas des critères de tri à proprement parler, mais l'algorithme de séquençage doit les respecter : l'ordre de sortie doit être compatible avec la constitution de palettes conformes à ces règles. #### C1. Palettes les plus complètes possible Objectif premier — optimisation transport. Seuil de remplissage ~95% (marge de sécurité). **Calcul : pro rata Bag/pal.** Chaque sac consomme `1/Bag_pal` de son lot. Le calcul est additif et gère nativement des lots avec des Bag/pal différents sur une même palette. ``` Exemple : 16 sacs d'un lot Bag/pal 20 + 7 sacs d'un lot Bag/pal 50 = 16/20 + 7/50 = 0,80 + 0,14 = 94% ``` Regrouper les lots de même Bag/pal sur une même palette fille facilite la complétude. > _Note : cette méthode remplace la logique DevOps #64854 de "prendre le Bag/pal max entre lots" (V1.0 implicite). Le pro rata est plus précis et ne nécessite pas de Bag/pal de référence unique._ #### C2. Ne pas splitter les lignes de stock Éviter de répartir les sacs d'une même ligne de stock sur plusieurs palettes. **Cette contrainte est prioritaire sur les règles de tri** : si respecter "Maïs first" implique de splitter une ligne, on regroupe la ligne complète quitte à décaler le maïs. #### Autres contraintes palette |Contrainte|Valeur|Source| |---|---|---| |Poids max palette|**1 250 kg**|AF (corrige 1 200 kg du DevOps)| |Hauteur max palette|1,90 m|AF — rejet au PIE si dépassement| |Gerbage|Interdit|—| |Mélange d'espèces|Autorisé sur une même palette fille|—| |Différenciation de marque|Aucune dans une même expédition|—| |Séparateurs (intercalaires) entre lots|Règle opérateur, hors WMS|—| ### Règles de tri (séquençage des sorties ASRS) Les tâches de picking d'un même OS sont triées selon les critères suivants, **par ordre de priorité décroissante** : #### 3.1. Critère 1 — Picking négatif en premier Les tâches de type PICKING_NÉGATIF passent **avant** les tâches de type PICKING_DIRECT. Le picking négatif est **prioritaire sur toutes les règles de tri suivantes**, y compris Maïs first : si une tâche négatif concerne du tournesol, elle passe avant une tâche maïs classique. > **V1.1** — Condition cumulative ajoutée pour la détermination NÉGATIF/DIRECT (cf. §6.3) : pourcentage quantité > seuil fiche article (défaut 55%) **ET** poids unitaire sac ≥ 7 kg. En dessous de 7 kg, pas de picking négatif (raison : instabilité palette si gros sacs ramenés sur petits sacs). ``` tri_1(tâche) → 0 si PICKING_NÉGATIF, 1 si PICKING_DIRECT ``` #### 3.2. Critère 2 — Espèce Maïs en premier Les tâches portant sur l'espèce **Maïs** passent avant les autres espèces (si la commande contient du maïs). Raison : le maïs est lourd/stable, il constitue la base de la palette fille. ``` tri_2(tâche) → 0 si espèce == MAÏS, 1 sinon ``` #### ~~3.3. Critère 3 — Regroupement par traitement commercial (TC)~~ **SUPPRIMÉ V1.1** > `CONTROLE_TRAITEMENT_COMMERCIAL = false`. L'entrepôt ne fait pas de bio. Réactivable si besoin futur. #### 3.3. Critère 3 — Espèce avec la plus grande quantité totale dans la commande _(anciennement critère 4 en V1.0)_ Les tâches sont regroupées par espèce, et l'espèce ayant la **plus grande quantité totale de sacs** dans l'OS passe en premier. Raison : commencer par l'espèce la plus volumineuse permet de constituer rapidement la base de la palette fille. ``` tri_3(tâche) → -quantité_totale_espèce(tâche.espèce, OS) // négatif pour tri décroissant ``` #### 3.4. Critère 4 — Article/lot le plus lourd en base _(anciennement critère 5 en V1.0)_ À espèce égale, les tâches portant sur les articles/lots **les plus lourds** passent en premier. Corollaire : les semences essais, très légères, se retrouvent naturellement en haut de palette. ``` tri_4(tâche) → -tâche.article.poids // négatif pour tri décroissant ``` #### 3.5. Critère 5 — Regroupement par palette source _(anciennement critère 6 en V1.0)_ Toutes les tâches portant sur la **même palette source** sont consécutives. Raison : l'opérateur enchaîne toutes les tâches d'une palette source avant de la libérer. ``` tri_5(tâche) → tâche.PALETTE_SOURCE.identifiant ``` ### Récapitulatif du tri multi-critères (V1.1) ``` FONCTION trier_tâches(tâches) : RETOURNER tâches.trier_par( (1) type_picking ASC // NÉGATIF (0) avant DIRECT (1) (2) espèce_maïs ASC // MAÏS (0) avant autres (1) (3) quantité_espèce DESC // espèce la + volumineuse en premier (4) poids_article DESC // article le + lourd en premier (5) palette_source // regroupement par palette source ) // Note V1.1 : le critère TC (V1.0 §3.3) est supprimé. // La contrainte anti-split lignes de stock (C2) est gérée // en amont lors de la constitution des palettes filles, // pas dans ce tri. ``` --- ## 4. Écriture des séquences (`Line.CstAtt`) Une fois les tâches triées, on attribue un numéro de séquence à chacune. ### 4.1. Règle des ex-aequo Quand deux tâches consécutives dans le tri sont **interchangeables** (l'ordre entre elles n'a aucun impact fonctionnel), elles reçoivent le **même numéro de séquence**. Cela laisse de la flexibilité au stacker_crane pour optimiser son débit. ### 4.2. Critères d'interchangeabilité Deux tâches A et B sont interchangeables si : - Elles portent sur la **même palette source**, **OU** - Elles portent sur des **palettes sources différentes** mais tous les critères de tri sont identiques : même type de picking, même espèce, même quantité espèce, même poids article. Rien ne les départage fonctionnellement. > _Note V1.1 : le TC n'entre plus dans les critères d'interchangeabilité._ ### 4.3. Algorithme d'écriture ``` FONCTION écrire_séquences(tâches_triées) : séquence_actuelle ← max(Line.CstAtt des tâches en cours) + 1 SI aucune tâche en cours : séquence_actuelle ← 1 POUR i DE 0 À len(tâches_triées) - 1 : tâche ← tâches_triées[i] tâche.Line.CstAtt ← séquence_actuelle SI i < len(tâches_triées) - 1 : tâche_suivante ← tâches_triées[i + 1] SI interchangeables(tâche, tâche_suivante) : CONTINUER SINON : séquence_actuelle ← séquence_actuelle + 1 ``` ### 4.4. Exemple ``` Commande avec 5 tâches, après tri : Tâche 1 : Palette A, Maïs, 500kg → séq 1 Tâche 2 : Palette B, Maïs, 500kg → séq 1 (interchangeable avec 1) Tâche 3 : Palette C, Maïs, 500kg → séq 1 (interchangeable) Tâche 4 : Palette D, Blé, 300kg → séq 2 (espèce différente) Tâche 5 : Palette E, Blé, 300kg → séq 2 (interchangeable avec 4) Résultat Line.CstAtt : [1, 1, 1, 2, 2] Le stacker_crane peut sortir les palettes A, B, C dans n'importe quel ordre, puis D ou E dans n'importe quel ordre. ``` > _Note V1.1 : l'exemple V1.0 avec TC différent (tâche 6) est retiré car le critère TC est désactivé._ --- ## 5. Comportement du stacker_crane après séquençage Ce n'est pas le périmètre de cet algorithme, mais pour mémoire : ``` Le stacker_crane : - IGNORE les tâches dont OS.CstAtt == false - Consomme les tâches dont OS.CstAtt == true - Respecte l'ordre croissant des Line.CstAtt - Entre tâches à séquence égale : libre d'optimiser (proximité ASRS, charge TK) - Crée les tâches de mouvement TK → PS ``` Les palettes arrivent ensuite au PS, où l'algorithme de placement (document dédié) décide sur quelle table du PK les poser. --- ## 6. Cas particuliers ### 6.1. Recalcul suite à une nouvelle tâche (réassignation de stock) Si une tâche est créée après que l'OS a déjà été séquencé, le `TaskCreatedEvent` déclenche un recalcul : ``` 1. OS.CstAtt ← false 2. Filtrer : tâches EN_ATTENTE uniquement 3. Re-trier et réécrire les Line.CstAtt (en commençant après le dernier numéro des tâches en cours) 4. OS.CstAtt ← true ``` ### 6.2. Relance d'un OS arrêté Si un OS est arrêté puis relancé (`OutboundOrderReleasedEvent`), le même process s'applique. Les tâches déjà en cours conservent leur séquence, les tâches en attente sont re-séquencées. ### 6.3. Picking négatif et détermination du type Le type de picking (NÉGATIF ou DIRECT) est déterminé **par tâche** au moment de la création des tâches par le MINI JOB Picking (LIM-75), selon la règle : ``` SI quantité_à_prélever > seuil_article × quantité_palette_source ET article unique dans la palette source ET pas d'attribut logistique à capturer ET poids_unitaire_sac ≥ 7 kg // ← AJOUT V1.1 ALORS → PICKING_NÉGATIF SINON → PICKING_DIRECT ``` > **V1.1** — La condition de poids ≥ 7 kg est ajoutée comme condition **cumulative** (ET). En dessous de 7 kg, pas de picking négatif même si le % dépasse le seuil. Raison : instabilité palette (gros sacs ramenés sur petits sacs). Le seuil % reste paramétrable par fiche article (champ "Complete quantity percent excess for negative picking", défaut : 55%). La détermination négatif/direct se fait **en amont** (MINI JOB Picking, LIM-75), avant l'algorithme de séquençage. L'algorithme de séquençage lit ce type mais ne le calcule pas. --- ## 7. Paramètres WMS utilisés |Paramètre|Description|Défaut|Statut V1.1| |---|---|---|---| |`CONTROLE_TRAITEMENT_COMMERCIAL`|Active le regroupement par TC dans le tri|~~`true`~~|**`false`** — désactivé| |Seuil picking négatif|Par fiche article ("Complete quantity percent excess for negative picking")|55%|Inchangé| |Poids min picking négatif|Poids unitaire sac minimum pour autoriser le picking négatif|**7 kg**|**NOUVEAU V1.1**| |Seuil remplissage palette|Taux cible de remplissage palette fille|**~95%**|**NOUVEAU V1.1**| |Poids max palette|Poids maximum d'une palette fille|**1 250 kg**|Corrigé (était 1 200 kg dans DevOps)| --- ## 8. Diagramme de flux ``` TaskCreatedEvent OutboundOrderReleasedEvent (nouvelle tâche picking) (OS passe en Released) │ │ ▼ │ Tâche type PICKING │ ET OS statut Released ? │ │ │ OUI │ │ │ └──────────┬────────────────────┘ │ ▼ OS.CstAtt ← false (stacker_crane bloqué) │ ▼ Récupérer tâches de l'OS │ ▼ Filtrer : tâches EN_ATTENTE uniquement (tâches en cours = intouchables) │ ▼ ┌────────────────────────────┐ │ TRIER │ │ │ │ 1. Picking négatif first │ │ 2. Espèce Maïs first │ │ 3. Espèce + volumineuse │ │ 4. Article + lourd │ │ 5. Regrouper par palette │ │ source │ └────────────┬───────────────┘ │ ▼ Écrire Line.CstAtt (ex-aequo si interchangeables) │ ▼ OS.CstAtt ← true (stacker_crane libéré) │ ▼ Stacker_crane consomme par Line.CstAtt croissant → crée mouvements TK → PS │ ▼ Palette arrive au PS → algo de placement PS → PK (autre document) ``` --- ## 9. Points non traités (hors scope) - Affichage opérateur au PK (combien de sacs ajouter, possibilité de dévier de la consigne) — à traiter une fois les fondations posées. - Picking négatif < 7 kg en option (avantage opérationnel sans obligation) — nécessite discussion élargie. - Messagerie carton (moins prioritaire que prépa classique, navette du lendemain, zone angle Est) — en attente de précisions. - Verrou réception → recomptage avant picking (mentionné dans l'AF uniquement, non reconfirmé). --- ## 10. Sources de référence Par ordre de fiabilité décroissante : 1. **Réunion 11/05/2026 + mails** — fait foi sur tous les points traités 2. **AF (Analyse Fonctionnelle)** — référence principale pour les points non abordés en réunion 3. **DevOps #64854** — le plus ancien, peut contenir des règles passées à la trappe mais utile pour vérification croisée