Files
projet_gestion_commande/backend/gestion/db/db_delivery.go
T
2026-05-13 16:43:20 +02:00

182 lines
6.1 KiB
Go

package db
import (
"fmt"
"log"
"slices"
"gorm.io/gorm"
)
// GetAvailableDeliveryPersons récupère tous les livreurs disponibles
func (d *Database) GetAvailableDeliveryPersons() ([]map[string]any, error) {
var livreurs []map[string]any
err := d.GDB.Raw(`
SELECT id, username, total, livraison
FROM users
WHERE role = 'livreur'
ORDER BY username`).Scan(&livreurs).Error
if err != nil {
return nil, fmt.Errorf("erreur lors de la récupération des livreurs: %w", err)
}
return livreurs, nil
}
// Admin appelle cette fonction pour assigner un livreur
func (d *Database) AssignDeliveryPerson(commandID int, livreurUsername string) error {
log.Printf("📦 [AssignDeliveryPerson] START - commandID=%d, livreur=%s", commandID, livreurUsername)
return d.GDB.Transaction(func(tx *gorm.DB) error {
var roleResult struct {
Role string `gorm:"column:role"`
}
err := tx.Raw(`SELECT role FROM users WHERE username = ? FOR UPDATE`, livreurUsername).Scan(&roleResult).Error
if err != nil {
log.Printf("❌ Erreur vérification livreur: %v", err)
return fmt.Errorf("erreur lors de la vérification du livreur: %w", err)
}
if roleResult.Role == "" {
log.Printf("❌ Livreur '%s' non trouvé", livreurUsername)
return fmt.Errorf("livreur non trouvé")
}
if roleResult.Role != "livreur" {
log.Printf("❌ L'utilisateur '%s' n'est pas un livreur (role=%s)", livreurUsername, roleResult.Role)
return fmt.Errorf("l'utilisateur n'est pas un livreur")
}
var cmdResult struct {
Status string `gorm:"column:status"`
LivreurAssign *string `gorm:"column:livreur_assign"`
}
err = tx.Raw(`SELECT status, livreur_assign FROM commandes WHERE id = ? FOR UPDATE`, commandID).Scan(&cmdResult).Error
if err != nil {
log.Printf("❌ Erreur vérification commande: %v", err)
return fmt.Errorf("erreur lors de la vérification de la commande: %w", err)
}
if cmdResult.Status == "" {
log.Printf("❌ Commande %d non trouvée", commandID)
return fmt.Errorf("commande non trouvée")
}
validStatusesForAssignment := []string{"pending", "assigned"}
if !slices.Contains(validStatusesForAssignment, cmdResult.Status) {
log.Printf("❌ Statut invalide pour assignation: %s", cmdResult.Status)
return fmt.Errorf("commande en statut '%s', impossible d'assigner un livreur", cmdResult.Status)
}
result := tx.Exec(`
UPDATE commandes
SET livreur_assign = ?,
status = 'assigned',
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
AND status IN ('pending', 'assigned')`, livreurUsername, commandID)
if result.Error != nil {
log.Printf("❌ Erreur UPDATE: %v", result.Error)
return fmt.Errorf("erreur lors de l'assignation du livreur: %w", result.Error)
}
if result.RowsAffected == 0 {
log.Printf("❌ Impossible d'assigner: conditions non remplies")
return fmt.Errorf("impossible d'assigner la commande (déjà assignée ou statut changé)")
}
if err := tx.Exec(`
INSERT INTO command_logs (command_id, status, message, author, created_at)
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)`,
commandID, "assigned",
fmt.Sprintf("Livraison assignée au livreur %s", livreurUsername),
"admin",
).Error; err != nil {
log.Printf("⚠️ Erreur ajout log: %v", err)
// Non bloquant
}
return nil
})
}
// GetDeliveryPersonCommands récupère les commandes assignées à un livreur
func (d *Database) GetDeliveryPersonCommands(livreurUsername string, status string) ([]map[string]any, error) {
query := `SELECT id, username, status, adresse, total_prix::float8 as total_prix, livreur_assign, created_at, updated_at
FROM commandes
WHERE livreur_assign = ?`
args := []any{livreurUsername}
if status != "" {
query += " AND status = ?"
args = append(args, status)
}
query += " ORDER BY created_at DESC"
var commands []map[string]any
if err := d.GDB.Raw(query, args...).Scan(&commands).Error; err != nil {
return nil, fmt.Errorf("erreur lors de la récupération des commandes: %w", err)
}
return commands, nil
}
func (d *Database) ApproveDelivery(commandID int, clientUsername string) error {
return d.GDB.Transaction(func(tx *gorm.DB) error {
var cmdResult struct {
Username string `gorm:"column:username"`
Status string `gorm:"column:status"`
LivreurAssign *string `gorm:"column:livreur_assign"`
}
err := tx.Raw(`
SELECT username, status, livreur_assign
FROM commandes WHERE id = ? FOR UPDATE`, commandID).Scan(&cmdResult).Error
if err != nil {
return fmt.Errorf("erreur lors de la vérification de la commande: %w", err)
}
if cmdResult.Username == "" {
return fmt.Errorf("commande non trouvée")
}
if cmdResult.Username != clientUsername {
return fmt.Errorf("cette commande ne vous appartient pas")
}
if cmdResult.Status != "livre" {
return fmt.Errorf("cette commande n'est pas encore livrée (statut actuel: %s)", cmdResult.Status)
}
result := tx.Exec(`
UPDATE commandes
SET status = 'approved', updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND status = 'livre' AND username = ?`, commandID, clientUsername)
if result.Error != nil {
return fmt.Errorf("erreur lors de l'approbation de la livraison: %w", result.Error)
}
if result.RowsAffected == 0 {
return fmt.Errorf("impossible d'approuver: statut changé ou commande introuvable")
}
if cmdResult.LivreurAssign != nil && *cmdResult.LivreurAssign != "" {
res := tx.Exec(`
UPDATE users
SET livraison = livraison + 1,
total = total + 1,
updated_at = CURRENT_TIMESTAMP
WHERE username = ? AND role = 'livreur'`, *cmdResult.LivreurAssign)
if res.Error != nil {
log.Printf("⚠️ Erreur incrémentation livreur: %v", res.Error)
} else if res.RowsAffected > 0 {
log.Printf(" ✅ Compteur livreur incrémenté: %s", *cmdResult.LivreurAssign)
}
}
if err := tx.Exec(`
INSERT INTO command_logs (command_id, status, message, author, created_at)
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)`,
commandID, "approved",
fmt.Sprintf("Livraison approuvée par le client %s", clientUsername),
clientUsername,
).Error; err != nil {
log.Printf("⚠️ Erreur ajout log: %v", err)
}
return nil
})
}