This commit is contained in:
@@ -290,11 +290,16 @@ func RespondToAddressProposal(c *gin.Context) {
|
||||
|
||||
// La colonne proposed_address est vidée par RespondToAddressProposal dès
|
||||
// qu'elle est traitée : on la lit avant l'appel pour pouvoir regéocoder la
|
||||
// nouvelle adresse en cas d'acceptation.
|
||||
// nouvelle adresse en cas d'acceptation. On récupère aussi le livreur
|
||||
// assigné : ProposeAddressChange autorise un changement d'adresse même en
|
||||
// "en_route" (voir commands.go ~L236-240), donc un livreur peut déjà être
|
||||
// en train de rouler vers l'ancienne adresse au moment de l'acceptation.
|
||||
var proposedAddress string
|
||||
var livreurAssign string
|
||||
if req.Accepted {
|
||||
if command, err := database.GetCommandByID(commandID); err == nil {
|
||||
proposedAddress, _ = command["proposed_address"].(string)
|
||||
livreurAssign, _ = command["livreur_assign"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,6 +310,19 @@ func RespondToAddressProposal(c *gin.Context) {
|
||||
|
||||
if req.Accepted && proposedAddress != "" {
|
||||
updateCommandDestinationCoords(database, geoService, commandID, proposedAddress)
|
||||
|
||||
// L'ETA en cache correspond au trajet vers l'ancienne destination —
|
||||
// on l'invalide pour forcer un recalcul sur les nouvelles coordonnées.
|
||||
db.Redis.Del(db.RedisCtx, fmt.Sprintf("command:eta:%d", commandID))
|
||||
|
||||
// Sans cette notification, le livreur déjà en route continuerait à
|
||||
// naviguer vers l'ancienne adresse sans savoir que la destination a
|
||||
// changé en base.
|
||||
if livreurAssign != "" {
|
||||
clientOrderID := database.GetClientOrderID(commandID)
|
||||
livreurMsg := fmt.Sprintf("⚠️ Le client a changé l'adresse de livraison de la commande #%d : %s. Merci de mettre à jour votre itinéraire.", clientOrderID, proposedAddress)
|
||||
database.NotifyLivreur(livreurAssign, commandID, "address_changed", livreurMsg)
|
||||
}
|
||||
}
|
||||
|
||||
action := "refusée"
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"gestion/db"
|
||||
"gestion/handlers"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Si le livreur est déjà en route quand le client accepte une proposition
|
||||
// d'adresse (ProposeAddressChange autorise ce cas même en "en_route" — voir
|
||||
// commands.go ~L236-240), il doit être notifié que la destination a changé,
|
||||
// sans quoi il continuerait à naviguer vers l'ancienne adresse alors que la
|
||||
// nouvelle est déjà enregistrée en base (voir RespondToAddressProposal).
|
||||
func TestRespondToAddressProposal_NotifiesLivreurWhenAlreadyEnRoute(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("appelle le vrai service Nominatim en réseau — sauté en mode -short")
|
||||
}
|
||||
cleanupStockTestData(t)
|
||||
username := newTestClient(t, "respond_addr_notif_client")
|
||||
livreur := newTestClient(t, "respond_addr_notif_livreur")
|
||||
productID := newTestProduct(t, "RespondAddrNotif", 10)
|
||||
cmdID := newTestCommandWithItem(t, username, "en_route", livreur, productID, 1, 10)
|
||||
|
||||
if err := testDB.ProposeAddressChange(cmdID, "12 rue Crebillon, 44000 Nantes", "admin_test"); err != nil {
|
||||
t.Fatalf("ProposeAddressChange: %v", err)
|
||||
}
|
||||
|
||||
notifKey := fmt.Sprintf("notifications:%s", livreur)
|
||||
db.Redis.Del(db.RedisCtx, notifKey)
|
||||
|
||||
body := []byte(`{"accepted":true}`)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/commands/address/respond", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = req
|
||||
c.Set("database", testDB)
|
||||
c.Set("geoService", ensureTestGeoService())
|
||||
c.Set("username", username)
|
||||
c.Set("role", "client")
|
||||
c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", cmdID)}}
|
||||
|
||||
handlers.RespondToAddressProposal(c)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("RespondToAddressProposal doit réussir: got=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
|
||||
entries, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, -1).Result()
|
||||
if err != nil {
|
||||
t.Fatalf("lecture notifications livreur: %v", err)
|
||||
}
|
||||
var found bool
|
||||
for _, raw := range entries {
|
||||
var notif struct {
|
||||
CommandID int `json:"command_id"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(raw), ¬if); err == nil && notif.CommandID == cmdID && notif.Type == "address_changed" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("le livreur déjà en route doit être notifié du changement d'adresse (type=address_changed, command_id=%d): notifications=%v", cmdID, entries)
|
||||
}
|
||||
}
|
||||
|
||||
// Si aucun livreur n'est assigné, il ne doit évidemment pas y avoir de
|
||||
// notification livreur envoyée (pas de panique/erreur non plus).
|
||||
func TestRespondToAddressProposal_NoLivreurNotificationWhenNoneAssigned(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("appelle le vrai service Nominatim en réseau — sauté en mode -short")
|
||||
}
|
||||
cleanupStockTestData(t)
|
||||
username := newTestClient(t, "respond_addr_notif_nolivreur")
|
||||
productID := newTestProduct(t, "RespondAddrNotifNoLivreur", 10)
|
||||
cmdID := newTestCommandWithItem(t, username, "pending", "", productID, 1, 10)
|
||||
|
||||
if err := testDB.ProposeAddressChange(cmdID, "12 rue Crebillon, 44000 Nantes", "admin_test"); err != nil {
|
||||
t.Fatalf("ProposeAddressChange: %v", err)
|
||||
}
|
||||
|
||||
body := []byte(`{"accepted":true}`)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/commands/address/respond", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = req
|
||||
c.Set("database", testDB)
|
||||
c.Set("geoService", ensureTestGeoService())
|
||||
c.Set("username", username)
|
||||
c.Set("role", "client")
|
||||
c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", cmdID)}}
|
||||
|
||||
handlers.RespondToAddressProposal(c)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("RespondToAddressProposal doit réussir: got=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user