114 lines
3.1 KiB
Go
114 lines
3.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"0451meishiditu/backend/internal/models"
|
|
"0451meishiditu/backend/internal/resp"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type dashboardOverview struct {
|
|
TotalStores int64 `json:"total_stores"`
|
|
TotalReviews int64 `json:"total_reviews"`
|
|
TotalCategories int64 `json:"total_categories"`
|
|
CategoryDist []categoryKV `json:"category_dist"`
|
|
StoresLast7Days []dateKV `json:"stores_last7days"`
|
|
TopRatedStores []topStoreRow `json:"top_rated_stores"`
|
|
}
|
|
|
|
type categoryKV struct {
|
|
CategoryID uint `json:"category_id"`
|
|
Name string `json:"name"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
type dateKV struct {
|
|
Date string `json:"date"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
type topStoreRow struct {
|
|
StoreID uint `json:"store_id"`
|
|
Name string `json:"name"`
|
|
Avg float64 `json:"avg"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (h *Handlers) DashboardOverview(c *gin.Context) {
|
|
ctx := c.Request.Context()
|
|
cacheKey := "admin:dashboard:overview:v1"
|
|
|
|
if b, err := h.rdb.Get(ctx, cacheKey).Bytes(); err == nil && len(b) > 0 {
|
|
var cached dashboardOverview
|
|
if json.Unmarshal(b, &cached) == nil {
|
|
resp.OK(c, cached)
|
|
return
|
|
}
|
|
}
|
|
|
|
ov, err := h.buildDashboard(ctx)
|
|
if err != nil {
|
|
resp.Fail(c, http.StatusInternalServerError, "db error")
|
|
return
|
|
}
|
|
if b, err := json.Marshal(ov); err == nil {
|
|
_ = h.rdb.Set(ctx, cacheKey, b, 30*time.Second).Err()
|
|
}
|
|
resp.OK(c, ov)
|
|
}
|
|
|
|
func (h *Handlers) buildDashboard(ctx context.Context) (dashboardOverview, error) {
|
|
var out dashboardOverview
|
|
|
|
if err := h.db.WithContext(ctx).Model(&models.Store{}).Count(&out.TotalStores).Error; err != nil {
|
|
return out, err
|
|
}
|
|
if err := h.db.WithContext(ctx).Model(&models.Review{}).Count(&out.TotalReviews).Error; err != nil {
|
|
return out, err
|
|
}
|
|
if err := h.db.WithContext(ctx).Model(&models.Category{}).Count(&out.TotalCategories).Error; err != nil {
|
|
return out, err
|
|
}
|
|
|
|
if err := h.db.WithContext(ctx).
|
|
Table("stores").
|
|
Select("categories.id as category_id, categories.name as name, count(stores.id) as count").
|
|
Joins("left join categories on categories.id = stores.category_id").
|
|
Where("stores.deleted_at is null").
|
|
Group("categories.id, categories.name").
|
|
Order("count desc").
|
|
Scan(&out.CategoryDist).Error; err != nil {
|
|
return out, err
|
|
}
|
|
|
|
if err := h.db.WithContext(ctx).
|
|
Table("stores").
|
|
Select("date(created_at) as date, count(id) as count").
|
|
Where("created_at >= date_sub(curdate(), interval 6 day) and deleted_at is null").
|
|
Group("date(created_at)").
|
|
Order("date asc").
|
|
Scan(&out.StoresLast7Days).Error; err != nil {
|
|
return out, err
|
|
}
|
|
|
|
if err := h.db.WithContext(ctx).
|
|
Table("reviews").
|
|
Select("stores.id as store_id, stores.name as name, avg(reviews.rating) as avg, count(reviews.id) as count").
|
|
Joins("left join stores on stores.id = reviews.store_id").
|
|
Where("reviews.status = 'approved' and reviews.deleted_at is null and stores.deleted_at is null").
|
|
Group("stores.id, stores.name").
|
|
Having("count(reviews.id) >= ?", 3).
|
|
Order("avg desc").
|
|
Limit(5).
|
|
Scan(&out.TopRatedStores).Error; err != nil {
|
|
return out, err
|
|
}
|
|
|
|
return out, nil
|
|
}
|