376 lines
12 KiB
Go
376 lines
12 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"gestion/db"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// RegisterPushToken enregistre le push token Expo d'un client
|
|
// POST /api/v1/push-token
|
|
func RegisterPushToken(c *gin.Context) {
|
|
clientID := c.GetInt("client_id")
|
|
if clientID == 0 {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
PushToken string `json:"push_token" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "push_token requis"})
|
|
return
|
|
}
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.SaveClientPushToken(clientID, req.PushToken); err != nil {
|
|
log.Printf("❌ [PUSH_TOKEN] Erreur sauvegarde token pour client %d: %v", clientID, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur enregistrement push token"})
|
|
return
|
|
}
|
|
|
|
log.Printf("✅ [PUSH_TOKEN] Token enregistré pour client %d", clientID)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// UnregisterPushToken supprime le push token d'un client (au logout)
|
|
// DELETE /api/v1/push-token
|
|
func UnregisterPushToken(c *gin.Context) {
|
|
clientID := c.GetInt("client_id")
|
|
if clientID == 0 {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.DeleteClientPushToken(clientID); err != nil {
|
|
log.Printf("❌ [PUSH_TOKEN] Erreur suppression token pour client %d: %v", clientID, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur suppression push token"})
|
|
return
|
|
}
|
|
|
|
log.Printf("✅ [PUSH_TOKEN] Token supprimé pour client %d", clientID)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// GetClientNotifications retourne les notifications du client connecté
|
|
// GET /api/v1/notifications
|
|
func GetClientNotifications(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
notifKey := "notifications:" + username
|
|
|
|
// Récupérer toutes les notifications (max 50)
|
|
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, 49).Result()
|
|
if err != nil {
|
|
log.Printf("❌ [GET_NOTIFICATIONS] Erreur Redis: %v", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur récupération notifications"})
|
|
return
|
|
}
|
|
|
|
type Notification struct {
|
|
CommandID int `json:"command_id"`
|
|
Type string `json:"type"`
|
|
Message string `json:"message"`
|
|
CreatedAt string `json:"created_at"`
|
|
Read bool `json:"read"`
|
|
}
|
|
|
|
notifications := make([]Notification, 0, len(results))
|
|
unreadCount := 0
|
|
|
|
for _, raw := range results {
|
|
var n Notification
|
|
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
|
continue
|
|
}
|
|
notifications = append(notifications, n)
|
|
if !n.Read {
|
|
unreadCount++
|
|
}
|
|
}
|
|
|
|
log.Printf("✅ [GET_NOTIFICATIONS] %d notifications pour %s (%d non lues)", len(notifications), username, unreadCount)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"notifications": notifications,
|
|
"unread_count": unreadCount,
|
|
"total": len(notifications),
|
|
})
|
|
}
|
|
|
|
// RegisterLivreurPushToken enregistre le push token Expo d'un livreur
|
|
// POST /api/v1/livreur/push-token
|
|
func RegisterLivreurPushToken(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
PushToken string `json:"push_token" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "push_token requis"})
|
|
return
|
|
}
|
|
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.SaveUserPushToken(username, req.PushToken); err != nil {
|
|
log.Printf("❌ [LIVREUR_PUSH_TOKEN] Erreur sauvegarde token pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur enregistrement push token"})
|
|
return
|
|
}
|
|
|
|
log.Printf("✅ [LIVREUR_PUSH_TOKEN] Token enregistré pour livreur %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// UnregisterLivreurPushToken supprime le push token d'un livreur (au logout)
|
|
// DELETE /api/v1/livreur/push-token
|
|
func UnregisterLivreurPushToken(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)
|
|
if err := database.DeleteUserPushToken(username); err != nil {
|
|
log.Printf("❌ [LIVREUR_PUSH_TOKEN] Erreur suppression token pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur suppression push token"})
|
|
return
|
|
}
|
|
|
|
log.Printf("✅ [LIVREUR_PUSH_TOKEN] Token supprimé pour livreur %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// GetLivreurNotifications retourne les notifications du livreur connecté
|
|
// GET /api/v1/livreur/notifications
|
|
func GetLivreurNotifications(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
notifKey := "notifications:" + username
|
|
|
|
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, 49).Result()
|
|
if err != nil {
|
|
log.Printf("❌ [LIVREUR_NOTIFICATIONS] Erreur Redis: %v", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur récupération notifications"})
|
|
return
|
|
}
|
|
|
|
type Notification struct {
|
|
CommandID int `json:"command_id"`
|
|
Type string `json:"type"`
|
|
Message string `json:"message"`
|
|
CreatedAt string `json:"created_at"`
|
|
Read bool `json:"read"`
|
|
}
|
|
|
|
notifications := make([]Notification, 0, len(results))
|
|
unreadCount := 0
|
|
|
|
for _, raw := range results {
|
|
var n Notification
|
|
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
|
continue
|
|
}
|
|
notifications = append(notifications, n)
|
|
if !n.Read {
|
|
unreadCount++
|
|
}
|
|
}
|
|
|
|
log.Printf("✅ [LIVREUR_NOTIFICATIONS] %d notifications pour %s (%d non lues)", len(notifications), username, unreadCount)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"notifications": notifications,
|
|
"unread_count": unreadCount,
|
|
"total": len(notifications),
|
|
})
|
|
}
|
|
|
|
// MarkLivreurNotificationsRead marque toutes les notifications du livreur comme lues
|
|
// POST /api/v1/livreur/notifications/read
|
|
func MarkLivreurNotificationsRead(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
notifKey := "notifications:" + username
|
|
|
|
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, -1).Result()
|
|
if err != nil {
|
|
log.Printf("❌ [LIVREUR_MARK_READ] Erreur Redis LRange: %v", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lecture notifications"})
|
|
return
|
|
}
|
|
|
|
markedCount := 0
|
|
for i, raw := range results {
|
|
var n map[string]interface{}
|
|
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
|
continue
|
|
}
|
|
if read, ok := n["read"].(bool); ok && read {
|
|
continue
|
|
}
|
|
n["read"] = true
|
|
updated, _ := json.Marshal(n)
|
|
db.Redis.LSet(db.RedisCtx, notifKey, int64(i), string(updated))
|
|
markedCount++
|
|
}
|
|
|
|
log.Printf("✅ [LIVREUR_MARK_READ] %d notifications marquées lues pour %s", markedCount, username)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"marked_count": markedCount,
|
|
})
|
|
}
|
|
|
|
// RegisterAdminPushToken enregistre le push token d'un admin
|
|
// POST /api/v2/admin/protected/push-token
|
|
func RegisterAdminPushToken(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
var req struct {
|
|
PushToken string `json:"push_token" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "push_token requis"})
|
|
return
|
|
}
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.SaveUserPushToken(username, req.PushToken); err != nil {
|
|
log.Printf("❌ [ADMIN_PUSH_TOKEN] Erreur sauvegarde pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur enregistrement push token"})
|
|
return
|
|
}
|
|
log.Printf("✅ [ADMIN_PUSH_TOKEN] Token enregistré pour admin %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// UnregisterAdminPushToken supprime le push token d'un admin (au logout)
|
|
// DELETE /api/v2/admin/protected/push-token
|
|
func UnregisterAdminPushToken(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)
|
|
if err := database.DeleteUserPushToken(username); err != nil {
|
|
log.Printf("❌ [ADMIN_PUSH_TOKEN] Erreur suppression pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur suppression push token"})
|
|
return
|
|
}
|
|
log.Printf("✅ [ADMIN_PUSH_TOKEN] Token supprimé pour admin %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// RegisterCabinePushToken enregistre le push token d'un agent cabine
|
|
// POST /api/v1/cabine/push-token
|
|
func RegisterCabinePushToken(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
var req struct {
|
|
PushToken string `json:"push_token" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "push_token requis"})
|
|
return
|
|
}
|
|
database := c.MustGet("database").(*db.Database)
|
|
if err := database.SaveUserPushToken(username, req.PushToken); err != nil {
|
|
log.Printf("❌ [CABINE_PUSH_TOKEN] Erreur sauvegarde pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur enregistrement push token"})
|
|
return
|
|
}
|
|
log.Printf("✅ [CABINE_PUSH_TOKEN] Token enregistré pour cabine %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// UnregisterCabinePushToken supprime le push token d'un agent cabine (au logout)
|
|
// DELETE /api/v1/cabine/push-token
|
|
func UnregisterCabinePushToken(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)
|
|
if err := database.DeleteUserPushToken(username); err != nil {
|
|
log.Printf("❌ [CABINE_PUSH_TOKEN] Erreur suppression pour %s: %v", username, err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur suppression push token"})
|
|
return
|
|
}
|
|
log.Printf("✅ [CABINE_PUSH_TOKEN] Token supprimé pour cabine %s", username)
|
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
|
}
|
|
|
|
// MarkNotificationsRead marque toutes les notifications comme lues
|
|
// POST /api/v1/notifications/read
|
|
func MarkNotificationsRead(c *gin.Context) {
|
|
username := c.GetString("username")
|
|
if username == "" {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
|
return
|
|
}
|
|
|
|
notifKey := "notifications:" + username
|
|
|
|
// Récupérer toutes les notifications
|
|
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, -1).Result()
|
|
if err != nil {
|
|
log.Printf("❌ [MARK_NOTIFICATIONS_READ] Erreur Redis LRange: %v", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lecture notifications"})
|
|
return
|
|
}
|
|
|
|
// Réécrire chaque notification avec read=true
|
|
markedCount := 0
|
|
for i, raw := range results {
|
|
var n map[string]interface{}
|
|
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
|
continue
|
|
}
|
|
if read, ok := n["read"].(bool); ok && read {
|
|
continue
|
|
}
|
|
n["read"] = true
|
|
updated, _ := json.Marshal(n)
|
|
db.Redis.LSet(db.RedisCtx, notifKey, int64(i), string(updated))
|
|
markedCount++
|
|
}
|
|
|
|
log.Printf("✅ [MARK_NOTIFICATIONS_READ] %d notifications marquées lues pour %s", markedCount, username)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"marked_count": markedCount,
|
|
})
|
|
}
|