chore: refacto
This commit is contained in:
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"gestion/db"
|
||||
"gestion/utils"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -21,12 +22,12 @@ func AddAddress(c *gin.Context) {
|
||||
InvalidAddress string `json:"invalid_address" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.AddAddress(req.CorrectAddress, req.InvalidAddress); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible d'ajouter l'adresse", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,12 +47,12 @@ func DeleteAddress(c *gin.Context) {
|
||||
InvalidAddress string `json:"invalid_address" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.DeleteAddress(req.InvalidAddress, req.CorrectAddress); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de supprimer l'adresse", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ func GetAllAddress(c *gin.Context) {
|
||||
|
||||
getAddress, err := database.AllAddress()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de récupérer les adresses", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"gestion/db"
|
||||
"gestion/utils"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
@@ -32,14 +33,13 @@ func AlertPolice(c *gin.Context) {
|
||||
usernameStr := username.(string)
|
||||
alert, err := database.CreateAlert(usernameStr, req.Message)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de créer l'alerte", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Notifier tous les admins/cabines en temps réel
|
||||
go database.NotifyAllAdminCabineAlert(alert.ID, usernameStr, req.Message)
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"success": true,
|
||||
"message": "Police alert created",
|
||||
"alert_id": alert.ID,
|
||||
@@ -61,13 +61,12 @@ func DeleteAlert(c *gin.Context) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Accès réservé aux livreurs"})
|
||||
return
|
||||
}
|
||||
err = database.DeleteAlertPolicy(alertID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
if err = database.DeleteAlertPolicy(alertID); err != nil {
|
||||
utils.ServerErr(c, "Impossible de supprimer l'alerte", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "Alert deleted",
|
||||
})
|
||||
@@ -89,11 +88,11 @@ func GetAlert(c *gin.Context) {
|
||||
}
|
||||
alert, err := database.GetAlertPolicy(alertID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Alerte non trouvée"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"alert": alert,
|
||||
})
|
||||
@@ -124,7 +123,6 @@ func EndAlert(c *gin.Context) {
|
||||
|
||||
usernameStr := username.(string)
|
||||
|
||||
// Vérifier que l'alerte appartient bien à ce livreur
|
||||
alert, err := database.GetAlertPolicy(alertID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Alerte non trouvée"})
|
||||
@@ -136,9 +134,8 @@ func EndAlert(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
err = database.EndAlert(alertID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de mettre fin à l'alerte", "details": err.Error()})
|
||||
if err = database.EndAlert(alertID); err != nil {
|
||||
utils.ServerErr(c, "Impossible de mettre fin à l'alerte", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -169,7 +166,7 @@ func GetMyAlerts(c *gin.Context) {
|
||||
|
||||
alerts, err := database.GetAlertsByUsername(usernameStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de récupérer les alertes", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de récupérer les alertes", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -192,7 +189,7 @@ func GetAllAlerts(c *gin.Context) {
|
||||
|
||||
alerts, err := database.GetAllAlerts()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de récupérer les alertes", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de récupérer les alertes", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -214,7 +211,7 @@ func GetActiveAlerts(c *gin.Context) {
|
||||
|
||||
alerts, err := database.GetActiveAlerts()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de récupérer les alertes", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de récupérer les alertes", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ func RegisterClient(c *gin.Context) {
|
||||
log.Printf("❌ [REGISTER_CLIENT] Erreur binding: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -301,7 +300,7 @@ func ChangePassword(c *gin.Context) {
|
||||
NewPassword string `json:"new_password" binding:"required,min=8"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides", "details": err.Error()})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ func SetCommandDestinationCoordinates(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur stockage Redis",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -217,7 +216,6 @@ func UpdateCommandAddressCabine(c *gin.Context) {
|
||||
if err := database.UpdateCommandAddress(commandID, req.DeliveryAddress); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la mise à jour de l'adresse",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -264,7 +262,6 @@ func GetLivreurPosition(c *gin.Context) {
|
||||
"success": false,
|
||||
"livreur": livreurUsername,
|
||||
"message": "Position non disponible (GPS désactivé ou livraison terminée)",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -394,7 +391,6 @@ func GetDeliveryIssues(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération problèmes",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -431,7 +427,6 @@ func CreateDeliveryIssue(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur création problème",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -468,7 +463,6 @@ func UpdateDeliveryIssue(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur mise à jour",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -516,7 +510,6 @@ func AddDeliverySupport(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur ajout support",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -540,7 +533,6 @@ func GetCommandLogs(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération logs",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -580,7 +572,6 @@ func ForceValidateDelivery(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Raison requise pour validation forcée",
|
||||
"details": err.Error(),
|
||||
"example": gin.H{
|
||||
"reason": "Client confirmé par téléphone",
|
||||
},
|
||||
@@ -632,7 +623,6 @@ func ForceValidateDelivery(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la validation forcée",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -641,7 +631,7 @@ func ForceValidateDelivery(c *gin.Context) {
|
||||
livreurAssign, _ := command["livreur_assign"].(string)
|
||||
|
||||
if clientUsername != "" {
|
||||
clientMsg := fmt.Sprintf("Votre commande #%d a été livrée. Merci !", commandID)
|
||||
clientMsg := fmt.Sprintf("Ta commande #%d a bien été livrée ! Bonne dégustation l'ami et à bientôt 😊", database.GetClientOrderID(commandID))
|
||||
database.NotifyClient(clientUsername, commandID, "livre", clientMsg)
|
||||
}
|
||||
|
||||
|
||||
@@ -339,19 +339,22 @@ func GetAllCancelledOrders(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
cancelReason, _ := order["cancel_reason"].(string)
|
||||
enrichedOrder := map[string]any{
|
||||
"id": order["id"],
|
||||
"username": order["username"],
|
||||
"total_prix": order["total_prix"],
|
||||
"created_at": order["created_at"],
|
||||
"updated_at": order["updated_at"],
|
||||
"items_count": len(items),
|
||||
"id": order["id"],
|
||||
"username": order["username"],
|
||||
"total_prix": order["total_prix"],
|
||||
"created_at": order["created_at"],
|
||||
"updated_at": order["updated_at"],
|
||||
"items_count": len(items),
|
||||
"cancel_reason": cancelReason,
|
||||
}
|
||||
|
||||
if cancellationLog != nil {
|
||||
enrichedOrder["cancellation"] = gin.H{
|
||||
"cancelled_at": cancellationLog["created_at"],
|
||||
"cancelled_by": cancellationLog["author"],
|
||||
"reason": cancelReason,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ func CreateCategory(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := db.ValidateCategoryColor(req.Color); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Couleur invalide (format hex requis, ex: #ff0000)"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func UpdateCategory(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := db.ValidateCategoryColor(req.Color); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Couleur invalide (format hex requis, ex: #ff0000)"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func DeleteCategory(c *gin.Context) {
|
||||
if err := database.DeleteCategory(id); err != nil {
|
||||
log.Printf("❌ [CATEGORIES] Suppression erreur: %v", err)
|
||||
if strings.Contains(err.Error(), "utilisée par") {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "Catégorie utilisée par des produits existants"})
|
||||
} else {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Catégorie non trouvée"})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -90,7 +91,6 @@ func GetMyCommandsWithTracking(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -118,6 +118,7 @@ func GetMyCommandsWithTracking(c *gin.Context) {
|
||||
|
||||
enrichedCommands[i] = gin.H{
|
||||
"id": cmd["id"],
|
||||
"client_order_number": cmd["client_order_number"],
|
||||
"status": cmd["status"],
|
||||
"status_message": getStatusMessage(cmd["status"].(string)),
|
||||
"adresse": cmd["adresse"],
|
||||
|
||||
@@ -81,7 +81,7 @@ func UpdateCommandAddress(c *gin.Context) {
|
||||
// ✅ Récupération sécurisée du username
|
||||
adminUsername, err := safeGetUsername(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ func ProposeAddressChange(c *gin.Context) {
|
||||
|
||||
staffUsername, err := safeGetUsername(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -198,15 +198,14 @@ func ProposeAddressChange(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := database.ProposeAddressChange(commandID, req.ProposedAddress, staffUsername); err != nil {
|
||||
log.Printf("❌ [PROPOSE_ADDR] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de proposer l'adresse", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Notifier le client
|
||||
clientUsername, _ := command["username"].(string)
|
||||
if clientUsername != "" {
|
||||
msg := fmt.Sprintf("📍 Une nouvelle adresse de livraison vous est proposée pour la commande #%d : %s. Veuillez l'accepter ou la refuser dans le suivi de commande.", commandID, req.ProposedAddress)
|
||||
msg := fmt.Sprintf("📍 Une nouvelle adresse de livraison vous est proposée pour votre commande #%d : %s. Veuillez l'accepter ou la refuser dans le suivi de commande.", database.GetClientOrderID(commandID), req.ProposedAddress)
|
||||
database.NotifyClient(clientUsername, commandID, "address_proposal", msg)
|
||||
}
|
||||
|
||||
@@ -248,8 +247,7 @@ func RespondToAddressProposal(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := database.RespondToAddressProposal(commandID, clientUsername, req.Accepted); err != nil {
|
||||
log.Printf("❌ [RESPOND_ADDR] Erreur: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de traiter la réponse", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -296,7 +294,6 @@ func GetAllCommands(c *gin.Context) {
|
||||
log.Printf("❌ [GET_CMDS] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des commandes",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -444,7 +441,7 @@ func StaffApproveDelivery(c *gin.Context) {
|
||||
totalPoints, pointCategory, clientUsername, err := database.ApproveDeliveryAtomicByStaff(commandID, staffUsername)
|
||||
if err != nil {
|
||||
log.Printf("❌ [STAFF_APPROVE] Erreur: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Impossible de confirmer la réception: " + err.Error()})
|
||||
utils.ServerErr(c, "Impossible de confirmer la réception", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -474,7 +471,7 @@ func ValidateDelivery(c *gin.Context) {
|
||||
|
||||
adminUsername, err := safeGetUsername(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -604,7 +601,6 @@ func GetAvailableDeliveryPersons(c *gin.Context) {
|
||||
log.Printf("❌ [GET_LIVREURS] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des livreurs",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -651,7 +647,6 @@ func AssignDeliveryPerson(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -665,7 +660,6 @@ func AssignDeliveryPerson(c *gin.Context) {
|
||||
log.Printf("❌ [ASSIGN] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur assignation livreur",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -704,7 +698,6 @@ func GetClientCommandsHistory(c *gin.Context) {
|
||||
log.Printf("❌ [HISTORY] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération historique",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -805,7 +798,7 @@ func NotifyClientToDescend(c *gin.Context) {
|
||||
}
|
||||
|
||||
staffUsername, _ := c.Get("username")
|
||||
msg := fmt.Sprintf("Votre commande #%d est prête ! Vous pouvez descendre la récupérer.", commandID)
|
||||
msg := fmt.Sprintf("Votre commande #%d est prête ! Vous pouvez descendre la récupérer.", database.GetClientOrderID(commandID))
|
||||
database.NotifyClient(clientUsername, commandID, "ready_pickup", msg)
|
||||
database.AddCommandLog(commandID, "notification", fmt.Sprintf("Client notifié de descendre par %s", staffUsername), staffUsername.(string))
|
||||
|
||||
@@ -859,7 +852,6 @@ func ShowItems(c *gin.Context) {
|
||||
log.Printf("❌ [ITEMS] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des items",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -951,7 +943,6 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
||||
log.Printf("❌ [ITEMS_DETAILED] Erreur DB: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération items",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -964,12 +955,13 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
||||
}
|
||||
|
||||
commandInfo := map[string]interface{}{
|
||||
"id": items[0]["command_id"],
|
||||
"command_status": items[0]["command_status"],
|
||||
"command_address": items[0]["command_address"],
|
||||
"total_prix": items[0]["total_prix"],
|
||||
"livreur_assign": items[0]["livreur_assign"],
|
||||
"command_created_at": items[0]["command_created_at"],
|
||||
"id": items[0]["command_id"],
|
||||
"command_status": items[0]["command_status"],
|
||||
"command_address": items[0]["command_address"],
|
||||
"total_prix": items[0]["total_prix"],
|
||||
"livreur_assign": items[0]["livreur_assign"],
|
||||
"command_created_at": items[0]["command_created_at"],
|
||||
"client_order_number": items[0]["client_order_number"],
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
@@ -1007,7 +999,6 @@ func UpdateItemStatus(c *gin.Context) {
|
||||
log.Printf("❌ [UPD_ITEM] Erreur JSON: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Status requis",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -1038,7 +1029,6 @@ func UpdateItemStatus(c *gin.Context) {
|
||||
log.Printf("❌ [UPD_ITEM] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la mise à jour",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -1065,7 +1055,7 @@ func DeleteCommandItem(c *gin.Context) {
|
||||
|
||||
adminUsername, err := safeGetUsername(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1084,8 +1074,7 @@ func DeleteCommandItem(c *gin.Context) {
|
||||
log.Printf("🗑️ [DEL_ITEM] Admin %s supprime item %d de cmd %d", adminUsername, itemID, commandID)
|
||||
|
||||
if err := database.DeleteCommandItem(commandID, itemID); err != nil {
|
||||
log.Printf("❌ [DEL_ITEM] Erreur: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de supprimer l'item", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1137,8 +1126,7 @@ func UpdateCommandStatusAdmin(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := database.UpdateCommandStatus(commandID, req.Status); err != nil {
|
||||
log.Printf("❌ [STATUS_ADMIN] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de mettre à jour le statut", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ func GetMyDeliveries(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -190,7 +189,6 @@ func UpdateDeliveryStatus(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -261,7 +259,6 @@ func UpdateDeliveryStatus(c *gin.Context) {
|
||||
if err := database.UpdateCommandStatus(commandID, req.Status); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur mise à jour",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -361,16 +358,16 @@ func UpdateDeliveryStatus(c *gin.Context) {
|
||||
} else {
|
||||
etaStr = fmt.Sprintf("%d min", etaMinutes)
|
||||
}
|
||||
clientMsg = fmt.Sprintf("🛵 Votre commande #%d est en route ! Arrivée dans ~%s", commandID, etaStr)
|
||||
clientMsg = fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route (~%s)", database.GetClientOrderID(commandID), etaStr)
|
||||
} else {
|
||||
clientMsg = fmt.Sprintf("🛵 Votre commande #%d est en route !", commandID)
|
||||
clientMsg = fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route.", database.GetClientOrderID(commandID))
|
||||
}
|
||||
case "arrived":
|
||||
clientMsg = fmt.Sprintf("🛵 Votre livreur est là ! Il sera chez vous dans 5 minutes (commande #%d)", commandID)
|
||||
clientMsg = fmt.Sprintf("Descend, le livreur est là dans 3min (commande #%d) 🛵", database.GetClientOrderID(commandID))
|
||||
case "livre":
|
||||
clientMsg = fmt.Sprintf("Votre commande #%d a été livrée. Merci !", commandID)
|
||||
clientMsg = fmt.Sprintf("Ta commande #%d a bien été livrée ! Bonne dégustation l'ami et à bientôt 😊", database.GetClientOrderID(commandID))
|
||||
case "cancelled":
|
||||
clientMsg = fmt.Sprintf("Votre commande #%d a été annulée par le livreur", commandID)
|
||||
clientMsg = fmt.Sprintf("Votre commande #%d a été annulée par le livreur", database.GetClientOrderID(commandID))
|
||||
}
|
||||
if clientMsg != "" {
|
||||
database.NotifyClient(clientUsername, commandID, req.Status, clientMsg)
|
||||
|
||||
@@ -40,7 +40,6 @@ func GetDeliveryPersonDetails(c *gin.Context) {
|
||||
log.Printf("❌ [GET_DELIVERY_DETAILS] Livreur non trouvé: %v", err)
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Livreur non trouvé",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -118,7 +117,6 @@ func UpdateDeliveryPersonStatusAdmin(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Statut requis",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -163,7 +161,6 @@ func UpdateDeliveryPersonStatusAdmin(c *gin.Context) {
|
||||
log.Printf("❌ [UPDATE_DELIVERY_STATUS] Erreur mise à jour: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur mise à jour statut",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -325,7 +322,6 @@ func GetDeliveryPersonHistory(c *gin.Context) {
|
||||
log.Printf("❌ [GET_DELIVERY_HISTORY] Erreur récupération: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération historique",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -373,7 +369,6 @@ func UpdateDeliveryPersonLocationAdmin(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Coordonnées GPS requises",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -421,7 +416,6 @@ func UpdateDeliveryPersonLocationAdmin(c *gin.Context) {
|
||||
log.Printf("❌ [UPDATE_DELIVERY_LOCATION] Erreur mise à jour: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur mise à jour position",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -515,7 +509,6 @@ func RemoveCommandFromQueue(c *gin.Context) {
|
||||
log.Printf("❌ [REMOVE_FROM_QUEUE] Erreur suppression: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur suppression de la queue",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,34 +21,24 @@ import (
|
||||
// GÉOCODAGE D'ADRESSES
|
||||
// ============================================
|
||||
|
||||
// GeocodeAddress convertit une adresse en coordonnées GPS
|
||||
func GeocodeAddress(c *gin.Context) {
|
||||
geoService := c.MustGet("geoService").(*services.GeoService)
|
||||
|
||||
var req struct {
|
||||
Address string `json:"address" binding:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Adresse requise",
|
||||
"details": err.Error(),
|
||||
})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Adresse requise"})
|
||||
return
|
||||
}
|
||||
|
||||
location, err := geoService.GeocodeAddress(req.Address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Impossible de géocoder cette adresse",
|
||||
"details": err.Error(),
|
||||
})
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Impossible de géocoder cette adresse"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("📍 Adresse géocodée: %s -> (%.6f, %.6f)",
|
||||
req.Address, location.Latitude, location.Longitude)
|
||||
|
||||
log.Printf("📍 Adresse géocodée: %s -> (%.6f, %.6f)", req.Address, location.Latitude, location.Longitude)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"latitude": location.Latitude,
|
||||
@@ -76,8 +66,7 @@ func FindNearestDeliveryPerson(c *gin.Context) {
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
"error": "Données invalides",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -89,8 +78,7 @@ func FindNearestDeliveryPerson(c *gin.Context) {
|
||||
location, err := geoService.GeocodeAddress(req.Address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Impossible de géocoder l'adresse",
|
||||
"details": err.Error(),
|
||||
"error": "Impossible de géocoder l'adresse",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -110,8 +98,7 @@ func FindNearestDeliveryPerson(c *gin.Context) {
|
||||
// Valider les coordonnées
|
||||
if err := services.ValidateCoordinates(targetCoords); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Coordonnées invalides",
|
||||
"details": err.Error(),
|
||||
"error": "Coordonnées invalides",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -135,8 +122,7 @@ func FindNearestDeliveryPerson(c *gin.Context) {
|
||||
nearest, err := geoService.FindNearestDeliveryPersonFast(targetCoords, usernames)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Aucun livreur avec position GPS valide",
|
||||
"details": err.Error(),
|
||||
"error": "Aucun livreur avec position GPS valide",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -193,8 +179,7 @@ func GetAllDeliveryDistances(c *gin.Context) {
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
"error": "Données invalides",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -205,8 +190,7 @@ func GetAllDeliveryDistances(c *gin.Context) {
|
||||
location, err := geoService.GeocodeAddress(req.Address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Impossible de géocoder l'adresse",
|
||||
"details": err.Error(),
|
||||
"error": "Impossible de géocoder l'adresse",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -224,8 +208,7 @@ func GetAllDeliveryDistances(c *gin.Context) {
|
||||
|
||||
if err := services.ValidateCoordinates(targetCoords); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Coordonnées invalides",
|
||||
"details": err.Error(),
|
||||
"error": "Coordonnées invalides",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -246,8 +229,7 @@ func GetAllDeliveryDistances(c *gin.Context) {
|
||||
distances, err := geoService.GetAllDeliveryDistances(targetCoords, usernames)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur calcul des distances",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur calcul des distances",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -317,7 +299,6 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Impossible de géocoder l'adresse de livraison",
|
||||
"address": address,
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -375,8 +356,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
travelTime, distance, err := calculateTravelTimeWithTomTom(geoService, singleDeliveryman, location.Latitude, location.Longitude)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur calcul ETA",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur calcul ETA",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -385,8 +365,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
err = database.AssignCommandToDeliverymanQueueWithCoords(commandID, singleDeliveryman, travelTime, location.Latitude, location.Longitude, address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de l'assignation",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur lors de l'assignation",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -440,8 +419,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
travelTime, distance, err := calculateTravelTimeWithTomTom(geoService, leastLoaded, location.Latitude, location.Longitude)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur calcul ETA",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur calcul ETA",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -450,8 +428,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
err = database.ForceAssignCommandToDeliverymanWithCoords(commandID, leastLoaded, travelTime, location.Latitude, location.Longitude, address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de l'assignation forcée",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur lors de l'assignation forcée",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -506,8 +483,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
nearest, err := geoService.FindNearestDeliveryPersonFast(targetCoords, usernames)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Aucun livreur avec position GPS valide",
|
||||
"details": err.Error(),
|
||||
"error": "Aucun livreur avec position GPS valide",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -527,8 +503,7 @@ func AutoAssignNearestDeliveryPerson(c *gin.Context) {
|
||||
err = database.AssignCommandToDeliverymanQueueWithCoords(commandID, nearest.Username, travelTime, location.Latitude, location.Longitude, address)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de l'assignation",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur lors de l'assignation",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -582,8 +557,7 @@ func AutoAssignAllPendingCommands(c *gin.Context) {
|
||||
commands, err := database.GetAllCommands("pending", "")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération des commandes",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur récupération des commandes",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -742,8 +716,7 @@ func GetAllDeliveryQueues(c *gin.Context) {
|
||||
overview, err := database.GetAllQueuesOverview()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération des queues",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur récupération des queues",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -802,8 +775,7 @@ func GetDeliverymanQueue(c *gin.Context) {
|
||||
queueInfo, err := database.GetDeliverymanQueueInfo(username)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération de la queue",
|
||||
"details": err.Error(),
|
||||
"error": "Erreur récupération de la queue",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -814,41 +786,23 @@ func GetDeliverymanQueue(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// VALIDATION D'ADRESSE
|
||||
// ============================================
|
||||
|
||||
// ValidateAddress vérifie si une adresse peut être géocodée
|
||||
// POST /api/v1/validate-address
|
||||
// Body: {"address": "123 Main St, Paris"}
|
||||
func ValidateAddress(c *gin.Context) {
|
||||
geoService := c.MustGet("geoService").(*services.GeoService)
|
||||
|
||||
var req struct {
|
||||
Address string `json:"address" binding:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Adresse requise",
|
||||
"details": err.Error(),
|
||||
})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Adresse requise"})
|
||||
return
|
||||
}
|
||||
|
||||
isValid := geoService.IsValidAddress(req.Address)
|
||||
|
||||
if !isValid {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"valid": false,
|
||||
"message": "Adresse introuvable ou invalide",
|
||||
})
|
||||
if !geoService.IsValidAddress(req.Address) {
|
||||
c.JSON(http.StatusOK, gin.H{"valid": false, "message": "Adresse introuvable ou invalide"})
|
||||
return
|
||||
}
|
||||
|
||||
// Récupérer les détails
|
||||
location, _ := geoService.GeocodeAddress(req.Address)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"valid": true,
|
||||
"message": "Adresse valide",
|
||||
@@ -858,13 +812,7 @@ func ValidateAddress(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// HELPER FUNCTION - CALCUL ETA AVEC TOMTOM
|
||||
// ============================================
|
||||
|
||||
// calculateTravelTimeWithTomTom calcule l'ETA avec TomTom ou fallback local
|
||||
func calculateTravelTimeWithTomTom(geoService *services.GeoService, deliverymanUsername string, targetLat, targetLon float64) (int, float64, error) {
|
||||
// Récupérer position du livreur
|
||||
deliverymanLoc, err := geoService.GetDeliveryPersonLocation(deliverymanUsername)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("position du livreur introuvable: %w", err)
|
||||
@@ -875,10 +823,8 @@ func calculateTravelTimeWithTomTom(geoService *services.GeoService, deliverymanU
|
||||
Longitude: targetLon,
|
||||
}
|
||||
|
||||
// Calculer ETA avec TomTom (avec fallback automatique intégré)
|
||||
travelTime, distance, err := services.GetETAWithTraffic(*deliverymanLoc, targetCoords)
|
||||
if err != nil {
|
||||
// Fallback sur calcul local
|
||||
distance = services.CalculateDistance(*deliverymanLoc, targetCoords)
|
||||
travelTime = services.CalculateETA(distance)
|
||||
log.Printf("⚠️ TomTom indisponible pour %s, fallback: %.2f km -> %d min",
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -43,7 +44,6 @@ func GetDeliveryPersonMapLinks(c *gin.Context) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"success": false,
|
||||
"error": "Position GPS non disponible pour ce livreur",
|
||||
"details": err.Error(),
|
||||
"message": "Le livreur n'a pas encore partagé sa position ou est hors ligne",
|
||||
})
|
||||
return
|
||||
@@ -117,7 +117,6 @@ func GetCommandNavigationLinks(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur génération des liens",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -41,7 +42,6 @@ func GetMyCompletedOrders(c *gin.Context) {
|
||||
log.Printf("❌ [HISTORY] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération de l'historique",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -120,7 +120,6 @@ func GetMyCompletedOrdersWithItems(c *gin.Context) {
|
||||
log.Printf("❌ [HISTORY_DETAILED] Erreur: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération de l'historique",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"gestion/db"
|
||||
"gestion/models"
|
||||
"gestion/services"
|
||||
"gestion/utils"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
@@ -32,7 +33,7 @@ func AddProductsBasket(c *gin.Context) {
|
||||
|
||||
var req BasketsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Requête invalide", "details": err.Error()})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,17 +63,17 @@ func AddProductsBasket(c *gin.Context) {
|
||||
}
|
||||
if err := database.DecrementProductStockByID(req.ProductID, req.Quantity); err != nil {
|
||||
log.Printf("❌ [ADD_PANIER] Erreur décrement stock product_id=%d: %v", req.ProductID, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible d'ajouter le produit au panier", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible d'ajouter le produit au panier", err)
|
||||
return
|
||||
}
|
||||
panier, err := database.AddProductInBasketByID(req.Username, req.ProductID, req.Quantity)
|
||||
if err != nil {
|
||||
log.Printf("❌ [ADD_PANIER] Erreur ajout product_id=%d qty=%.3f: %v", req.ProductID, req.Quantity, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible d'ajouter le produit au panier", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible d'ajouter le produit au panier", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"success": true, "message": "Produit ajouté au panier avec succès", "panier": panier})
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "Produit ajouté au panier avec succès", "panier": panier})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -128,11 +129,7 @@ func GetAllBaskets(c *gin.Context) {
|
||||
|
||||
baskets, err := database.GetAllProductsInBasket(username)
|
||||
if err != nil {
|
||||
log.Printf("❌ [GET_PANIER] Erreur récupération: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération du panier",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération du panier", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -165,11 +162,7 @@ func DeleteProductFromBasket(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
log.Printf("❌ [DEL_PANIER] Erreur JSON: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données requises manquantes",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -211,11 +204,7 @@ func DeleteProductFromBasket(c *gin.Context) {
|
||||
// Supprimer l'article
|
||||
err = database.DeleteProductFromBasket(req.ID)
|
||||
if err != nil {
|
||||
log.Printf("❌ [DEL_PANIER] Erreur suppression: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la suppression",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la suppression", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -259,11 +248,7 @@ func ClearBasket(c *gin.Context) {
|
||||
|
||||
err = database.ClearBasket(authUsernameStr)
|
||||
if err != nil {
|
||||
log.Printf("❌ [CLEAR_PANIER] Erreur vidage: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors du vidage du panier",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors du vidage du panier", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -305,7 +290,7 @@ func ValidateBasket(c *gin.Context) {
|
||||
|
||||
cmd := &models.Command{DeliveryAddress: req.DeliveryAddress}
|
||||
if err := database.CheckAddress(cmd); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "corrected_address": cmd.DeliveryAddress})
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Adresse non reconnue", "corrected_address": cmd.DeliveryAddress})
|
||||
return
|
||||
}
|
||||
req.DeliveryAddress = cmd.DeliveryAddress
|
||||
@@ -323,8 +308,7 @@ func ValidateBasket(c *gin.Context) {
|
||||
// ============================================
|
||||
items, err := database.GetBasketItems(usernameStr)
|
||||
if err != nil {
|
||||
log.Printf("❌ [CHECKOUT] Erreur récupération panier: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de récupérer le panier", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de récupérer le panier", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -487,7 +471,7 @@ func ValidateBasket(c *gin.Context) {
|
||||
_, _ = database.CreateCryptoPayment(commandID, payResp.PaymentID.String(), payResp.Status, payResp.PriceCurrency, payResp.PayCurrency, payResp.PayAddress, priceAmt, payAmt)
|
||||
|
||||
log.Printf("✅ [CHECKOUT] Commande %d en attente paiement crypto (%s)", commandID, req.PayCurrency)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"success": true,
|
||||
"command_id": commandID,
|
||||
"payment_method": "crypto",
|
||||
@@ -510,8 +494,7 @@ func ValidateBasket(c *gin.Context) {
|
||||
// ============================================
|
||||
err = database.ClearBasket(usernameStr)
|
||||
if err != nil {
|
||||
log.Printf("❌ [CHECKOUT] Erreur vidage panier: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Impossible de vider le panier", "details": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de vider le panier", err)
|
||||
return
|
||||
}
|
||||
log.Printf("🧹 [CHECKOUT] Panier vidé")
|
||||
@@ -585,7 +568,8 @@ func ValidateBasket(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Notifier le client
|
||||
clientMsg := fmt.Sprintf("Votre commande #%d est confirmée ! Un livreur est en route.", commandID)
|
||||
clientOrderID := database.GetClientOrderID(commandID)
|
||||
clientMsg := fmt.Sprintf("Ta commande #%d est prise en compte ! Merci de rester branché et vigilant sur les notifs à venir.", clientOrderID)
|
||||
database.NotifyClient(usernameStr, commandID, "assigned", clientMsg)
|
||||
|
||||
assigned = true
|
||||
@@ -611,12 +595,13 @@ func ValidateBasket(c *gin.Context) {
|
||||
// ============================================
|
||||
newBalance, _ := database.GetClientReferralBalance(usernameStr)
|
||||
resp := gin.H{
|
||||
"success": true,
|
||||
"command_id": commandID,
|
||||
"delivery_address": req.DeliveryAddress,
|
||||
"status": "pending",
|
||||
"referral_used": referralUsed,
|
||||
"referral_balance": newBalance,
|
||||
"success": true,
|
||||
"command_id": commandID,
|
||||
"client_order_number": command.ClientOrderID,
|
||||
"delivery_address": req.DeliveryAddress,
|
||||
"status": "pending",
|
||||
"referral_used": referralUsed,
|
||||
"referral_balance": newBalance,
|
||||
}
|
||||
|
||||
if assigned {
|
||||
@@ -631,7 +616,7 @@ func ValidateBasket(c *gin.Context) {
|
||||
log.Printf("✅ [CHECKOUT] Réponse 200 - Commande %d en attente", commandID)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, resp)
|
||||
c.JSON(http.StatusCreated, resp)
|
||||
}
|
||||
|
||||
// getBaseURL construit l'URL de base depuis la requête en cours
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"gestion/db"
|
||||
"gestion/services"
|
||||
"gestion/utils"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -94,10 +95,7 @@ func AutoAssignNextCommand(c *gin.Context) {
|
||||
|
||||
err = database.AutoAssignCommand(nextCommand.CommandID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de l'assignation automatique",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de l'assignation automatique", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -137,12 +135,8 @@ func UpdateLivreurLocation(c *gin.Context) {
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides - latitude et longitude requises",
|
||||
"details": err.Error(),
|
||||
"format": gin.H{
|
||||
"latitude": "number (required)",
|
||||
"longitude": "number (required)",
|
||||
},
|
||||
"error": "Données invalides - latitude et longitude requises",
|
||||
"format": gin.H{"latitude": "number (required)", "longitude": "number (required)"},
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -169,10 +163,7 @@ func UpdateLivreurLocation(c *gin.Context) {
|
||||
// ✅ 1. Mettre à jour la position GPS dans Redis
|
||||
err := database.UpdateDeliveryPersonLocation(usernameStr, req.Latitude, req.Longitude)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la mise à jour de la position",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la mise à jour de la position", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -251,7 +242,6 @@ func GetMyLocation(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Position non disponible",
|
||||
"details": err.Error(),
|
||||
"message": "Veuillez d'abord mettre à jour votre position",
|
||||
})
|
||||
return
|
||||
@@ -286,10 +276,7 @@ func GetDeliveryPersonLocation(c *gin.Context) {
|
||||
|
||||
position, err := database.GetLivreurPosition(username)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Position non trouvée pour ce livreur",
|
||||
"details": err.Error(),
|
||||
})
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Position non trouvée pour ce livreur"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -373,7 +360,6 @@ func GetDeliverymanLocationForCommand(c *gin.Context) {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "Position du livreur non disponible",
|
||||
"details": err.Error(),
|
||||
"message": "Le livreur n'a pas encore partagé sa position",
|
||||
"command_info": gin.H{
|
||||
"command_id": commandID,
|
||||
@@ -501,10 +487,7 @@ func UpdateDeliveryPersonStatus(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -531,10 +514,7 @@ func UpdateDeliveryPersonStatus(c *gin.Context) {
|
||||
|
||||
err := database.SetDeliveryPersonStatus(usernameStr, req.Status, 0)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la mise à jour du statut",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la mise à jour du statut", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -613,10 +593,7 @@ func GetMyQueue(c *gin.Context) {
|
||||
|
||||
queueInfo, err := database.GetDeliverymanQueueInfo(usernameStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur récupération de la queue",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur récupération de la queue", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -640,10 +617,7 @@ func GetAvailableDeliveryPersonsRealtime(c *gin.Context) {
|
||||
|
||||
livreurs, err := database.GetAvailableDeliveryPersonsRedis()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des livreurs",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération des livreurs", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -687,10 +661,7 @@ func SetCommandETAHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.BindErr(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -724,10 +695,7 @@ func SetCommandETAHandler(c *gin.Context) {
|
||||
// Mettre à jour l'ETA dans Redis
|
||||
err = database.SetCommandETA(commandID, req.ETAMinutes)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la mise à jour de l'ETA",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la mise à jour de l'ETA", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -830,10 +798,7 @@ func GetMyPenalties(c *gin.Context) {
|
||||
// ✅ UTILISE LA MÉTHODE DÉDIÉE GetClientPenaltiesInfo
|
||||
penaltiesInfo, err := database.GetClientPenaltiesInfo(usernameStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des pénalités",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération des pénalités", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -869,10 +834,7 @@ func GetClientPenaltiesAdmin(c *gin.Context) {
|
||||
// ✅ UTILISE GetClientPenaltiesInfo
|
||||
penaltiesInfo, err := database.GetClientPenaltiesInfo(username)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des pénalités",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération des pénalités", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -896,10 +858,7 @@ func GetAllClientsWithPenalties(c *gin.Context) {
|
||||
// ✅ UTILISE GetAllClientsWithPenalties
|
||||
clients, err := database.GetAllClientsWithPenalties()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des clients",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération des clients", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -926,10 +885,7 @@ func GetPenaltiesStats(c *gin.Context) {
|
||||
// ✅ UTILISE GetClientPenaltiesStats
|
||||
stats, err := database.GetClientPenaltiesStats()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la récupération des statistiques",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la récupération des statistiques", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -970,10 +926,7 @@ func ResetClientPointAdmin(c *gin.Context) {
|
||||
|
||||
err := database.ResetClientPoint(username, req.Pool, extraPoolKey)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la réinitialisation",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la réinitialisation", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1008,10 +961,7 @@ func ResetClientPenaltiesAdmin(c *gin.Context) {
|
||||
// ✅ UTILISE ResetClientPenalties
|
||||
err := database.ResetClientPenalties(username, req.ResetCancellationsCount)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur lors de la réinitialisation",
|
||||
"details": err.Error(),
|
||||
})
|
||||
utils.ServerErr(c, "Erreur lors de la réinitialisation", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"gestion/db"
|
||||
"gestion/utils"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
@@ -26,7 +27,7 @@ func GetMyReferralBalance(c *gin.Context) {
|
||||
|
||||
balance, err := database.GetClientReferralBalance(username.(string))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Solde de parrainage introuvable"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,8 +48,7 @@ func CreditClientReferralAdmin(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := database.CreditClientReferral(targetUsername, req.Amount); err != nil {
|
||||
log.Printf("❌ [REFERRAL] Crédit échoué pour %s: %v", targetUsername, err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
utils.ServerErr(c, "Impossible de créditer le solde", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func GetClientReferralAdmin(c *gin.Context) {
|
||||
|
||||
balance, err := database.GetClientReferralBalance(targetUsername)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Client introuvable"})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ func GetPublicSettings(c *gin.Context) {
|
||||
"pool_names": poolNames,
|
||||
"pool_keys": poolKeys,
|
||||
"referral_enabled": settings.ReferralEnabled,
|
||||
"referral_amount": settings.ReferralAmount,
|
||||
"delivery_schedule": settings.DeliverySchedule,
|
||||
"crypto_payment_enabled": settings.CryptoPaymentEnabled,
|
||||
"crypto_only": settings.CryptoOnly,
|
||||
|
||||
@@ -34,7 +34,6 @@ func UpdateMyProfile(c *gin.Context) {
|
||||
log.Printf("❌ [UPDATE_MY_PROFILE] Erreur binding: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -186,7 +185,6 @@ func UpdateClientByAdmin(c *gin.Context) {
|
||||
log.Printf("❌ [UPDATE_CLIENT_ADMIN] Erreur binding: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Données invalides",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -56,7 +57,6 @@ func ValidateDeliveryByLivreur(c *gin.Context) {
|
||||
log.Printf("❌ [VALIDATE_LIVREUR] Erreur JSON: %v", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Coordonnées GPS requises",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -99,7 +99,6 @@ func ValidateDeliveryByLivreur(c *gin.Context) {
|
||||
log.Printf("❌ [VALIDATE_LIVREUR] Erreur update statut: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur validation",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -299,7 +298,6 @@ func StartDelivery(c *gin.Context) {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "Coordonnées GPS requises",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -336,7 +334,6 @@ func StartDelivery(c *gin.Context) {
|
||||
if err := database.UpdateCommandStatus(commandID, "en_route"); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Erreur mise à jour statut",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -354,7 +351,7 @@ func StartDelivery(c *gin.Context) {
|
||||
|
||||
// Notifier le client
|
||||
if clientUsername, _ := command["username"].(string); clientUsername != "" {
|
||||
msg := fmt.Sprintf("🛵 Votre commande #%d est en route !", commandID)
|
||||
msg := fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route.", database.GetClientOrderID(commandID))
|
||||
database.NotifyClient(clientUsername, commandID, "en_route", msg)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user