Files
projet_gestion_commande/backend/gestion/db/redis_eta_management.go
T
2026-04-22 19:06:35 +02:00

187 lines
5.1 KiB
Go

package db
import (
"fmt"
"gestion/services"
"strconv"
"time"
"github.com/redis/go-redis/v9"
)
func (d *Database) SetCommandETA(commandID, minutes int) error {
key := fmt.Sprintf("command:eta:%d", commandID)
now := time.Now()
arrivalTime := now.Add(time.Duration(minutes) * time.Minute)
eta := map[string]any{
"command_id": commandID,
"total_eta_minutes": minutes,
"eta_minutes": minutes,
"wait_time_minutes": 0,
"travel_time_minutes": minutes,
"queue_position": 1,
"updated_at": now.Unix(),
"arrival_time": arrivalTime.Unix(),
"estimated_arrival": arrivalTime.Format(time.RFC3339),
}
_, err := Redis.HSet(RedisCtx, key, eta).Result()
if err != nil {
return fmt.Errorf("erreur sauvegarde ETA: %w", err)
}
Redis.Expire(RedisCtx, key, 2*time.Hour)
d.ScheduleETANotifications(commandID, minutes)
return nil
}
// GetCommandETA récupère l'ETA d'une commande depuis Redis
func (d *Database) GetCommandETA(commandID int) (map[string]string, error) {
key := fmt.Sprintf("command:eta:%d", commandID)
etaData, err := Redis.HGetAll(RedisCtx, key).Result()
if err != nil {
return nil, err
}
if len(etaData) == 0 {
return nil, fmt.Errorf("aucun ETA trouvé pour la commande %d", commandID)
}
return etaData, nil
}
// CheckCommandETAExists vérifie si un ETA existe pour une commande
func (d *Database) CheckCommandETAExists(commandID int) bool {
key := fmt.Sprintf("command:eta:%d", commandID)
exists, _ := Redis.Exists(RedisCtx, key).Result()
return exists > 0
}
// ScheduleETANotifications programme les notifications 5min et 3min
func (d *Database) ScheduleETANotifications(commandID, etaMinutes int) error {
arrivalTime := time.Now().Add(time.Duration(etaMinutes) * time.Minute)
if etaMinutes > 5 {
notify5min := arrivalTime.Add(-5 * time.Minute).Unix()
Redis.ZAdd(RedisCtx, "notifications:scheduled", redis.Z{
Score: float64(notify5min),
Member: fmt.Sprintf("%d:5min", commandID),
})
}
if etaMinutes > 3 {
notify3min := arrivalTime.Add(-3 * time.Minute).Unix()
Redis.ZAdd(RedisCtx, "notifications:scheduled", redis.Z{
Score: float64(notify3min),
Member: fmt.Sprintf("%d:3min", commandID),
})
}
return nil
}
// ProcessScheduledNotifications traite les notifications à envoyer
func (d *Database) ProcessScheduledNotifications() error {
now := float64(time.Now().Unix())
results, err := Redis.ZRangeByScore(RedisCtx, "notifications:scheduled", &redis.ZRangeBy{
Min: "0",
Max: strconv.FormatFloat(now, 'f', 0, 64),
}).Result()
if err != nil {
return err
}
for _, result := range results {
parts := splitNotificationKey(result)
commandID, _ := strconv.Atoi(parts[0])
notifType := parts[1]
d.SendETANotification(commandID, notifType)
Redis.ZRem(RedisCtx, "notifications:scheduled", result)
}
return nil
}
// SendETANotification envoie une notification ETA
func (d *Database) SendETANotification(commandID int, notifType string) {
message := fmt.Sprintf("Votre commande #%d arrive dans %s", d.GetClientOrderID(commandID), notifType)
channel := fmt.Sprintf("notifications:command:%d", commandID)
Redis.Publish(RedisCtx, channel, message)
}
// CalculateETAForDeliveryman calcule l'ETA entre un livreur et une destination
func (d *Database) CalculateETAForDeliveryman(deliveryman string, destLat, destLng float64) int {
livreurLat, livreurLng, err := d.GetDeliveryPersonLocation(deliveryman)
if err != nil {
return services.MinETA
}
from := services.Coordinates{
Latitude: livreurLat,
Longitude: livreurLng,
}
to := services.Coordinates{
Latitude: destLat,
Longitude: destLng,
}
eta, _, err2 := services.CalculateETAWithTomTom(from, to)
if err2 != nil {
distance := services.CalculateDistance(from, to)
eta = services.CalculateETA(distance)
}
return eta
}
// CalculateDistanceBetweenPoints calcule la distance entre deux points
func (d *Database) CalculateDistanceBetweenPoints(lat1, lng1, lat2, lng2 float64) float64 {
from := services.Coordinates{Latitude: lat1, Longitude: lng1}
to := services.Coordinates{Latitude: lat2, Longitude: lng2}
return services.CalculateDistance(from, to)
}
// CalculateETABetweenPoints calcule l'ETA entre deux points
func (d *Database) CalculateETABetweenPoints(lat1, lng1, lat2, lng2 float64) int {
distance := d.CalculateDistanceBetweenPoints(lat1, lng1, lat2, lng2)
return services.CalculateETA(distance)
}
func (d *Database) GetDeliverymanQueueStats(deliveryman string) (map[string]any, error) {
return d.GetDeliverymanQueueInfo(deliveryman)
}
func (d *Database) SetCommandETAWithDetails(commandID, totalETA, queuePosition int) error {
key := fmt.Sprintf("command:eta:%d", commandID)
now := time.Now()
arrivalTime := now.Add(time.Duration(totalETA) * time.Minute)
eta := map[string]any{
"command_id": commandID,
"total_eta_minutes": totalETA,
"queue_position": queuePosition,
"updated_at": now.Unix(),
"arrival_time": arrivalTime.Unix(),
"estimated_arrival": arrivalTime.Format(time.RFC3339),
}
_, err := Redis.HSet(RedisCtx, key, eta).Result()
if err != nil {
return fmt.Errorf("erreur sauvegarde ETA: %w", err)
}
Redis.Expire(RedisCtx, key, 4*time.Hour)
return nil
}