feat: 迁移日汇总任务并修复商务菜单图标
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kra/internal/biz/business"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestReportBuildStorageReplacesBothTablesAtomically(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
ctx := context.Background()
|
||||
day := time.Date(2026, 11, 4, 0, 0, 0, 0, time.FixedZone("Asia/Shanghai", 8*3600))
|
||||
for _, sql := range []string{
|
||||
"CREATE TABLE tab_user(id INTEGER,source_db TEXT,puid INTEGER,promote_id INTEGER,fgame_id INTEGER,idcard TEXT,register_time TEXT)",
|
||||
"CREATE TABLE tab_user_day_login(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,login_time INTEGER)",
|
||||
"CREATE TABLE tab_user_play_info(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,server_id TEXT,create_time INTEGER,play_time INTEGER)",
|
||||
"CREATE TABLE tab_spend(user_id INTEGER,source_db TEXT,promote_id INTEGER,game_id INTEGER,server_id TEXT,pay_time INTEGER,pay_status INTEGER,pay_amount DECIMAL(20,2))",
|
||||
"CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)",
|
||||
"INSERT INTO tab_game VALUES(1,'lx','当前游戏')",
|
||||
"CREATE TABLE tab_sw_report_day(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,dedup_mode INTEGER,new_register_cnt INTEGER,active_cnt INTEGER,pay_cnt INTEGER,new_pay_cnt INTEGER,total_pay DECIMAL(20,2))",
|
||||
"CREATE TABLE tab_sw_report_day_key(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,dedup_mode INTEGER,metric INTEGER,identity_key TEXT)",
|
||||
"CREATE TABLE tab_sw_report_server_day(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,server_num TEXT,dedup_mode INTEGER,new_register_cnt INTEGER,active_cnt INTEGER,pay_cnt INTEGER,total_pay DECIMAL(20,2))",
|
||||
"CREATE TABLE tab_sw_report_server_day_key(id INTEGER PRIMARY KEY,stat_date DATE,source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,server_num TEXT,dedup_mode INTEGER,metric INTEGER,identity_key TEXT)",
|
||||
} {
|
||||
if err := db.Exec(sql).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, sql := range []string{
|
||||
"INSERT INTO tab_user VALUES(1,'lx',0,10,1,'cardX',?),(2,'lx',1,10,1,'sub',?),(3,'lx',NULL,10,1,'null',?)",
|
||||
} {
|
||||
if err := db.Exec(sql, day.Unix(), day.Unix(), day.Unix()).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, sql := range []string{
|
||||
"INSERT INTO tab_user_day_login VALUES(1,'lx',NULL,1,?),(2,'lx',10,1,?),(3,'lx',10,1,?)",
|
||||
"INSERT INTO tab_spend VALUES(1,'lx',10,1,'001',?,1,10),(2,'lx',10,1,'001',?,1,20),(3,'lx',10,1,'001',?,0,999)",
|
||||
} {
|
||||
if err := db.Exec(sql, day.Unix(), day.Unix(), day.Unix()).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := db.Exec("INSERT INTO tab_user_play_info VALUES(2,'lx',10,1,' 001 ',?,?)", day.Unix(), day.Unix()).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
uc := business.NewReportBuildUsecase(NewReportBuildRepo(testData{db}))
|
||||
run := func(kind business.ReportBuildKind) error {
|
||||
return uc.Run(ctx, kind, "backfill", "2026-11-04", "2026-11-04")
|
||||
}
|
||||
if err := run(business.DailyReport); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var counts []struct {
|
||||
DedupMode, NewRegisterCnt, ActiveCnt, PayCnt, NewPayCnt int
|
||||
TotalPay string
|
||||
GameName string
|
||||
}
|
||||
if err := db.Table("tab_sw_report_day").Order("dedup_mode").Scan(&counts).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(counts) != 2 || counts[0].NewRegisterCnt != 1 || counts[0].ActiveCnt != 1 || counts[0].PayCnt != 2 || counts[0].NewPayCnt != 1 || portraitTestMoney(counts[0].TotalPay) != "30.00" || counts[0].GameName != "当前游戏" {
|
||||
t.Fatalf("日报主账号/付费/金额规则错误: %+v", counts)
|
||||
}
|
||||
if err := run(business.ServerReport); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var server struct {
|
||||
NewRegisterCnt, ActiveCnt, PayCnt int
|
||||
ServerNum string
|
||||
}
|
||||
if err := db.Table("tab_sw_report_server_day").Where("dedup_mode=0").Take(&server).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if server.NewRegisterCnt != 1 || server.ActiveCnt != 1 || server.PayCnt != 2 || server.ServerNum != "001" {
|
||||
t.Fatalf("区服创角应包含子账号: %+v", server)
|
||||
}
|
||||
if err := run(business.DailyReport); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var before int64
|
||||
if err := db.Table("tab_sw_report_day").Where("stat_date=?", "2026-11-04").Count(&before).Error; err != nil || before != 2 {
|
||||
t.Fatal("回跑日期必须保持自然日格式且不能重复累积行")
|
||||
}
|
||||
db.Table("tab_sw_report_day_key").Count(&before)
|
||||
if err := db.Exec("CREATE TRIGGER reject_report_key BEFORE INSERT ON tab_sw_report_day_key BEGIN SELECT RAISE(ABORT,'测试写入失败'); END").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.Exec("UPDATE tab_spend SET pay_amount=100 WHERE user_id=1").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := run(business.DailyReport); err == nil {
|
||||
t.Fatal("身份键写入失败必须回滚")
|
||||
}
|
||||
var after int64
|
||||
db.Table("tab_sw_report_day_key").Count(&after)
|
||||
var amount string
|
||||
db.Table("tab_sw_report_day").Select("total_pay").Where("dedup_mode=0").Scan(&amount)
|
||||
if before != after || portraitTestMoney(amount) != "30.00" {
|
||||
t.Fatal("失败后丢失原身份键或覆盖原汇总")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user