This commit is contained in:
@@ -37,11 +37,14 @@ func (d *Database) ReadResetAt(key string) time.Time {
|
||||
|
||||
// ── Construction des clauses WHERE (filtrage par reset) ────────────────────
|
||||
|
||||
// statusFilterClause construit "<baseStatus> [AND created_at >= ?]" et renvoie
|
||||
// la clause ainsi que les arguments à binder, dans l'ordre.
|
||||
func statusFilterClause(baseStatus string, resetAt time.Time) (string, []interface{}) {
|
||||
// statusFilterClause construit "<baseStatus> [AND <dateColumn> >= ?]" et
|
||||
// renvoie la clause ainsi que les arguments à binder, dans l'ordre.
|
||||
// dateColumn doit être qualifié par l'alias de table (ex: "c.created_at") dès
|
||||
// que la requête appelante fait une jointure où plusieurs tables possèdent une
|
||||
// colonne created_at, sous peine d'erreur Postgres "ambiguous column".
|
||||
func statusFilterClause(baseStatus string, resetAt time.Time, dateColumn string) (string, []interface{}) {
|
||||
if !resetAt.IsZero() {
|
||||
return baseStatus + " AND created_at >= ?", []interface{}{resetAt.Format(time.RFC3339)}
|
||||
return baseStatus + " AND " + dateColumn + " >= ?", []interface{}{resetAt.Format(time.RFC3339)}
|
||||
}
|
||||
return baseStatus, nil
|
||||
}
|
||||
@@ -92,7 +95,7 @@ func (d *Database) LoadAdminStatsFilters() AdminStatsFilters {
|
||||
// ── Commandes par jour de la semaine (non annulées) ─────────────────────────
|
||||
|
||||
func (d *Database) OrderPerDaysPerWeeks(wdRows *[]models.WeekdayRow, resetAt time.Time) error {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
query := `
|
||||
SELECT EXTRACT(DOW FROM created_at)::int AS dow, COUNT(*) AS count
|
||||
FROM commandes
|
||||
@@ -106,7 +109,7 @@ func (d *Database) OrderPerDaysPerWeeks(wdRows *[]models.WeekdayRow, resetAt tim
|
||||
// ── Commandes par jour sur 30 jours ──────────────────────────────────────────
|
||||
|
||||
func (d *Database) OrdersByDayLast30(dayRows *[]models.DayRow, resetAt time.Time) error {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
query := `
|
||||
SELECT DATE(created_at) AS day, COUNT(*) AS count
|
||||
FROM commandes
|
||||
@@ -121,7 +124,7 @@ func (d *Database) OrdersByDayLast30(dayRows *[]models.DayRow, resetAt time.Time
|
||||
// ── Revenus par jour sur 30 jours (commandes approuvées) ─────────────────────
|
||||
|
||||
func (d *Database) RevenueByDayLast30(dayRevRows *[]models.DayRevenueRow, resetAt time.Time) error {
|
||||
where, args := statusFilterClause("status = 'approved'", resetAt)
|
||||
where, args := statusFilterClause("status = 'approved'", resetAt, "created_at")
|
||||
query := `
|
||||
SELECT DATE(created_at) AS day, COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) AS revenue
|
||||
FROM commandes
|
||||
@@ -146,7 +149,7 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
|
||||
start := time.Date(monthStart.Year(), monthStart.Month(), 1, 0, 0, 0, 0, monthStart.Location())
|
||||
end := start.AddDate(0, 1, 0)
|
||||
|
||||
where, whereArgs := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, whereArgs := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
|
||||
query := `
|
||||
SELECT
|
||||
@@ -195,7 +198,7 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
|
||||
// cohérent avec TotalRevenue/RevenueByDayLast30, pour ne pas compter comme
|
||||
// "revenu" une commande encore en cours qui pourrait être annulée).
|
||||
func (d *Database) OrdersAndRevenueByHour(hourRows *[]models.HourRow, resetAt time.Time) error {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
query := `
|
||||
SELECT
|
||||
EXTRACT(HOUR FROM created_at)::int AS hour,
|
||||
@@ -215,7 +218,7 @@ func (d *Database) OrdersAndRevenueByHour(hourRows *[]models.HourRow, resetAt ti
|
||||
// commandes reflètent l'activité (non annulées), le revenu ne compte que les
|
||||
// commandes approuvées (revenu confirmé, cohérent avec le résumé global).
|
||||
func (d *Database) TopProducts(prodRows *[]models.ProductRow, resetAt time.Time, limit int) error {
|
||||
where, args := statusFilterClause("c.status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("c.status != 'cancelled'", resetAt, "c.created_at")
|
||||
args = append(args, limit)
|
||||
query := `
|
||||
SELECT
|
||||
@@ -245,7 +248,7 @@ func (d *Database) TopProducts(prodRows *[]models.ProductRow, resetAt time.Time,
|
||||
// QuantityBreakdown : quantité/nombre de commandes reflètent l'activité (non
|
||||
// annulées), le revenu ne compte que les commandes approuvées (revenu confirmé).
|
||||
func (d *Database) QuantityBreakdown(qtyRows *[]models.QuantityBreakdownRow, resetAt time.Time) error {
|
||||
where, args := statusFilterClause("c.status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("c.status != 'cancelled'", resetAt, "c.created_at")
|
||||
query := `
|
||||
SELECT
|
||||
ci.product_id,
|
||||
@@ -351,7 +354,7 @@ func (d *Database) DailyOrdersCount() (int64, error) {
|
||||
|
||||
// TotalOrders renvoie le nombre total de commandes filtré par le reset "commandes".
|
||||
func (d *Database) TotalOrders(resetAt time.Time) (int64, error) {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
var total int64
|
||||
err := d.GDB.Raw(`SELECT COUNT(*) FROM commandes WHERE `+where, args...).Scan(&total).Error
|
||||
return total, err
|
||||
@@ -359,7 +362,7 @@ func (d *Database) TotalOrders(resetAt time.Time) (int64, error) {
|
||||
|
||||
// TotalRevenue renvoie le revenu total (commandes approuvées) filtré par le reset "revenus".
|
||||
func (d *Database) TotalRevenue(resetAt time.Time) (float64, error) {
|
||||
where, args := statusFilterClause("status = 'approved'", resetAt)
|
||||
where, args := statusFilterClause("status = 'approved'", resetAt, "created_at")
|
||||
var total float64
|
||||
err := d.GDB.Raw(`SELECT COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) FROM commandes WHERE `+where, args...).
|
||||
Scan(&total).Error
|
||||
@@ -368,7 +371,7 @@ func (d *Database) TotalRevenue(resetAt time.Time) (float64, error) {
|
||||
|
||||
// ActiveDaysLast30 renvoie le nombre de jours distincts ayant eu au moins une commande sur 30 jours.
|
||||
func (d *Database) ActiveDaysLast30(resetAt time.Time) (int64, error) {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
var activeDays int64
|
||||
query := `
|
||||
SELECT COUNT(DISTINCT DATE(created_at))
|
||||
@@ -380,7 +383,7 @@ func (d *Database) ActiveDaysLast30(resetAt time.Time) (int64, error) {
|
||||
|
||||
// OrdersCountLast30 renvoie le nombre de commandes sur les 30 derniers jours.
|
||||
func (d *Database) OrdersCountLast30(resetAt time.Time) (int64, error) {
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt)
|
||||
where, args := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||
var count int64
|
||||
query := `
|
||||
SELECT COUNT(*) FROM commandes
|
||||
|
||||
Reference in New Issue
Block a user