package tests import ( "encoding/json" "net/http" "net/http/httptest" "testing" "gestion/handlers" "github.com/gin-gonic/gin" ) func myDeliveriesContext(username, status string) (*gin.Context, *httptest.ResponseRecorder) { url := "/api/v1/livreur/deliveries" if status != "" { url += "?status=" + status } req := httptest.NewRequest(http.MethodGet, url, nil) rec := httptest.NewRecorder() c, _ := gin.CreateTestContext(rec) c.Request = req c.Set("database", testDB) c.Set("username", username) c.Set("role", "livreur") return c, rec } // Le livreur doit voir qu'un article a bénéficié d'une promotion de prix // (promo_discount > 0), pour pouvoir justifier au client un montant total // inférieur au prix catalogue — voir GetDeliveryDetails/GetMyDeliveries // (backend/gestion/handlers/deleviry.go) et GetCommandItems/GetCommandItemsBatch // (backend/gestion/db/db_command_items.go). func TestGetDeliveryDetails_ExposesPromoDiscountPerItem(t *testing.T) { cleanupStockTestData(t) client := newTestClient(t, "delivpromo_client") livreur := newTestClient(t, "delivpromo_livreur") productID := newTestProduct(t, "DelivPromoDiscount", 20) // 3g normalement à 50€, facturés 25€ (-50%) : promo_discount = 25€. cmdID := newTestCommandWithItem(t, client, "en_route", livreur, productID, 3, 25) if err := testDB.GDB.Exec( `UPDATE command_items SET promo_discount = 25 WHERE command_id = ? AND product_id = ?`, cmdID, productID, ).Error; err != nil { t.Fatalf("mise à jour promo_discount: %v", err) } c, rec := deliveryDetailsContext(livreur, cmdID) handlers.GetDeliveryDetails(c) if rec.Code != http.StatusOK { t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String()) } var resp struct { Success bool `json:"success"` Delivery struct { Items []struct { Produit string `json:"produit"` Prix float64 `json:"prix"` PromoDiscount float64 `json:"promo_discount"` } `json:"items"` } `json:"delivery"` } if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { t.Fatalf("décodage réponse: %v body=%s", err, rec.Body.String()) } if !resp.Success || len(resp.Delivery.Items) != 1 { t.Fatalf("réponse inattendue: body=%s", rec.Body.String()) } item := resp.Delivery.Items[0] if item.PromoDiscount != 25 { t.Errorf("promo_discount doit être exposé au livreur: got=%.2f want=25.00 (body=%s)", item.PromoDiscount, rec.Body.String()) } if item.Prix != 25 { t.Errorf("le prix affiché doit rester le prix déjà réduit facturé: got=%.2f want=25.00", item.Prix) } } // Même vérification côté GetMyDeliveries (liste des livraisons), qui passe // par un chemin de requête différent (GetCommandItemsBatch) que // GetDeliveryDetails (GetCommandItems). func TestGetMyDeliveries_ExposesPromoDiscountPerItem(t *testing.T) { cleanupStockTestData(t) client := newTestClient(t, "delivpromo_list_client") livreur := newTestClient(t, "delivpromo_list_livreur") productID := newTestProduct(t, "DelivPromoListDiscount", 20) cmdID := newTestCommandWithItem(t, client, "en_route", livreur, productID, 3, 25) if err := testDB.GDB.Exec( `UPDATE command_items SET promo_discount = 25 WHERE command_id = ? AND product_id = ?`, cmdID, productID, ).Error; err != nil { t.Fatalf("mise à jour promo_discount: %v", err) } c, rec := myDeliveriesContext(livreur, "") handlers.GetMyDeliveries(c) if rec.Code != http.StatusOK { t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String()) } var resp struct { Success bool `json:"success"` Deliveries []struct { ID int `json:"id"` Items []struct { PromoDiscount float64 `json:"promo_discount"` } `json:"items"` } `json:"deliveries"` } if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { t.Fatalf("décodage réponse: %v body=%s", err, rec.Body.String()) } if !resp.Success { t.Fatalf("réponse non successful: body=%s", rec.Body.String()) } var found bool for _, d := range resp.Deliveries { if d.ID != cmdID { continue } if len(d.Items) != 1 || d.Items[0].PromoDiscount != 25 { t.Fatalf("promo_discount doit être exposé dans GetMyDeliveries: %+v", d.Items) } found = true } if !found { t.Fatalf("commande %d introuvable dans la réponse: body=%s", cmdID, rec.Body.String()) } }