183 lines
5.0 KiB
Go
183 lines
5.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"gestion/db"
|
|
"gestion/models"
|
|
"gestion/utils"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// GetMyPointsRewards retourne les points et les récompenses disponibles du client connecté.
|
|
// La récompense est globale : son seuil s'applique indépendamment à chaque pool.
|
|
func GetMyPointsRewards(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
|
|
settings, err := database.GetSettings()
|
|
if err != nil {
|
|
utils.ServerErr(c, "Erreur lecture paramètres", err)
|
|
return
|
|
}
|
|
|
|
if !settings.PointsEnabled || len(settings.PointsPools) == 0 {
|
|
c.JSON(http.StatusOK, gin.H{"enabled": false, "pools": []gin.H{}, "reward": nil})
|
|
return
|
|
}
|
|
|
|
pointsExtra, pointsRedeemed, err := database.GetClientPointsAndRewards(username)
|
|
if err != nil {
|
|
utils.ServerErr(c, "Erreur lecture points", err)
|
|
return
|
|
}
|
|
|
|
reward := settings.PointsReward
|
|
|
|
type PoolInfo struct {
|
|
Key string `json:"key"`
|
|
Name string `json:"name"`
|
|
Points int `json:"points"`
|
|
RewardsEarned int `json:"rewards_earned"`
|
|
RewardsClaimed int `json:"rewards_claimed"`
|
|
RewardsAvailable int `json:"rewards_available"`
|
|
EligibleConfigs []models.RewardCategoryConfig `json:"eligible_configs"`
|
|
}
|
|
|
|
pools := make([]PoolInfo, 0, len(settings.PointsPools))
|
|
for _, pool := range settings.PointsPools {
|
|
pts := pointsExtra[pool.Key]
|
|
redeemed := pointsRedeemed[pool.Key]
|
|
|
|
var earned, available int
|
|
if reward != nil && reward.Threshold > 0 {
|
|
earned = pts / reward.Threshold
|
|
available = earned - redeemed
|
|
if available < 0 {
|
|
available = 0
|
|
}
|
|
}
|
|
|
|
// Filtrer les category_configs aux seules catégories du pool
|
|
poolCats := make(map[string]bool, len(pool.Categories))
|
|
for _, c := range pool.Categories {
|
|
poolCats[c] = true
|
|
}
|
|
eligibleConfigs := make([]models.RewardCategoryConfig, 0)
|
|
if reward != nil {
|
|
for _, cfg := range reward.CategoryConfigs {
|
|
if poolCats[cfg.Category] {
|
|
eligibleConfigs = append(eligibleConfigs, cfg)
|
|
}
|
|
}
|
|
}
|
|
|
|
pools = append(pools, PoolInfo{
|
|
Key: pool.Key,
|
|
Name: pool.Name,
|
|
Points: pts,
|
|
RewardsEarned: earned,
|
|
RewardsClaimed: redeemed,
|
|
RewardsAvailable: available,
|
|
EligibleConfigs: eligibleConfigs,
|
|
})
|
|
}
|
|
|
|
// Retourner la récompense sans category_configs (les configs sont par pool)
|
|
var rewardMeta gin.H
|
|
if reward != nil {
|
|
rewardMeta = gin.H{
|
|
"threshold": reward.Threshold,
|
|
"type": reward.Type,
|
|
"description": reward.Description,
|
|
}
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"enabled": true, "pools": pools, "reward": rewardMeta})
|
|
}
|
|
|
|
// ClaimMyReward réclame une récompense sur un pool donné si le client a atteint le seuil.
|
|
func ClaimMyReward(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
PoolKey string `json:"pool_key" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "pool_key requis"})
|
|
return
|
|
}
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
|
|
settings, err := database.GetSettings()
|
|
if err != nil {
|
|
utils.ServerErr(c, "Erreur lecture paramètres", err)
|
|
return
|
|
}
|
|
|
|
if !settings.PointsEnabled {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "Système de points désactivé"})
|
|
return
|
|
}
|
|
|
|
reward := settings.PointsReward
|
|
if reward == nil || reward.Threshold <= 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Aucune récompense configurée"})
|
|
return
|
|
}
|
|
|
|
// Vérifier que le pool existe
|
|
poolExists := false
|
|
for _, p := range settings.PointsPools {
|
|
if p.Key == req.PoolKey {
|
|
poolExists = true
|
|
break
|
|
}
|
|
}
|
|
if !poolExists {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Pool introuvable"})
|
|
return
|
|
}
|
|
|
|
remaining, err := database.ClaimPoolReward(username, req.PoolKey, reward.Threshold)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "pas de récompense disponible") {
|
|
c.JSON(http.StatusConflict, gin.H{"error": "Pas assez de points pour réclamer une récompense"})
|
|
return
|
|
}
|
|
utils.ServerErr(c, "Erreur réclamation récompense", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"description": reward.Description,
|
|
"remaining_rewards": remaining,
|
|
})
|
|
}
|
|
|
|
// AdminResetClientRedeemed remet à zéro les récompenses réclamées d'un client (admin).
|
|
func AdminResetClientRedeemed(c *gin.Context) {
|
|
username := c.Param("username")
|
|
poolKey := c.Query("pool_key")
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.ResetClientRedeemed(username, poolKey); err != nil {
|
|
utils.ServerErr(c, "Erreur reset récompenses", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|