105 lines
3.8 KiB
Go
105 lines
3.8 KiB
Go
package business
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type DashboardWindow struct{ Begin, End, PreviousBegin, PreviousEnd time.Time }
|
|
type DashboardMetrics struct {
|
|
Register, Active, Effective, ActiveChannels, NewChannels int64
|
|
LockedChannels, TerminatedChannels int64
|
|
Pay string
|
|
}
|
|
type DashboardData struct {
|
|
Current, Previous DashboardMetrics
|
|
Available bool
|
|
EventsAvailable bool
|
|
}
|
|
type DashboardRepo interface {
|
|
Overview(context.Context, AnalyticsScope, []string, DashboardWindow) (*DashboardData, error)
|
|
}
|
|
type DashboardOverview struct {
|
|
Cards map[string]*WorkbenchCard
|
|
Begin, End string
|
|
Settings OtherSettings
|
|
Available bool
|
|
}
|
|
type DashboardUsecase struct {
|
|
repo DashboardRepo
|
|
workbench *WorkbenchUsecase
|
|
effective *EffectivenessUsecase
|
|
now func() time.Time
|
|
}
|
|
|
|
func NewDashboardUsecase(repo DashboardRepo, workbench *WorkbenchUsecase, effective *EffectivenessUsecase) *DashboardUsecase {
|
|
return &DashboardUsecase{repo: repo, workbench: workbench, effective: effective, now: time.Now}
|
|
}
|
|
func (uc *DashboardUsecase) Overview(ctx context.Context, sources []string, period string, begin, end *time.Time) (*DashboardOverview, error) {
|
|
scope, err := uc.workbench.scope(ctx, sources)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
today := workbenchWindow(uc.now()).Today
|
|
b, e := today, today
|
|
switch period {
|
|
case "", "today":
|
|
case "yesterday":
|
|
b, e = today.AddDate(0, 0, -1), today.AddDate(0, 0, -1)
|
|
case "last7":
|
|
b = today.AddDate(0, 0, -6)
|
|
case "last30":
|
|
b = today.AddDate(0, 0, -29)
|
|
case "custom":
|
|
if begin == nil || end == nil {
|
|
return nil, ErrPerformanceInput
|
|
}
|
|
b, e = *begin, *end
|
|
default:
|
|
return nil, ErrPerformanceInput
|
|
}
|
|
if e.Before(b) || e.After(today) {
|
|
return nil, ErrPerformanceInput
|
|
}
|
|
days := int(e.Sub(b).Hours()/24) + 1
|
|
window := DashboardWindow{Begin: b, End: e, PreviousBegin: b.AddDate(0, 0, -days), PreviousEnd: b.AddDate(0, 0, -1)}
|
|
if err := uc.effective.Ensure(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
rule, err := uc.effective.Rule(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data, err := uc.repo.Overview(ctx, scope, sources, window)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r := &DashboardOverview{Cards: map[string]*WorkbenchCard{}, Begin: b.Format("2006-01-02"), End: e.Format("2006-01-02"), Settings: rule, Available: data.Available}
|
|
num := func(v int64) string { return strconv.FormatInt(v, 10) }
|
|
for _, card := range []struct{ key, current, previous string }{{"todayRegister", num(data.Current.Register), num(data.Previous.Register)}, {"todayActive", num(data.Current.Active), num(data.Previous.Active)}, {"todayPay", data.Current.Pay, data.Previous.Pay}, {"effectivePromote", num(data.Current.Effective), num(data.Previous.Effective)}, {"activePromote", num(data.Current.ActiveChannels), num(data.Previous.ActiveChannels)}, {"newPromote", num(data.Current.NewChannels), num(data.Previous.NewChannels)}} {
|
|
value, err := workbenchCard(card.current, card.previous, "较上一同期", data.Available)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.Cards[card.key] = value
|
|
}
|
|
// The imported SDK channel table has only current state; historical event
|
|
// counts must stay unavailable until a timestamped event source is connected.
|
|
for _, card := range []struct {
|
|
key string
|
|
current, previous int64
|
|
}{{"lockedPromote", data.Current.LockedChannels, data.Previous.LockedChannels}, {"terminatedPromote", data.Current.TerminatedChannels, data.Previous.TerminatedChannels}} {
|
|
label := "较上一同期"
|
|
if !data.EventsAvailable {
|
|
label = "事件数据未接入"
|
|
}
|
|
value, err := workbenchCard(num(card.current), num(card.previous), label, data.Available && data.EventsAvailable)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.Cards[card.key] = value
|
|
}
|
|
return r, nil
|
|
}
|