Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
b41a8ca9
Commit
b41a8ca9
authored
Mar 10, 2026
by
haruka
Browse files
add test
parent
de18bce9
Changes
3
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/subscription_reset_quota_test.go
0 → 100644
View file @
b41a8ca9
//go:build unit
package
service
import
(
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/require"
)
// resetQuotaUserSubRepoStub 支持 GetByID、ResetDailyUsage、ResetWeeklyUsage,
// 其余方法继承 userSubRepoNoop(panic)。
type
resetQuotaUserSubRepoStub
struct
{
userSubRepoNoop
sub
*
UserSubscription
resetDailyCalled
bool
resetWeeklyCalled
bool
resetDailyErr
error
resetWeeklyErr
error
}
func
(
r
*
resetQuotaUserSubRepoStub
)
GetByID
(
_
context
.
Context
,
id
int64
)
(
*
UserSubscription
,
error
)
{
if
r
.
sub
==
nil
||
r
.
sub
.
ID
!=
id
{
return
nil
,
ErrSubscriptionNotFound
}
cp
:=
*
r
.
sub
return
&
cp
,
nil
}
func
(
r
*
resetQuotaUserSubRepoStub
)
ResetDailyUsage
(
_
context
.
Context
,
_
int64
,
_
time
.
Time
)
error
{
r
.
resetDailyCalled
=
true
return
r
.
resetDailyErr
}
func
(
r
*
resetQuotaUserSubRepoStub
)
ResetWeeklyUsage
(
_
context
.
Context
,
_
int64
,
_
time
.
Time
)
error
{
r
.
resetWeeklyCalled
=
true
return
r
.
resetWeeklyErr
}
func
newResetQuotaSvc
(
stub
*
resetQuotaUserSubRepoStub
)
*
SubscriptionService
{
return
NewSubscriptionService
(
groupRepoNoop
{},
stub
,
nil
,
nil
,
nil
)
}
func
TestAdminResetQuota_ResetBoth
(
t
*
testing
.
T
)
{
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
&
UserSubscription
{
ID
:
1
,
UserID
:
10
,
GroupID
:
20
},
}
svc
:=
newResetQuotaSvc
(
stub
)
result
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
1
,
true
,
true
)
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
t
,
result
)
require
.
True
(
t
,
stub
.
resetDailyCalled
,
"应调用 ResetDailyUsage"
)
require
.
True
(
t
,
stub
.
resetWeeklyCalled
,
"应调用 ResetWeeklyUsage"
)
}
func
TestAdminResetQuota_ResetDailyOnly
(
t
*
testing
.
T
)
{
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
&
UserSubscription
{
ID
:
2
,
UserID
:
10
,
GroupID
:
20
},
}
svc
:=
newResetQuotaSvc
(
stub
)
result
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
2
,
true
,
false
)
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
t
,
result
)
require
.
True
(
t
,
stub
.
resetDailyCalled
,
"应调用 ResetDailyUsage"
)
require
.
False
(
t
,
stub
.
resetWeeklyCalled
,
"不应调用 ResetWeeklyUsage"
)
}
func
TestAdminResetQuota_ResetWeeklyOnly
(
t
*
testing
.
T
)
{
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
&
UserSubscription
{
ID
:
3
,
UserID
:
10
,
GroupID
:
20
},
}
svc
:=
newResetQuotaSvc
(
stub
)
result
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
3
,
false
,
true
)
require
.
NoError
(
t
,
err
)
require
.
NotNil
(
t
,
result
)
require
.
False
(
t
,
stub
.
resetDailyCalled
,
"不应调用 ResetDailyUsage"
)
require
.
True
(
t
,
stub
.
resetWeeklyCalled
,
"应调用 ResetWeeklyUsage"
)
}
func
TestAdminResetQuota_SubscriptionNotFound
(
t
*
testing
.
T
)
{
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
nil
}
svc
:=
newResetQuotaSvc
(
stub
)
_
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
999
,
true
,
true
)
require
.
ErrorIs
(
t
,
err
,
ErrSubscriptionNotFound
)
require
.
False
(
t
,
stub
.
resetDailyCalled
)
require
.
False
(
t
,
stub
.
resetWeeklyCalled
)
}
func
TestAdminResetQuota_ResetDailyUsageError
(
t
*
testing
.
T
)
{
dbErr
:=
errors
.
New
(
"db error"
)
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
&
UserSubscription
{
ID
:
4
,
UserID
:
10
,
GroupID
:
20
},
resetDailyErr
:
dbErr
,
}
svc
:=
newResetQuotaSvc
(
stub
)
_
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
4
,
true
,
true
)
require
.
ErrorIs
(
t
,
err
,
dbErr
)
require
.
True
(
t
,
stub
.
resetDailyCalled
)
require
.
False
(
t
,
stub
.
resetWeeklyCalled
,
"daily 失败后不应继续调用 weekly"
)
}
func
TestAdminResetQuota_ResetWeeklyUsageError
(
t
*
testing
.
T
)
{
dbErr
:=
errors
.
New
(
"db error"
)
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
&
UserSubscription
{
ID
:
5
,
UserID
:
10
,
GroupID
:
20
},
resetWeeklyErr
:
dbErr
,
}
svc
:=
newResetQuotaSvc
(
stub
)
_
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
5
,
false
,
true
)
require
.
ErrorIs
(
t
,
err
,
dbErr
)
require
.
True
(
t
,
stub
.
resetWeeklyCalled
)
}
func
TestAdminResetQuota_ReturnsRefreshedSub
(
t
*
testing
.
T
)
{
now
:=
time
.
Now
()
windowStart
:=
startOfDay
(
now
)
sub
:=
&
UserSubscription
{
ID
:
6
,
UserID
:
10
,
GroupID
:
20
,
DailyUsageUSD
:
99.9
,
}
stub
:=
&
resetQuotaUserSubRepoStub
{
sub
:
sub
}
// 模拟 ResetDailyUsage 将 DB 中的数据归零
stub
.
resetDailyErr
=
nil
stub
.
ResetDailyUsage
(
context
.
Background
(),
sub
.
ID
,
windowStart
)
//nolint:errcheck
// 手动更新 stub 中的 sub,模拟 DB 写入效果
stub
.
resetDailyCalled
=
false
stub
.
sub
.
DailyUsageUSD
=
0
stub
.
sub
.
DailyWindowStart
=
&
windowStart
svc
:=
newResetQuotaSvc
(
stub
)
result
,
err
:=
svc
.
AdminResetQuota
(
context
.
Background
(),
6
,
true
,
false
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
float64
(
0
),
result
.
DailyUsageUSD
,
"返回的订阅应反映已归零的用量"
)
}
backend/internal/service/subscription_service.go
View file @
b41a8ca9
...
...
@@ -707,15 +707,11 @@ func (s *SubscriptionService) AdminResetQuota(ctx context.Context, subscriptionI
if
err
:=
s
.
userSubRepo
.
ResetDailyUsage
(
ctx
,
sub
.
ID
,
windowStart
);
err
!=
nil
{
return
nil
,
err
}
sub
.
DailyWindowStart
=
&
windowStart
sub
.
DailyUsageUSD
=
0
}
if
resetWeekly
{
if
err
:=
s
.
userSubRepo
.
ResetWeeklyUsage
(
ctx
,
sub
.
ID
,
windowStart
);
err
!=
nil
{
return
nil
,
err
}
sub
.
WeeklyWindowStart
=
&
windowStart
sub
.
WeeklyUsageUSD
=
0
}
// Invalidate caches, same as CheckAndResetWindows
s
.
InvalidateSubCache
(
sub
.
UserID
,
sub
.
GroupID
)
...
...
frontend/src/views/admin/SubscriptionsView.vue
View file @
b41a8ca9
...
...
@@ -373,7 +373,8 @@
<
button
v
-
if
=
"
row.status === 'active'
"
@
click
=
"
handleResetQuota(row)
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-orange-50 hover:text-orange-600 dark:hover:bg-orange-900/20 dark:hover:text-orange-400
"
:
disabled
=
"
resettingQuota && resettingSubscription?.id === row.id
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-orange-50 hover:text-orange-600 dark:hover:bg-orange-900/20 dark:hover:text-orange-400 disabled:cursor-not-allowed disabled:opacity-50
"
>
<
Icon
name
=
"
refresh
"
size
=
"
sm
"
/>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.subscriptions.resetQuota
'
)
}}
<
/span
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment