màj wiki avec retour MES lot-5 AD
This commit is contained in:
@@ -0,0 +1,431 @@
|
||||
## Choix de la table du PK pour chaque palette arrivant au PS
|
||||
|
||||
> **Version 1.0** — 27 avril 2026
|
||||
>
|
||||
> Ce document décrit l'algorithme exécuté par le WMS lorsqu'une palette source arrive au **PS (poste de sortie)** et que celui-ci demande au WMS **sur quelle table du PK** la poser.
|
||||
>
|
||||
> **Ce qui est hors périmètre** : l'ordre de sortie des palettes du TK, le tri par espèce/TC/quantité/poids, l'écriture des `Line.CstAtt` et `OS.CstAtt`. Tout cela est géré par un autre process (déclenché sur `TaskCreatedEvent` / `OutboundOrderReleasedEvent`). Ici, les palettes arrivent **déjà triées** au PS.
|
||||
|
||||
---
|
||||
|
||||
## 0. Rappel du contexte physique
|
||||
|
||||
Chaque PK dispose de **3 tables** soumises à une contrainte d'adjacence stricte :
|
||||
|
||||
```
|
||||
TABLE_GAUCHE ←→ TABLE_CENTRE ←→ TABLE_DROITE
|
||||
✅ adjacentes ✅ adjacentes
|
||||
|
||||
TABLE_GAUCHE ←————————————————→ TABLE_DROITE
|
||||
❌ INTERDIT
|
||||
```
|
||||
|
||||
**Règles de mouvement :**
|
||||
|
||||
- Le stock est **toujours sur une palette**, jamais directement posé sur la table.
|
||||
- L'opérateur peut déplacer du **stock** (sacs, colis) d'une palette à une autre **uniquement entre deux tables adjacentes**.
|
||||
- Il est **interdit de déplacer une palette d'une table à une autre**. Seul l'AGV peut déplacer une palette (arrivée, évacuation, recentrage).
|
||||
- **TABLE_CENTRE** est le pivot : c'est la seule table adjacente aux deux autres.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 1. Déclenchement
|
||||
|
||||
L'algorithme est appelé **à chaque fois qu'une palette arrive physiquement au PS**. Le PS interroge le WMS qui retourne une réponse parmi :
|
||||
|
||||
- **TABLE_GAUCHE**, **TABLE_CENTRE** ou **TABLE_DROITE** → la palette est envoyée sur cette table.
|
||||
- **Buffer ESx** → aucune table n'est disponible, la palette est redirigée vers un emplacement buffer.
|
||||
- **Attente** → ni table ni buffer disponible, la palette reste au PS.
|
||||
|
||||
---
|
||||
|
||||
## 2. Entrées de l'algorithme
|
||||
|
||||
| Donnée | Source |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
|
||||
| **Tâche courante** : palette source, article, quantité, type de picking (NÉGATIF / DIRECT), `Line.CstAtt` (numéro de séquence) | Tâche associée à la palette |
|
||||
| **État des 3 tables du PK cible** : VIDE, PALETTE_FILLE_ACTIVE, PALETTE_FILLE_EN_ATTENTE, PALETTE_SOURCE_EN_PICKING, PALETTE_SOURCE_EN_ATTENTE, EN_ATTENTE_EVACUATION | État temps réel du PK |
|
||||
| **Tâches suivantes de l'OS** (triées par `Line.CstAtt` croissant) | OS en base |
|
||||
| **Buffers ES disponibles** : parmi ES1–ES16, ceux qui ne sont ni occupés ni ciblés par une tâche en cours | État temps réel des buffers |
|
||||
| **Nombre de buffers déjà affectés à ce PK** vs `MAX_PRELOAD_PAR_PK` (défaut : 3) | Compteur par PK |
|
||||
| **Traitement commercial (TC)** de l'article et flag `CONTROLE_TRAITEMENT_COMMERCIAL` | Fiche article / paramètre WMS |
|
||||
|
||||
---
|
||||
|
||||
## 3. Décision de niveau 1 : table du PK ou buffer ?
|
||||
|
||||
```
|
||||
FONCTION décider_destination(palette, PK) :
|
||||
|
||||
table_cible ← choisir_table(palette, PK) // voir §4
|
||||
|
||||
SI table_cible ≠ NULL :
|
||||
RETOURNER table_cible
|
||||
|
||||
// Aucune table disponible → tenter un buffer
|
||||
SI nb_buffers_affectés(PK) < MAX_PRELOAD_PAR_PK :
|
||||
buffer ← premier ES libre (pas de palette, pas de tâche en vol)
|
||||
SI buffer existe :
|
||||
RETOURNER buffer
|
||||
|
||||
// Ni table ni buffer disponible
|
||||
RETOURNER ATTENTE
|
||||
// La palette reste au PS, le WMS réessaiera
|
||||
// dès qu'une place se libère (table ou buffer)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Décision de niveau 2 : choix de la table
|
||||
|
||||
Le choix dépend du **type de picking** de la tâche associée à la palette.
|
||||
|
||||
### 4.1. Cas PICKING_NÉGATIF
|
||||
|
||||
|
||||
En picking négatif, la palette source arrive sur une table, l'opérateur retire l'excédent sur une palette posée sur une **table adjacente**, puis échange d'étiquettes : la palette source devient la palette fille.
|
||||
|
||||
La palette a besoin de **2 tables** : une pour elle, une adjacente libre pour l'excédent.
|
||||
|
||||
```
|
||||
FONCTION choisir_table_picking_négatif(PK) :
|
||||
|
||||
// ─── Priorité 1 : centre + un côté libre ───
|
||||
// La palette source va au centre (pivot), l'excédent ira sur un côté.
|
||||
// Maximise la flexibilité : le centre est adjacent aux deux côtés.
|
||||
|
||||
SI TABLE_CENTRE == VIDE ET TABLE_GAUCHE == VIDE :
|
||||
RETOURNER TABLE_CENTRE
|
||||
|
||||
SI TABLE_CENTRE == VIDE ET TABLE_DROITE == VIDE :
|
||||
RETOURNER TABLE_CENTRE
|
||||
|
||||
// ─── Priorité 2 : côté + centre libre ───
|
||||
// Moins optimal (la palette source n'est pas au pivot)
|
||||
// mais fonctionnel si le centre est libre pour l'excédent.
|
||||
|
||||
SI TABLE_GAUCHE == VIDE ET TABLE_CENTRE == VIDE :
|
||||
RETOURNER TABLE_GAUCHE
|
||||
|
||||
SI TABLE_DROITE == VIDE ET TABLE_CENTRE == VIDE :
|
||||
RETOURNER TABLE_DROITE
|
||||
|
||||
// ─── Priorité 3 : centre libre + un côté libérable ───
|
||||
|
||||
SI TABLE_CENTRE == VIDE ET TABLE_GAUCHE est libérable :
|
||||
évacuer(TABLE_GAUCHE)
|
||||
RETOURNER TABLE_CENTRE
|
||||
|
||||
SI TABLE_CENTRE == VIDE ET TABLE_DROITE est libérable :
|
||||
évacuer(TABLE_DROITE)
|
||||
RETOURNER TABLE_CENTRE
|
||||
|
||||
// ─── Priorité 4 : un côté libre + centre libérable ───
|
||||
|
||||
SI TABLE_GAUCHE == VIDE ET TABLE_CENTRE est libérable :
|
||||
évacuer(TABLE_CENTRE)
|
||||
RETOURNER TABLE_GAUCHE
|
||||
|
||||
SI TABLE_DROITE == VIDE ET TABLE_CENTRE est libérable :
|
||||
évacuer(TABLE_CENTRE)
|
||||
RETOURNER TABLE_DROITE
|
||||
|
||||
// ─── Dernier recours : évacuation forcée ───
|
||||
évacuer_table_prioritaire(PK) // cf. §6
|
||||
RETOURNER choisir_table_picking_négatif(PK) // rappel récursif
|
||||
```
|
||||
### 4.2. Cas PICKING_DIRECT
|
||||
|
||||
En picking direct, la palette source doit être posée sur une table **adjacente à la palette fille active**. Le choix se fait donc en fonction de l'emplacement de la palette fille.
|
||||
|
||||
```
|
||||
FONCTION choisir_table_picking_direct(tâche, PK) :
|
||||
|
||||
// ─── Étape 1 : localiser la palette fille compatible ───
|
||||
table_fille ← localiser_palette_fille(tâche, PK) // cf. §4.3
|
||||
|
||||
SI table_fille == NULL :
|
||||
// Pas encore de palette fille → il faudra en créer une.
|
||||
// On anticipe son emplacement pour choisir la table source.
|
||||
table_fille ← choisir_table_pour_nouvelle_palette_fille(PK) // cf. §4.4
|
||||
|
||||
// ─── Étape 2 : choisir une table adjacente pour la palette source ───
|
||||
tables_adj ← tables_adjacentes(table_fille)
|
||||
// TABLE_GAUCHE → [TABLE_CENTRE]
|
||||
// TABLE_CENTRE → [TABLE_GAUCHE, TABLE_DROITE]
|
||||
// TABLE_DROITE → [TABLE_CENTRE]
|
||||
|
||||
// Prio A : la palette source est déjà sur une adjacente
|
||||
// (cas multi-tâches pour le même OS depuis la même palette)
|
||||
POUR chaque t DANS tables_adj :
|
||||
SI t contient tâche.PALETTE_SOURCE :
|
||||
RETOURNER t
|
||||
|
||||
// Prio B : adjacente VIDE
|
||||
// Si 2 adjacentes libres (PF au centre) → appliquer ping-pong (cf. §5)
|
||||
adjacentes_vides ← [t POUR t DANS tables_adj SI t == VIDE]
|
||||
SI len(adjacentes_vides) == 2 :
|
||||
RETOURNER choisir_côté_ping_pong(PK)
|
||||
SI len(adjacentes_vides) == 1 :
|
||||
RETOURNER adjacentes_vides[0]
|
||||
|
||||
// Prio C : adjacente en cours d'évacuation (AGV en route, bientôt libre)
|
||||
POUR chaque t DANS tables_adj :
|
||||
SI t == EN_ATTENTE_EVACUATION :
|
||||
RETOURNER t
|
||||
|
||||
// Prio D : forcer l'évacuation d'une adjacente
|
||||
t_à_libérer ← choisir_table_à_évacuer(tables_adj) // cf. §6
|
||||
évacuer(t_à_libérer)
|
||||
RETOURNER t_à_libérer
|
||||
```
|
||||
|
||||
### 4.3. Localisation de la palette fille compatible
|
||||
|
||||
```
|
||||
FONCTION localiser_palette_fille(tâche, PK) :
|
||||
|
||||
// Chercher d'abord parmi les PF actives
|
||||
POUR chaque table DANS [TABLE_GAUCHE, TABLE_CENTRE, TABLE_DROITE] :
|
||||
SI table.état == PALETTE_FILLE_ACTIVE :
|
||||
SI CONTROLE_TRAITEMENT_COMMERCIAL == false :
|
||||
RETOURNER table
|
||||
SINON SI table.palette.TC == tâche.article.TC :
|
||||
RETOURNER table
|
||||
|
||||
// Puis parmi les PF en attente (sera réactivée par l'exécution)
|
||||
POUR chaque table DANS [TABLE_GAUCHE, TABLE_CENTRE, TABLE_DROITE] :
|
||||
SI table.état == PALETTE_FILLE_EN_ATTENTE :
|
||||
SI CONTROLE_TRAITEMENT_COMMERCIAL == false
|
||||
OU table.palette.TC == tâche.article.TC :
|
||||
RETOURNER table
|
||||
|
||||
RETOURNER NULL // aucune palette fille compatible
|
||||
```
|
||||
|
||||
### 4.4. Choix de la table pour une nouvelle palette fille
|
||||
|
||||
```
|
||||
FONCTION choisir_table_pour_nouvelle_palette_fille(PK) :
|
||||
|
||||
// TABLE_CENTRE = pivot, adjacente aux 2 côtés → maximise la flexibilité
|
||||
SI TABLE_CENTRE == VIDE :
|
||||
RETOURNER TABLE_CENTRE
|
||||
|
||||
SI TABLE_GAUCHE == VIDE :
|
||||
RETOURNER TABLE_GAUCHE
|
||||
|
||||
SI TABLE_DROITE == VIDE :
|
||||
RETOURNER TABLE_DROITE
|
||||
|
||||
// Aucune table vide → forcer une évacuation
|
||||
évacuer_table_prioritaire(PK) // cf. §6
|
||||
RETOURNER choisir_table_pour_nouvelle_palette_fille(PK) // rappel récursif
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Optimisation ping-pong
|
||||
|
||||
Le ping-pong est l'optimisation principale pour le débit. Il n'est possible que lorsque la **palette fille est au centre** : les palettes sources alternent alors entre TABLE_GAUCHE et TABLE_DROITE, de sorte que la palette suivante est déjà en place quand l'opérateur termine.
|
||||
|
||||
```
|
||||
FONCTION choisir_côté_ping_pong(PK) :
|
||||
|
||||
// Identifier le côté actuellement occupé par une palette source
|
||||
SI TABLE_GAUCHE.état ∈ {PALETTE_SOURCE_EN_PICKING, PALETTE_SOURCE_EN_ATTENTE} :
|
||||
RETOURNER TABLE_DROITE // envoyer du côté opposé
|
||||
|
||||
SI TABLE_DROITE.état ∈ {PALETTE_SOURCE_EN_PICKING, PALETTE_SOURCE_EN_ATTENTE} :
|
||||
RETOURNER TABLE_GAUCHE // envoyer du côté opposé
|
||||
|
||||
// Aucun côté occupé → choix arbitraire
|
||||
RETOURNER TABLE_GAUCHE
|
||||
```
|
||||
|
||||
**Recentrage** : si la palette fille est sur un côté (issue d'un picking négatif), le ping-pong est impossible. Si le nombre de PICKING_DIRECT restants ≥ `SEUIL_RECENTRAGE_PF` (défaut : 3), le WMS peut déclencher un mouvement AGV pour recentrer la PF sur TABLE_CENTRE.
|
||||
|
||||
---
|
||||
|
||||
## 6. Évacuation des tables — Priorité
|
||||
|
||||
Lorsque aucune table n'est libre et qu'il faut en libérer une :
|
||||
|
||||
```
|
||||
FONCTION évacuer_table_prioritaire(PK) :
|
||||
|
||||
// 1. Palette vide → retrait manuel instantané (pas d'AGV)
|
||||
POUR chaque table :
|
||||
SI table contient palette VIDE :
|
||||
Opérateur retire manuellement → table = VIDE
|
||||
RETOURNER table
|
||||
|
||||
// 2. Table déjà en attente d'évacuation → AGV en route, attendre
|
||||
POUR chaque table :
|
||||
SI table.état == EN_ATTENTE_EVACUATION :
|
||||
Attendre fin du mouvement AGV
|
||||
RETOURNER table
|
||||
|
||||
// 3. Palette source en attente, non réutilisée par la prochaine tâche
|
||||
POUR chaque table :
|
||||
SI table.état == PALETTE_SOURCE_EN_ATTENTE
|
||||
ET table.palette ∉ prochaines_tâches_de_l_OS :
|
||||
Commander AGV : table → buffer ES ou ASRS
|
||||
RETOURNER table
|
||||
|
||||
// 4. Palette fille en attente → évacuer vers image de quai
|
||||
POUR chaque table :
|
||||
SI table.état == PALETTE_FILLE_EN_ATTENTE :
|
||||
Commander AGV : table → image de quai
|
||||
RETOURNER table
|
||||
|
||||
// 5. Palette source en attente (même si réutilisée) → buffer ES
|
||||
POUR chaque table :
|
||||
SI table.état == PALETTE_SOURCE_EN_ATTENTE :
|
||||
Commander AGV : table → buffer ES
|
||||
RETOURNER table
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Gestion des sorties buffer → PK
|
||||
|
||||
Quand une table se libère au PK, le WMS choisit parmi les palettes en buffer affectées à ce PK.
|
||||
|
||||
```
|
||||
FONCTION choisir_palette_buffer_vers_PK(PK, table_libérée) :
|
||||
|
||||
palettes_en_buffer ← toutes les palettes en ES affectées à ce PK
|
||||
|
||||
SI palettes_en_buffer est vide :
|
||||
RETOURNER NULL // rien en buffer
|
||||
|
||||
// Trier par Line.CstAtt croissant (plus petit = plus prioritaire)
|
||||
palettes_triées ← trier(palettes_en_buffer, par Line.CstAtt ASC)
|
||||
|
||||
// Prendre la palette avec la plus petite séquence
|
||||
// qui est compatible avec la table libérée
|
||||
POUR chaque palette DANS palettes_triées :
|
||||
SI compatible(palette, table_libérée, PK) :
|
||||
Commander AGV : buffer → table_libérée
|
||||
RETOURNER palette
|
||||
|
||||
RETOURNER NULL // attendre qu'une table compatible se libère
|
||||
```
|
||||
|
||||
**Règle critique** : l'ordre de sortie des buffers est dicté par `Line.CstAtt`, **pas** par l'ordre d'arrivée physique en buffer.
|
||||
|
||||
---
|
||||
|
||||
## 8. Palettes multi-commandes
|
||||
|
||||
Une palette source peut être assignée à plusieurs OS.
|
||||
|
||||
```
|
||||
Après picking de la commande en cours :
|
||||
SI palette a encore des tâches pour d'autres OS :
|
||||
→ Marquer palette = MULTI_COMMANDE
|
||||
→ Commander AGV : table → buffer ES libre
|
||||
→ La palette reste en buffer jusqu'au lancement de l'OS suivant
|
||||
|
||||
Calcul de capacité buffer :
|
||||
Une palette multi-commande au PK ou en mouvement compte
|
||||
comme une place buffer occupée dans le calcul de MAX_PRELOAD_PAR_PK.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Priorité d'accès aux buffers entre PK
|
||||
|
||||
Lorsque les buffers ES sont saturés :
|
||||
|
||||
```
|
||||
Priorité définie par la séquence du mode "Picking" dans MODES_PKxx (LIM-69).
|
||||
|
||||
Séquence 1 = priorité la plus haute.
|
||||
|
||||
Exemple :
|
||||
PK01 : PICKING;1 → priorité haute
|
||||
PK03 : PICKING;2 → priorité moyenne
|
||||
PK05 : PICKING;3 → priorité basse
|
||||
|
||||
Quand un buffer se libère :
|
||||
→ Affecté en priorité au PK avec la séquence la plus basse
|
||||
parmi ceux qui ont des palettes en attente.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Paramètres WMS utilisés
|
||||
|
||||
|Paramètre|Description|Défaut|
|
||||
|---|---|---|
|
||||
|`MAX_PRELOAD_PAR_PK`|Nombre max de palettes pré-chargées en buffer ES par PK|3|
|
||||
|`SEUIL_RECENTRAGE_PF`|Nombre min de PICKING_DIRECT restants pour recentrer la PF au centre|3|
|
||||
|`CONTROLE_TRAITEMENT_COMMERCIAL`|Séparer ou non les articles par TC sur les palettes filles|`true`|
|
||||
|`MODES_PKxx`|Modes autorisés + priorité par PK (LIM-69)|—|
|
||||
|`PK_BIGBAG`|Autorise ou non les big-bags par PK (LIM-70)|—|
|
||||
|
||||
---
|
||||
|
||||
## 11. Diagramme de flux synthétique
|
||||
|
||||
```
|
||||
Palette arrive au PS (poste de sortie)
|
||||
Le PS demande au WMS : "sur quelle table ?"
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Type de picking ? │
|
||||
└───┬────────────┬────┘
|
||||
│ │
|
||||
NÉGATIF DIRECT
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────────────────┐
|
||||
│ 2 tables │ │ Localiser palette fille │
|
||||
│ nécessaires: │ │ compatible (TC) │
|
||||
│ palette + │ │ │
|
||||
│ adjacente │ │ Si aucune → anticiper │
|
||||
│ pour excéd. │ │ position nouvelle PF │
|
||||
└──────┬───────┘ └─────────────┬────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────────────────┐
|
||||
│ Prio 1: centre│ │ Choisir table adjacente │
|
||||
│ + côté │ │ à la PF : │
|
||||
│ │ │ - déjà occupée par PS ? │
|
||||
│ Prio 2: │ │ - VIDE ? (ping-pong) │
|
||||
│ côté + │ │ - en évacuation ? │
|
||||
│ centre │ │ - forcer évacuation │
|
||||
│ │ │ │
|
||||
│ Prio 3: │ └─────────────┬────────────┘
|
||||
│ évacuation │ │
|
||||
└──────┬───────┘ │
|
||||
│ │
|
||||
└────────┬───────────────┘
|
||||
│
|
||||
▼
|
||||
Table trouvée ?
|
||||
┌────┴────┐
|
||||
OUI NON
|
||||
│ │
|
||||
▼ ▼
|
||||
Palette → Buffer dispo
|
||||
table PK (< MAX_PRELOAD) ?
|
||||
┌────┴────┐
|
||||
OUI NON
|
||||
│ │
|
||||
▼ ▼
|
||||
Palette → Palette reste
|
||||
buffer ESx au PS (attente)
|
||||
|
||||
|
||||
═══════════════════════════════════════════
|
||||
|
||||
Quand une table se libère au PK :
|
||||
→ Chercher en buffer la palette avec
|
||||
le plus petit Line.CstAtt pour ce PK
|
||||
→ Commander AGV : buffer → table
|
||||
```
|
||||
Reference in New Issue
Block a user