win 2a7b731484 feat(finance): implement Phase 1 core P&L service + wire into dashboard
- Add internal/service/finance/types.go: AssetType enum, param/result structs
- Add internal/service/finance/service.go: Service interface, read-only ctor
- Add internal/service/finance/query_user.go: QueryUserProfitLoss (4 fan-out scans)
- Add internal/service/finance/query_activity.go: QueryActivityProfitLoss (4 fan-out scans)
- Add internal/service/finance/service_test.go: 22 integration tests (all pass)
- Wire finance.Service into admin handler (admin.go)
- Replace dashboard_activity cost scan with finance.Service call (D-09: value_cents single source of truth)
- Revenue/gamepass/draw-count scans unchanged; response schema fully compatible

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-21 18:38:33 +08:00

40 lines
1.3 KiB
Go

package finance
import (
"context"
"bindbox-game/internal/pkg/logger"
"bindbox-game/internal/repository/mysql"
"gorm.io/gorm"
)
// Service defines the finance P&L query interface.
type Service interface {
QueryUserProfitLoss(ctx context.Context, params UserProfitLossParams) (*ProfitLossResult, error)
QueryActivityProfitLoss(ctx context.Context, params ActivityProfitLossParams) (*ProfitLossResult, error)
}
type service struct {
logger logger.CustomLogger
dbR *gorm.DB // read replica only — QUA-02: no writes in this package
}
// New creates a new finance Service backed by the read-only DB replica.
// CRITICAL: only db.GetDbR() is called — never GetDbW() (QUA-02).
func New(l logger.CustomLogger, db mysql.Repo) Service {
return &service{
logger: l,
dbR: db.GetDbR(),
}
}
// QueryUserProfitLoss dispatches to the user-dimension implementation (Plan 02).
func (s *service) QueryUserProfitLoss(ctx context.Context, params UserProfitLossParams) (*ProfitLossResult, error) {
return s.queryUser(ctx, params)
}
// QueryActivityProfitLoss dispatches to the activity-dimension implementation (Plan 03).
func (s *service) QueryActivityProfitLoss(ctx context.Context, params ActivityProfitLossParams) (*ProfitLossResult, error) {
return s.queryActivity(ctx, params)
}