chore: add ansible backend docker frontend-prep
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gestion/services"
|
||||
"log"
|
||||
"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]interface{}{
|
||||
"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)
|
||||
|
||||
log.Printf("✅ ETA défini pour commande %d: %d minutes (arrivée: %s)",
|
||||
commandID, minutes, arrivalTime.Format("15:04"))
|
||||
|
||||
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),
|
||||
})
|
||||
}
|
||||
|
||||
log.Printf("✅ Notifications programmées pour commande %d (ETA: %d min)", commandID, etaMinutes)
|
||||
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", commandID, notifType)
|
||||
|
||||
channel := fmt.Sprintf("notifications:command:%d", commandID)
|
||||
Redis.Publish(RedisCtx, channel, message)
|
||||
|
||||
log.Printf("📢 Notification envoyée: %s", 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 {
|
||||
log.Printf("⚠️ Position livreur %s non trouvée, utilisation ETA par défaut", deliveryman)
|
||||
return services.MinETA
|
||||
}
|
||||
|
||||
from := services.Coordinates{
|
||||
Latitude: livreurLat,
|
||||
Longitude: livreurLng,
|
||||
}
|
||||
to := services.Coordinates{
|
||||
Latitude: destLat,
|
||||
Longitude: destLng,
|
||||
}
|
||||
|
||||
distance := services.CalculateDistance(from, to)
|
||||
eta := services.CalculateETA(distance)
|
||||
|
||||
log.Printf("📍 ETA calculé pour %s: %.2f km -> %d min", deliveryman, distance, eta)
|
||||
|
||||
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]interface{}, 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]interface{}{
|
||||
"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)
|
||||
|
||||
log.Printf("✅ ETA détaillé pour commande %d: Total=%dmin Position=%d",
|
||||
commandID, totalETA, queuePosition)
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user