fix(billing): 异步任务退款时同步减少 used_quota (#6795)
* fix(billing): 异步任务退款时同步减少 used_quota 退款时仅恢复了 quota(剩余额度),但未同步减少 used_quota(已用额度), 导致"总额度"(quota + used_quota)随退款次数持续虚增,超出用户实际充值金额。 修复三处退款路径: - RefundTaskQuota:任务失败完整退款 - RecalculateTaskQuota:差额结算退款分支 - controller/midjourney.go:Midjourney 任务失败退款 新增 model.UpdateUserUsedQuota 公开函数,仅调整 used_quota 不影响 request_count。 * fix(billing): 任务退款时同步扣减渠道 used_quota * fix(billing): complete async task refund accounting * style(model): group internal Midjourney fields --------- Co-authored-by: CaIon <i@caion.me>
This commit is contained in:
@@ -89,6 +89,61 @@ func TestUserUpdateDoesNotOverwriteConcurrentAccountingOrTokenChanges(t *testing
|
||||
assert.Equal(t, "rotated-token", got.GetAccessToken())
|
||||
}
|
||||
|
||||
func TestUsageAccountingSupportsSignedDirectAndBatchDeltas(t *testing.T) {
|
||||
setupUserUpdateTestState(t)
|
||||
resetBatchUpdateTestState(t)
|
||||
|
||||
user := User{
|
||||
Id: 10,
|
||||
Username: "usage-adjustment-user",
|
||||
Password: "password",
|
||||
Status: common.UserStatusEnabled,
|
||||
UsedQuota: 1000,
|
||||
RequestCount: 3,
|
||||
}
|
||||
channel := Channel{
|
||||
Id: 10,
|
||||
Name: "usage-adjustment-channel",
|
||||
Key: "sk-test",
|
||||
Status: common.ChannelStatusEnabled,
|
||||
UsedQuota: 1000,
|
||||
}
|
||||
require.NoError(t, DB.Create(&user).Error)
|
||||
require.NoError(t, DB.Create(&channel).Error)
|
||||
|
||||
UpdateUserUsedQuota(user.Id, -200)
|
||||
UpdateUserUsedQuota(user.Id, 50)
|
||||
UpdateChannelUsedQuota(channel.Id, -200)
|
||||
UpdateChannelUsedQuota(channel.Id, 50)
|
||||
|
||||
var got User
|
||||
require.NoError(t, DB.Select("used_quota", "request_count").First(&got, user.Id).Error)
|
||||
assert.Equal(t, 850, got.UsedQuota)
|
||||
assert.Equal(t, 3, got.RequestCount)
|
||||
var gotChannel Channel
|
||||
require.NoError(t, DB.Select("used_quota").First(&gotChannel, channel.Id).Error)
|
||||
assert.Equal(t, int64(850), gotChannel.UsedQuota)
|
||||
|
||||
common.BatchUpdateEnabled = true
|
||||
UpdateUserUsedQuota(user.Id, 400)
|
||||
UpdateUserUsedQuota(user.Id, -100)
|
||||
UpdateChannelUsedQuota(channel.Id, 400)
|
||||
UpdateChannelUsedQuota(channel.Id, -100)
|
||||
|
||||
require.NoError(t, DB.Select("used_quota", "request_count").First(&got, user.Id).Error)
|
||||
assert.Equal(t, 850, got.UsedQuota, "batch deltas must remain queued until flush")
|
||||
assert.Equal(t, 3, got.RequestCount)
|
||||
require.NoError(t, DB.Select("used_quota").First(&gotChannel, channel.Id).Error)
|
||||
assert.Equal(t, int64(850), gotChannel.UsedQuota, "batch deltas must remain queued until flush")
|
||||
|
||||
batchUpdate()
|
||||
require.NoError(t, DB.Select("used_quota", "request_count").First(&got, user.Id).Error)
|
||||
assert.Equal(t, 1150, got.UsedQuota)
|
||||
assert.Equal(t, 3, got.RequestCount)
|
||||
require.NoError(t, DB.Select("used_quota").First(&gotChannel, channel.Id).Error)
|
||||
assert.Equal(t, int64(1150), gotChannel.UsedQuota)
|
||||
}
|
||||
|
||||
func TestUpdateUserAccessTokenOnlyUpdatesAccessToken(t *testing.T) {
|
||||
setupUserUpdateTestState(t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user