// ============================================ // db/commands_history.go // ============================================ // Fonctions pour l'historique des commandes terminées package db import ( "database/sql" "fmt" "log" "time" ) // GetCompletedCommandsByUsername récupère toutes les commandes terminées (approved) d'un utilisateur // ✅ Retourne uniquement les commandes avec status = "approved" // ✅ Ordonnées par date de création décroissante (plus récentes en premier) func (d *Database) GetCompletedCommandsByUsername(username string) ([]map[string]interface{}, error) { log.Printf("📚 [GetCompletedCommands] START - username=%s", username) query := ` SELECT id, username, status, adresse, total_prix, livreur_assign, created_at, updated_at FROM commandes WHERE username = $1 AND status = 'approved' ORDER BY created_at DESC ` rows, err := d.Query(query, username) if err != nil { log.Printf("❌ [GetCompletedCommands] Erreur query: %v", err) return nil, fmt.Errorf("erreur lors de la récupération des commandes terminées: %w", err) } defer rows.Close() var commands []map[string]interface{} for rows.Next() { var id int var username, status, adresse string var livreurAssign sql.NullString var totalPrix float64 var createdAt, updatedAt time.Time err := rows.Scan( &id, &username, &status, &adresse, &totalPrix, &livreurAssign, &createdAt, &updatedAt, ) if err != nil { log.Printf("❌ [GetCompletedCommands] Erreur scan: %v", err) return nil, fmt.Errorf("erreur lors du scan de la commande: %w", err) } command := map[string]interface{}{ "id": id, "username": username, "status": status, "adresse": adresse, "total_prix": totalPrix, "created_at": createdAt, "updated_at": updatedAt, } // Ajouter livreur_assign seulement s'il n'est pas NULL if livreurAssign.Valid { command["livreur_assign"] = livreurAssign.String } else { command["livreur_assign"] = nil } commands = append(commands, command) } if err = rows.Err(); err != nil { log.Printf("❌ [GetCompletedCommands] Erreur itération: %v", err) return nil, fmt.Errorf("erreur lors de l'itération des résultats: %w", err) } log.Printf("✅ [GetCompletedCommands] %d commandes terminées trouvées pour %s", len(commands), username) return commands, nil } // GetCompletedCommandsWithItems récupère les commandes terminées avec leurs items // ✅ Retourne les commandes approved avec tous les détails func (d *Database) GetCompletedCommandsWithItems(username string) ([]map[string]interface{}, error) { log.Printf("📚 [GetCompletedWithItems] START - username=%s", username) // 1. Récupérer les commandes terminées commands, err := d.GetCompletedCommandsByUsername(username) if err != nil { return nil, err } // 2. Pour chaque commande, récupérer les items var enrichedCommands []map[string]interface{} for _, command := range commands { commandID, ok := command["id"].(int) if !ok { continue } // Récupérer les items items, err := d.GetCommandItems(commandID) if err != nil { log.Printf("⚠️ [GetCompletedWithItems] Erreur items pour cmd %d: %v", commandID, err) items = []map[string]interface{}{} } // Enrichir la commande enrichedCommand := make(map[string]interface{}) for k, v := range command { enrichedCommand[k] = v } enrichedCommand["items"] = items enrichedCommand["items_count"] = len(items) enrichedCommands = append(enrichedCommands, enrichedCommand) } log.Printf("✅ [GetCompletedWithItems] %d commandes enrichies", len(enrichedCommands)) return enrichedCommands, nil } // GetCommandsStatsByUsername récupère les statistiques des commandes d'un utilisateur // ✅ Compte total, approved, pending, cancelled, etc. func (d *Database) GetCommandsStatsByUsername(username string) (map[string]interface{}, error) { log.Printf("📊 [GetCommandsStats] START - username=%s", username) 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 = $1 ` var approvedCount, pendingCount, assignedCount, enRouteCount, livreCount, cancelledCount, totalCount int var totalSpent float64 err := d.QueryRow(query, username).Scan( &approvedCount, &pendingCount, &assignedCount, &enRouteCount, &livreCount, &cancelledCount, &totalCount, &totalSpent, ) if err != nil { log.Printf("❌ [GetCommandsStats] Erreur: %v", err) return nil, fmt.Errorf("erreur lors de la récupération des statistiques: %w", err) } stats := map[string]interface{}{ "approved_count": approvedCount, "pending_count": pendingCount, "assigned_count": assignedCount, "en_route_count": enRouteCount, "livre_count": livreCount, "cancelled_count": cancelledCount, "total_count": totalCount, "total_spent": totalSpent, } log.Printf("✅ [GetCommandsStats] Stats calculées: total=%d, approved=%d, spent=%.2f€", totalCount, approvedCount, totalSpent) return stats, nil } // GetCommandsByStatus récupère les commandes d'un utilisateur par statut // ✅ Permet de filtrer par un statut spécifique func (d *Database) GetCommandsByStatus(username, status string) ([]map[string]interface{}, error) { log.Printf("📋 [GetCommandsByStatus] START - username=%s, status=%s", username, status) query := ` SELECT id, username, status, adresse, total_prix, livreur_assign, created_at, updated_at FROM commandes WHERE username = $1 AND status = $2 ORDER BY created_at DESC ` rows, err := d.Query(query, username, status) if err != nil { log.Printf("❌ [GetCommandsByStatus] Erreur query: %v", err) return nil, fmt.Errorf("erreur lors de la récupération des commandes: %w", err) } defer rows.Close() var commands []map[string]interface{} for rows.Next() { var id int var username, status, adresse string var livreurAssign sql.NullString var totalPrix float64 var createdAt, updatedAt time.Time err := rows.Scan( &id, &username, &status, &adresse, &totalPrix, &livreurAssign, &createdAt, &updatedAt, ) if err != nil { log.Printf("❌ [GetCommandsByStatus] Erreur scan: %v", err) return nil, fmt.Errorf("erreur lors du scan: %w", err) } command := map[string]interface{}{ "id": id, "username": username, "status": status, "adresse": adresse, "total_prix": totalPrix, "created_at": createdAt, "updated_at": updatedAt, } if livreurAssign.Valid { command["livreur_assign"] = livreurAssign.String } else { command["livreur_assign"] = nil } commands = append(commands, command) } if err = rows.Err(); err != nil { log.Printf("❌ [GetCommandsByStatus] Erreur itération: %v", err) return nil, fmt.Errorf("erreur lors de l'itération: %w", err) } log.Printf("✅ [GetCommandsByStatus] %d commandes trouvées", len(commands)) return commands, nil } // GetRecentCompletedOrders récupère les N dernières commandes terminées d'un utilisateur // ✅ Utile pour afficher les dernières commandes dans le dashboard func (d *Database) GetRecentCompletedOrders(username string, limit int) ([]map[string]interface{}, error) { log.Printf("📚 [GetRecentCompleted] START - username=%s, limit=%d", username, limit) query := ` SELECT id, username, status, adresse, total_prix, livreur_assign, created_at, updated_at FROM commandes WHERE username = $1 AND status = 'approved' ORDER BY created_at DESC LIMIT $2 ` rows, err := d.Query(query, username, limit) if err != nil { log.Printf("❌ [GetRecentCompleted] Erreur query: %v", err) return nil, fmt.Errorf("erreur lors de la récupération: %w", err) } defer rows.Close() var commands []map[string]interface{} for rows.Next() { var id int var username, status, adresse string var livreurAssign sql.NullString var totalPrix float64 var createdAt, updatedAt time.Time err := rows.Scan( &id, &username, &status, &adresse, &totalPrix, &livreurAssign, &createdAt, &updatedAt, ) if err != nil { log.Printf("❌ [GetRecentCompleted] Erreur scan: %v", err) return nil, fmt.Errorf("erreur lors du scan: %w", err) } command := map[string]interface{}{ "id": id, "username": username, "status": status, "adresse": adresse, "total_prix": totalPrix, "created_at": createdAt, "updated_at": updatedAt, } if livreurAssign.Valid { command["livreur_assign"] = livreurAssign.String } else { command["livreur_assign"] = nil } commands = append(commands, command) } if err = rows.Err(); err != nil { log.Printf("❌ [GetRecentCompleted] Erreur itération: %v", err) return nil, fmt.Errorf("erreur lors de l'itération: %w", err) } log.Printf("✅ [GetRecentCompleted] %d commandes récentes trouvées", len(commands)) return commands, nil }