chore: update
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -497,3 +498,119 @@ func ReportDeliveryIssue(c *gin.Context) {
|
||||
log.Printf("📋 [ISSUE] Créé par %s pour commande #%d: %s", username, commandID, req.IssueType)
|
||||
c.JSON(http.StatusCreated, gin.H{"success": true, "issue": issue})
|
||||
}
|
||||
|
||||
// GET /api/v1/livreur/stats
|
||||
func GetMyDeliveryStats(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
|
||||
username, exists := c.Get("username")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
if c.GetString("role") != "livreur" {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Accès réservé aux livreurs"})
|
||||
return
|
||||
}
|
||||
usernameStr := username.(string)
|
||||
gdb := database.GDB
|
||||
|
||||
type DayRow struct {
|
||||
Day time.Time `gorm:"column:day"`
|
||||
Count int `gorm:"column:count"`
|
||||
Revenue float64 `gorm:"column:revenue"`
|
||||
}
|
||||
type WeekRow struct {
|
||||
WeekNum int `gorm:"column:week_num"`
|
||||
Year int `gorm:"column:year"`
|
||||
Count int `gorm:"column:count"`
|
||||
Revenue float64 `gorm:"column:revenue"`
|
||||
}
|
||||
type MonthRow struct {
|
||||
MonthNum int `gorm:"column:month_num"`
|
||||
Year int `gorm:"column:year"`
|
||||
Count int `gorm:"column:count"`
|
||||
Revenue float64 `gorm:"column:revenue"`
|
||||
}
|
||||
|
||||
var dayRows []DayRow
|
||||
gdb.Raw(`
|
||||
SELECT DATE(updated_at) AS day,
|
||||
COUNT(*) AS count,
|
||||
COALESCE(SUM(total_prix), 0) AS revenue
|
||||
FROM commandes
|
||||
WHERE livreur_assign = ?
|
||||
AND status IN ('livre', 'approved')
|
||||
AND updated_at >= NOW() - INTERVAL '30 days'
|
||||
GROUP BY DATE(updated_at)
|
||||
ORDER BY day
|
||||
`, usernameStr).Scan(&dayRows)
|
||||
|
||||
var weekRows []WeekRow
|
||||
gdb.Raw(`
|
||||
SELECT EXTRACT(WEEK FROM updated_at)::int AS week_num,
|
||||
EXTRACT(YEAR FROM updated_at)::int AS year,
|
||||
COUNT(*) AS count,
|
||||
COALESCE(SUM(total_prix), 0) AS revenue
|
||||
FROM commandes
|
||||
WHERE livreur_assign = ?
|
||||
AND status IN ('livre', 'approved')
|
||||
AND updated_at >= NOW() - INTERVAL '12 weeks'
|
||||
GROUP BY week_num, year
|
||||
ORDER BY year, week_num
|
||||
`, usernameStr).Scan(&weekRows)
|
||||
|
||||
var monthRows []MonthRow
|
||||
gdb.Raw(`
|
||||
SELECT EXTRACT(MONTH FROM updated_at)::int AS month_num,
|
||||
EXTRACT(YEAR FROM updated_at)::int AS year,
|
||||
COUNT(*) AS count,
|
||||
COALESCE(SUM(total_prix), 0) AS revenue
|
||||
FROM commandes
|
||||
WHERE livreur_assign = ?
|
||||
AND status IN ('livre', 'approved')
|
||||
AND updated_at >= NOW() - INTERVAL '12 months'
|
||||
GROUP BY month_num, year
|
||||
ORDER BY year, month_num
|
||||
`, usernameStr).Scan(&monthRows)
|
||||
|
||||
monthNames := [13]string{"", "Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Jul", "Aoû", "Sep", "Oct", "Nov", "Déc"}
|
||||
|
||||
byDay := make([]gin.H, len(dayRows))
|
||||
for i, r := range dayRows {
|
||||
byDay[i] = gin.H{
|
||||
"label": r.Day.Format("02/01"),
|
||||
"count": r.Count,
|
||||
"revenue": r.Revenue,
|
||||
}
|
||||
}
|
||||
|
||||
byWeek := make([]gin.H, len(weekRows))
|
||||
for i, r := range weekRows {
|
||||
byWeek[i] = gin.H{
|
||||
"label": fmt.Sprintf("S%d", r.WeekNum),
|
||||
"count": r.Count,
|
||||
"revenue": r.Revenue,
|
||||
}
|
||||
}
|
||||
|
||||
byMonth := make([]gin.H, len(monthRows))
|
||||
for i, r := range monthRows {
|
||||
label := "?"
|
||||
if r.MonthNum >= 1 && r.MonthNum <= 12 {
|
||||
label = monthNames[r.MonthNum]
|
||||
}
|
||||
byMonth[i] = gin.H{
|
||||
"label": label,
|
||||
"count": r.Count,
|
||||
"revenue": r.Revenue,
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"by_day": byDay,
|
||||
"by_week": byWeek,
|
||||
"by_month": byMonth,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -379,6 +379,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
|
||||
// QUEUE PERSONNELLE
|
||||
// ============================================
|
||||
livreurGroupV1.GET("/queue", handlers.GetMyQueue)
|
||||
livreurGroupV1.GET("/stats", handlers.GetMyDeliveryStats)
|
||||
|
||||
// ============================================
|
||||
// ALERTES POLICE
|
||||
|
||||
@@ -19,6 +19,8 @@ TELEGRAM_WEBHOOK_URL=https://uber-demo.club/webhook/telegram
|
||||
BACKEND_LINK_SECRET=QxAEEGUGRMtWbNvC2REo27haN78Rl5c5EQ
|
||||
LBTELEGRAM_URL=http://lbtelegram:8081
|
||||
LBTELEGRAM_BOT1_USERNAME=GetRezStealer_bot
|
||||
LBTELEGRAM_BOT2_USERNAME=rezDJDFJSFUltraFast_bot
|
||||
BACKEND_LINK_SECRET=change_me_internal_secret
|
||||
API_PORT=8080
|
||||
FRONTEND_PORT=5173
|
||||
GIN_MODE=release
|
||||
|
||||
@@ -126,7 +126,23 @@ server {
|
||||
}
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Webhooks Telegram (LBTelegram — /webhook/bot1, /webhook/bot2…)
|
||||
# Webhook Telegram principal → backend Go
|
||||
# ---------------------------------------------------
|
||||
location = /webhook/telegram {
|
||||
limit_except POST { deny all; }
|
||||
|
||||
set $upstream_backend http://backend:8080;
|
||||
proxy_pass $upstream_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Webhooks LBTelegram (/webhook/bot1, /webhook/bot2…)
|
||||
# ---------------------------------------------------
|
||||
location /webhook/ {
|
||||
limit_except POST { deny all; }
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
services:
|
||||
# =========================================================
|
||||
# Backend Go
|
||||
# =========================================================
|
||||
backend:
|
||||
image: xor1234/backend-mln:pre-prod
|
||||
container_name: gestion-backend
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DB_HOST=${DB_HOST:-postgres}
|
||||
- DB_PORT=${DB_PORT:-5432}
|
||||
- DB_USER=${DB_USER:-postgres}
|
||||
- DB_PASSWORD=${DB_PASSWORD}
|
||||
- DB_NAME=${DB_NAME:-gestion_db}
|
||||
- DB_SSLMODE=${DB_SSLMODE:-disable}
|
||||
- SESSION_SECRET=${SESSION_SECRET}
|
||||
- USER_JWT_SECRET=${USER_JWT_SECRET}
|
||||
- USER_JWT_SECRET_OLD=${USER_JWT_SECRET_OLD}
|
||||
- ADMIN_JWT_SECRET=${ADMIN_JWT_SECRET}
|
||||
- ADMIN_JWT_SECRET_OLD=${ADMIN_JWT_SECRET_OLD}
|
||||
- REDIS_HOST=${REDIS_HOST:-redis}
|
||||
- REDIS_PORT=${REDIS_PORT:-6379}
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
- TOMTOM_API_KEY=${TOMTOM_API_KEY}
|
||||
- TOMTOM_API_KEY_1=${TOMTOM_API_KEY_1}
|
||||
- TOMTOM_API_KEY_2=${TOMTOM_API_KEY_2}
|
||||
- TOMTOM_API_KEY_3=${TOMTOM_API_KEY_3}
|
||||
- API_PORT=${API_PORT:-8080}
|
||||
- NOWPAYMENTS_IPN_SECRET=${NOWPAYMENTS_IPN_SECRET}
|
||||
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
||||
- TELEGRAM_BOT_USERNAME=${TELEGRAM_BOT_USERNAME}
|
||||
- TELEGRAM_WEBHOOK_SECRET=${TELEGRAM_WEBHOOK_SECRET}
|
||||
- TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL}
|
||||
- LBTELEGRAM_URL=http://lbtelegram:8081
|
||||
- LBTELEGRAM_BOT1_USERNAME=${LBTELEGRAM_BOT1_USERNAME:-GetRezStealer_bot}
|
||||
- LBTELEGRAM_BOT2_USERNAME=${LBTELEGRAM_BOT2_USERNAME:-rezDJDFJSFUltraFast_bot}
|
||||
- BACKEND_LINK_SECRET=${BACKEND_LINK_SECRET:-change_me_internal_secret}
|
||||
volumes:
|
||||
- backend_uploads:/app/uploads
|
||||
networks:
|
||||
- gestion-network
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
|
||||
# =========================================================
|
||||
# Frontend Web (React/Vite — servi en HTTP interne)
|
||||
# =========================================================
|
||||
frontend:
|
||||
image: xor1234/frontend-mln:pre-prod
|
||||
container_name: gestion-frontend
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gestion-network
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
waf:
|
||||
image: xor1234/backend-mln:waf-pre-prod
|
||||
container_name: gestion-waf
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DISABLE_MODSEC_ENV_SUBST=true
|
||||
- PARANOIA=2
|
||||
- ANOMALY_INBOUND=5
|
||||
- ANOMALY_OUTBOUND=4
|
||||
- MODSEC_AUDIT_LOG=/var/log/modsec/modsec_audit.log
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- backend_uploads:/usr/share/nginx/html/uploads:ro
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
- ./backend/nginx.conf:/etc/nginx/conf.d/app.conf:ro
|
||||
- ./backend/custom-rules.conf:/etc/nginx/modsec/custom-rules.conf:ro
|
||||
- /var/log/waf/nginx:/var/log/nginx
|
||||
- /var/log/waf/modsec:/var/log/modsec
|
||||
networks:
|
||||
- gestion-network
|
||||
depends_on:
|
||||
- backend
|
||||
- frontend
|
||||
|
||||
# =========================================================
|
||||
# PostgreSQL
|
||||
# =========================================================
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: gestion-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=${DB_USER:-postgres}
|
||||
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||
- POSTGRES_DB=${DB_NAME:-gestion_db}
|
||||
- PGDATA=/var/lib/postgresql/data/pgdata
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- gestion-network
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-gestion_db}",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# =========================================================
|
||||
# Redis
|
||||
# =========================================================
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: gestion-redis
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
redis-server
|
||||
--requirepass ${REDIS_PASSWORD}
|
||||
--appendonly yes
|
||||
--appendfsync everysec
|
||||
--maxmemory 256mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- gestion-network
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"redis-cli",
|
||||
"--no-auth-warning",
|
||||
"-a",
|
||||
"${REDIS_PASSWORD}",
|
||||
"ping",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# =========================================================
|
||||
# LBTelegram — Gateway Telegram load balancer
|
||||
# =========================================================
|
||||
lbtelegram:
|
||||
image: xor1234/load-balancer-tlg:latest
|
||||
container_name: gestion-lbtelegram
|
||||
restart: unless-stopped
|
||||
env_file: ./.env.lbtelegram
|
||||
environment:
|
||||
- REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0
|
||||
- DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}?sslmode=disable
|
||||
networks:
|
||||
- gestion-network
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
backend:
|
||||
condition: service_started
|
||||
|
||||
clamav:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1g
|
||||
cpus: 0.5
|
||||
image: clamav/clamav:latest
|
||||
container_name: gestion-clamav
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- backend_uploads:/app/uploads:ro
|
||||
- clamav_data:/var/lib/clamav
|
||||
networks:
|
||||
- gestion-network
|
||||
healthcheck:
|
||||
test: ["CMD", "clamdcheck.sh"]
|
||||
interval: 60s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 120s
|
||||
|
||||
dozzle-agent:
|
||||
image: amir20/dozzle:latest
|
||||
command: agent
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- "7007:7007"
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
gestion-network:
|
||||
driver: bridge
|
||||
internal: false
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: gestion-br0
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
driver: local
|
||||
redis_data:
|
||||
driver: local
|
||||
backend_uploads:
|
||||
driver: local
|
||||
clamav_data:
|
||||
driver: local
|
||||
@@ -27,8 +27,13 @@ services:
|
||||
- TOMTOM_API_KEY_3=${TOMTOM_API_KEY_3}
|
||||
- API_PORT=${API_PORT:-8080}
|
||||
- NOWPAYMENTS_IPN_SECRET=${NOWPAYMENTS_IPN_SECRET}
|
||||
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
||||
- TELEGRAM_BOT_USERNAME=${TELEGRAM_BOT_USERNAME}
|
||||
- TELEGRAM_WEBHOOK_SECRET=${TELEGRAM_WEBHOOK_SECRET}
|
||||
- TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL}
|
||||
- LBTELEGRAM_URL=http://lbtelegram:8081
|
||||
- LBTELEGRAM_BOT1_USERNAME=${LBTELEGRAM_BOT1_USERNAME:-rezsssnfdsjfdsfbot}
|
||||
- LBTELEGRAM_BOT1_USERNAME=${LBTELEGRAM_BOT1_USERNAME:-GetRezStealer_bot}
|
||||
- LBTELEGRAM_BOT2_USERNAME=${LBTELEGRAM_BOT2_USERNAME:-rezDJDFJSFUltraFast_bot}
|
||||
- BACKEND_LINK_SECRET=${BACKEND_LINK_SECRET:-change_me_internal_secret}
|
||||
volumes:
|
||||
- backend_uploads:/app/uploads
|
||||
@@ -145,7 +150,7 @@ services:
|
||||
image: xor1234/load-balancer-tlg:latest
|
||||
container_name: gestion-lbtelegram
|
||||
restart: unless-stopped
|
||||
env_file: ./lbtelegram.env
|
||||
env_file: ./.env.lbtelegram
|
||||
environment:
|
||||
- REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/0
|
||||
- DATABASE_URL=postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}?sslmode=disable
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Gateway
|
||||
PORT=8081
|
||||
ENV=production
|
||||
BOT_COUNT=2
|
||||
|
||||
# Bots Telegram
|
||||
BOT1_TOKEN=change_me_bot1_token
|
||||
BOT1_USERNAME=change_me_bot1_username
|
||||
BOT1_WEBHOOK_SECRET=change_me_bot1_webhook_secret
|
||||
|
||||
BOT2_TOKEN=change_me_bot2_token
|
||||
BOT2_USERNAME=change_me_bot2_username
|
||||
BOT2_WEBHOOK_SECRET=change_me_bot2_webhook_secret
|
||||
|
||||
# URL publique de la gateway (pour setWebhook Telegram)
|
||||
GATEWAY_URL=https://uber-demo.club
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=change_me_jwt_secret
|
||||
JWT_TTL_SECONDS=300
|
||||
|
||||
# Load balancer: roundrobin | leastconn | failover
|
||||
LB_STRATEGY=failover
|
||||
|
||||
# Health check interval en secondes
|
||||
HEALTH_CHECK_INTERVAL=30
|
||||
|
||||
# URL interne du backend pour valider les tokens de liaison
|
||||
BACKEND_LINK_URL=http://backend:8080/api/internal/telegram/link
|
||||
BACKEND_LINK_SECRET=change_me_backend_link_secret
|
||||
Reference in New Issue
Block a user