2026-07-21 18:08:55 +08:00

53 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package mysql
import (
"context"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
)
// GetHostRevenueStats 的“钻石收益/送礼人数”只读主播周期钻石流水;
// POINT 是可兑换资产任务奖励、Agency 分成和提现退回都不能被误算成收礼钻石。
func (r *Repository) GetHostRevenueStats(ctx context.Context, query ledger.HostRevenueStatsQuery) (ledger.HostRevenueStats, error) {
if r == nil || r.db == nil {
return ledger.HostRevenueStats{}, xerr.New(xerr.Unavailable, "mysql repository is not configured")
}
var stats ledger.HostRevenueStats
startCycle := time.UnixMilli(query.StartAtMS).UTC().Format("2006-01")
endCycle := time.UnixMilli(query.EndAtMS - 1).UTC().Format("2006-01")
// (app_code,user_id,cycle_key,created_at_ms) 索引先限定单主播和最多 13 个周期,
// 再在已收敛的送礼流水上按时间求和/去重,不扫全表也不解析大 JSON 字段。
if err := r.db.QueryRowContext(ctx, `
SELECT
COALESCE(SUM(diamond_delta), 0),
COUNT(DISTINCT CASE WHEN sender_user_id > 0 THEN sender_user_id END)
FROM host_period_diamond_entries FORCE INDEX (idx_host_period_diamond_entries_user_cycle)
WHERE app_code = ? AND user_id = ? AND cycle_key BETWEEN ? AND ?
AND created_at_ms >= ? AND created_at_ms < ?`,
appcode.FromContext(ctx), query.HostUserID, startCycle, endCycle, query.StartAtMS, query.EndAtMS,
).Scan(&stats.DiamondEarnings, &stats.GiftSenders); err != nil {
return ledger.HostRevenueStats{}, err
}
// “已兑换”保留现有 POINT 资产口径,但只计用户主动兑金币、转币商和平台提现首次冻结;
// 审核扣 frozen 、驳回释放和其他 POINT 变动不重复计入。
if err := r.db.QueryRowContext(ctx, `
SELECT COALESCE(SUM(-e.available_delta), 0)
FROM wallet_entries e FORCE INDEX (idx_wallet_entries_asset_user_time)
INNER JOIN wallet_transactions t
ON t.app_code = e.app_code AND t.transaction_id = e.transaction_id
WHERE e.app_code = ? AND e.user_id = ? AND e.asset_type = ?
AND e.created_at_ms >= ? AND e.created_at_ms < ?
AND e.available_delta < 0
AND t.biz_type IN (?, ?, ?)`,
appcode.FromContext(ctx), query.HostUserID, ledger.AssetPoint, query.StartAtMS, query.EndAtMS,
bizTypePointExchangeToCoin, bizTypePointTransferToCoinSeller, bizTypeSalaryWithdrawalFreeze,
).Scan(&stats.DiamondExchanged); err != nil {
return ledger.HostRevenueStats{}, err
}
return stats, nil
}