mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-21 05:21:20 +00:00
fix(admin): preserve quota limits on partial group updates
This commit is contained in:
@@ -81,8 +81,8 @@ func (f optionalLimitField) ToServiceInput() *float64 {
|
||||
if f.value != nil {
|
||||
return f.value
|
||||
}
|
||||
zero := 0.0
|
||||
return &zero
|
||||
unlimited := -1.0
|
||||
return &unlimited
|
||||
}
|
||||
|
||||
// NewGroupHandler creates a new admin group handler
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUpdateGroupRequestLimitFieldsTriState(t *testing.T) {
|
||||
t.Run("omitted means unchanged", func(t *testing.T) {
|
||||
var req UpdateGroupRequest
|
||||
require.NoError(t, json.Unmarshal([]byte(`{}`), &req))
|
||||
require.Nil(t, req.DailyLimitUSD.ToServiceInput())
|
||||
require.Nil(t, req.WeeklyLimitUSD.ToServiceInput())
|
||||
require.Nil(t, req.MonthlyLimitUSD.ToServiceInput())
|
||||
})
|
||||
|
||||
t.Run("null means unlimited", func(t *testing.T) {
|
||||
var req UpdateGroupRequest
|
||||
require.NoError(t, json.Unmarshal([]byte(`{"daily_limit_usd":null}`), &req))
|
||||
limit := req.DailyLimitUSD.ToServiceInput()
|
||||
require.NotNil(t, limit)
|
||||
require.Negative(t, *limit)
|
||||
})
|
||||
|
||||
t.Run("number is preserved", func(t *testing.T) {
|
||||
var req UpdateGroupRequest
|
||||
require.NoError(t, json.Unmarshal([]byte(`{"weekly_limit_usd":0,"monthly_limit_usd":42.5}`), &req))
|
||||
require.Equal(t, 0.0, *req.WeeklyLimitUSD.ToServiceInput())
|
||||
require.Equal(t, 42.5, *req.MonthlyLimitUSD.ToServiceInput())
|
||||
})
|
||||
}
|
||||
@@ -680,11 +680,16 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd
|
||||
if input.SubscriptionType != "" {
|
||||
group.SubscriptionType = input.SubscriptionType
|
||||
}
|
||||
// 限额字段:nil/负数 表示"无限制",0 表示"不允许用量",正数表示具体限额
|
||||
// 前端始终发送这三个字段,无需 nil 守卫
|
||||
group.DailyLimitUSD = normalizeLimit(input.DailyLimitUSD)
|
||||
group.WeeklyLimitUSD = normalizeLimit(input.WeeklyLimitUSD)
|
||||
group.MonthlyLimitUSD = normalizeLimit(input.MonthlyLimitUSD)
|
||||
// 限额字段:nil 表示不修改,负数表示"无限制",0 表示"不允许用量",正数表示具体限额。
|
||||
if input.DailyLimitUSD != nil {
|
||||
group.DailyLimitUSD = normalizeLimit(input.DailyLimitUSD)
|
||||
}
|
||||
if input.WeeklyLimitUSD != nil {
|
||||
group.WeeklyLimitUSD = normalizeLimit(input.WeeklyLimitUSD)
|
||||
}
|
||||
if input.MonthlyLimitUSD != nil {
|
||||
group.MonthlyLimitUSD = normalizeLimit(input.MonthlyLimitUSD)
|
||||
}
|
||||
// 图片生成计费配置:负数表示清除(使用默认价格)
|
||||
if input.AllowImageGeneration != nil {
|
||||
group.AllowImageGeneration = *input.AllowImageGeneration
|
||||
|
||||
@@ -603,6 +603,42 @@ func TestAdminService_UpdateGroup_PreservesImageGenerationControlsWhenOmitted(t
|
||||
require.InDelta(t, 0.5, repo.updated.ImageRateMultiplier, 1e-12)
|
||||
}
|
||||
|
||||
func TestAdminService_UpdateGroup_LimitFieldsPartialUpdate(t *testing.T) {
|
||||
daily, weekly, monthly := 10.0, 20.0, 30.0
|
||||
existingGroup := &Group{
|
||||
ID: 1,
|
||||
Name: "existing-group",
|
||||
Platform: PlatformOpenAI,
|
||||
Status: StatusActive,
|
||||
DailyLimitUSD: &daily,
|
||||
WeeklyLimitUSD: &weekly,
|
||||
MonthlyLimitUSD: &monthly,
|
||||
}
|
||||
repo := &groupRepoStubForAdmin{getByID: existingGroup}
|
||||
svc := &adminServiceImpl{groupRepo: repo}
|
||||
|
||||
t.Run("non-quota update preserves all limits", func(t *testing.T) {
|
||||
description := "updated"
|
||||
group, err := svc.UpdateGroup(context.Background(), existingGroup.ID, &UpdateGroupInput{Description: &description})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 10.0, *group.DailyLimitUSD)
|
||||
require.Equal(t, 20.0, *group.WeeklyLimitUSD)
|
||||
require.Equal(t, 30.0, *group.MonthlyLimitUSD)
|
||||
})
|
||||
|
||||
t.Run("explicit changes and unlimited clear only touched limits", func(t *testing.T) {
|
||||
newDaily, unlimited := 15.0, -1.0
|
||||
group, err := svc.UpdateGroup(context.Background(), existingGroup.ID, &UpdateGroupInput{
|
||||
DailyLimitUSD: &newDaily,
|
||||
WeeklyLimitUSD: &unlimited,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 15.0, *group.DailyLimitUSD)
|
||||
require.Nil(t, group.WeeklyLimitUSD)
|
||||
require.Equal(t, 30.0, *group.MonthlyLimitUSD)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdminService_UpdateGroup_DisablesBatchImageWhenImageGenerationDisabled(t *testing.T) {
|
||||
existingGroup := &Group{
|
||||
ID: 1,
|
||||
|
||||
Reference in New Issue
Block a user