You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.4 KiB
50 lines
1.4 KiB
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)
|
|
}
|
|
|