chore: build
This commit is contained in:
@@ -263,6 +263,62 @@ func RespondToAddressProposal(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateOwnCommandAddress permet à un client de corriger l'adresse de sa
|
||||
// propre commande (ex: suite à un échec de géocodage bloquant l'assignation
|
||||
// auto). Refusé si la commande est déjà en_route ou terminée (voir requête
|
||||
// SQL dans db.UpdateOwnCommandAddress).
|
||||
func UpdateOwnCommandAddress(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
geoService := c.MustGet("geoService").(*services.GeoService)
|
||||
|
||||
userRole := c.GetString("role")
|
||||
if !utils.CheckRoleClient(c, userRole) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
|
||||
return
|
||||
}
|
||||
clientUsername, err := safeGetUsername(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentification requise"})
|
||||
return
|
||||
}
|
||||
|
||||
rateLimitKey := fmt.Sprintf("update_own_addr:%s", clientUsername)
|
||||
if !checkRateLimit(rateLimitKey) {
|
||||
c.JSON(http.StatusTooManyRequests, gin.H{"error": "Trop de requêtes, réessayez plus tard"})
|
||||
return
|
||||
}
|
||||
|
||||
commandID, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil || commandID <= 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID de commande invalide"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
DeliveryAddress string `json:"delivery_address" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides"})
|
||||
return
|
||||
}
|
||||
|
||||
if !geoService.IsValidAddress(req.DeliveryAddress) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Adresse introuvable, vérifiez l'orthographe ou le code postal"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.UpdateOwnCommandAddress(commandID, clientUsername, req.DeliveryAddress); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("✅ [UPD_OWN_ADDR] Commande %d mise à jour par %s", commandID, clientUsername)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "Adresse mise à jour",
|
||||
})
|
||||
}
|
||||
|
||||
func ExportApprovedCommandsCSV(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gestion/db"
|
||||
"gestion/services"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -30,6 +32,7 @@ const (
|
||||
// POST /api/v1/deliveries/:id/start
|
||||
func StartDelivery(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
geoService := c.MustGet("geoService").(*services.GeoService)
|
||||
|
||||
username, exists := c.Get("username")
|
||||
if !exists || c.GetString("role") != "livreur" {
|
||||
@@ -114,11 +117,47 @@ func StartDelivery(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if etaMinutes == 0 && req.Latitude != 0 && req.Longitude != 0 {
|
||||
if etaMinutes == 0 {
|
||||
destLat, _ := command["dest_latitude"].(float64)
|
||||
destLon, _ := command["dest_longitude"].(float64)
|
||||
|
||||
// Fallback 1 : cache Redis (géocodage déjà fait à l'assignation
|
||||
// mais pas encore persisté en DB — cf. goroutine async dans
|
||||
// handlers/commands.go AssignCommandToDeliveryman).
|
||||
if destLat == 0 || destLon == 0 {
|
||||
destCacheKey := fmt.Sprintf("command:destination:%d", commandID)
|
||||
if destData, err := db.Redis.Get(db.RedisCtx, destCacheKey).Result(); err == nil && destData != "" {
|
||||
var coords struct {
|
||||
Lat float64 `json:"lat"`
|
||||
Lon float64 `json:"lon"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(destData), &coords); err == nil && coords.Lat != 0 && coords.Lon != 0 {
|
||||
destLat, destLon = coords.Lat, coords.Lon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback 2 : géocodage synchrone de l'adresse. Couvre le cas où
|
||||
// le livreur démarre la livraison avant que la goroutine async
|
||||
// d'assignation ait fini de géocoder (race condition).
|
||||
if (destLat == 0 || destLon == 0) && geoService != nil {
|
||||
if adresse, _ := command["adresse"].(string); adresse != "" {
|
||||
if location, err := geoService.GeocodeAddress(adresse); err == nil && location != nil {
|
||||
destLat, destLon = location.Latitude, location.Longitude
|
||||
database.GDB.Exec(
|
||||
"UPDATE commandes SET dest_latitude = ?, dest_longitude = ? WHERE id = ?",
|
||||
destLat, destLon, commandID,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if destLat != 0 && destLon != 0 {
|
||||
etaMinutes = database.CalculateETAForDeliveryman(usernameStr, destLat, destLon)
|
||||
} else {
|
||||
// Fallback 3 : aucune coordonnée exploitable — ETA par
|
||||
// défaut plutôt que pas d'ETA du tout dans le message.
|
||||
etaMinutes = 30
|
||||
}
|
||||
}
|
||||
if etaMinutes > 0 {
|
||||
|
||||
Reference in New Issue
Block a user