package billing import ( "context" "github.com/youruser/base/model" "gorm.io/gorm" ) // QuotaService handles quota freeze/settle/unfreeze operations type QuotaService struct{} func NewQuotaService() *QuotaService { return &QuotaService{} } // CheckAndFreeze checks if user has sufficient balance and freezes the estimated cost. // Returns nil if successful, error if insufficient balance. // If apiKeyId > 0, it's a user-provided key — skip billing. func (s *QuotaService) CheckAndFreeze(ctx context.Context, db *gorm.DB, userId int64, estimatedCost float64, apiKeyId int64) error { // User-provided keys skip billing if apiKeyId > 0 { return nil } // Ensure quota record exists _, err := model.AIUserQuotaEnsure(ctx, db, userId) if err != nil { return err } return model.AIUserQuotaFreeze(ctx, db, userId, estimatedCost) } // Settle finalizes billing: releases frozen amount, deducts actual cost, refunds difference. func (s *QuotaService) Settle(ctx context.Context, db *gorm.DB, userId int64, frozenAmount, actualCost float64, apiKeyId int64) error { if apiKeyId > 0 { return nil } return model.AIUserQuotaSettle(ctx, db, userId, frozenAmount, actualCost) } // Unfreeze releases frozen amount back to balance (used on error). func (s *QuotaService) Unfreeze(ctx context.Context, db *gorm.DB, userId int64, amount float64, apiKeyId int64) error { if apiKeyId > 0 { return nil } return model.AIUserQuotaUnfreeze(ctx, db, userId, amount) }