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.
91 lines
2.8 KiB
91 lines
2.8 KiB
package model
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// AIUserQuotaFindByUser 根据用户ID查询额度
|
|
func AIUserQuotaFindByUser(ctx context.Context, db *gorm.DB, userId int64) (*AIUserQuota, error) {
|
|
var quota AIUserQuota
|
|
result := db.WithContext(ctx).Where("user_id = ?", userId).First("a)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return nil, ErrNotFound
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return "a, nil
|
|
}
|
|
|
|
// AIUserQuotaEnsure 查找或创建用户额度记录
|
|
func AIUserQuotaEnsure(ctx context.Context, db *gorm.DB, userId int64) (*AIUserQuota, error) {
|
|
var quota AIUserQuota
|
|
result := db.WithContext(ctx).Where("user_id = ?", userId).First("a)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
quota = AIUserQuota{UserId: userId}
|
|
if err := db.WithContext(ctx).Create("a).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return "a, nil
|
|
}
|
|
return nil, result.Error
|
|
}
|
|
return "a, nil
|
|
}
|
|
|
|
// AIUserQuotaFreeze 冻结额度(原子操作:balance -= amount, frozen_amount += amount)
|
|
func AIUserQuotaFreeze(ctx context.Context, db *gorm.DB, userId int64, amount float64) error {
|
|
result := db.WithContext(ctx).Model(&AIUserQuota{}).
|
|
Where("user_id = ? AND balance >= ?", userId, amount).
|
|
Updates(map[string]interface{}{
|
|
"balance": gorm.Expr("balance - ?", amount),
|
|
"frozen_amount": gorm.Expr("frozen_amount + ?", amount),
|
|
})
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return errors.New("insufficient balance")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AIUserQuotaSettle 结算额度(原子操作:frozen_amount -= frozenAmount, total_consumed += actualCost, balance += refund)
|
|
func AIUserQuotaSettle(ctx context.Context, db *gorm.DB, userId int64, frozenAmount, actualCost float64) error {
|
|
refund := frozenAmount - actualCost
|
|
result := db.WithContext(ctx).Model(&AIUserQuota{}).
|
|
Where("user_id = ?", userId).
|
|
Updates(map[string]interface{}{
|
|
"frozen_amount": gorm.Expr("frozen_amount - ?", frozenAmount),
|
|
"total_consumed": gorm.Expr("total_consumed + ?", actualCost),
|
|
"balance": gorm.Expr("balance + ?", refund),
|
|
})
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return ErrNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AIUserQuotaUnfreeze 解冻额度(原子操作:frozen_amount -= amount, balance += amount)
|
|
func AIUserQuotaUnfreeze(ctx context.Context, db *gorm.DB, userId int64, amount float64) error {
|
|
result := db.WithContext(ctx).Model(&AIUserQuota{}).
|
|
Where("user_id = ?", userId).
|
|
Updates(map[string]interface{}{
|
|
"frozen_amount": gorm.Expr("frozen_amount - ?", amount),
|
|
"balance": gorm.Expr("balance + ?", amount),
|
|
})
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return ErrNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|