350 lines
9.2 KiB
Go
350 lines
9.2 KiB
Go
// ============================================
|
|
// 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
|
|
}
|