màj wiki avec retour MES lot-5 AD

This commit is contained in:
Arthur Ria
2026-05-20 09:41:27 +02:00
commit 23eb3f3c84
4106 changed files with 469381 additions and 0 deletions
@@ -0,0 +1,471 @@
---
title: "Séquençage des tâches de picking TK → PS"
tags: [picking, séquençage, transstockeur, événement, workflow, algorithme]
status: draft
standard_ref: concepts/picking.md
jira_refs: [LIM-84, LIM-61]
confluence_refs: []
sources: ["LIM-84 LOT2.2 [PICKING] Séquençage des tâches de picking TK PS.md", "Logique combinatoire picking - TK vers PS - V1.1.md", "REU PICKING SEQUENCAGE 11-05-2026 - Analyse comparative notes + AF + devops.md"]
last_updated: 2026-05-12
author: Arthur
---
# Séquençage des tâches de picking TK → PS
> **Résumé** : algorithme événementiel qui ordonne les tâches de picking
> depuis les transstockeurs (TK) vers les postes de sortie (PS). Il
> écrit les numéros de séquence `Line.CstAtt` sur chaque tâche et
> contrôle le flag `OS.CstAtt` pour autoriser le stacker_crane.
> **Standard EasyWMS** : → voir [Picking](../../concepts/picking.md)
> Ce qui suit documente les **spécificités Limagrain** par rapport au
> standard.
## Contexte projet
Le séquençage TK → PS est critique pour garantir que les palettes
arrivent aux postes de picking dans le bon ordre. L'algorithme
s'exécute **en amont** de l'algorithme de
[placement PS → PK](placement-ps-pk.md) : les palettes arrivent au PS
**déjà triées**.
Quatre solutions ont été envisagées avant de retenir une approche
événementielle (solution 4).
## Historique des solutions envisagées
### Solution 1 — Process isolé sur finalisation des tâches d'OS
Déclenchement à la finalisation de la création des tâches d'un OS.
Séquençage via `OS.Line.CstAtt`, marquage OS traité via
`OS.CstAtt = true`.
**Problème** : pas assez dynamique en cas de recréation de tâches suite
à des imprévus dans le WMS.
### Solution 2 — Calcul dans le workflow stacker_crane
Intégration du tri directement dans les WF
`Galileo_StackerCraneSearch_PR` / `StackerCrane_SortTasks_PR`, avec
recalcul complet du pool de tâches à chaque exécution. Supprimerait le
besoin de `OS.Line.CstAtt` et `OS.CstAtt`.
**Problème** : complexité élevée (requêtes LINQ imbriquées sur les
tâches multi-OS).
### Solution 3 — Solution 1 transformée en job
Reprise du process de la solution 1 sous forme de job planifié, en
excluant les tâches de picking en cours.
**Problème** : pas assez réactif par rapport à la cadence de recherche
d'ordre des TK.
### Solution 4 — Process événementiel (retenue)
Reprise de la solution 1 déclenchée sur deux événements, avec
mécanisme de verrouillage `OS.CstAtt` pour bloquer le stacker_crane
pendant le séquençage.
**Avantages** : simple à développer, isolée et découplée du reste,
flexible et réactive.
## Changelog V1.1 (11/05/2026)
Modifications issues de la réunion Arthur + Justine (Mecalux) — Olivier
(Limagrain), croisées avec l'AF §6.4.8 et le DevOps #64854 :
- **Hiérarchie des règles** : nouvel ordre de priorité validé.
La complétude palette et l'anti-split de lignes de stock sont des
contraintes amont prioritaires sur les règles de tri
- **Picking négatif** : ajout condition cumulative poids ≥ 7 kg
- **Traitement commercial** : critère de regroupement par TC
**supprimé** (`CONTROLE_TRAITEMENT_COMMERCIAL = false`). Pas de bio
sur cet entrepôt
- **Calcul de remplissage** : méthode pro rata Bag/pal validée,
remplace la logique DevOps "Bag/pal max"
- **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
> Voir la section [Arbitrage des contradictions](#arbitrage-des-contradictions-reu-11052026)
> pour le détail des décisions.
## Déclenchement
L'algorithme est déclenché sur **deux événements** :
### 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)
```
### 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)
```
## 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)
// ─── Étape 5 : écrire les séquences ───
écrire_séquences(tâches_triées)
// ─── Étape 6 : libérer l'OS ───
OS.CstAtt ← true
```
```mermaid
sequenceDiagram
participant EVT as Événement (TaskCreated / OS Released)
participant SEQ as Process séquençage
participant SC as Stacker Crane
EVT->>SEQ: Déclenche
SEQ->>SEQ: OS.CstAtt = false
Note over SC: Bloqué — ne prend pas<br/>de tâche de cet OS
SEQ->>SEQ: Récupère tâches en attente
SEQ->>SEQ: Applique tri + écrit séquences
SEQ->>SEQ: OS.CstAtt = true
Note over SC: Débloqué — reprend<br/>les tâches séquencées
```
## Contraintes amont (constitution des palettes filles)
Ces contraintes orientent le regroupement des lignes sur les palettes
filles **avant** le tri. 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%.
**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.
> Cette méthode remplace la logique DevOps #64854 de "prendre le
> Bag/pal max entre lots". 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. **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) | 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** :
### 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. Prioritaire sur toutes les règles suivantes, y compris
Maïs first : si une tâche négatif concerne du tournesol, elle passe
avant une tâche maïs classique.
Condition cumulative pour la détermination NÉGATIF / DIRECT (cf.
[détermination picking négatif](#détermination-picking-négatif)) :
pourcentage quantité > seuil fiche article (défaut 55%) **ET** poids
unitaire sac ≥ 7 kg. En dessous de 7 kg, pas de picking négatif.
```
tri_1(tâche) → 0 si PICKING_NÉGATIF, 1 si PICKING_DIRECT
```
### 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. 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
```
### ~~Critère 3 (V1.0) — Traitement commercial~~ SUPPRIMÉ V1.1
`CONTROLE_TRAITEMENT_COMMERCIAL = false`. L'entrepôt ne fait pas de
bio. Paramètre réactivable si besoin futur.
### Critère 3 — Espèce la plus volumineuse
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. 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)
```
### Critère 4 — Article/lot le plus lourd en base
À 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
```
### Critère 5 — Regroupement par palette source
Toutes les tâches portant sur la **même palette source** sont
consécutives. 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
(4) poids_article DESC // article le + lourd
(5) palette_source // regroupement par palette
)
```
## Écriture des séquences (Line.CstAtt)
### Règle des ex-aequo
Quand deux tâches consécutives 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.
### 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
### 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
```
### 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)
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)
Résultat Line.CstAtt : [1, 1, 1, 2, 2]
Le stacker_crane peut sortir A, B, C dans n'importe quel ordre,
puis D ou E dans n'importe quel ordre.
```
## Comportement du stacker_crane après séquençage
Le stacker_crane **ignore** les tâches dont `OS.CstAtt == false`,
consomme celles dont `OS.CstAtt == true` par `Line.CstAtt` croissant,
et entre tâches à séquence égale il optimise librement (proximité ASRS,
charge TK). Il crée les tâches de mouvement TK → PS.
Les palettes arrivent ensuite au PS, où l'algorithme de
[placement PS → PK](placement-ps-pk.md) décide sur quelle table les
poser.
## Détermination picking négatif
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) :
```
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
ALORS → PICKING_NÉGATIF
SINON → PICKING_DIRECT
```
Le seuil % reste paramétrable par fiche article (champ "Complete
quantity percent excess for negative picking", défaut : 55%).
La détermination 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.
## Cas particuliers
### 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 : verrouillage, re-tri des
tâches en attente uniquement (en commençant après le dernier numéro des
tâches en cours), puis libération.
### Relance d'un OS arrêté
Si un OS est arrêté puis relancé (`OutboundOrderReleasedEvent`), le
même process s'applique. Les tâches en cours conservent leur séquence,
les tâches en attente sont re-séquencées.
## Arbitrage des contradictions (réu. 11/05/2026)
Analyse comparative de 3 sources (DevOps #64854, AF §6.4.8, réunion
11/05/2026 Arthur + Justine + Olivier). **Tous les points sont résolus.**
| Sujet | DevOps | AF | Réunion (fait foi) |
|-------|--------|----|--------------------|
| Traitement commercial | À creuser | Séparation stricte | **Supprimé** (`CONTROLE_TRAITEMENT_COMMERCIAL = false`) |
| Seuil picking négatif | Pas de seuil explicite | > 50% | **Deux conditions cumulatives** : % seuil fiche article (défaut 55%) ET poids sac ≥ 7 kg |
| Poids max palette | 1 200 kg | 1 250 kg | **1 250 kg** (AF fait foi) |
| Picking négatif vs Maïs first | Pas de hiérarchie | Maïs en tête, négatif séparé | **Picking négatif prioritaire** (confirmé Olivier) |
| Semences essais en haut | Oui (dédié) | Non mentionné | **Couvert par règle du plus lourd en base** (essais = légères → haut) |
| Lots même Bag/pal | Prioriser regroupement | — | **Retenu** (WF palettes complètes) |
| Différenciation marque | Aucune | — | **Confirmé** |
| Calcul Bag/pal multi-lots | "Prendre le Bag/pal max" | Équivalent palette | **Pro rata** (chaque sac = 1/Bag_pal de son lot) |
## Paramètres WMS
| Paramètre | Description | Défaut | Statut V1.1 |
|-----------|-------------|--------|-------------|
| `CONTROLE_TRAITEMENT_COMMERCIAL` | Regroupement par TC dans le tri | ~~true~~ | **false** — désactivé |
| Seuil picking négatif (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 remplissage palette fille | **~95%** | **Nouveau V1.1** |
| Poids max palette | Poids maximum palette fille | **1 250 kg** | Corrigé (était 1 200 kg) |
| `OS.CstAtt` | Flag verrouillage OS pendant séquençage (true = stacker_crane autorisé) | true | Inchangé |
| `MAX_NB_BUFFER_PK` | Nombre de buffers disponibles par PK | 3 | Inchangé |
## Points d'attention
⚠️ Le custom LIM-61 (vérification capacité buffer) doit être modifié
pour prendre en compte les palettes multi-PK.
⚠️ Le verrouillage `OS.CstAtt` est temporaire (durée du séquençage) —
en cas d'erreur du process, l'OS risque de rester bloqué.
⚠️ Les tâches **en cours** sont exclues du séquençage — seules les
tâches en attente sont réordonnées.
⚠️ La condition poids ≥ 7 kg pour le picking négatif est ajoutée pour
éviter l'instabilité palette (gros sacs ramenés sur petits sacs).
## 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, navette du lendemain, zone
angle Est) — en attente de précisions
- Verrou réception → recomptage avant picking (mentionné dans l'AF
uniquement, non reconfirmé)
## Questions ouvertes
- [ ] Comportement en cas d'erreur du process de séquençage — OS reste
bloqué avec CstAtt = false ? (@Nicolas)
- [ ] Impact sur les performances si beaucoup d'OS sont Released
simultanément — risque de contention sur les événements ? (@Fabien)
## Historique des modifications
| Date | Auteur | Modification |
|------|--------|--------------|
| 2026-05-12 | Arthur | Création initiale depuis LIM-84 |
| 2026-05-12 | Arthur | Refonte complète : intégration spec V1.1 (algo complet, contraintes amont, 5 critères tri, écriture séquences, ex-aequo, cas particuliers) + arbitrage contradictions réunion 11/05/2026 |
## Références
| Source | Type | Date |
|--------|------|------|
| [LIM-84](https://easywmsfrance.atlassian.net/browse/LIM-84) | Ticket Jira | 2026 |
| [LIM-61](https://easywmsfrance.atlassian.net/browse/LIM-61) | Ticket Jira (custom capacité buffer) | 2026 |
| Logique combinatoire picking - TK vers PS - V1.1 | Spécification technique | 11/05/2026 |
| REU PICKING SEQUENCAGE 11-05-2026 | CR réunion + analyse comparative | 11/05/2026 |
| DevOps #64854 | Note historique | — |
| AF §6.4.8 | Analyse fonctionnelle V1.5 | 28/11/2025 |