From 0039dda8a07af1f97cffb63a37109d4aee49da7d Mon Sep 17 00:00:00 2001 From: Xor290 Date: Wed, 13 May 2026 16:43:20 +0200 Subject: [PATCH] refacto --- backend/gestion/db/db_basket.go | 146 ------------------- backend/gestion/db/db_clients.go | 128 +++------------- backend/gestion/db/db_command_items.go | 169 +++++----------------- backend/gestion/db/db_command_priority.go | 91 +----------- backend/gestion/db/db_commands.go | 22 --- backend/gestion/db/db_delivery.go | 16 -- backend/gestion/db/db_delivery_manage.go | 76 ---------- backend/gestion/db/db_history.go | 113 --------------- 8 files changed, 61 insertions(+), 700 deletions(-) diff --git a/backend/gestion/db/db_basket.go b/backend/gestion/db/db_basket.go index 2ae7f554..9142dad5 100644 --- a/backend/gestion/db/db_basket.go +++ b/backend/gestion/db/db_basket.go @@ -7,58 +7,6 @@ import ( "gorm.io/gorm" ) -// AddProductInBasket ajoute un produit au panier de l'utilisateur -func (d *Database) AddProductInBasket(username, nameProduct string, quantity float64, category string) (*models.Panier, error) { - var productResult struct { - ID int `gorm:"column:id"` - } - err := d.GDB.Raw(`SELECT id FROM products WHERE LOWER(name) = LOWER(?) AND LOWER(category) = LOWER(?)`, - nameProduct, category).Scan(&productResult).Error - if err != nil { - return nil, fmt.Errorf("erreur lors de la recherche du produit: %w", err) - } - if productResult.ID == 0 { - return nil, fmt.Errorf("produit '%s' non trouvé dans la catégorie '%s'", nameProduct, category) - } - productID := productResult.ID - - price, err := d.GetProductPrice(nameProduct, category, quantity) - if err != nil { - return nil, fmt.Errorf("erreur récupération prix: %w", err) - } - - var existing struct { - ID int `gorm:"column:id"` - Quantity float64 `gorm:"column:quantity"` - Price float64 `gorm:"column:price"` - } - d.GDB.Raw(`SELECT id, quantity, price FROM baskets WHERE username = ? AND product_id = ?`, - username, productID).Scan(&existing) - - var basket models.Panier - if existing.ID != 0 { - newQuantity := existing.Quantity + quantity - newPrice := existing.Price + price - err = d.GDB.Raw(` - UPDATE baskets SET quantity = ?, price = ?, created_at = CURRENT_TIMESTAMP - WHERE id = ? RETURNING id, username, product_id, quantity, price, created_at`, - newQuantity, newPrice, existing.ID).Scan(&basket).Error - if err != nil { - return nil, fmt.Errorf("erreur lors de la mise à jour du panier: %w", err) - } - } else { - err = d.GDB.Raw(` - INSERT INTO baskets (username, product_id, quantity, price, created_at) - VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP) - RETURNING id, username, product_id, quantity, price, created_at`, - username, productID, quantity, price).Scan(&basket).Error - if err != nil { - return nil, fmt.Errorf("erreur lors de l'ajout au panier: %w", err) - } - } - return &basket, nil -} - // GetProductPrice récupère le prix réel d'un produit pour une quantité donnée (legacy) func (d *Database) GetProductPrice(name, category string, quantity float64) (float64, error) { var result struct { @@ -79,32 +27,6 @@ func (d *Database) GetProductPrice(name, category string, quantity float64) (flo return result.Price, nil } -func (d *Database) GetProductStock(name, category string) (float64, error) { - var result struct { - Stock float64 `gorm:"column:stock"` - } - err := d.GDB.Raw(`SELECT stock FROM products WHERE LOWER(name) = LOWER(?) AND LOWER(category) = LOWER(?)`, - name, category).Scan(&result).Error - if err != nil { - return 0, fmt.Errorf("produit non trouvé: %w", err) - } - return result.Stock, nil -} - -func (d *Database) DecrementProductStock(name, category string, quantity float64) error { - result := d.GDB.Exec(` - UPDATE products SET stock = stock - ? - WHERE LOWER(name) = LOWER(?) AND LOWER(category) = LOWER(?) AND stock >= ?`, - quantity, name, category, quantity) - if result.Error != nil { - return fmt.Errorf("erreur mise à jour stock: %w", result.Error) - } - if result.RowsAffected == 0 { - return fmt.Errorf("stock insuffisant pour le produit") - } - return nil -} - // GetAllProductsInBasket récupère tous les produits du panier d'un utilisateur func (d *Database) GetAllProductsInBasket(username string) ([]models.Panier, error) { var baskets []models.Panier @@ -223,74 +145,6 @@ func (d *Database) ClearBasketOnCheckout(username string) error { return d.GDB.Exec(`DELETE FROM baskets WHERE username = ?`, username).Error } -// GetBasketTotal calcule le montant total du panier d'un utilisateur -func (d *Database) GetBasketTotal(username string) (float64, error) { - var result struct { - Total float64 `gorm:"column:total"` - } - err := d.GDB.Raw(`SELECT COALESCE(SUM(price), 0) as total FROM baskets WHERE username = ?`, - username).Scan(&result).Error - if err != nil { - return 0, fmt.Errorf("erreur lors du calcul du total: %w", err) - } - return result.Total, nil -} - -// GetBasketItemCount compte le nombre d'items dans le panier -func (d *Database) GetBasketItemCount(username string) (int, error) { - var result struct { - Count int `gorm:"column:count"` - } - err := d.GDB.Raw(`SELECT COUNT(*) as count FROM baskets WHERE username = ?`, - username).Scan(&result).Error - if err != nil { - return 0, fmt.Errorf("erreur lors du comptage des items: %w", err) - } - return result.Count, nil -} - -func (d *Database) UpdateBasketItemQuantity(basketID int, newQuantity float64) error { - if newQuantity <= 0 { - return fmt.Errorf("quantité invalide") - } - return d.GDB.Transaction(func(tx *gorm.DB) error { - var item struct { - ProductID int `gorm:"column:product_id"` - Quantity float64 `gorm:"column:quantity"` - } - if err := tx.Raw(`SELECT product_id, quantity FROM baskets WHERE id = ? FOR UPDATE`, basketID).Scan(&item).Error; err != nil { - return fmt.Errorf("produit non trouvé: %w", err) - } - if item.ProductID == 0 { - return fmt.Errorf("panier item introuvable: %d", basketID) - } - - diff := newQuantity - item.Quantity - - if diff > 0 { - result := tx.Exec(`UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?`, - diff, item.ProductID, diff) - if result.Error != nil { - return fmt.Errorf("erreur stock: %w", result.Error) - } - if result.RowsAffected == 0 { - return fmt.Errorf("stock insuffisant") - } - } else if diff < 0 { - if err := tx.Exec(`UPDATE products SET stock = stock + ? WHERE id = ?`, - -diff, item.ProductID).Error; err != nil { - return fmt.Errorf("erreur stock: %w", err) - } - } - - if err := tx.Exec(`UPDATE baskets SET quantity = ? WHERE id = ?`, - newQuantity, basketID).Error; err != nil { - return fmt.Errorf("erreur panier: %w", err) - } - return 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 diff --git a/backend/gestion/db/db_clients.go b/backend/gestion/db/db_clients.go index e928afef..6ca18c4d 100644 --- a/backend/gestion/db/db_clients.go +++ b/backend/gestion/db/db_clients.go @@ -35,16 +35,16 @@ func (d *Database) CreateClient(client *models.Client) error { // GetClientByID récupère un client par son ID func (d *Database) GetClientByID(id int) (*models.Client, error) { var row struct { - ID int `gorm:"column:id"` - Username string `gorm:"column:username"` - Password string `gorm:"column:password"` - Nom string `gorm:"column:nom"` - Prenom string `gorm:"column:prenom"` - Telephone string `gorm:"column:telephone"` - Command int `gorm:"column:command"` - Amende float64 `gorm:"column:amende"` - PointsExtraJSON []byte `gorm:"column:points_extra"` - CreatedAt time.Time `gorm:"column:created_at"` + ID int `gorm:"column:id"` + Username string `gorm:"column:username"` + Password string `gorm:"column:password"` + Nom string `gorm:"column:nom"` + Prenom string `gorm:"column:prenom"` + Telephone string `gorm:"column:telephone"` + Command int `gorm:"column:command"` + Amende float64 `gorm:"column:amende"` + PointsExtraJSON []byte `gorm:"column:points_extra"` + CreatedAt time.Time `gorm:"column:created_at"` } err := d.GDB.Raw(` SELECT id, username, password, nom, prenom, telephone, command, amende, @@ -190,44 +190,6 @@ func (d *Database) UpdateClientPasswordAndClearFlag(clientID int, hashedPassword return nil } -// GetClientStats récupère les statistiques d'un client -func (d *Database) GetClientStats(clientID int) (map[string]interface{}, error) { - client, err := d.GetClientByID(clientID) - if err != nil { - return nil, err - } - - var statsResult struct { - Total int `gorm:"column:total"` - Pending int `gorm:"column:pending"` - Completed int `gorm:"column:completed"` - } - if err := d.GDB.Raw(` - SELECT - COUNT(*) as total, - COALESCE(SUM(CASE WHEN status = 'pending' OR status = 'livre' THEN 1 ELSE 0 END), 0) as pending, - COALESCE(SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END), 0) as completed - FROM commandes WHERE username = ?`, client.Username).Scan(&statsResult).Error; err != nil { - log.Printf("⚠️ Erreur calcul stats: %v", err) - } - - stats := map[string]interface{}{ - "id": clientID, - "username": client.Username, - "nom": client.Nom, - "prenom": client.Prenom, - "telephone": client.Telephone, - "total_commands": statsResult.Total, - "pending_commands": statsResult.Pending, - "completed_commands": statsResult.Completed, - "points_extra": client.PointsExtra, - "amende": client.Amende, - "member_since": client.CreatedAt, - } - - return stats, nil -} - func (d *Database) GetClientAmende(username string) (float64, error) { var result struct { Amende float64 `gorm:"column:amende"` @@ -242,37 +204,6 @@ func (d *Database) GetClientAmende(username string) (float64, error) { return result.Amende, nil } -func (d *Database) PayClientPenalties(username string, amountPaid float64) error { - log.Printf("💳 [PayClientPenalties] Paiement de %.2f points pour %s", amountPaid, username) - - currentAmount, err := d.GetClientAmende(username) - if err != nil { - return err - } - - if currentAmount <= 0 { - return fmt.Errorf("aucune pénalité à payer") - } - - if amountPaid < currentAmount { - return fmt.Errorf("montant insuffisant: %.2f payé, %.2f requis", amountPaid, currentAmount) - } - - result := d.GDB.Model(&models.Client{}).Where("username = ?", username).Update("amende", 0.0) - if result.Error != nil { - log.Printf("❌ [PayClientPenalties] Erreur UPDATE: %v", result.Error) - return fmt.Errorf("erreur paiement pénalités: %w", result.Error) - } - if result.RowsAffected == 0 { - return fmt.Errorf("client non trouvé") - } - - cacheKey := fmt.Sprintf("client:%s", username) - Redis.Del(RedisCtx, cacheKey) - - return nil -} - // IncrementClientCommandCount incrémente le compteur de commandes du client func (d *Database) IncrementClientCommandCount(username string) error { result := d.GDB.Model(&models.Client{}).Where("username = ?", username).UpdateColumn("command", gorm.Expr("command + 1")) @@ -413,7 +344,7 @@ func (d *Database) SetClientTwoFAEnabled(clientID int, enabled bool) error { return d.GDB.Model(&models.Client{}).Where("id = ?", clientID).Update("two_fa_enabled", enabled).Error } -func (d *Database) GetClientPenaltiesInfo(username string) (map[string]interface{}, error) { +func (d *Database) GetClientPenaltiesInfo(username string) (map[string]any, error) { amende, err := d.GetClientAmende(username) if err != nil { return nil, err @@ -428,13 +359,13 @@ func (d *Database) GetClientPenaltiesInfo(username string) (map[string]interface cancellationHistory, err := d.GetClientCancellationHistory(username) if err != nil { log.Printf("⚠️ [GetClientPenaltiesInfo] Erreur récup historique: %v", err) - cancellationHistory = map[string]interface{}{ + cancellationHistory = map[string]any{ "cancellations_count": cancellationsCount, "next_penalty": 20, } } - info := map[string]interface{}{ + info := map[string]any{ "username": username, "total_penalty": amende, "cancellations_count": cancellationsCount, @@ -445,21 +376,6 @@ func (d *Database) GetClientPenaltiesInfo(username string) (map[string]interface return info, nil } -// CheckClientCanOrder vérifie si un client peut passer commande (pas de pénalités impayées) -func (d *Database) CheckClientCanOrder(username string) (bool, float64, error) { - amende, err := d.GetClientAmende(username) - if err != nil { - return false, 0, err - } - - if amende > 0 { - log.Printf("⚠️ [CheckClientCanOrder] Client %s bloqué: %.2f points de pénalités", username, amende) - return false, amende, fmt.Errorf("pénalités impayées: %.2f points", amende) - } - - return true, 0, nil -} - // ResetClientPoint réinitialise les points d'un client. // extraPoolKey != "" → reset points_extra[extraPoolKey] uniquement // extraPoolKey == "" (poolIdx=-1) → reset total points_extra @@ -520,12 +436,12 @@ func (d *Database) ResetClientPenalties(username string, resetCancellationsCount return nil } -func (d *Database) GetAllClientsWithPenalties() ([]map[string]interface{}, error) { +func (d *Database) GetAllClientsWithPenalties() ([]map[string]any, error) { var rows []struct { - Username string `gorm:"column:username"` - Amende float64 `gorm:"column:amende"` - CancellationsCount int `gorm:"column:cancellations_count"` - UpdatedAt interface{} `gorm:"column:updated_at"` + Username string `gorm:"column:username"` + Amende float64 `gorm:"column:amende"` + CancellationsCount int `gorm:"column:cancellations_count"` + UpdatedAt any `gorm:"column:updated_at"` } err := d.GDB.Raw(` SELECT username, amende, COALESCE(cancellations_count, 0) as cancellations_count, updated_at @@ -537,9 +453,9 @@ func (d *Database) GetAllClientsWithPenalties() ([]map[string]interface{}, error return nil, fmt.Errorf("erreur récupération clients: %w", err) } - clients := make([]map[string]interface{}, 0, len(rows)) + clients := make([]map[string]any, 0, len(rows)) for _, row := range rows { - clients = append(clients, map[string]interface{}{ + clients = append(clients, map[string]any{ "username": row.Username, "total_penalty": row.Amende, "cancellations_count": row.CancellationsCount, @@ -552,7 +468,7 @@ func (d *Database) GetAllClientsWithPenalties() ([]map[string]interface{}, error return clients, nil } -func (d *Database) GetClientPenaltiesStats() (map[string]interface{}, error) { +func (d *Database) GetClientPenaltiesStats() (map[string]any, error) { var result struct { ClientsWithPenalties int `gorm:"column:clients_with_penalties"` TotalPenalties float64 `gorm:"column:total_penalties"` @@ -574,7 +490,7 @@ func (d *Database) GetClientPenaltiesStats() (map[string]interface{}, error) { return nil, fmt.Errorf("erreur récupération stats: %w", err) } - stats := map[string]interface{}{ + stats := map[string]any{ "clients_with_penalties": result.ClientsWithPenalties, "total_penalties": result.TotalPenalties, "average_penalty": result.AvgPenalty, diff --git a/backend/gestion/db/db_command_items.go b/backend/gestion/db/db_command_items.go index 512f5e7d..1ab4d8ce 100644 --- a/backend/gestion/db/db_command_items.go +++ b/backend/gestion/db/db_command_items.go @@ -3,6 +3,7 @@ package db import ( "fmt" "log" + "slices" "strings" "time" ) @@ -79,10 +80,8 @@ func validateItemStatus(status string) error { status = strings.ToLower(strings.TrimSpace(status)) - for _, valid := range validStatuses { - if status == valid { - return nil - } + if !slices.Contains(validStatuses, status) { + return fmt.Errorf("...") } return fmt.Errorf("statut invalide: %s", status) @@ -181,7 +180,7 @@ func (d *Database) InsertCommandItemWithClientInfo( // GET COMMAND ITEMS - VERSION SÉCURISÉE + FIX NULL // ============================================ -func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, error) { +func (d *Database) GetCommandItems(commandID int) ([]map[string]any, error) { log.Printf("📦 [GetCommandItems] START - commandID=%d", commandID) // ✅ VALIDATION @@ -191,28 +190,28 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err } var rows []struct { - ID int `gorm:"column:id"` - CommandID int `gorm:"column:command_id"` - Produit string `gorm:"column:produit"` - ProductID *int64 `gorm:"column:product_id"` - Quantite float64 `gorm:"column:quantite"` - Prix float64 `gorm:"column:prix"` - ClientUsername string `gorm:"column:client_username"` - ClientNom string `gorm:"column:client_nom"` - ClientPrenom string `gorm:"column:client_prenom"` - ClientTelephone string `gorm:"column:client_telephone"` - DeliveryAddress *string `gorm:"column:delivery_address"` - Status *string `gorm:"column:status"` - CreatedAt time.Time `gorm:"column:created_at"` - UpdatedAt time.Time `gorm:"column:updated_at"` - CommandStatus *string `gorm:"column:command_status"` - CommandAddress *string `gorm:"column:command_address"` - TotalPrix float64 `gorm:"column:total_prix"` - ReferralUsed float64 `gorm:"column:referral_used"` - LivreurAssign *string `gorm:"column:livreur_assign"` - CommandCreatedAt *time.Time `gorm:"column:command_created_at"` - Category string `gorm:"column:category"` - ClientOrderNumber int `gorm:"column:client_order_number"` + ID int `gorm:"column:id"` + CommandID int `gorm:"column:command_id"` + Produit string `gorm:"column:produit"` + ProductID *int64 `gorm:"column:product_id"` + Quantite float64 `gorm:"column:quantite"` + Prix float64 `gorm:"column:prix"` + ClientUsername string `gorm:"column:client_username"` + ClientNom string `gorm:"column:client_nom"` + ClientPrenom string `gorm:"column:client_prenom"` + ClientTelephone string `gorm:"column:client_telephone"` + DeliveryAddress *string `gorm:"column:delivery_address"` + Status *string `gorm:"column:status"` + CreatedAt time.Time `gorm:"column:created_at"` + UpdatedAt time.Time `gorm:"column:updated_at"` + CommandStatus *string `gorm:"column:command_status"` + CommandAddress *string `gorm:"column:command_address"` + TotalPrix float64 `gorm:"column:total_prix"` + ReferralUsed float64 `gorm:"column:referral_used"` + LivreurAssign *string `gorm:"column:livreur_assign"` + CommandCreatedAt *time.Time `gorm:"column:command_created_at"` + Category string `gorm:"column:category"` + ClientOrderNumber int `gorm:"column:client_order_number"` } err := d.GDB.Raw(` @@ -249,19 +248,19 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err return nil, fmt.Errorf("erreur récupération items: %w", err) } - items := make([]map[string]interface{}, 0, len(rows)) + items := make([]map[string]any, 0, len(rows)) for _, row := range rows { productIDValue := 0 if row.ProductID != nil { productIDValue = int(*row.ProductID) } - var commandCreatedAt interface{} + var commandCreatedAt any if row.CommandCreatedAt != nil { commandCreatedAt = *row.CommandCreatedAt } - item := map[string]interface{}{ + item := map[string]any{ "id": row.ID, "command_id": row.CommandID, "produit": row.Produit, @@ -277,11 +276,11 @@ func (d *Database) GetCommandItems(commandID int) ([]map[string]interface{}, err "created_at": row.CreatedAt, "updated_at": row.UpdatedAt, // Infos commande - "command_status": ptrStr(row.CommandStatus), - "command_address": ptrStr(row.CommandAddress), - "total_prix": row.TotalPrix, - "referral_used": row.ReferralUsed, - "livreur_assign": ptrStr(row.LivreurAssign), + "command_status": ptrStr(row.CommandStatus), + "command_address": ptrStr(row.CommandAddress), + "total_prix": row.TotalPrix, + "referral_used": row.ReferralUsed, + "livreur_assign": ptrStr(row.LivreurAssign), "command_created_at": commandCreatedAt, "category": row.Category, "client_order_number": row.ClientOrderNumber, @@ -301,104 +300,6 @@ func ptrStr(s *string) string { return *s } -func (d *Database) GetCommandItemsByUsername(username string) ([]map[string]interface{}, error) { - if err := validateUsername(username); err != nil { - log.Printf("❌ [GetCommandItemsByUsername] %v", err) - return nil, err - } - - var rows []struct { - ID int `gorm:"column:id"` - CommandID int `gorm:"column:command_id"` - Produit string `gorm:"column:produit"` - ProductID *int64 `gorm:"column:product_id"` - Quantite float64 `gorm:"column:quantite"` - Prix float64 `gorm:"column:prix"` - ClientUsername string `gorm:"column:client_username"` - ClientNom string `gorm:"column:client_nom"` - ClientPrenom string `gorm:"column:client_prenom"` - ClientTelephone string `gorm:"column:client_telephone"` - DeliveryAddress *string `gorm:"column:delivery_address"` - Status *string `gorm:"column:status"` - CreatedAt time.Time `gorm:"column:created_at"` - UpdatedAt time.Time `gorm:"column:updated_at"` - CommandStatus *string `gorm:"column:command_status"` - CommandAddress *string `gorm:"column:command_address"` - TotalPrix float64 `gorm:"column:total_prix"` - LivreurAssign *string `gorm:"column:livreur_assign"` - CommandCreatedAt *time.Time `gorm:"column:command_created_at"` - } - - err := d.GDB.Raw(` - SELECT - ci.id, - ci.command_id, - ci.produit, - ci.product_id, - ci.quantite, - ci.prix, - ci.client_username, - ci.client_nom, - ci.client_prenom, - ci.client_telephone, - ci.delivery_address, - ci.status, - ci.created_at, - ci.updated_at, - c.status as command_status, - c.adresse as command_address, - c.total_prix, - c.livreur_assign, - c.created_at as command_created_at - FROM command_items ci - LEFT JOIN commandes c ON ci.command_id = c.id - WHERE ci.client_username = ? - ORDER BY ci.command_id DESC, ci.id ASC`, username).Scan(&rows).Error - if err != nil { - log.Printf("❌ Erreur query: %v", err) - return nil, fmt.Errorf("erreur récupération items: %w", err) - } - - items := make([]map[string]interface{}, 0, len(rows)) - for _, row := range rows { - productIDValue := 0 - if row.ProductID != nil { - productIDValue = int(*row.ProductID) - } - - var commandCreatedAt interface{} - if row.CommandCreatedAt != nil { - commandCreatedAt = *row.CommandCreatedAt - } - - item := map[string]interface{}{ - "id": row.ID, - "command_id": row.CommandID, - "produit": row.Produit, - "product_id": productIDValue, - "quantite": row.Quantite, - "prix": row.Prix, - "client_username": row.ClientUsername, - "client_nom": row.ClientNom, - "client_prenom": row.ClientPrenom, - "client_telephone": row.ClientTelephone, - "delivery_address": ptrStr(row.DeliveryAddress), - "status": ptrStr(row.Status), - "created_at": row.CreatedAt, - "updated_at": row.UpdatedAt, - "command_status": ptrStr(row.CommandStatus), - "command_address": ptrStr(row.CommandAddress), - "total_prix": row.TotalPrix, - "livreur_assign": ptrStr(row.LivreurAssign), - "command_created_at": commandCreatedAt, - } - items = append(items, item) - } - - log.Printf("✅ %d items récupérés pour l'utilisateur %s", len(items), username) - return items, nil -} - func (d *Database) DeleteCommandItem(commandID, itemID int) error { log.Printf("🗑️ [DeleteCommandItem] START - commandID=%d, itemID=%d", commandID, itemID) @@ -411,7 +312,7 @@ func (d *Database) DeleteCommandItem(commandID, itemID int) error { // Récupérer le prix et la quantité avant suppression pour mettre à jour le total var result struct { - Prix float64 `gorm:"column:prix"` + Prix float64 `gorm:"column:prix"` Quantite float64 `gorm:"column:quantite"` } if err := d.GDB.Raw(`SELECT prix, quantite FROM command_items WHERE id = ? AND command_id = ?`, itemID, commandID).Scan(&result).Error; err != nil { diff --git a/backend/gestion/db/db_command_priority.go b/backend/gestion/db/db_command_priority.go index 2092b5a2..61b42bbf 100644 --- a/backend/gestion/db/db_command_priority.go +++ b/backend/gestion/db/db_command_priority.go @@ -7,7 +7,6 @@ package db import ( "fmt" - "gestion/models" "log" "slices" ) @@ -44,95 +43,13 @@ func (d *Database) GetAllCommandsOldestFirst(status, username string) ([]map[str return commands, nil } -// GetOldestPendingCommand récupère la commande pending la plus ancienne -func (d *Database) GetOldestPendingCommand() (map[string]any, error) { - var commands []map[string]any - err := d.GDB.Raw(` - SELECT c.id, c.username, c.status, c.adresse, c.total_prix, - c.livreur_assign, c.created_at, c.updated_at - FROM commandes c - WHERE c.status = 'pending' - ORDER BY c.created_at ASC - LIMIT 1`).Scan(&commands).Error - if err != nil { - return nil, fmt.Errorf("erreur récupération commande la plus ancienne: %w", err) - } - if len(commands) == 0 { - return nil, nil - } - return commands[0], nil -} - -// GetPendingCommandsWithPriority récupère les commandes pending avec calcul de priorité -func (d *Database) GetPendingCommandsWithPriority() ([]*models.CommandPriority, error) { - var rows []struct { - ID int `gorm:"column:id"` - Username string `gorm:"column:username"` - Status string `gorm:"column:status"` - Adresse string `gorm:"column:adresse"` - TotalPrix float64 `gorm:"column:total_prix"` - CreatedAt string `gorm:"column:created_at"` - UpdatedAt string `gorm:"column:updated_at"` - WaitingSeconds float64 `gorm:"column:waiting_seconds"` - } - - err := d.GDB.Raw(` - SELECT c.id, c.username, c.status, c.adresse, c.total_prix, - c.created_at, c.updated_at, - EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - c.created_at)) as waiting_seconds - FROM commandes c - WHERE c.status = 'pending' - ORDER BY c.created_at ASC`).Scan(&rows).Error - if err != nil { - return nil, fmt.Errorf("erreur récupération commandes avec priorité: %w", err) - } - - commands := make([]*models.CommandPriority, 0, len(rows)) - for _, row := range rows { - cmd := &models.CommandPriority{ - ID: row.ID, - Username: row.Username, - Status: row.Status, - Address: row.Adresse, - TotalPrice: row.TotalPrix, - WaitingSeconds: int(row.WaitingSeconds), - WaitingMinutes: int(row.WaitingSeconds / 60), - } - commands = append(commands, cmd) - } - - return commands, nil -} - -// GetCommandWaitingTime récupère le temps d'attente d'une commande -func (d *Database) GetCommandWaitingTime(commandID int) (int, error) { - var result struct { - WaitingSeconds int `gorm:"column:waiting_seconds"` - } - err := d.GDB.Raw(` - SELECT EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - created_at))::INTEGER as waiting_seconds - FROM commandes WHERE id = ?`, commandID).Scan(&result).Error - if err != nil { - return 0, fmt.Errorf("erreur récupération temps d'attente: %w", err) - } - if result.WaitingSeconds == 0 { - // Vérifie si la commande existe vraiment - var exists bool - d.GDB.Raw(`SELECT EXISTS(SELECT 1 FROM commandes WHERE id = ?)`, commandID).Scan(&exists) - if !exists { - return 0, fmt.Errorf("commande non trouvée") - } - } - return result.WaitingSeconds, nil -} - // GetPendingCommandsStats récupère des statistiques sur les commandes en attente func (d *Database) GetPendingCommandsStats() (map[string]any, error) { var result struct { - TotalPending int `gorm:"column:total_pending"` - AvgWaitingSeconds *float64 `gorm:"column:avg_waiting_seconds"` - OldestCommandDate *string `gorm:"column:oldest_command_date"` - NewestCommandDate *string `gorm:"column:newest_command_date"` + TotalPending int `gorm:"column:total_pending"` + AvgWaitingSeconds *float64 `gorm:"column:avg_waiting_seconds"` + OldestCommandDate *string `gorm:"column:oldest_command_date"` + NewestCommandDate *string `gorm:"column:newest_command_date"` } err := d.GDB.Raw(` diff --git a/backend/gestion/db/db_commands.go b/backend/gestion/db/db_commands.go index f1e05617..6952b8ed 100644 --- a/backend/gestion/db/db_commands.go +++ b/backend/gestion/db/db_commands.go @@ -349,14 +349,6 @@ func (d *Database) GetAllCommands(status, username string) ([]map[string]any, er return commands, nil } -func (d *Database) GetCommandCount() (int, error) { - var count int64 - if err := d.GDB.Model(&models.Command{}).Count(&count).Error; err != nil { - return 0, fmt.Errorf("erreur récupération count commandes: %w", err) - } - return int(count), nil -} - func (d *Database) SetCommandReferralUsed(commandID int, amount float64) error { return d.GDB.Exec(`UPDATE commandes SET referral_used = ? WHERE id = ?`, amount, commandID).Error } @@ -432,20 +424,6 @@ func (d *Database) GetClientOrderID(commandID int) int { return result.ClientOrderID } -func (d *Database) GetCommandAddress(commandID int) (string, error) { - var result struct { - Adresse string `gorm:"column:adresse"` - } - if err := d.GDB.Model(&models.Command{}).Select("adresse").Where("id = ?", commandID).First(&result).Error; err != nil { - return "", fmt.Errorf("erreur lors de la récupération de l'adresse: %w", err) - } - if result.Adresse == "" { - return "", fmt.Errorf("commande non trouvée") - } - - return result.Adresse, nil -} - func (d *Database) UpdateCommandAddress(commandID int, deliveryAddress string) error { if len(deliveryAddress) > 500 { return fmt.Errorf("adresse trop longue (max 500 caractères)") diff --git a/backend/gestion/db/db_delivery.go b/backend/gestion/db/db_delivery.go index e364d6cf..810b8458 100644 --- a/backend/gestion/db/db_delivery.go +++ b/backend/gestion/db/db_delivery.go @@ -117,22 +117,6 @@ func (d *Database) GetDeliveryPersonCommands(livreurUsername string, status stri return commands, nil } -func (d *Database) IncrementLivreurDeliveryCount(livreurUsername string) error { - result := d.GDB.Exec(` - UPDATE users - SET livraison = livraison + 1, - total = total + 1, - updated_at = CURRENT_TIMESTAMP - WHERE username = ? AND role = 'livreur'`, livreurUsername) - if result.Error != nil { - return fmt.Errorf("erreur lors de l'incrémentation des livraisons: %w", result.Error) - } - if result.RowsAffected == 0 { - return fmt.Errorf("livreur non trouvé") - } - return nil -} - func (d *Database) ApproveDelivery(commandID int, clientUsername string) error { return d.GDB.Transaction(func(tx *gorm.DB) error { var cmdResult struct { diff --git a/backend/gestion/db/db_delivery_manage.go b/backend/gestion/db/db_delivery_manage.go index 57947a1e..8796cf7e 100644 --- a/backend/gestion/db/db_delivery_manage.go +++ b/backend/gestion/db/db_delivery_manage.go @@ -221,79 +221,3 @@ func (d *Database) UpdateCommandLivreur(commandID int, livreurUsername string) e } return nil } - -// GetAllDeliveryPersonsStats récupère les stats de tous les livreurs -func (d *Database) GetAllDeliveryPersonsStats() ([]map[string]any, error) { - livreurs, err := d.GetAvailableDeliveryPersons() - if err != nil { - return nil, fmt.Errorf("erreur récupération livreurs: %w", err) - } - - var stats []map[string]any - for _, livreur := range livreurs { - username := livreur["username"].(string) - - totalDeliveries, _ := d.CountDeliveriesByStatus(username, "") - completedDeliveries, _ := d.CountDeliveriesByStatus(username, "approved") - queueSize, _ := d.GetDeliverymanQueueSize(username) - status, _ := d.GetDeliveryPersonStatus(username) - - stats = append(stats, map[string]any{ - "username": username, - "total_deliveries": totalDeliveries, - "completed_deliveries": completedDeliveries, - "queue_size": queueSize, - "status": status, - }) - } - return stats, nil -} - -// GetDeliveryPersonsByStatus récupère les livreurs par statut -func (d *Database) GetDeliveryPersonsByStatus(status string) ([]string, error) { - livreurs, err := d.GetAvailableDeliveryPersons() - if err != nil { - return nil, fmt.Errorf("erreur récupération livreurs: %w", err) - } - - var filteredLivreurs []string - for _, livreur := range livreurs { - username := livreur["username"].(string) - currentStatus, _ := d.GetDeliveryPersonStatus(username) - if currentStatus == status { - filteredLivreurs = append(filteredLivreurs, username) - } - } - return filteredLivreurs, nil -} - -// GetAvailableDeliveryPersonsCount compte les livreurs disponibles -func (d *Database) GetAvailableDeliveryPersonsCount() (int, error) { - availableLivreurs, err := d.GetDeliveryPersonsByStatus("available") - if err != nil { - return 0, err - } - return len(availableLivreurs), nil -} - -// ClearDeliveryPersonData supprime toutes les données d'un livreur (admin uniquement) -func (d *Database) ClearDeliveryPersonData(livreurUsername string) error { - log.Printf("🗑️ [ClearDeliveryData] Nettoyage données pour: %s", livreurUsername) - - keys := []string{ - fmt.Sprintf("delivery:status:%s", livreurUsername), - fmt.Sprintf("delivery:location:%s", livreurUsername), - fmt.Sprintf("delivery:queue:%s", livreurUsername), - fmt.Sprintf("delivery:queue:size:%s", livreurUsername), - fmt.Sprintf("delivery:current:%s", livreurUsername), - } - - for _, key := range keys { - if err := Redis.Del(RedisCtx, key).Err(); err != nil { - log.Printf("⚠️ [ClearDeliveryData] Erreur suppression clé %s: %v", key, err) - } - } - - log.Printf("✅ [ClearDeliveryData] Données nettoyées pour %s", livreurUsername) - return nil -} diff --git a/backend/gestion/db/db_history.go b/backend/gestion/db/db_history.go index 70d8c437..c510b639 100644 --- a/backend/gestion/db/db_history.go +++ b/backend/gestion/db/db_history.go @@ -8,8 +8,6 @@ package db import ( "fmt" "log" - "maps" - "strconv" ) // GetCompletedCommandsByUsername récupère toutes les commandes terminées (approved) d'un utilisateur @@ -37,114 +35,3 @@ func (d *Database) GetCompletedCommandsByUsername(username string) ([]map[string } return commands, nil } - -// GetCompletedCommandsWithItems récupère les commandes terminées avec leurs items -func (d *Database) GetCompletedCommandsWithItems(username string) ([]map[string]any, error) { - commands, err := d.GetCompletedCommandsByUsername(username) - if err != nil { - return nil, err - } - - var enrichedCommands []map[string]any - - for _, command := range commands { - commandID, _ := strconv.Atoi(fmt.Sprintf("%v", command["id"])) - if commandID == 0 { - continue - } - - items, err := d.GetCommandItems(commandID) - if err != nil { - log.Printf("⚠️ [GetCompletedWithItems] Erreur items pour cmd %d: %v", commandID, err) - items = []map[string]any{} - } - - enrichedCommand := make(map[string]any) - maps.Copy(enrichedCommand, command) - enrichedCommand["items"] = items - enrichedCommand["items_count"] = len(items) - - enrichedCommands = append(enrichedCommands, enrichedCommand) - } - - return enrichedCommands, nil -} - -// GetCommandsStatsByUsername récupère les statistiques des commandes d'un utilisateur -func (d *Database) GetCommandsStatsByUsername(username string) (map[string]any, error) { - query := ` - SELECT - COUNT(*) FILTER (WHERE status = 'approved') as approved_count, - COUNT(*) FILTER (WHERE status = 'pending') as pending_count, - COUNT(*) FILTER (WHERE status = 'assigned') as assigned_count, - COUNT(*) FILTER (WHERE status = 'en_route') as en_route_count, - COUNT(*) FILTER (WHERE status = 'livre') as livre_count, - COUNT(*) FILTER (WHERE status = 'cancelled') as cancelled_count, - COUNT(*) as total_count, - COALESCE(SUM(total_prix) FILTER (WHERE status = 'approved'), 0) as total_spent - FROM commandes - WHERE username = ? - ` - - var result map[string]any - if err := d.GDB.Raw(query, username).Scan(&result).Error; err != nil { - log.Printf("❌ [GetCommandsStats] Erreur: %v", err) - return nil, fmt.Errorf("erreur lors de la récupération des statistiques: %w", err) - } - - return result, nil -} - -// GetCommandsByStatus récupère les commandes d'un utilisateur par statut -func (d *Database) GetCommandsByStatus(username, status string) ([]map[string]any, error) { - log.Printf("📋 [GetCommandsByStatus] START - username=%s, status=%s", username, status) - - query := ` - SELECT - id, - client_order_id AS client_order_number, - username, - status, - adresse, - total_prix::float8 as total_prix, - livreur_assign, - created_at, - updated_at - FROM commandes - WHERE username = ? AND status = ? - ORDER BY created_at DESC - ` - - var commands []map[string]any - if err := d.GDB.Raw(query, username, status).Scan(&commands).Error; err != nil { - return nil, fmt.Errorf("erreur lors de la récupération des commandes: %w", err) - } - return commands, nil -} - -// GetRecentCompletedOrders récupère les N dernières commandes terminées d'un utilisateur -func (d *Database) GetRecentCompletedOrders(username string, limit int) ([]map[string]any, error) { - query := ` - SELECT - id, - client_order_id AS client_order_number, - username, - status, - adresse, - total_prix::float8 as total_prix, - livreur_assign, - created_at, - updated_at - FROM commandes - WHERE username = ? AND status = 'approved' - ORDER BY created_at DESC - LIMIT ? - ` - - var commands []map[string]any - if err := d.GDB.Raw(query, username, limit).Scan(&commands).Error; err != nil { - log.Printf("❌ [GetRecentCompleted] Erreur query: %v", err) - return nil, fmt.Errorf("erreur lors de la récupération: %w", err) - } - return commands, nil -}