Files
projet_gestion_commande/backend/gestion/db/db_sanction_client.go
T

176 lines
5.1 KiB
Go

// ============================================
// db/cancel_sanctions_db.go
// GESTION DES SANCTIONS ÉVOLUTIVES
// ============================================
package db
import (
"fmt"
"log"
)
// GetClientCancellationsCount récupère le nombre d'annulations tardives d'un client
func (d *Database) GetClientCancellationsCount(username string) (int, error) {
var count int
query := `SELECT COALESCE(cancellations_count, 0) FROM clients WHERE username = $1`
err := d.QueryRow(query, username).Scan(&count)
if err != nil {
log.Printf("❌ [GetCancellationsCount] Erreur: %v", err)
return 0, fmt.Errorf("erreur récupération compteur: %w", err)
}
return count, nil
}
// IncrementClientCancellationsCount incrémente le compteur d'annulations
func (d *Database) IncrementClientCancellationsCount(username string) error {
query := `UPDATE clients
SET cancellations_count = COALESCE(cancellations_count, 0) + 1,
updated_at = CURRENT_TIMESTAMP
WHERE username = $1`
result, err := d.Exec(query, username)
if err != nil {
log.Printf("❌ [IncrementCancellations] Erreur: %v", err)
return fmt.Errorf("erreur incrémentation: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("erreur vérification: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("client non trouvé")
}
log.Printf("✅ [IncrementCancellations] Compteur incrémenté pour %s", username)
// Invalider le cache Redis
cacheKey := fmt.Sprintf("client:%s", username)
Redis.Del(RedisCtx, cacheKey)
return nil
}
// CalculateCancellationPenalty calcule la pénalité selon l'historique
// 1ère fois: 20 points
// 2ème fois: 50 points
// 3ème fois: 100 points
// 4ème+ fois: 150 points
func (d *Database) CalculateCancellationPenalty(username string) (int, error) {
count, err := d.GetClientCancellationsCount(username)
if err != nil {
return 0, err
}
var penalty int
switch {
case count == 0:
penalty = 20 // Première annulation tardive
case count == 1:
penalty = 50 // Deuxième annulation tardive
case count == 2:
penalty = 100 // Troisième annulation tardive
default:
penalty = 150 // À partir de la 4ème annulation
}
log.Printf("💰 [CalculatePenalty] Client %s - Annulations: %d → Pénalité: %d points",
username, count, penalty)
return penalty, nil
}
// ApplyCancellationPenalty applique une pénalité, incrémente le compteur et REMET TOUS LES POINTS À ZÉRO
// ✅ MODIFIÉ: Récupère les points AVANT de les remettre à zéro pour le log dans le handler
func (d *Database) ApplyCancellationPenalty(username string) (int, error) {
// ✅ ÉTAPE 0: Récupérer les points AVANT modification (pour le handler)
// Note: Le handler récupère aussi les points, mais on garde cette fonction autonome
// Calculer la pénalité AVANT d'incrémenter
penalty, err := d.CalculateCancellationPenalty(username)
if err != nil {
return 0, err
}
log.Printf("⚠️ [ApplyCancellationPenalty] Client %s - Pénalité calculée: %d points", username, penalty)
// ✅ ÉTAPE 1: Incrémenter le compteur d'annulations
if err := d.IncrementClientCancellationsCount(username); err != nil {
return 0, err
}
// ✅ ÉTAPE 2: Mettre l'amende au montant de la pénalité ET remettre TOUS les points à zéro
query := `UPDATE clients
SET amende = $1,
point = 0,
point_zipette = 0,
updated_at = CURRENT_TIMESTAMP
WHERE username = $2`
result, err := d.Exec(query, float64(penalty), username)
if err != nil {
log.Printf("❌ [ApplyCancellationPenalty] Erreur UPDATE: %v", err)
return 0, fmt.Errorf("erreur application pénalité: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return 0, fmt.Errorf("erreur vérification: %w", err)
}
if rowsAffected == 0 {
return 0, fmt.Errorf("client non trouvé")
}
log.Printf("✅ [ApplyCancellationPenalty] %d points d'amende appliqués à %s + TOUS points remis à 0 (weed + zipette)", penalty, username)
// Invalider le cache Redis
cacheKey := fmt.Sprintf("client:%s", username)
Redis.Del(RedisCtx, cacheKey)
return penalty, nil
}
// GetClientCancellationHistory récupère l'historique d'annulations d'un client
func (d *Database) GetClientCancellationHistory(username string) (map[string]interface{}, error) {
count, err := d.GetClientCancellationsCount(username)
if err != nil {
return nil, err
}
// Calculer la prochaine pénalité
var nextPenalty int
switch count {
case 0:
nextPenalty = 20
case 1:
nextPenalty = 50
case 2:
nextPenalty = 100
default:
nextPenalty = 150
}
// Récupérer l'amende actuelle
client, err := d.GetClientByUsername(username)
var currentAmende float64
if err == nil {
currentAmende = client.Amende
}
return map[string]interface{}{
"cancellations_count": count,
"current_amende": currentAmende,
"next_penalty": nextPenalty,
"penalty_scale": map[string]int{
"1st": 20,
"2nd": 50,
"3rd": 100,
"4th+": 150,
},
"warning": "TOUS les points de fidélité (weed/hash ET zipette) seront remis à zéro lors de la prochaine annulation tardive",
}, nil
}