This commit is contained in:
@@ -37,11 +37,14 @@ func (d *Database) ReadResetAt(key string) time.Time {
|
|||||||
|
|
||||||
// ── Construction des clauses WHERE (filtrage par reset) ────────────────────
|
// ── Construction des clauses WHERE (filtrage par reset) ────────────────────
|
||||||
|
|
||||||
// statusFilterClause construit "<baseStatus> [AND created_at >= ?]" et renvoie
|
// statusFilterClause construit "<baseStatus> [AND <dateColumn> >= ?]" et
|
||||||
// la clause ainsi que les arguments à binder, dans l'ordre.
|
// renvoie la clause ainsi que les arguments à binder, dans l'ordre.
|
||||||
func statusFilterClause(baseStatus string, resetAt time.Time) (string, []interface{}) {
|
// 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() {
|
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
|
return baseStatus, nil
|
||||||
}
|
}
|
||||||
@@ -92,7 +95,7 @@ func (d *Database) LoadAdminStatsFilters() AdminStatsFilters {
|
|||||||
// ── Commandes par jour de la semaine (non annulées) ─────────────────────────
|
// ── Commandes par jour de la semaine (non annulées) ─────────────────────────
|
||||||
|
|
||||||
func (d *Database) OrderPerDaysPerWeeks(wdRows *[]models.WeekdayRow, resetAt time.Time) error {
|
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 := `
|
query := `
|
||||||
SELECT EXTRACT(DOW FROM created_at)::int AS dow, COUNT(*) AS count
|
SELECT EXTRACT(DOW FROM created_at)::int AS dow, COUNT(*) AS count
|
||||||
FROM commandes
|
FROM commandes
|
||||||
@@ -106,7 +109,7 @@ func (d *Database) OrderPerDaysPerWeeks(wdRows *[]models.WeekdayRow, resetAt tim
|
|||||||
// ── Commandes par jour sur 30 jours ──────────────────────────────────────────
|
// ── Commandes par jour sur 30 jours ──────────────────────────────────────────
|
||||||
|
|
||||||
func (d *Database) OrdersByDayLast30(dayRows *[]models.DayRow, resetAt time.Time) error {
|
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 := `
|
query := `
|
||||||
SELECT DATE(created_at) AS day, COUNT(*) AS count
|
SELECT DATE(created_at) AS day, COUNT(*) AS count
|
||||||
FROM commandes
|
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) ─────────────────────
|
// ── Revenus par jour sur 30 jours (commandes approuvées) ─────────────────────
|
||||||
|
|
||||||
func (d *Database) RevenueByDayLast30(dayRevRows *[]models.DayRevenueRow, resetAt time.Time) error {
|
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 := `
|
query := `
|
||||||
SELECT DATE(created_at) AS day, COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) AS revenue
|
SELECT DATE(created_at) AS day, COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) AS revenue
|
||||||
FROM commandes
|
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())
|
start := time.Date(monthStart.Year(), monthStart.Month(), 1, 0, 0, 0, 0, monthStart.Location())
|
||||||
end := start.AddDate(0, 1, 0)
|
end := start.AddDate(0, 1, 0)
|
||||||
|
|
||||||
where, whereArgs := statusFilterClause("status != 'cancelled'", resetAt)
|
where, whereArgs := statusFilterClause("status != 'cancelled'", resetAt, "created_at")
|
||||||
|
|
||||||
query := `
|
query := `
|
||||||
SELECT
|
SELECT
|
||||||
@@ -195,7 +198,7 @@ func (d *Database) StatsByDayForMonth(rows *[]DailyMonthStatRow, monthStart time
|
|||||||
// cohérent avec TotalRevenue/RevenueByDayLast30, pour ne pas compter comme
|
// cohérent avec TotalRevenue/RevenueByDayLast30, pour ne pas compter comme
|
||||||
// "revenu" une commande encore en cours qui pourrait être annulée).
|
// "revenu" une commande encore en cours qui pourrait être annulée).
|
||||||
func (d *Database) OrdersAndRevenueByHour(hourRows *[]models.HourRow, resetAt time.Time) error {
|
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 := `
|
query := `
|
||||||
SELECT
|
SELECT
|
||||||
EXTRACT(HOUR FROM created_at)::int AS hour,
|
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 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).
|
// 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 {
|
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)
|
args = append(args, limit)
|
||||||
query := `
|
query := `
|
||||||
SELECT
|
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
|
// QuantityBreakdown : quantité/nombre de commandes reflètent l'activité (non
|
||||||
// annulées), le revenu ne compte que les commandes approuvées (revenu confirmé).
|
// annulées), le revenu ne compte que les commandes approuvées (revenu confirmé).
|
||||||
func (d *Database) QuantityBreakdown(qtyRows *[]models.QuantityBreakdownRow, resetAt time.Time) error {
|
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 := `
|
query := `
|
||||||
SELECT
|
SELECT
|
||||||
ci.product_id,
|
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".
|
// TotalOrders renvoie le nombre total de commandes filtré par le reset "commandes".
|
||||||
func (d *Database) TotalOrders(resetAt time.Time) (int64, error) {
|
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
|
var total int64
|
||||||
err := d.GDB.Raw(`SELECT COUNT(*) FROM commandes WHERE `+where, args...).Scan(&total).Error
|
err := d.GDB.Raw(`SELECT COUNT(*) FROM commandes WHERE `+where, args...).Scan(&total).Error
|
||||||
return total, err
|
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".
|
// TotalRevenue renvoie le revenu total (commandes approuvées) filtré par le reset "revenus".
|
||||||
func (d *Database) TotalRevenue(resetAt time.Time) (float64, error) {
|
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
|
var total float64
|
||||||
err := d.GDB.Raw(`SELECT COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) FROM commandes WHERE `+where, args...).
|
err := d.GDB.Raw(`SELECT COALESCE(SUM(total_prix - COALESCE(referral_used, 0)), 0) FROM commandes WHERE `+where, args...).
|
||||||
Scan(&total).Error
|
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.
|
// 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) {
|
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
|
var activeDays int64
|
||||||
query := `
|
query := `
|
||||||
SELECT COUNT(DISTINCT DATE(created_at))
|
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.
|
// OrdersCountLast30 renvoie le nombre de commandes sur les 30 derniers jours.
|
||||||
func (d *Database) OrdersCountLast30(resetAt time.Time) (int64, error) {
|
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
|
var count int64
|
||||||
query := `
|
query := `
|
||||||
SELECT COUNT(*) FROM commandes
|
SELECT COUNT(*) FROM commandes
|
||||||
|
|||||||
Reference in New Issue
Block a user