609 lines
18 KiB
Go
609 lines
18 KiB
Go
package db
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"gestion/models"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// ============================================
|
|
// 🆕 GESTION AUTOMATIQUE DU STATUT BUSY
|
|
// ============================================
|
|
|
|
// UpdateDeliverymanStatusBasedOnQueue met à jour automatiquement le statut
|
|
func (d *Database) UpdateDeliverymanStatusBasedOnQueue(deliveryman string) error {
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
|
queueSize, err := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
if err != nil {
|
|
return fmt.Errorf("erreur récupération taille queue: %w", err)
|
|
}
|
|
|
|
statusKey := fmt.Sprintf("delivery:status:%s", deliveryman)
|
|
data, err := Redis.Get(RedisCtx, statusKey).Result()
|
|
if err != nil {
|
|
log.Printf("⚠️ [STATUS] Livreur %s n'a pas de statut Redis", deliveryman)
|
|
return nil
|
|
}
|
|
|
|
var status models.DeliveryPersonStatus
|
|
if err := json.Unmarshal([]byte(data), &status); err != nil {
|
|
return err
|
|
}
|
|
|
|
var newStatus string
|
|
var currentCommand int
|
|
|
|
if queueSize >= MAX_COMMANDS_PER_DELIVERYMAN {
|
|
newStatus = "busy"
|
|
currentCommand = 0
|
|
log.Printf("🔴 [STATUS] %s -> BUSY (queue pleine: %d/10)", deliveryman, queueSize)
|
|
} else {
|
|
if status.Status == "delivering" && status.CurrentCommand > 0 {
|
|
newStatus = "delivering"
|
|
currentCommand = status.CurrentCommand
|
|
log.Printf("🟡 [STATUS] %s -> DELIVERING (queue: %d/10, livraison en cours: cmd %d)",
|
|
deliveryman, queueSize, currentCommand)
|
|
} else {
|
|
newStatus = "available"
|
|
currentCommand = 0
|
|
log.Printf("🟢 [STATUS] %s -> AVAILABLE (queue: %d/10)", deliveryman, queueSize)
|
|
}
|
|
}
|
|
|
|
return d.SetDeliveryPersonStatus(deliveryman, newStatus, currentCommand)
|
|
}
|
|
|
|
// CanDeliverymanAcceptCommands vérifie si un livreur peut accepter de nouvelles commandes
|
|
func (d *Database) CanDeliverymanAcceptCommands(deliveryman string) bool {
|
|
statusKey := fmt.Sprintf("delivery:status:%s", deliveryman)
|
|
data, err := Redis.Get(RedisCtx, statusKey).Result()
|
|
if err != nil {
|
|
log.Printf("⚠️ [CHECK] Livreur %s sans statut Redis", deliveryman)
|
|
return true
|
|
}
|
|
|
|
var status models.DeliveryPersonStatus
|
|
if err := json.Unmarshal([]byte(data), &status); err != nil {
|
|
return true
|
|
}
|
|
|
|
if status.Status == "offline" {
|
|
return false
|
|
}
|
|
|
|
// 3. Vérifier la taille de la queue
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
|
queueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
|
|
// 4. Si queue >= 10, refuser
|
|
if queueSize >= MAX_COMMANDS_PER_DELIVERYMAN {
|
|
log.Printf("🔴 [CHECK] %s REFUSÉ: queue pleine (%d/10)", deliveryman, queueSize)
|
|
return false
|
|
}
|
|
|
|
log.Printf("🟢 [CHECK] %s AUTORISÉ (%d/10)", deliveryman, queueSize)
|
|
return true
|
|
}
|
|
|
|
// GetAvailableDeliveryPersonsForAssignment récupère UNIQUEMENT les livreurs pouvant accepter
|
|
func (d *Database) GetAvailableDeliveryPersonsForAssignment() ([]models.DeliveryPersonStatus, error) {
|
|
keys, err := Redis.Keys(RedisCtx, "delivery:status:*").Result()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var available []models.DeliveryPersonStatus
|
|
|
|
for _, key := range keys {
|
|
data, err := Redis.Get(RedisCtx, key).Result()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
var status models.DeliveryPersonStatus
|
|
if err := json.Unmarshal([]byte(data), &status); err != nil {
|
|
continue
|
|
}
|
|
|
|
if d.CanDeliverymanAcceptCommands(status.Username) {
|
|
available = append(available, status)
|
|
}
|
|
}
|
|
|
|
log.Printf("📊 [AVAILABLE] %d livreur(s) disponible(s) pour assignation", len(available))
|
|
|
|
return available, nil
|
|
}
|
|
|
|
// ============================================
|
|
// 🔄 FONCTIONS MODIFIÉES AVEC AUTO-STATUS
|
|
// ============================================
|
|
|
|
// AddToDeliverymanQueue - VERSION MISE À JOUR avec auto-update du statut
|
|
func (d *Database) AddToDeliverymanQueue(deliveryman string, queueItem models.CommandQueue) error {
|
|
data, err := json.Marshal(queueItem)
|
|
if err != nil {
|
|
return fmt.Errorf("erreur serialisation: %w", err)
|
|
}
|
|
|
|
commandKey := fmt.Sprintf("queue:pending:%d", queueItem.CommandID)
|
|
Redis.Set(RedisCtx, commandKey, data, 24*time.Hour)
|
|
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
|
score := float64(time.Now().Unix())
|
|
|
|
err = Redis.ZAdd(RedisCtx, queueKey, redis.Z{
|
|
Score: score,
|
|
Member: queueItem.CommandID,
|
|
}).Err()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("erreur ajout queue Redis: %w", err)
|
|
}
|
|
|
|
counterKey := fmt.Sprintf("queue:deliveryman:%s:count", deliveryman)
|
|
Redis.Incr(RedisCtx, counterKey)
|
|
|
|
go d.UpdateDeliverymanStatusBasedOnQueue(deliveryman)
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddCommandToQueue ajoute une commande à la file d'attente Redis (version simple)
|
|
func (d *Database) AddCommandToQueue(commandID int) error {
|
|
if err := d.ValidateCommandBeforeQueue(commandID); err != nil {
|
|
log.Printf("❌ [QUEUE] Commande %d REFUSÉE: %v", commandID, err)
|
|
return fmt.Errorf("validation échouée: %w", err)
|
|
}
|
|
|
|
command, err := d.GetCommandByID(commandID)
|
|
if err != nil {
|
|
return fmt.Errorf("commande introuvable: %w", err)
|
|
}
|
|
var lat, lng float64
|
|
if command["dest_latitude"] != nil {
|
|
if latVal, ok := command["dest_latitude"].(float64); ok {
|
|
lat = latVal
|
|
}
|
|
}
|
|
if command["dest_longitude"] != nil {
|
|
if lngVal, ok := command["dest_longitude"].(float64); ok {
|
|
lng = lngVal
|
|
}
|
|
}
|
|
|
|
var totalPrice float64
|
|
if tp, ok := command["total_prix"].(float64); ok {
|
|
totalPrice = tp
|
|
}
|
|
|
|
var address string
|
|
if addr, ok := command["delivery_address"].(string); ok {
|
|
address = addr
|
|
}
|
|
|
|
queueItem := models.CommandQueue{
|
|
CommandID: commandID,
|
|
Username: command["username"].(string),
|
|
TotalPrice: totalPrice,
|
|
Address: address,
|
|
Lat: lat,
|
|
Lng: lng,
|
|
CreatedAt: time.Now(),
|
|
EstimatedETA: 0,
|
|
}
|
|
|
|
return d.AddToGeneralQueue(queueItem)
|
|
}
|
|
|
|
// AddCommandToSmartQueue - Ajoute une commande avec attribution au livreur le moins chargé
|
|
func (d *Database) AddCommandToSmartQueue(commandID int, address string) error {
|
|
if err := d.ValidateCommandBeforeQueue(commandID); err != nil {
|
|
log.Printf("❌ [QUEUE] Commande %d REFUSÉE: %v", commandID, err)
|
|
return fmt.Errorf("validation échouée: %w", err)
|
|
}
|
|
command, err := d.GetCommandByID(commandID)
|
|
if err != nil {
|
|
return fmt.Errorf("commande introuvable: %w", err)
|
|
}
|
|
var lat, lng float64
|
|
if command["dest_latitude"] != nil {
|
|
if latVal, ok := command["dest_latitude"].(float64); ok {
|
|
lat = latVal
|
|
}
|
|
}
|
|
if command["dest_longitude"] != nil {
|
|
if lngVal, ok := command["dest_longitude"].(float64); ok {
|
|
lng = lngVal
|
|
}
|
|
}
|
|
|
|
var totalPrice float64
|
|
if tp, ok := command["total_prix"].(float64); ok {
|
|
totalPrice = tp
|
|
}
|
|
|
|
queueItem := models.CommandQueue{
|
|
CommandID: commandID,
|
|
Username: command["username"].(string),
|
|
TotalPrice: totalPrice,
|
|
Address: address,
|
|
Lat: lat,
|
|
Lng: lng,
|
|
CreatedAt: time.Now(),
|
|
EstimatedETA: 0,
|
|
}
|
|
|
|
// ✅ MODIFIÉ: Utiliser FindLeastLoadedDeliveryman qui respecte maintenant le statut
|
|
assignedDeliveryman, err := d.FindLeastLoadedDeliveryman()
|
|
if err != nil {
|
|
log.Printf("⚠️ Aucun livreur trouvé, ajout à la queue générale")
|
|
return d.AddToGeneralQueue(queueItem)
|
|
}
|
|
|
|
err = d.AddToDeliverymanQueue(assignedDeliveryman, queueItem)
|
|
if err != nil {
|
|
return fmt.Errorf("erreur ajout à la queue du livreur: %w", err)
|
|
}
|
|
|
|
log.Printf("📋 Commande %d assignée à la queue de %s", commandID, assignedDeliveryman)
|
|
|
|
d.PublishCommandEvent(commandID, "queued",
|
|
fmt.Sprintf("En attente dans la queue de %s", assignedDeliveryman))
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddToGeneralQueue ajoute une commande à la queue générale (fallback)
|
|
func (d *Database) AddToGeneralQueue(queueItem models.CommandQueue) error {
|
|
data, err := json.Marshal(queueItem)
|
|
if err != nil {
|
|
return fmt.Errorf("erreur serialisation: %w", err)
|
|
}
|
|
|
|
score := float64(time.Now().Unix())
|
|
key := fmt.Sprintf("queue:pending:%d", queueItem.CommandID)
|
|
|
|
pipe := Redis.Pipeline()
|
|
pipe.Set(RedisCtx, key, data, 24*time.Hour)
|
|
pipe.ZAdd(RedisCtx, "queue:pending:sorted", redis.Z{
|
|
Score: score,
|
|
Member: queueItem.CommandID,
|
|
})
|
|
|
|
_, err = pipe.Exec(RedisCtx)
|
|
if err != nil {
|
|
return fmt.Errorf("erreur ajout queue générale: %w", err)
|
|
}
|
|
|
|
log.Printf("📥 Commande %d ajoutée à la queue générale", queueItem.CommandID)
|
|
return nil
|
|
}
|
|
|
|
// RemoveCommandFromQueue - VERSION AMÉLIORÉE avec auto-update du statut
|
|
func (d *Database) RemoveCommandFromQueue(commandID int) error {
|
|
key := fmt.Sprintf("queue:pending:%d", commandID)
|
|
commandIDStr := strconv.Itoa(commandID)
|
|
|
|
pipe := Redis.Pipeline()
|
|
pipe.Del(RedisCtx, key)
|
|
pipe.ZRem(RedisCtx, "queue:pending:sorted", commandIDStr)
|
|
pipe.ZRem(RedisCtx, "queue:priority:sorted", commandIDStr)
|
|
|
|
// Trouver et retirer de la queue du livreur
|
|
keys, _ := Redis.Keys(RedisCtx, "queue:deliveryman:*").Result()
|
|
var affectedDeliveryman string
|
|
|
|
for _, queueKey := range keys {
|
|
if len(queueKey) > 6 && queueKey[len(queueKey)-6:] == ":count" {
|
|
continue
|
|
}
|
|
|
|
// Vérifier si la commande est dans cette queue
|
|
_, err := Redis.ZRank(RedisCtx, queueKey, commandIDStr).Result()
|
|
if err == nil {
|
|
// Commande trouvée dans cette queue
|
|
affectedDeliveryman = queueKey[len("queue:deliveryman:"):]
|
|
pipe.ZRem(RedisCtx, queueKey, commandIDStr)
|
|
|
|
// Décrémenter le compteur
|
|
counterKey := fmt.Sprintf("queue:deliveryman:%s:count", affectedDeliveryman)
|
|
pipe.Decr(RedisCtx, counterKey)
|
|
break
|
|
}
|
|
}
|
|
|
|
_, err := pipe.Exec(RedisCtx)
|
|
if err != nil {
|
|
return fmt.Errorf("erreur suppression: %w", err)
|
|
}
|
|
|
|
log.Printf("✅ Commande %d retirée de la file", commandID)
|
|
|
|
// ✅ NOUVEAU: Mettre à jour le statut si un livreur était affecté
|
|
if affectedDeliveryman != "" {
|
|
go d.UpdateDeliverymanStatusBasedOnQueue(affectedDeliveryman)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Database) GetNextCommandInQueue() (*models.CommandQueue, error) {
|
|
|
|
normalResults, err := Redis.ZRangeWithScores(RedisCtx, "queue:pending:sorted", 0, 0).Result()
|
|
|
|
if err != nil || len(normalResults) == 0 {
|
|
return nil, fmt.Errorf("aucune commande en attente")
|
|
}
|
|
|
|
commandID := extractCommandID(normalResults[0].Member)
|
|
if commandID <= 0 {
|
|
return nil, fmt.Errorf("ID commande invalide")
|
|
}
|
|
|
|
key := fmt.Sprintf("queue:pending:%d", commandID)
|
|
data, err := Redis.Get(RedisCtx, key).Result()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("commande introuvable: %w", err)
|
|
}
|
|
|
|
var queue models.CommandQueue
|
|
if err := json.Unmarshal([]byte(data), &queue); err != nil {
|
|
return nil, fmt.Errorf("erreur désérialisation: %w", err)
|
|
}
|
|
return &queue, nil
|
|
}
|
|
|
|
// GetLastCommandInQueue récupère la dernière commande dans la queue d'un livreur
|
|
func (d *Database) GetLastCommandInQueue(deliveryman string) (*models.CommandQueue, error) {
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
|
|
|
// Récupérer la dernière commande (index -1)
|
|
commandIDs, err := Redis.ZRange(RedisCtx, queueKey, -1, -1).Result()
|
|
if err != nil || len(commandIDs) == 0 {
|
|
return nil, fmt.Errorf("queue vide")
|
|
}
|
|
|
|
commandID := extractCommandID(commandIDs[0])
|
|
if commandID <= 0 {
|
|
return nil, fmt.Errorf("ID invalide")
|
|
}
|
|
|
|
commandKey := fmt.Sprintf("queue:pending:%d", commandID)
|
|
data, err := Redis.Get(RedisCtx, commandKey).Result()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var queueItem models.CommandQueue
|
|
if err := json.Unmarshal([]byte(data), &queueItem); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &queueItem, nil
|
|
}
|
|
|
|
// GetCommandQueuePosition récupère la position d'une commande dans la queue
|
|
func (d *Database) GetCommandQueuePosition(commandID int) (int, error) {
|
|
commandIDStr := strconv.Itoa(commandID)
|
|
|
|
// Chercher d'abord dans les queues des livreurs
|
|
keys, _ := Redis.Keys(RedisCtx, "queue:deliveryman:*").Result()
|
|
|
|
for _, queueKey := range keys {
|
|
// Éviter les clés de compteur
|
|
if len(queueKey) > 6 && queueKey[len(queueKey)-6:] == ":count" {
|
|
continue
|
|
}
|
|
|
|
rank, err := Redis.ZRank(RedisCtx, queueKey, commandIDStr).Result()
|
|
if err == nil {
|
|
return int(rank) + 1, nil
|
|
}
|
|
}
|
|
|
|
// Chercher dans la queue générale
|
|
rank, err := Redis.ZRank(RedisCtx, "queue:pending:sorted", commandIDStr).Result()
|
|
if err == nil {
|
|
return int(rank) + 1, nil
|
|
}
|
|
|
|
return 0, fmt.Errorf("commande non trouvée dans les queues")
|
|
}
|
|
|
|
func (d *Database) ClearDeliverymanQueue(deliveryman string) error {
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", deliveryman)
|
|
|
|
// Récupérer toutes les commandes
|
|
commandIDs, _ := Redis.ZRange(RedisCtx, queueKey, 0, -1).Result()
|
|
|
|
// Redistribuer chaque commande
|
|
for _, cmdIDStr := range commandIDs {
|
|
commandID := extractCommandID(cmdIDStr)
|
|
if commandID <= 0 {
|
|
continue
|
|
}
|
|
|
|
commandKey := fmt.Sprintf("queue:pending:%d", commandID)
|
|
data, err := Redis.Get(RedisCtx, commandKey).Result()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
var queueItem models.CommandQueue
|
|
if err := json.Unmarshal([]byte(data), &queueItem); err != nil {
|
|
continue
|
|
}
|
|
|
|
newDeliveryman, err := d.FindLeastLoadedDeliveryman()
|
|
if err != nil {
|
|
d.AddToGeneralQueue(queueItem)
|
|
continue
|
|
}
|
|
|
|
if newDeliveryman != deliveryman {
|
|
d.AddToDeliverymanQueue(newDeliveryman, queueItem)
|
|
log.Printf("🔄 Commande %d réassignée de %s à %s",
|
|
commandID, deliveryman, newDeliveryman)
|
|
}
|
|
}
|
|
|
|
// Vider la queue
|
|
Redis.Del(RedisCtx, queueKey)
|
|
Redis.Del(RedisCtx, fmt.Sprintf("queue:deliveryman:%s:count", deliveryman))
|
|
|
|
go d.UpdateDeliverymanStatusBasedOnQueue(deliveryman)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Database) SetDeliveryPersonStatus(username, status string, commandID int) error {
|
|
key := fmt.Sprintf("delivery:status:%s", username)
|
|
|
|
statusData := models.DeliveryPersonStatus{
|
|
Username: username,
|
|
Status: status,
|
|
CurrentCommand: commandID,
|
|
LastUpdate: time.Now(),
|
|
}
|
|
|
|
data, _ := json.Marshal(statusData)
|
|
err := Redis.Set(RedisCtx, key, data, 24*time.Hour).Err()
|
|
|
|
if err == nil {
|
|
log.Printf("✅ Statut livreur %s: %s", username, status)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// GetAvailableDeliveryPersonsRedis récupère les livreurs disponibles (LEGACY)
|
|
func (d *Database) GetAvailableDeliveryPersonsRedis() ([]models.DeliveryPersonStatus, error) {
|
|
var available []models.DeliveryPersonStatus
|
|
err := d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
if s.Status == "available" {
|
|
available = append(available, s)
|
|
}
|
|
})
|
|
return available, err
|
|
}
|
|
|
|
// GetAllActiveDeliveryPersons retourne les livreurs actifs pouvant accepter des commandes
|
|
func (d *Database) GetAllActiveDeliveryPersons() ([]models.DeliveryPersonStatus, error) {
|
|
var active []models.DeliveryPersonStatus
|
|
err := d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
if s.Status != "offline" && d.CanDeliverymanAcceptCommands(s.Username) {
|
|
active = append(active, s)
|
|
}
|
|
})
|
|
return active, err
|
|
}
|
|
|
|
// CountActiveDeliverymen compte le nombre de livreurs actifs (non offline)
|
|
func (d *Database) CountActiveDeliverymen() (int, error) {
|
|
count := 0
|
|
err := d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
if s.Status != "offline" {
|
|
count++
|
|
}
|
|
})
|
|
return count, err
|
|
}
|
|
|
|
func (d *Database) GetSingleActiveDeliveryman() (string, error) {
|
|
found := ""
|
|
d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) { //nolint
|
|
if found == "" && s.Status != "offline" {
|
|
found = s.Username
|
|
}
|
|
})
|
|
if found == "" {
|
|
return "", fmt.Errorf("aucun livreur actif trouvé")
|
|
}
|
|
return found, nil
|
|
}
|
|
|
|
// GetAllActiveDeliverymenUsernames retourne les usernames de tous les livreurs actifs
|
|
func (d *Database) GetAllActiveDeliverymenUsernames() ([]string, error) {
|
|
var usernames []string
|
|
err := d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
if s.Status != "offline" {
|
|
usernames = append(usernames, s.Username)
|
|
}
|
|
})
|
|
return usernames, err
|
|
}
|
|
|
|
// SyncAllDeliverymanStatuses synchronise tous les statuts (à appeler au démarrage)
|
|
func (d *Database) SyncAllDeliverymanStatuses() error {
|
|
log.Println("🔄 [SYNC] Synchronisation des statuts livreurs...")
|
|
return d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
d.UpdateDeliverymanStatusBasedOnQueue(s.Username)
|
|
})
|
|
}
|
|
|
|
// GetDeliverymanCapacityReport génère un rapport détaillé
|
|
func (d *Database) GetDeliverymanCapacityReport() (map[string]any, error) {
|
|
report := map[string]any{
|
|
"total_deliverymen": 0,
|
|
"available": 0,
|
|
"busy_full": 0,
|
|
"busy_delivering": 0,
|
|
"offline": 0,
|
|
"details": []map[string]any{},
|
|
}
|
|
|
|
err := d.iterDeliveryStatuses(func(s models.DeliveryPersonStatus) {
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", s.Username)
|
|
queueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
canAccept := d.CanDeliverymanAcceptCommands(s.Username)
|
|
|
|
report["total_deliverymen"] = report["total_deliverymen"].(int) + 1
|
|
switch {
|
|
case s.Status == "offline":
|
|
report["offline"] = report["offline"].(int) + 1
|
|
case s.Status == "busy" && queueSize >= MAX_COMMANDS_PER_DELIVERYMAN:
|
|
report["busy_full"] = report["busy_full"].(int) + 1
|
|
case s.Status == "busy":
|
|
report["busy_delivering"] = report["busy_delivering"].(int) + 1
|
|
case canAccept:
|
|
report["available"] = report["available"].(int) + 1
|
|
}
|
|
|
|
report["details"] = append(report["details"].([]map[string]any), map[string]any{
|
|
"username": s.Username,
|
|
"status": s.Status,
|
|
"queue_size": queueSize,
|
|
"capacity": fmt.Sprintf("%d/10", queueSize),
|
|
"can_accept": canAccept,
|
|
"current_order": s.CurrentCommand,
|
|
})
|
|
})
|
|
return report, err
|
|
}
|
|
|
|
// iterDeliveryStatuses itère sur tous les statuts Redis des livreurs et appelle fn pour chacun.
|
|
func (d *Database) iterDeliveryStatuses(fn func(models.DeliveryPersonStatus)) error {
|
|
keys, err := Redis.Keys(RedisCtx, "delivery:status:*").Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, key := range keys {
|
|
data, err := Redis.Get(RedisCtx, key).Result()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
var status models.DeliveryPersonStatus
|
|
if err := json.Unmarshal([]byte(data), &status); err != nil {
|
|
continue
|
|
}
|
|
fn(status)
|
|
}
|
|
return nil
|
|
}
|