chore: fix UI

This commit is contained in:
2026-04-26 18:23:50 +02:00
parent 322882d587
commit a120ad6391
11 changed files with 317 additions and 44 deletions
+110 -1
View File
@@ -754,8 +754,26 @@ func ApplyClientPenalty(c *gin.Context) {
return
}
// Vérifier si amende == solde parrainage → compensation automatique
referralBalance, err := database.GetClientReferralBalance(req.Username)
if err == nil && float64(req.Points) == referralBalance && referralBalance > 0 {
if err := database.DebitReferralBalance(req.Username, referralBalance); err != nil {
utils.ServerErr(c, "Erreur débit solde parrainage", err)
return
}
log.Printf("🔄 [PENALTY] Compensation parrainage pour %s: amende %d€ annulée, solde parrainage %.2f€ débité par %s",
req.Username, req.Points, referralBalance, adminUsername)
c.JSON(http.StatusOK, gin.H{
"success": true,
"username": req.Username,
"compensated": true,
"message": "Amende annulée — solde parrainage débité en compensation",
})
return
}
// ✅ APPLIQUER PÉNALITÉ
err := database.AddClientPenalty(req.Username, req.Points)
err = database.AddClientPenalty(req.Username, req.Points)
if err != nil {
log.Printf("❌ [PENALTY] Erreur: %v", err)
@@ -1055,6 +1073,97 @@ func AddClientPointsAdmin(c *gin.Context) {
})
}
// SubtractClientPointsAdmin retire des points à un client (plancher à 0)
// POST /api/v2/admin/protected/client/:username/points/subtract
// Body: {"pool_key": "pool_0", "points": 10}
func SubtractClientPointsAdmin(c *gin.Context) {
userRole := c.GetString("role")
if userRole != "admin" && userRole != "cabine" {
c.JSON(http.StatusForbidden, gin.H{"error": "Accès refusé"})
return
}
username := c.Param("username")
if username == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Username requis"})
return
}
var req struct {
PoolKey string `json:"pool_key" binding:"required"`
Points int `json:"points" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides"})
return
}
if req.Points <= 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "Le nombre de points à retirer doit être positif"})
return
}
database := c.MustGet("database").(*db.Database)
settings, err := database.GetSettings()
if err != nil {
utils.ServerErr(c, "Erreur récupération paramètres", err)
return
}
poolExists := false
for _, pool := range settings.PointsPools {
if pool.Key == req.PoolKey {
poolExists = true
break
}
}
if !poolExists {
c.JSON(http.StatusBadRequest, gin.H{"error": "Pool de points invalide"})
return
}
// Récupérer le client pour vérifier le solde actuel
client, err := database.GetClientByUsername(username)
if err != nil || client == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Client non trouvé"})
return
}
current := client.PointsExtra[req.PoolKey]
// Plancher à 0
toSubtract := req.Points
if toSubtract > current {
toSubtract = current
}
if toSubtract == 0 {
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "Aucun point à retirer (solde déjà à 0)",
"username": username,
"pool_key": req.PoolKey,
"points": 0,
})
return
}
if err := database.AddClientPointsByCategory(username, -toSubtract, req.PoolKey); err != nil {
utils.ServerErr(c, "Erreur retrait de points", err)
return
}
log.Printf("✅ [SUBTRACT_POINTS] %d points (pool=%s) retirés à %s par %s",
toSubtract, req.PoolKey, username, c.GetString("username"))
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "Points retirés avec succès",
"username": username,
"pool_key": req.PoolKey,
"points": toSubtract,
})
}
// ============================================
// STATISTIQUES TEMPS RÉEL
// ============================================