chore: add ansible backend docker frontend-prep
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
// ============================================
|
||||
// handlers/client_tracking.go - NOUVEAU FICHIER
|
||||
// ➕ SUIVI COMMANDE POUR CLIENTS
|
||||
// ============================================
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"gestion/db"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetCommandStatus - Statut temps réel d'une commande
|
||||
// GET /api/v1/commands/:id/status
|
||||
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
|
||||
}
|
||||
|
||||
log.Printf("📊 [STATUS] Client %s demande statut cmd %d", usernameStr, commandID)
|
||||
|
||||
// Récupérer la 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 != 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
|
||||
}
|
||||
|
||||
// Récupérer ETA
|
||||
etaData, _ := database.GetCommandETA(commandID)
|
||||
|
||||
// Récupérer infos livreur (si assigné)
|
||||
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"],
|
||||
}
|
||||
}
|
||||
|
||||
// Mapper le statut en message lisible
|
||||
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
|
||||
// GET /api/v1/my-commands
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"commands": enrichedCommands,
|
||||
"count": len(enrichedCommands),
|
||||
})
|
||||
}
|
||||
|
||||
// GetCommandTracking - Suivi détaillé d'une commande
|
||||
// GET /api/v1/commands/:id/tracking
|
||||
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
|
||||
}
|
||||
|
||||
// Récupérer logs
|
||||
logs, _ := database.GetCommandLogs(commandID)
|
||||
|
||||
// ETA
|
||||
etaData, _ := database.GetCommandETA(commandID)
|
||||
|
||||
// Timeline (basé sur les logs)
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// HELPERS
|
||||
// ============================================
|
||||
|
||||
// getStatusMessage retourne un message lisible pour le client
|
||||
func getStatusMessage(status string) string {
|
||||
messages := map[string]string{
|
||||
"pending": "⏳ En attente d'assignation",
|
||||
"assigned": "✅ Livreur assigné",
|
||||
"support": "👨💼 En préparation",
|
||||
"en_route": "🚗 En cours de livraison",
|
||||
"arrived": "📍 Livreur arrivé",
|
||||
"livre": "📦 Livré - En attente de confirmation",
|
||||
"delivered": "✅ Livré",
|
||||
"approved": "🎉 Livraison confirmée",
|
||||
"failed": "❌ Échec de livraison",
|
||||
"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]interface{}) []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": "👤",
|
||||
"support": "📦",
|
||||
"en_route": "🚗",
|
||||
"arrived": "📍",
|
||||
"livre": "✅",
|
||||
"approved": "🎉",
|
||||
"failed": "❌",
|
||||
"cancelled": "🚫",
|
||||
}
|
||||
|
||||
if icon, ok := icons[status]; ok {
|
||||
return icon
|
||||
}
|
||||
return "📋"
|
||||
}
|
||||
Reference in New Issue
Block a user