113 lines
3.2 KiB
Go
113 lines
3.2 KiB
Go
package db
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"gestion/models"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
func (d *Database) UpdateDeliveryPersonLocation(username string, lat, lon float64) error {
|
|
// 1️⃣ Mettre à jour la position GPS dans Redis
|
|
key := fmt.Sprintf("delivery:location:%s", username)
|
|
location := map[string]interface{}{
|
|
"latitude": lat,
|
|
"longitude": lon,
|
|
"last_update": time.Now().Unix(),
|
|
}
|
|
data, _ := json.Marshal(location)
|
|
err := Redis.Set(RedisCtx, key, data, 1*time.Hour).Err()
|
|
if err != nil {
|
|
return fmt.Errorf("erreur mise à jour position: %w", err)
|
|
}
|
|
|
|
log.Printf("📍 Position GPS mise à jour pour %s: (%.6f, %.6f)", username, lat, lon)
|
|
|
|
// 2️⃣ ✅ NOUVEAU: Auto-initialiser/synchroniser le statut
|
|
statusKey := fmt.Sprintf("delivery:status:%s", username)
|
|
statusData, err := Redis.Get(RedisCtx, statusKey).Result()
|
|
|
|
if err != nil || statusData == "" {
|
|
// ✅ Pas de statut → Créer "available" par défaut
|
|
log.Printf("🆕 [INIT_STATUS] Création statut 'available' pour %s (première position GPS)", username)
|
|
d.SetDeliveryPersonStatus(username, "available", 0)
|
|
} else {
|
|
// ✅ Statut existe → Vérifier s'il faut le réactiver
|
|
var status models.DeliveryPersonStatus
|
|
json.Unmarshal([]byte(statusData), &status)
|
|
|
|
if status.Status == "offline" {
|
|
// Si le livreur était offline et envoie sa position → Le remettre available
|
|
log.Printf("🔄 [REACTIVATE] %s passe de 'offline' à 'available' (position GPS reçue)", username)
|
|
d.SetDeliveryPersonStatus(username, "available", 0)
|
|
} else {
|
|
// ✅ Statut actif → Synchroniser basé sur la queue
|
|
go d.UpdateDeliverymanStatusBasedOnQueue(username)
|
|
}
|
|
}
|
|
|
|
// 3️⃣ Publier l'événement de mise à jour de position
|
|
d.PublishDeliveryPersonLocationUpdate(username, lat, lon)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetDeliveryPersonLocation récupère la position d'un livreur
|
|
func (d *Database) GetDeliveryPersonLocation(username string) (float64, float64, error) {
|
|
key := fmt.Sprintf("delivery:location:%s", username)
|
|
data, err := Redis.Get(RedisCtx, key).Result()
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf("position non trouvée pour %s: %w", username, err)
|
|
}
|
|
|
|
if data == "" {
|
|
return 0, 0, fmt.Errorf("aucune donnée de position pour %s", username)
|
|
}
|
|
|
|
var location map[string]interface{}
|
|
if err := json.Unmarshal([]byte(data), &location); err != nil {
|
|
return 0, 0, fmt.Errorf("erreur parsing JSON Redis: %w", err)
|
|
}
|
|
|
|
// Extraire latitude avec gestion de type robuste
|
|
var lat, lon float64
|
|
if v, ok := location["latitude"]; ok && v != nil {
|
|
switch val := v.(type) {
|
|
case float64:
|
|
lat = val
|
|
case float32:
|
|
lat = float64(val)
|
|
case int:
|
|
lat = float64(val)
|
|
case int64:
|
|
lat = float64(val)
|
|
case string:
|
|
lat, _ = strconv.ParseFloat(val, 64)
|
|
}
|
|
}
|
|
|
|
// Extraire longitude avec gestion de type robuste
|
|
if v, ok := location["longitude"]; ok && v != nil {
|
|
switch val := v.(type) {
|
|
case float64:
|
|
lon = val
|
|
case float32:
|
|
lon = float64(val)
|
|
case int:
|
|
lon = float64(val)
|
|
case int64:
|
|
lon = float64(val)
|
|
case string:
|
|
lon, _ = strconv.ParseFloat(val, 64)
|
|
}
|
|
}
|
|
|
|
if lat == 0 && lon == 0 {
|
|
return 0, 0, fmt.Errorf("coordonnées invalides (0,0) pour %s", username)
|
|
}
|
|
|
|
return lat, lon, nil
|
|
}
|