Files
projet_gestion_commande/backend/gestion/handlers/client_tracking.go
T
2026-03-27 22:23:46 +01:00

240 lines
6.1 KiB
Go

package handlers
import (
"gestion/db"
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
// GetCommandStatus - Statut temps réel d'une commande
func GetCommandStatus(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
username, exists := c.Get("username")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentification requise"})
return
}
usernameStr := username.(string)
commandID, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID invalide"})
return
}
command, err := database.GetCommandByID(commandID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"})
return
}
cmdUsername, _ := command["username"].(string)
if cmdUsername != usernameStr {
log.Printf("❌ [STATUS] Accès refusé - cmd de %s demandée par %s", cmdUsername, usernameStr)
c.JSON(http.StatusForbidden, gin.H{
"error": "Cette commande ne vous appartient pas",
})
return
}
etaData, _ := database.GetCommandETA(commandID)
livreurInfo := gin.H{
"assigned": false,
}
if livreurAssign, ok := command["livreur_assign"].(string); ok && livreurAssign != "" {
queueInfo, _ := database.GetDeliverymanQueueInfo(livreurAssign)
livreurInfo = gin.H{
"assigned": true,
"livreur_name": livreurAssign,
"queue_position": queueInfo["queue_size"],
}
}
statusMessage := getStatusMessage(command["status"].(string))
c.JSON(http.StatusOK, gin.H{
"success": true,
"command_id": commandID,
"status": command["status"],
"status_message": statusMessage,
"adresse": command["adresse"],
"total_prix": command["total_prix"],
"created_at": command["created_at"],
"livreur": livreurInfo,
"eta": etaData,
})
}
// GetMyCommandsWithTracking - Liste des commandes avec suivi
func GetMyCommandsWithTracking(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
username, exists := c.Get("username")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentification requise"})
return
}
usernameStr := username.(string)
status := c.Query("status")
log.Printf("📋 [MY_CMDS] Client %s demande ses commandes (status=%s)", usernameStr, status)
commands, err := database.GetAllCommands(status, usernameStr)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Erreur récupération",
"details": err.Error(),
})
return
}
// Enrichir avec tracking
enrichedCommands := make([]gin.H, len(commands))
for i, cmd := range commands {
commandID, _ := cmd["id"].(int)
// ETA
etaData, _ := database.GetCommandETA(commandID)
// Infos livreur
livreurInfo := gin.H{
"assigned": false,
}
if livreurAssign, ok := cmd["livreur_assign"].(string); ok && livreurAssign != "" {
queueInfo, _ := database.GetDeliverymanQueueInfo(livreurAssign)
livreurInfo = gin.H{
"assigned": true,
"livreur_name": livreurAssign,
"queue_position": queueInfo["queue_size"],
}
}
enrichedCommands[i] = gin.H{
"id": cmd["id"],
"status": cmd["status"],
"status_message": getStatusMessage(cmd["status"].(string)),
"adresse": cmd["adresse"],
"total_prix": cmd["total_prix"],
"created_at": cmd["created_at"],
"livreur": livreurInfo,
"eta": etaData,
"proposed_address": cmd["proposed_address"],
"address_proposal_status": cmd["address_proposal_status"],
}
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"commands": enrichedCommands,
"count": len(enrichedCommands),
})
}
// GetCommandTracking - Suivi détaillé d'une commande
func GetCommandTracking(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
username := c.GetString("username")
commandID, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "ID invalide"})
return
}
// Récupérer commande
command, err := database.GetCommandByID(commandID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"})
return
}
// Vérifier propriété
cmdUsername, _ := command["username"].(string)
if cmdUsername != username {
c.JSON(http.StatusForbidden, gin.H{
"error": "Cette commande ne vous appartient pas",
})
return
}
logs, _ := database.GetCommandLogs(commandID)
etaData, _ := database.GetCommandETA(commandID)
timeline := buildTimeline(logs)
c.JSON(http.StatusOK, gin.H{
"success": true,
"command_id": commandID,
"status": command["status"],
"status_message": getStatusMessage(command["status"].(string)),
"eta": etaData,
"timeline": timeline,
"logs": logs,
})
}
func getStatusMessage(status string) string {
messages := map[string]string{
"pending": "⏳ En attente d'assignation",
"assigned": "✅ Livreur assigné",
"en_route": "🚗 En cours de livraison",
"arrived": "📍 Livreur arrivé",
"livre": "📦 Livré - En attente de confirmation",
"delivered": "✅ Livré",
"approved": "🎉 Livraison confirmée",
"cancelled": "🚫 Annulée",
"disabled": "⚠️ Désactivée",
}
if msg, ok := messages[status]; ok {
return msg
}
return "📋 " + status
}
// buildTimeline construit une timeline depuis les logs
func buildTimeline(logs []map[string]any) []gin.H {
timeline := make([]gin.H, 0)
for _, logEntry := range logs {
status, _ := logEntry["status"].(string)
message, _ := logEntry["message"].(string)
createdAt, _ := logEntry["created_at"]
timeline = append(timeline, gin.H{
"status": status,
"message": message,
"icon": getStatusIcon(status),
"created_at": createdAt,
})
}
return timeline
}
// getStatusIcon retourne une icône pour la timeline
func getStatusIcon(status string) string {
icons := map[string]string{
"created": "🛒",
"assigned": "👤",
"en_route": "🚗",
"arrived": "📍",
"livre": "✅",
"approved": "🎉",
"cancelled": "🚫",
}
if icon, ok := icons[status]; ok {
return icon
}
return "📋"
}