chore: refacto
This commit is contained in:
@@ -347,6 +347,18 @@ func (d *Database) CheckBasketReservations(username string) (bool, error) {
|
|||||||
return result.Count > 0, nil
|
return result.Count > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Database) GetBasketItemOwner(basketID int) (string, error) {
|
||||||
|
var username string
|
||||||
|
err := d.GDB.Raw(`SELECT username FROM baskets WHERE id = ?`, basketID).Scan(&username).Error
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if username == "" {
|
||||||
|
return "", fmt.Errorf("article non trouvé")
|
||||||
|
}
|
||||||
|
return username, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Database) GetBasketItems(username string) ([]map[string]any, error) {
|
func (d *Database) GetBasketItems(username string) ([]map[string]any, error) {
|
||||||
var items []map[string]any
|
var items []map[string]any
|
||||||
if err := d.GDB.Raw(`SELECT product_id, quantity::float8 as quantity, price::float8 as price FROM baskets WHERE username = ?`,
|
if err := d.GDB.Raw(`SELECT product_id, quantity::float8 as quantity, price::float8 as price FROM baskets WHERE username = ?`,
|
||||||
|
|||||||
@@ -134,8 +134,11 @@ func (d *Database) CalculateETAForDeliveryman(deliveryman string, destLat, destL
|
|||||||
Longitude: destLng,
|
Longitude: destLng,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eta, _, err2 := services.CalculateETAWithTomTom(from, to)
|
||||||
|
if err2 != nil {
|
||||||
distance := services.CalculateDistance(from, to)
|
distance := services.CalculateDistance(from, to)
|
||||||
eta := services.CalculateETA(distance)
|
eta = services.CalculateETA(distance)
|
||||||
|
}
|
||||||
|
|
||||||
return eta
|
return eta
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// NETTOYAGE DES COMMANDES INVALIDES
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
// CleanupInvalidQueueCommands supprime toutes les commandes avec des données manquantes
|
// CleanupInvalidQueueCommands supprime toutes les commandes avec des données manquantes
|
||||||
func (d *Database) CleanupInvalidQueueCommands() (int, error) {
|
func (d *Database) CleanupInvalidQueueCommands() (int, error) {
|
||||||
log.Println("🧹 [CLEANUP] Démarrage du nettoyage des commandes invalides...")
|
log.Println("🧹 [CLEANUP] Démarrage du nettoyage des commandes invalides...")
|
||||||
@@ -42,7 +38,6 @@ func (d *Database) CleanupInvalidQueueCommands() (int, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ VALIDATION DES CHAMPS REQUIS
|
|
||||||
isValid := true
|
isValid := true
|
||||||
reasons := []string{}
|
reasons := []string{}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"gestion/utils"
|
"gestion/utils"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -68,7 +69,6 @@ func validateAddress(address string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCommandAddress met à jour l'adresse de livraison d'une commande
|
|
||||||
func UpdateCommandAddress(c *gin.Context) {
|
func UpdateCommandAddress(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
@@ -78,14 +78,12 @@ func UpdateCommandAddress(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Récupération sécurisée du username
|
|
||||||
adminUsername, err := safeGetUsername(c)
|
adminUsername, err := safeGetUsername(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Rate limiting
|
|
||||||
rateLimitKey := fmt.Sprintf("update_addr:%s", adminUsername)
|
rateLimitKey := fmt.Sprintf("update_addr:%s", adminUsername)
|
||||||
if !checkRateLimit(rateLimitKey) {
|
if !checkRateLimit(rateLimitKey) {
|
||||||
log.Printf("⚠️ [UPD_ADDR] Rate limit dépassé pour %s", adminUsername)
|
log.Printf("⚠️ [UPD_ADDR] Rate limit dépassé pour %s", adminUsername)
|
||||||
@@ -184,7 +182,6 @@ func ProposeAddressChange(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupérer la commande pour vérifier statut et obtenir username client
|
|
||||||
command, err := database.GetCommandByID(commandID)
|
command, err := database.GetCommandByID(commandID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"})
|
c.JSON(http.StatusNotFound, gin.H{"error": "Commande non trouvée"})
|
||||||
@@ -202,7 +199,6 @@ func ProposeAddressChange(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifier le client
|
|
||||||
clientUsername, _ := command["username"].(string)
|
clientUsername, _ := command["username"].(string)
|
||||||
if clientUsername != "" {
|
if clientUsername != "" {
|
||||||
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)
|
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)
|
||||||
@@ -287,8 +283,6 @@ func GetAllCommands(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("🔍 [GET_CMDS] Filtre - status=[%s], username=[%s]", status, username)
|
|
||||||
|
|
||||||
commands, err := database.GetAllCommands(status, username)
|
commands, err := database.GetAllCommands(status, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ [GET_CMDS] Erreur: %v", err)
|
log.Printf("❌ [GET_CMDS] Erreur: %v", err)
|
||||||
@@ -297,13 +291,8 @@ func GetAllCommands(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ MODIFICATION: Pour le count, utiliser len(commands) au lieu de GetCommandCount()
|
|
||||||
// Cela permet d'avoir le vrai nombre de commandes retournées
|
|
||||||
countCommand := len(commands)
|
countCommand := len(commands)
|
||||||
|
|
||||||
log.Printf("✅ [GET_CMDS] Trouvées: %d commandes", countCommand)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"commands": commands,
|
"commands": commands,
|
||||||
@@ -312,7 +301,6 @@ func GetAllCommands(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCommandByID récupère une commande complète avec logs
|
// GetCommandByID récupère une commande complète avec logs
|
||||||
// GET /api/v1/commands/:id
|
|
||||||
func GetCommandByID(c *gin.Context) {
|
func GetCommandByID(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
@@ -338,17 +326,14 @@ func GetCommandByID(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ CRITIQUE: Vérification de propriété
|
|
||||||
cmdUsername, _ := command["username"].(string)
|
cmdUsername, _ := command["username"].(string)
|
||||||
|
|
||||||
// Seuls l'admin, la cabine ou le propriétaire peuvent voir la commande
|
|
||||||
if userRole != "admin" && userRole != "cabine" && cmdUsername != username {
|
if userRole != "admin" && userRole != "cabine" && cmdUsername != username {
|
||||||
log.Printf("❌ [GET_CMD] Accès refusé - User %s tente d'accéder à cmd de %s", username, cmdUsername)
|
log.Printf("❌ [GET_CMD] Accès refusé - User %s tente d'accéder à cmd de %s", username, cmdUsername)
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
|
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Logs uniquement pour admin/cabine
|
|
||||||
if userRole == "admin" || userRole == "cabine" {
|
if userRole == "admin" || userRole == "cabine" {
|
||||||
logs, err := database.GetCommandLogs(commandID)
|
logs, err := database.GetCommandLogs(commandID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -373,7 +358,6 @@ func ApproveDelivery(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Rate limiting
|
|
||||||
rateLimitKey := fmt.Sprintf("approve:%s", username)
|
rateLimitKey := fmt.Sprintf("approve:%s", username)
|
||||||
if !checkRateLimit(rateLimitKey) {
|
if !checkRateLimit(rateLimitKey) {
|
||||||
c.JSON(http.StatusTooManyRequests, gin.H{"error": "Trop de requêtes"})
|
c.JSON(http.StatusTooManyRequests, gin.H{"error": "Trop de requêtes"})
|
||||||
@@ -387,13 +371,9 @@ func ApproveDelivery(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("✅ [APPROVE] Client %s approuve cmd %d", username, commandID)
|
log.Printf("✅ [APPROVE] Client %s approuve cmd %d", username, commandID)
|
||||||
|
|
||||||
// ✅ TRANSACTION ATOMIQUE dans la DB pour éviter race condition
|
|
||||||
// Cette fonction doit être créée dans le fichier db
|
|
||||||
totalPoints, pointCategory, err := database.ApproveDeliveryAtomic(commandID, username)
|
totalPoints, pointCategory, err := database.ApproveDeliveryAtomic(commandID, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ [APPROVE] Erreur: %v", err)
|
log.Printf("❌ [APPROVE] Erreur: %v", err)
|
||||||
// ❌ Ne pas exposer les détails de l'erreur
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "Impossible d'approuver la livraison",
|
"error": "Impossible d'approuver la livraison",
|
||||||
})
|
})
|
||||||
@@ -536,15 +516,7 @@ func ValidateDelivery(c *gin.Context) {
|
|||||||
currentStatus, _ := command["status"].(string)
|
currentStatus, _ := command["status"].(string)
|
||||||
|
|
||||||
validStatuses := []string{"assigned", "en_route", "pending", "livre"}
|
validStatuses := []string{"assigned", "en_route", "pending", "livre"}
|
||||||
isValid := false
|
if !slices.Contains(validStatuses, currentStatus) {
|
||||||
for _, s := range validStatuses {
|
|
||||||
if currentStatus == s {
|
|
||||||
isValid = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isValid {
|
|
||||||
failed = append(failed, gin.H{
|
failed = append(failed, gin.H{
|
||||||
"command_id": commandID,
|
"command_id": commandID,
|
||||||
"error": "Statut invalide pour validation",
|
"error": "Statut invalide pour validation",
|
||||||
@@ -811,18 +783,12 @@ func NotifyClientToDescend(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// DÉTAILS COMMANDES & ITEMS
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
// ShowItems affiche les items d'une commande (Admin/Cabine)
|
// ShowItems affiche les items d'une commande (Admin/Cabine)
|
||||||
// GET /api/v1/admin/commands/:id/items
|
|
||||||
func ShowItems(c *gin.Context) {
|
func ShowItems(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
userRole := c.GetString("role")
|
userRole := c.GetString("role")
|
||||||
|
|
||||||
// ✅ SÉCURITÉ: Admin ou Cabine seulement
|
|
||||||
if userRole != "admin" && userRole != "cabine" {
|
if userRole != "admin" && userRole != "cabine" {
|
||||||
log.Printf("❌ [ITEMS] Accès refusé - role=%s", userRole)
|
log.Printf("❌ [ITEMS] Accès refusé - role=%s", userRole)
|
||||||
c.JSON(http.StatusForbidden, gin.H{
|
c.JSON(http.StatusForbidden, gin.H{
|
||||||
@@ -860,7 +826,7 @@ func ShowItems(c *gin.Context) {
|
|||||||
log.Printf("⚠️ [ITEMS] Aucun item trouvé")
|
log.Printf("⚠️ [ITEMS] Aucun item trouvé")
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": true,
|
"success": true,
|
||||||
"items": []map[string]interface{}{},
|
"items": []map[string]any{},
|
||||||
"count": 0,
|
"count": 0,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -868,7 +834,7 @@ func ShowItems(c *gin.Context) {
|
|||||||
|
|
||||||
log.Printf("✅ [ITEMS] %d items récupérés", len(items))
|
log.Printf("✅ [ITEMS] %d items récupérés", len(items))
|
||||||
|
|
||||||
commandInfo := map[string]interface{}{
|
commandInfo := map[string]any{
|
||||||
"id": items[0]["command_id"],
|
"id": items[0]["command_id"],
|
||||||
"status": items[0]["command_status"],
|
"status": items[0]["command_status"],
|
||||||
"address": items[0]["command_address"],
|
"address": items[0]["command_address"],
|
||||||
@@ -878,7 +844,7 @@ func ShowItems(c *gin.Context) {
|
|||||||
"created_at": items[0]["command_created_at"],
|
"created_at": items[0]["command_created_at"],
|
||||||
}
|
}
|
||||||
|
|
||||||
clientInfo := map[string]interface{}{
|
clientInfo := map[string]any{
|
||||||
"username": items[0]["client_username"],
|
"username": items[0]["client_username"],
|
||||||
"nom": items[0]["client_nom"],
|
"nom": items[0]["client_nom"],
|
||||||
"prenom": items[0]["client_prenom"],
|
"prenom": items[0]["client_prenom"],
|
||||||
@@ -895,11 +861,9 @@ func ShowItems(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCommandItemsWithDetails récupère les items enrichis
|
// GetCommandItemsWithDetails récupère les items enrichis
|
||||||
// GET /api/v1/commands/:id/items/detailed
|
|
||||||
func GetCommandItemsWithDetails(c *gin.Context) {
|
func GetCommandItemsWithDetails(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
// 🔐 Auth obligatoire
|
|
||||||
username, exists := c.Get("username")
|
username, exists := c.Get("username")
|
||||||
if !exists {
|
if !exists {
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||||
@@ -919,7 +883,6 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
|||||||
log.Printf("📦 [ITEMS_DETAILED] User=%s Role=%s Cmd=%d",
|
log.Printf("📦 [ITEMS_DETAILED] User=%s Role=%s Cmd=%d",
|
||||||
usernameStr, userRole, commandID)
|
usernameStr, userRole, commandID)
|
||||||
|
|
||||||
// 🔒 ÉTAPE 1 — Vérifier l'accès à la commande
|
|
||||||
allowed, err := database.CanUserAccessCommand(commandID, usernameStr, userRole)
|
allowed, err := database.CanUserAccessCommand(commandID, usernameStr, userRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ [ITEMS_DETAILED] Erreur vérif accès: %v", err)
|
log.Printf("❌ [ITEMS_DETAILED] Erreur vérif accès: %v", err)
|
||||||
@@ -937,7 +900,6 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔓 ÉTAPE 2 — Accès autorisé, récupérer les items
|
|
||||||
items, err := database.GetCommandItems(commandID)
|
items, err := database.GetCommandItems(commandID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ [ITEMS_DETAILED] Erreur DB: %v", err)
|
log.Printf("❌ [ITEMS_DETAILED] Erreur DB: %v", err)
|
||||||
@@ -954,7 +916,7 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
commandInfo := map[string]interface{}{
|
commandInfo := map[string]any{
|
||||||
"id": items[0]["command_id"],
|
"id": items[0]["command_id"],
|
||||||
"command_status": items[0]["command_status"],
|
"command_status": items[0]["command_status"],
|
||||||
"command_address": items[0]["command_address"],
|
"command_address": items[0]["command_address"],
|
||||||
@@ -979,8 +941,6 @@ func GetCommandItemsWithDetails(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateItemStatus met à jour le statut d'un item
|
|
||||||
// PUT /api/v1/admin/items/:item_id/status
|
|
||||||
func UpdateItemStatus(c *gin.Context) {
|
func UpdateItemStatus(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|
||||||
@@ -1006,15 +966,7 @@ func UpdateItemStatus(c *gin.Context) {
|
|||||||
log.Printf("📝 [UPD_ITEM] Mise à jour: item=%d, status=%s", itemID, req.Status)
|
log.Printf("📝 [UPD_ITEM] Mise à jour: item=%d, status=%s", itemID, req.Status)
|
||||||
|
|
||||||
validStatuses := []string{"pending", "preparing", "delivered"}
|
validStatuses := []string{"pending", "preparing", "delivered"}
|
||||||
isValid := false
|
if !slices.Contains(validStatuses, req.Status) {
|
||||||
for _, vs := range validStatuses {
|
|
||||||
if req.Status == vs {
|
|
||||||
isValid = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isValid {
|
|
||||||
log.Printf("❌ [UPD_ITEM] Statut invalide: %s", req.Status)
|
log.Printf("❌ [UPD_ITEM] Statut invalide: %s", req.Status)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "Statut invalide",
|
"error": "Statut invalide",
|
||||||
@@ -1043,7 +995,6 @@ func UpdateItemStatus(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteCommandItem supprime un item d'une commande
|
|
||||||
// DELETE /api/v2/admin/protected/orders/:id/items/:item_id
|
// DELETE /api/v2/admin/protected/orders/:id/items/:item_id
|
||||||
func DeleteCommandItem(c *gin.Context) {
|
func DeleteCommandItem(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
@@ -1092,7 +1043,6 @@ func DeleteCommandItem(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateCommandStatusAdmin met à jour le statut d'une commande (Admin)
|
|
||||||
// PUT /api/v2/admin/protected/orders/:id/status
|
// PUT /api/v2/admin/protected/orders/:id/status
|
||||||
func UpdateCommandStatusAdmin(c *gin.Context) {
|
func UpdateCommandStatusAdmin(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
|||||||
@@ -179,11 +179,7 @@ func DeleteProductFromBasket(c *gin.Context) {
|
|||||||
log.Printf("🗑️ [DEL_PANIER] Suppression article: id=%d, client=%s", req.ID, authUsernameStr)
|
log.Printf("🗑️ [DEL_PANIER] Suppression article: id=%d, client=%s", req.ID, authUsernameStr)
|
||||||
|
|
||||||
// ✅ SÉCURITÉ 2: Vérifier que l'article appartient à ce client
|
// ✅ SÉCURITÉ 2: Vérifier que l'article appartient à ce client
|
||||||
var itemUsername string
|
itemUsername, err := database.GetBasketItemOwner(req.ID)
|
||||||
err := database.QueryRow(
|
|
||||||
"SELECT username FROM baskets WHERE id = $1",
|
|
||||||
req.ID,
|
|
||||||
).Scan(&itemUsername)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("❌ [DEL_PANIER] Article non trouvé: id=%d", req.ID)
|
log.Printf("❌ [DEL_PANIER] Article non trouvé: id=%d", req.ID)
|
||||||
@@ -260,12 +256,7 @@ func ClearBasket(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// ✅ SÉCURISÉ: ValidateBasket - CHECKOUT FINAL
|
|
||||||
// ============================================
|
|
||||||
// POST /api/v1/checkout
|
// POST /api/v1/checkout
|
||||||
// Crée la commande depuis le panier et le vide
|
|
||||||
// ⚠️ SEUL ENDPOINT DE CRÉATION DE COMMANDE (CreateCommandFromBasket supprimé)
|
|
||||||
func ValidateBasket(c *gin.Context) {
|
func ValidateBasket(c *gin.Context) {
|
||||||
database := c.MustGet("database").(*db.Database)
|
database := c.MustGet("database").(*db.Database)
|
||||||
geoService := c.MustGet("geoService").(*services.GeoService)
|
geoService := c.MustGet("geoService").(*services.GeoService)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -351,7 +350,32 @@ func StartDelivery(c *gin.Context) {
|
|||||||
|
|
||||||
// Notifier le client
|
// Notifier le client
|
||||||
if clientUsername, _ := command["username"].(string); clientUsername != "" {
|
if clientUsername, _ := command["username"].(string); clientUsername != "" {
|
||||||
msg := fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route.", database.GetClientOrderID(commandID))
|
var msg string
|
||||||
|
etaMinutes := 0
|
||||||
|
if req.Latitude != 0 && req.Longitude != 0 {
|
||||||
|
destLat, _ := command["dest_latitude"].(float64)
|
||||||
|
destLon, _ := command["dest_longitude"].(float64)
|
||||||
|
if destLat != 0 && destLon != 0 {
|
||||||
|
etaMinutes = database.CalculateETAForDeliveryman(usernameStr, destLat, destLon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if etaMinutes > 0 {
|
||||||
|
var etaStr string
|
||||||
|
if etaMinutes >= 60 {
|
||||||
|
h := etaMinutes / 60
|
||||||
|
m := etaMinutes % 60
|
||||||
|
if m > 0 {
|
||||||
|
etaStr = fmt.Sprintf("%dh%02d", h, m)
|
||||||
|
} else {
|
||||||
|
etaStr = fmt.Sprintf("%dh", h)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
etaStr = fmt.Sprintf("%d min", etaMinutes)
|
||||||
|
}
|
||||||
|
msg = fmt.Sprintf("Un livreur vient de prendre en charge ta commande #%d, il est en route (~%s)", database.GetClientOrderID(commandID), etaStr)
|
||||||
|
} else {
|
||||||
|
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)
|
database.NotifyClient(clientUsername, commandID, "en_route", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ func StartAutoAssignmentCron(database *db.Database, geoService *services.GeoServ
|
|||||||
|
|
||||||
log.Println("⏰ [CRON] Auto-Assignment Worker démarré (1 min) avec système de priorisation")
|
log.Println("⏰ [CRON] Auto-Assignment Worker démarré (1 min) avec système de priorisation")
|
||||||
|
|
||||||
// Exécution immédiate au démarrage
|
|
||||||
go processAutoAssignmentWithPriority(database, geoService)
|
go processAutoAssignmentWithPriority(database, geoService)
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
|
|||||||
Reference in New Issue
Block a user