chore: build
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gestion/handlers"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// newTestDeliveredOrder crée une commande livrée/approuvée assignée à un
|
||||
// livreur avec une date de mise à jour contrôlée (GetMyDeliveryStats groupe
|
||||
// par updated_at, pas created_at).
|
||||
func newTestDeliveredOrder(t *testing.T, livreurUsername, clientUsername, status string, productID int, quantite, prix, referralUsed float64, updatedAt time.Time) {
|
||||
t.Helper()
|
||||
var cmdID int
|
||||
if err := testDB.GDB.Raw(
|
||||
`INSERT INTO commandes (username, status, livreur_assign, adresse, total_prix, referral_used, created_at, updated_at)
|
||||
VALUES (?, ?, ?, 'Adresse test', ?, ?, ?, ?) RETURNING id`,
|
||||
clientUsername, status, livreurUsername, prix, referralUsed, updatedAt, updatedAt,
|
||||
).Scan(&cmdID).Error; err != nil {
|
||||
t.Fatalf("création commande livrée test: %v", err)
|
||||
}
|
||||
if err := testDB.GDB.Exec(
|
||||
`INSERT INTO command_items (command_id, product_id, produit, quantite, prix, status)
|
||||
VALUES (?, ?, 'item test', ?, ?, 'delivered')`,
|
||||
cmdID, productID, quantite, prix,
|
||||
).Error; err != nil {
|
||||
t.Fatalf("création item commande livrée test: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func livreurStatsContext(username string) (*gin.Context, *httptest.ResponseRecorder) {
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/livreur/stats", 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
|
||||
}
|
||||
|
||||
type deliveryStatsResponse struct {
|
||||
Success bool `json:"success"`
|
||||
TodayCount int `json:"today_count"`
|
||||
TodayRevenue float64 `json:"today_revenue"`
|
||||
}
|
||||
|
||||
// today_count/today_revenue ne doivent compter que les livraisons du jour
|
||||
// courant (livre/approved), nettes du crédit de parrainage — pas les jours
|
||||
// précédents, même récents (voir by_day/by_week qui eux les agrègent).
|
||||
func TestGetMyDeliveryStats_TodayCountAndRevenue(t *testing.T) {
|
||||
cleanupStockTestData(t)
|
||||
livreurUsername := newTestClient(t, "stats_livreur_today")
|
||||
clientUsername := newTestClient(t, "stats_livreur_today_client")
|
||||
productID := newTestProduct(t, "StatsLivreurToday", 100)
|
||||
|
||||
now := time.Now()
|
||||
yesterday := now.AddDate(0, 0, -1)
|
||||
|
||||
newTestDeliveredOrder(t, livreurUsername, clientUsername, "approved", productID, 2, 40, 10, now) // net 30, aujourd'hui
|
||||
newTestDeliveredOrder(t, livreurUsername, clientUsername, "approved", productID, 1, 25, 0, yesterday) // hier, ne doit pas compter dans "today"
|
||||
|
||||
c, rec := livreurStatsContext(livreurUsername)
|
||||
handlers.GetMyDeliveryStats(c)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
|
||||
var resp deliveryStatsResponse
|
||||
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("success=false, body=%s", rec.Body.String())
|
||||
}
|
||||
if resp.TodayCount != 1 {
|
||||
t.Errorf("today_count: got=%d want=1 (la commande d'hier ne doit pas compter)", resp.TodayCount)
|
||||
}
|
||||
if resp.TodayRevenue != 30 {
|
||||
t.Errorf("today_revenue: got=%.2f want=30 (40 - 10 de parrainage)", resp.TodayRevenue)
|
||||
}
|
||||
}
|
||||
|
||||
// Aucune livraison aujourd'hui : today_count/today_revenue doivent être 0,
|
||||
// pas une absence de champ (voir le bug initial où le seul indicateur de
|
||||
// "livraisons du jour" était l'absence de ligne dans by_day).
|
||||
func TestGetMyDeliveryStats_TodayCountZeroWhenNoDeliveryToday(t *testing.T) {
|
||||
cleanupStockTestData(t)
|
||||
livreurUsername := newTestClient(t, "stats_livreur_none")
|
||||
|
||||
c, rec := livreurStatsContext(livreurUsername)
|
||||
handlers.GetMyDeliveryStats(c)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status HTTP: got=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var resp deliveryStatsResponse
|
||||
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.TodayCount != 0 {
|
||||
t.Errorf("today_count: got=%d want=0", resp.TodayCount)
|
||||
}
|
||||
if resp.TodayRevenue != 0 {
|
||||
t.Errorf("today_revenue: got=%.2f want=0", resp.TodayRevenue)
|
||||
}
|
||||
}
|
||||
|
||||
// Seules les commandes assignées à CE livreur doivent être comptées.
|
||||
func TestGetMyDeliveryStats_OnlyCountsOwnDeliveries(t *testing.T) {
|
||||
cleanupStockTestData(t)
|
||||
livreurA := newTestClient(t, "stats_livreur_a")
|
||||
livreurB := newTestClient(t, "stats_livreur_b")
|
||||
client := newTestClient(t, "stats_livreur_shared_client")
|
||||
productID := newTestProduct(t, "StatsLivreurIsolation", 100)
|
||||
now := time.Now()
|
||||
|
||||
newTestDeliveredOrder(t, livreurA, client, "approved", productID, 1, 20, 0, now)
|
||||
newTestDeliveredOrder(t, livreurB, client, "approved", productID, 1, 999, 0, now)
|
||||
|
||||
c, rec := livreurStatsContext(livreurA)
|
||||
handlers.GetMyDeliveryStats(c)
|
||||
|
||||
var resp deliveryStatsResponse
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("décodage réponse: %v", err)
|
||||
}
|
||||
if resp.TodayCount != 1 || resp.TodayRevenue != 20 {
|
||||
t.Errorf("stats livreur A ne doivent refléter que ses propres livraisons: got count=%d revenue=%.2f want count=1 revenue=20", resp.TodayCount, resp.TodayRevenue)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user