109 lines
3.5 KiB
Go
109 lines
3.5 KiB
Go
package model
|
||
|
||
import (
|
||
"strings"
|
||
|
||
"gorm.io/gorm"
|
||
"gorm.io/gorm/clause"
|
||
)
|
||
|
||
// AffFunnelDaily 分销商邀请漏斗按日汇总:短链点击、带邀请码注册页浏览(UTC 日期维度)。
|
||
type AffFunnelDaily struct {
|
||
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
|
||
InviterId int `json:"inviter_id" gorm:"not null;uniqueIndex:idx_aff_funnel_inv_day,priority:1;index:idx_aff_funnel_inv_date,priority:1"`
|
||
StatDate string `json:"stat_date" gorm:"type:varchar(10);not null;uniqueIndex:idx_aff_funnel_inv_day,priority:2;index:idx_aff_funnel_inv_date,priority:2;column:stat_date"` // YYYY-MM-DD UTC
|
||
ShortLinkClicks int `json:"short_link_clicks" gorm:"not null;default:0"`
|
||
RegisterPageViews int `json:"register_page_views" gorm:"not null;default:0"`
|
||
}
|
||
|
||
func (AffFunnelDaily) TableName() string {
|
||
return "aff_funnel_daily"
|
||
}
|
||
|
||
// UpsertAffFunnelIncrShortLink 短链 /r/:code 点击 +1(按 inviter 与 UTC 日期)。
|
||
func UpsertAffFunnelIncrShortLink(inviterId int, statDate string) error {
|
||
if inviterId <= 0 {
|
||
return nil
|
||
}
|
||
statDate = strings.TrimSpace(statDate)
|
||
if statDate == "" {
|
||
return nil
|
||
}
|
||
row := AffFunnelDaily{
|
||
InviterId: inviterId,
|
||
StatDate: statDate,
|
||
ShortLinkClicks: 1,
|
||
RegisterPageViews: 0,
|
||
}
|
||
return DB.Clauses(clause.OnConflict{
|
||
Columns: []clause.Column{{Name: "inviter_id"}, {Name: "stat_date"}},
|
||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||
"short_link_clicks": gorm.Expr("short_link_clicks + ?", 1),
|
||
}),
|
||
}).Create(&row).Error
|
||
}
|
||
|
||
// UpsertAffFunnelIncrRegisterPageView 注册页带 aff 参数浏览 +1。
|
||
func UpsertAffFunnelIncrRegisterPageView(inviterId int, statDate string) error {
|
||
if inviterId <= 0 {
|
||
return nil
|
||
}
|
||
statDate = strings.TrimSpace(statDate)
|
||
if statDate == "" {
|
||
return nil
|
||
}
|
||
row := AffFunnelDaily{
|
||
InviterId: inviterId,
|
||
StatDate: statDate,
|
||
ShortLinkClicks: 0,
|
||
RegisterPageViews: 1,
|
||
}
|
||
return DB.Clauses(clause.OnConflict{
|
||
Columns: []clause.Column{{Name: "inviter_id"}, {Name: "stat_date"}},
|
||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||
"register_page_views": gorm.Expr("register_page_views + ?", 1),
|
||
}),
|
||
}).Create(&row).Error
|
||
}
|
||
|
||
// ListAffFunnelDailyForInviter 返回 inviter 在 [dateFrom, dateTo](含)内的漏斗日表行。
|
||
func ListAffFunnelDailyForInviter(inviterId int, dateFrom, dateTo string) ([]AffFunnelDaily, error) {
|
||
if inviterId <= 0 {
|
||
return []AffFunnelDaily{}, nil
|
||
}
|
||
var rows []AffFunnelDaily
|
||
err := DB.Where("inviter_id = ? AND stat_date >= ? AND stat_date <= ?", inviterId, dateFrom, dateTo).
|
||
Order("stat_date ASC").Find(&rows).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if rows == nil {
|
||
rows = []AffFunnelDaily{}
|
||
}
|
||
return rows, nil
|
||
}
|
||
|
||
// SumAffFunnelDailyPlatform 按日汇总全平台漏斗(管理端大盘)。
|
||
func SumAffFunnelDailyPlatform(dateFrom, dateTo string) (map[string]struct{ Clicks, RegViews int }, error) {
|
||
out := make(map[string]struct{ Clicks, RegViews int })
|
||
type row struct {
|
||
StatDate string
|
||
ShortLinkClicks int
|
||
RegisterPageViews int
|
||
}
|
||
var list []row
|
||
err := DB.Model(&AffFunnelDaily{}).
|
||
Select("stat_date, COALESCE(SUM(short_link_clicks),0) AS short_link_clicks, COALESCE(SUM(register_page_views),0) AS register_page_views").
|
||
Where("stat_date >= ? AND stat_date <= ?", dateFrom, dateTo).
|
||
Group("stat_date").
|
||
Order("stat_date ASC").
|
||
Scan(&list).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for _, r := range list {
|
||
out[r.StatDate] = struct{ Clicks, RegViews int }{r.ShortLinkClicks, r.RegisterPageViews}
|
||
}
|
||
return out, nil
|
||
}
|