- Go API server with PostgreSQL + Redis - AI floor replacement (OpenRouter Gemini) - Product database (10 brands, 3539 products) - Recommendation engine, calculator, articles - Redis async queue + worker pool - Hot product caching, brand view tracking - JWT auth, favorites, projects - Docker deployment ready Co-Authored-By: Claude <noreply@anthropic.com>
71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
)
|
|
|
|
|
|
// RecordBrandView inserts a brand view record.
|
|
func RecordBrandView(d *sql.DB, userID, brand string) error {
|
|
_, err := d.Exec(`
|
|
INSERT INTO user_brand_views (user_id, brand) VALUES ($1, $2)
|
|
`, userID, brand)
|
|
return err
|
|
}
|
|
|
|
// FrequentBrand represents a brand the user interacts with frequently.
|
|
type FrequentBrand struct {
|
|
Brand string `json:"brand"`
|
|
ViewCount int `json:"view_count"`
|
|
FavCount int `json:"fav_count"`
|
|
LogoURL string `json:"logo_url,omitempty"`
|
|
StyleCount int `json:"style_count,omitempty"`
|
|
}
|
|
|
|
// GetFrequentBrands returns brands where user has views≥3 or favorites≥2.
|
|
func GetFrequentBrands(d *sql.DB, userID string) ([]FrequentBrand, error) {
|
|
rows, err := d.Query(`
|
|
SELECT brand,
|
|
COALESCE(v.cnt, 0) AS view_count,
|
|
COALESCE(f.cnt, 0) AS fav_count
|
|
FROM (
|
|
SELECT brand, COUNT(*) AS cnt
|
|
FROM user_brand_views
|
|
WHERE user_id = $1
|
|
GROUP BY brand
|
|
HAVING COUNT(*) >= 3
|
|
) v
|
|
FULL OUTER JOIN (
|
|
SELECT brand, COUNT(*) AS cnt
|
|
FROM favorites
|
|
WHERE user_id = $1
|
|
GROUP BY brand
|
|
HAVING COUNT(*) >= 2
|
|
) f USING (brand)
|
|
ORDER BY COALESCE(v.cnt, 0) + COALESCE(f.cnt, 0) * 2 DESC
|
|
`, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var out []FrequentBrand
|
|
for rows.Next() {
|
|
var fb FrequentBrand
|
|
if err := rows.Scan(&fb.Brand, &fb.ViewCount, &fb.FavCount); err != nil {
|
|
continue
|
|
}
|
|
// Load brand logo and stats
|
|
logoMap := loadBrandLogos()
|
|
if u, ok := logoMap[fb.Brand]; ok {
|
|
fb.LogoURL = u
|
|
}
|
|
// Get style count from products
|
|
var sc int
|
|
d.QueryRow(`SELECT COUNT(DISTINCT style_name) FROM products WHERE brand = $1`, fb.Brand).Scan(&sc)
|
|
fb.StyleCount = sc
|
|
out = append(out, fb)
|
|
}
|
|
return out, rows.Err()
|
|
}
|