chore: build
Backend - Build & Lint / build (push) Failing after 16m14s

This commit is contained in:
2026-06-28 13:52:47 +02:00
parent 3be323fcfe
commit b8aab5643f
3 changed files with 119 additions and 13 deletions
+41 -12
View File
@@ -115,8 +115,6 @@ func (d *Database) RevenueByDayLast30(dayRevRows *[]models.DayRevenueRow, resetA
// ── Commandes par jour sur un mois calendaire complet ────────────────────────
// DailyMonthStatRow représente l'agrégat d'un jour donné (commandes, revenu,
// quantité vendue) au sein d'un mois calendaire.
type DailyMonthStatRow struct {
Day time.Time
Count int
@@ -124,10 +122,6 @@ type DailyMonthStatRow struct {
Quantity float64
}
// StatsByDayForMonth renvoie, pour chaque jour ayant au moins une commande dans
// le mois calendaire de `monthStart` (1er jour du mois, 00:00), le nombre de
// commandes (non annulées), le revenu (commandes approuvées) et la quantité
// totale d'articles vendus. resetAt filtre sur created_at si non nul.
func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time.Time, resetAt time.Time) error {
start := time.Date(monthStart.Year(), monthStart.Month(), 1, 0, 0, 0, 0, monthStart.Location())
end := start.AddDate(0, 1, 0)
@@ -137,7 +131,7 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
query := `
SELECT
d.day,
COALESCE(co.count, 0) AS count,
COALESCE(d.count, 0) AS count,
COALESCE(rv.revenue, 0) AS revenue,
COALESCE(qt.quantity, 0) AS quantity
FROM (
@@ -166,7 +160,7 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
ORDER BY d.day
`
// Ordre des "?" dans la requête : (start, end, [reset]) pour le bloc "co",
// Ordre des "?" dans la requête : (start, end, [reset]) pour le bloc "d",
// puis (start, end) pour "rv", puis (start, end) pour "qt".
args := []interface{}{start, end}
args = append(args, whereArgs...)
@@ -176,10 +170,6 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
return d.GDB.Raw(query, args...).Scan(rows).Error
}
// ── Commandes & revenus par heure (non annulées) ─────────────────────────────
// ── Commandes & revenus par heure (non annulées) ─────────────────────────────
func (d *Database) OrdersAndRevenueByHour(hourRows *[]models.HourRow, resetAt time.Time) error {
where, args := statusFilterClause("status != 'cancelled'", resetAt)
query := `
@@ -269,6 +259,45 @@ func (d *Database) DailyProductDetail(dailyRows *[]models.DailyProductRow) error
return d.GDB.Raw(query).Scan(dailyRows).Error
}
func (d *Database) DailyProductDetailForDate(dailyRows *[]models.DailyProductRow, date time.Time) error {
start := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
end := start.AddDate(0, 0, 1)
query := `
SELECT
ci.product_id,
ci.produit AS product_name,
COALESCE(p.category, 'Sans catégorie') AS category,
COALESCE(cat.color, '#7c3aed') AS category_color,
SUM(ci.quantite) AS total_quantity,
COUNT(DISTINCT ci.command_id) AS order_count,
SUM(ci.prix) AS revenue
FROM command_items ci
JOIN commandes c ON c.id = ci.command_id
LEFT JOIN products p ON p.id = ci.product_id
LEFT JOIN categories cat ON cat.name = p.category
WHERE c.created_at >= ? AND c.created_at < ?
AND c.status != 'cancelled'
GROUP BY ci.product_id, ci.produit, p.category, cat.color
ORDER BY p.category, SUM(ci.quantite) DESC
`
return d.GDB.Raw(query, start, end).Scan(dailyRows).Error
}
// DailyOrdersCountForDate renvoie le nombre de commandes (non annulées) pour
// une date précise.
func (d *Database) DailyOrdersCountForDate(date time.Time) (int64, error) {
start := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
end := start.AddDate(0, 0, 1)
var count int64
err := d.GDB.Raw(`
SELECT COUNT(DISTINCT id) FROM commandes
WHERE created_at >= ? AND created_at < ? AND status != 'cancelled'
`, start, end).Scan(&count).Error
return count, err
}
// DailyOrdersCount renvoie le nombre de commandes (non annulées) du jour.
func (d *Database) DailyOrdersCount() (int64, error) {
var count int64
+77
View File
@@ -117,6 +117,83 @@ func GetAdminStatsByMonth(c *gin.Context) {
})
}
func GetAdminDailyDetail(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
dateParam := c.Query("date")
date := time.Now()
if dateParam != "" {
parsed, err := time.Parse("2006-01-02", dateParam)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("paramètre date invalide (attendu YYYY-MM-DD) : %s", dateParam)})
return
}
date = parsed
}
var dailyRows []models.DailyProductRow
if err := database.DailyProductDetailForDate(&dailyRows, date); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Erreur lors de la récupération du détail du jour: %s", err)})
return
}
type dailyCatGroup struct {
Category string
CategoryColor string
TotalQuantity float64
TotalRevenue float64
Products []gin.H
}
var dailyCats []dailyCatGroup
dailyCatIdx := map[string]int{}
dailyTotalRevenue := 0.0
dailyTotalQty := 0.0
for _, r := range dailyRows {
dailyTotalRevenue += r.Revenue
dailyTotalQty += r.TotalQuantity
idx, ok := dailyCatIdx[r.Category]
if !ok {
idx = len(dailyCats)
dailyCats = append(dailyCats, dailyCatGroup{
Category: r.Category,
CategoryColor: r.CategoryColor,
})
dailyCatIdx[r.Category] = idx
}
dailyCats[idx].TotalQuantity += r.TotalQuantity
dailyCats[idx].TotalRevenue += r.Revenue
dailyCats[idx].Products = append(dailyCats[idx].Products, gin.H{
"product_id": r.ProductID,
"name": r.ProductName,
"quantity": r.TotalQuantity,
"order_count": r.OrderCount,
"revenue": r.Revenue,
})
}
dailyCatsJSON := make([]gin.H, len(dailyCats))
for i, g := range dailyCats {
dailyCatsJSON[i] = gin.H{
"category": g.Category,
"category_color": g.CategoryColor,
"total_quantity": g.TotalQuantity,
"total_revenue": g.TotalRevenue,
"products": g.Products,
}
}
dailyTotalOrders, _ := database.DailyOrdersCountForDate(date)
c.JSON(http.StatusOK, gin.H{
"date": date.Format("02/01/2006"),
"total_orders": dailyTotalOrders,
"total_quantity": dailyTotalQty,
"total_revenue": dailyTotalRevenue,
"categories": dailyCatsJSON,
})
}
// GetAdminStats returns aggregated order & product statistics for the admin dashboard.
func GetAdminStats(c *gin.Context) {
database := c.MustGet("database").(*db.Database)
+1 -1
View File
@@ -212,7 +212,7 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
adminGroupV2.GET("/stats/monthly", handlers.GetAdminStatsByMonth)
adminGroupV2.POST("/active/product/price/:id", handlers.ActivePrice)
adminGroupV2.POST("/desactive/product/price/:id", handlers.DesActivePrice)
adminGroupV2.GET("/stats/daily", handlers.GetAdminDailyDetail)
// ============================================
// COMMANDES - GESTION DE BASE
// ============================================