fix(fami): 恢复公会中心统计数据
This commit is contained in:
parent
3dd58b2f9c
commit
6428a26413
@ -91,7 +91,7 @@ func (h *Handler) getBDCenterStats(writer http.ResponseWriter, request *http.Req
|
|||||||
items[index] = bdCenterAgencyStatsData{
|
items[index] = bdCenterAgencyStatsData{
|
||||||
Agency: hostAgencyFromProto(agency), Owner: owner, Country: owner.Country,
|
Agency: hostAgencyFromProto(agency), Owner: owner, Country: owner.Country,
|
||||||
TotalHosts: len(hostIDs), GiftedHostCount: stats.GetStats().GetGiftedHostCount(),
|
TotalHosts: len(hostIDs), GiftedHostCount: stats.GetStats().GetGiftedHostCount(),
|
||||||
DiamondEarnings: stats.GetStats().GetGiftIncome(), JoinedAtMS: agency.GetCreatedAtMs(),
|
DiamondEarnings: bdCenterAgencyHostIncome(stats.GetStats()), JoinedAtMS: agency.GetCreatedAtMs(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,3 +115,12 @@ func (h *Handler) getBDCenterStats(writer http.ResponseWriter, request *http.Req
|
|||||||
"items": items, "total": len(items),
|
"items": items, "total": len(items),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bdCenterAgencyHostIncome 合并工资型与永久积分型 Host 礼物投影,覆盖政策切换前后的查询区间;
|
||||||
|
// Agency 分成和已结算工资属于其他口径,不能混入 BD 页面展示的 Agency Host 总收入。
|
||||||
|
func bdCenterAgencyHostIncome(stats *walletv1.AgencyHostGiftStats) int64 {
|
||||||
|
if stats == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return stats.GetGiftIncome() + stats.GetPointDiamondHostIncome()
|
||||||
|
}
|
||||||
|
|||||||
@ -33,6 +33,21 @@ func TestParseHostCenterStatsRangeUsesInclusiveNaturalDays(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBDCenterAgencyHostIncomeIncludesBothPolicyProjections(t *testing.T) {
|
||||||
|
stats := &walletv1.AgencyHostGiftStats{
|
||||||
|
GiftIncome: 8800,
|
||||||
|
PointDiamondHostIncome: 1200,
|
||||||
|
// Agency 分成不能计入 BD 表格里的直属 Host 总收入。
|
||||||
|
PointDiamondAgencyShareIncome: 300,
|
||||||
|
}
|
||||||
|
if got := bdCenterAgencyHostIncome(stats); got != 10000 {
|
||||||
|
t.Fatalf("bd agency host income = %d, want 10000", got)
|
||||||
|
}
|
||||||
|
if got := bdCenterAgencyHostIncome(nil); got != 0 {
|
||||||
|
t.Fatalf("nil bd agency stats income = %d, want 0", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseHostCenterStatsRangeRejectsInvalidOrOversizedRanges(t *testing.T) {
|
func TestParseHostCenterStatsRangeRejectsInvalidOrOversizedRanges(t *testing.T) {
|
||||||
for _, rawURL := range []string{
|
for _, rawURL := range []string{
|
||||||
"/api/v1/host-center/stats?start_date=2026-07-12&end_date=2026-07-01",
|
"/api/v1/host-center/stats?start_date=2026-07-12&end_date=2026-07-01",
|
||||||
|
|||||||
@ -31,20 +31,43 @@ func (r *Repository) GetHostEngagementStats(ctx context.Context, query hostdomai
|
|||||||
return hostdomain.EngagementStats{}, err
|
return hostdomain.EngagementStats{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 私聊事实严格按当前 App 的复合索引读取;Fami 尚未上线,不再跨租户回捞旧错误数据。
|
// Fami 上线前的 C2C 回调曾把事实写入默认租户;读取按两个精确 app_code 索引区间
|
||||||
// 这样所有 App 走同一查询路径,也避免默认 App 身份成为业务分支。
|
// 合并,并用发送者主数据校验真实租户,既恢复历史私信人数又不把 Lalu 用户串入 Fami。
|
||||||
if err := r.db.QueryRowContext(ctx, `
|
privateMessageSQL := `
|
||||||
SELECT COUNT(DISTINCT matched.sender_user_id)
|
SELECT COUNT(DISTINCT matched.sender_user_id)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT sender_user_id
|
SELECT sender_user_id
|
||||||
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
||||||
WHERE app_code = ? AND target_user_id = ?
|
WHERE app_code = ? AND target_user_id = ?
|
||||||
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
||||||
|
) matched
|
||||||
|
INNER JOIN users sender
|
||||||
|
ON sender.user_id = matched.sender_user_id AND sender.app_code = ?`
|
||||||
|
privateMessageArgs := []any{appCode, query.HostUserID, query.StartAtMS, query.EndAtMS, appCode}
|
||||||
|
if appCode != appcode.Default {
|
||||||
|
// UNION ALL 保持两个复合索引范围独立可用;最终 DISTINCT 收敛迁移前后重复发送者。
|
||||||
|
privateMessageSQL = `
|
||||||
|
SELECT COUNT(DISTINCT matched.sender_user_id)
|
||||||
|
FROM (
|
||||||
|
SELECT sender_user_id
|
||||||
|
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
||||||
|
WHERE app_code = ? AND target_user_id = ?
|
||||||
|
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
||||||
|
UNION ALL
|
||||||
|
SELECT sender_user_id
|
||||||
|
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
||||||
|
WHERE app_code = ? AND target_user_id = ?
|
||||||
|
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
||||||
) matched
|
) matched
|
||||||
INNER JOIN users sender
|
INNER JOIN users sender
|
||||||
ON sender.user_id = matched.sender_user_id AND sender.app_code = ?`,
|
ON sender.user_id = matched.sender_user_id AND sender.app_code = ?`
|
||||||
appCode, query.HostUserID, query.StartAtMS, query.EndAtMS, appCode,
|
privateMessageArgs = []any{
|
||||||
).Scan(&stats.PrivateMessageSenders); err != nil {
|
appCode, query.HostUserID, query.StartAtMS, query.EndAtMS,
|
||||||
|
appcode.Default, query.HostUserID, query.StartAtMS, query.EndAtMS,
|
||||||
|
appCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := r.db.QueryRowContext(ctx, privateMessageSQL, privateMessageArgs...).Scan(&stats.PrivateMessageSenders); err != nil {
|
||||||
return hostdomain.EngagementStats{}, err
|
return hostdomain.EngagementStats{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,17 @@ func TestGetHostEngagementStatsAggregatesOwnedFacts(t *testing.T) {
|
|||||||
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
||||||
WHERE app_code = ? AND target_user_id = ?
|
WHERE app_code = ? AND target_user_id = ?
|
||||||
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
||||||
|
UNION ALL
|
||||||
|
SELECT sender_user_id
|
||||||
|
FROM user_private_message_events FORCE INDEX (idx_private_message_target_time)
|
||||||
|
WHERE app_code = ? AND target_user_id = ?
|
||||||
|
AND occurred_at_ms >= ? AND occurred_at_ms < ?
|
||||||
) matched
|
) matched
|
||||||
INNER JOIN users sender
|
INNER JOIN users sender
|
||||||
ON sender.user_id = matched.sender_user_id AND sender.app_code = ?`)).
|
ON sender.user_id = matched.sender_user_id AND sender.app_code = ?`)).
|
||||||
WithArgs(
|
WithArgs(
|
||||||
"fami", int64(42), int64(1783296000000), int64(1783900800000),
|
"fami", int64(42), int64(1783296000000), int64(1783900800000),
|
||||||
|
"lalu", int64(42), int64(1783296000000), int64(1783900800000),
|
||||||
"fami",
|
"fami",
|
||||||
).
|
).
|
||||||
WillReturnRows(sqlmock.NewRows([]string{"senders"}).AddRow(int64(6)))
|
WillReturnRows(sqlmock.NewRows([]string{"senders"}).AddRow(int64(6)))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user