fix: gofmt formatting across all Go source files

This commit is contained in:
erio
2026-04-14 07:43:08 +08:00
parent 9e0d12d3b0
commit 1e6912ea2e
18 changed files with 143 additions and 84 deletions

View File

@@ -310,11 +310,11 @@ type UpdateSettingsRequest struct {
EnableCCHSigning *bool `json:"enable_cch_signing"`
// Balance low notification
BalanceLowNotifyEnabled *bool `json:"balance_low_notify_enabled"`
BalanceLowNotifyThreshold *float64 `json:"balance_low_notify_threshold"`
BalanceLowNotifyRechargeURL *string `json:"balance_low_notify_recharge_url"`
AccountQuotaNotifyEnabled *bool `json:"account_quota_notify_enabled"`
AccountQuotaNotifyEmails *[]dto.NotifyEmailEntry `json:"account_quota_notify_emails"`
BalanceLowNotifyEnabled *bool `json:"balance_low_notify_enabled"`
BalanceLowNotifyThreshold *float64 `json:"balance_low_notify_threshold"`
BalanceLowNotifyRechargeURL *string `json:"balance_low_notify_recharge_url"`
AccountQuotaNotifyEnabled *bool `json:"account_quota_notify_enabled"`
AccountQuotaNotifyEmails *[]dto.NotifyEmailEntry `json:"account_quota_notify_emails"`
// Payment configuration (integrated into settings, full replace)
PaymentEnabled *bool `json:"payment_enabled"`

View File

@@ -150,11 +150,11 @@ type SystemSettings struct {
PaymentCancelRateLimitMode string `json:"payment_cancel_rate_limit_window_mode"`
// Balance low notification
BalanceLowNotifyEnabled bool `json:"balance_low_notify_enabled"`
BalanceLowNotifyThreshold float64 `json:"balance_low_notify_threshold"`
BalanceLowNotifyRechargeURL string `json:"balance_low_notify_recharge_url"`
AccountQuotaNotifyEnabled bool `json:"account_quota_notify_enabled"`
AccountQuotaNotifyEmails []NotifyEmailEntry `json:"account_quota_notify_emails"`
BalanceLowNotifyEnabled bool `json:"balance_low_notify_enabled"`
BalanceLowNotifyThreshold float64 `json:"balance_low_notify_threshold"`
BalanceLowNotifyRechargeURL string `json:"balance_low_notify_recharge_url"`
AccountQuotaNotifyEnabled bool `json:"account_quota_notify_enabled"`
AccountQuotaNotifyEmails []NotifyEmailEntry `json:"account_quota_notify_emails"`
}
type DefaultSubscriptionSetting struct {

View File

@@ -19,11 +19,11 @@ type User struct {
UpdatedAt time.Time `json:"updated_at"`
// 余额不足通知
BalanceNotifyEnabled bool `json:"balance_notify_enabled"`
BalanceNotifyThresholdType string `json:"balance_notify_threshold_type"`
BalanceNotifyThreshold *float64 `json:"balance_notify_threshold"`
BalanceNotifyEnabled bool `json:"balance_notify_enabled"`
BalanceNotifyThresholdType string `json:"balance_notify_threshold_type"`
BalanceNotifyThreshold *float64 `json:"balance_notify_threshold"`
BalanceNotifyExtraEmails []NotifyEmailEntry `json:"balance_notify_extra_emails"`
TotalRecharged float64 `json:"total_recharged"`
TotalRecharged float64 `json:"total_recharged"`
APIKeys []APIKey `json:"api_keys,omitempty"`
Subscriptions []UserSubscription `json:"subscriptions,omitempty"`

View File

@@ -242,7 +242,7 @@ func TestFilterByLimits(t *testing.T) {
wantIDs: nil,
},
{
name: "empty candidates returns empty",
name: "empty candidates returns empty",
candidates: nil,
paymentType: "alipay",
orderAmount: 10,

View File

@@ -98,9 +98,9 @@ func TestNewAlipay(t *testing.T) {
errSubstr: "privateKey",
},
{
name: "nil config map returns error for appId",
config: map[string]string{},
wantErr: true,
name: "nil config map returns error for appId",
config: map[string]string{},
wantErr: true,
errSubstr: "appId",
},
}

View File

@@ -1533,39 +1533,48 @@ func (a *Account) QuotaNotifyConfig(dim string) (enabled bool, threshold float64
}
func (a *Account) GetQuotaNotifyDailyEnabled() bool {
e, _, _ := a.QuotaNotifyConfig(quotaDimDaily); return e
e, _, _ := a.QuotaNotifyConfig(quotaDimDaily)
return e
}
func (a *Account) GetQuotaNotifyDailyThreshold() float64 {
_, t, _ := a.QuotaNotifyConfig(quotaDimDaily); return t
_, t, _ := a.QuotaNotifyConfig(quotaDimDaily)
return t
}
func (a *Account) GetQuotaNotifyDailyThresholdType() string {
_, _, tt := a.QuotaNotifyConfig(quotaDimDaily); return tt
_, _, tt := a.QuotaNotifyConfig(quotaDimDaily)
return tt
}
func (a *Account) GetQuotaNotifyWeeklyEnabled() bool {
e, _, _ := a.QuotaNotifyConfig(quotaDimWeekly); return e
e, _, _ := a.QuotaNotifyConfig(quotaDimWeekly)
return e
}
func (a *Account) GetQuotaNotifyWeeklyThreshold() float64 {
_, t, _ := a.QuotaNotifyConfig(quotaDimWeekly); return t
_, t, _ := a.QuotaNotifyConfig(quotaDimWeekly)
return t
}
func (a *Account) GetQuotaNotifyWeeklyThresholdType() string {
_, _, tt := a.QuotaNotifyConfig(quotaDimWeekly); return tt
_, _, tt := a.QuotaNotifyConfig(quotaDimWeekly)
return tt
}
func (a *Account) GetQuotaNotifyTotalEnabled() bool {
e, _, _ := a.QuotaNotifyConfig(quotaDimTotal); return e
e, _, _ := a.QuotaNotifyConfig(quotaDimTotal)
return e
}
func (a *Account) GetQuotaNotifyTotalThreshold() float64 {
_, t, _ := a.QuotaNotifyConfig(quotaDimTotal); return t
_, t, _ := a.QuotaNotifyConfig(quotaDimTotal)
return t
}
func (a *Account) GetQuotaNotifyTotalThresholdType() string {
_, _, tt := a.QuotaNotifyConfig(quotaDimTotal); return tt
_, _, tt := a.QuotaNotifyConfig(quotaDimTotal)
return tt
}
// nextFixedDailyReset 计算在 after 之后的下一个每日固定重置时间点

View File

@@ -65,15 +65,15 @@ func TestBuildBalanceLowEmailBody_NoRechargeURLOmitsButton(t *testing.T) {
func TestBuildQuotaAlertEmailBody_AllFieldsPresent(t *testing.T) {
s := &BalanceNotifyService{}
body := s.buildQuotaAlertEmailBody(
42, // accountID
"acc-foo", // accountName
"anthropic", // platform
"日限额 / Daily", // dimLabel
750.50, // used
1000.0, // limit
249.50, // remaining
"$249.50", // thresholdDisplay
"MySite", // siteName
42, // accountID
"acc-foo", // accountName
"anthropic", // platform
"日限额 / Daily", // dimLabel
750.50, // used
1000.0, // limit
249.50, // remaining
"$249.50", // thresholdDisplay
"MySite", // siteName
)
require.Contains(t, body, "MySite")

View File

@@ -251,8 +251,8 @@ const (
SettingKeyEnableCCHSigning = "enable_cch_signing"
// Balance Low Notification
SettingKeyBalanceLowNotifyEnabled = "balance_low_notify_enabled" // 全局开关
SettingKeyBalanceLowNotifyThreshold = "balance_low_notify_threshold" // 默认阈值USD
SettingKeyBalanceLowNotifyEnabled = "balance_low_notify_enabled" // 全局开关
SettingKeyBalanceLowNotifyThreshold = "balance_low_notify_threshold" // 默认阈值USD
SettingKeyBalanceLowNotifyRechargeURL = "balance_low_notify_recharge_url" // 充值页面 URL
// Account Quota Notification

View File

@@ -131,9 +131,9 @@ func TestValidatePlanPatch_NilOriginalPrice(t *testing.T) {
// --- validatePlanPatch: other fields ---
func ptrStr(s string) *string { return &s }
func ptrInt(i int) *int { return &i }
func ptrInt64(i int64) *int64 { return &i }
func ptrStr(s string) *string { return &s }
func ptrInt(i int) *int { return &i }
func ptrInt64(i int64) *int64 { return &i }
func ptrFloat(f float64) *float64 { return &f }
func TestValidatePlanPatch_EmptyName(t *testing.T) {

View File

@@ -22,16 +22,17 @@ func (s *PaymentConfigService) ListProviderInstances(ctx context.Context) ([]*db
// ProviderInstanceResponse is the API response for a provider instance.
type ProviderInstanceResponse struct {
ID int64 `json:"id"`
ProviderKey string `json:"provider_key"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Limits string `json:"limits"`
Enabled bool `json:"enabled"`
RefundEnabled bool `json:"refund_enabled"`
SortOrder int `json:"sort_order"`
PaymentMode string `json:"payment_mode"`
ID int64 `json:"id"`
ProviderKey string `json:"provider_key"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Limits string `json:"limits"`
Enabled bool `json:"enabled"`
RefundEnabled bool `json:"refund_enabled"`
AllowUserRefund bool `json:"allow_user_refund"`
SortOrder int `json:"sort_order"`
PaymentMode string `json:"payment_mode"`
}
// ListProviderInstancesWithConfig returns provider instances with decrypted config.
@@ -46,8 +47,8 @@ func (s *PaymentConfigService) ListProviderInstancesWithConfig(ctx context.Conte
resp := ProviderInstanceResponse{
ID: int64(inst.ID), ProviderKey: inst.ProviderKey, Name: inst.Name,
SupportedTypes: splitTypes(inst.SupportedTypes), Limits: inst.Limits,
Enabled: inst.Enabled, RefundEnabled: inst.RefundEnabled, SortOrder: inst.SortOrder,
PaymentMode: inst.PaymentMode,
Enabled: inst.Enabled, RefundEnabled: inst.RefundEnabled, AllowUserRefund: inst.AllowUserRefund,
SortOrder: inst.SortOrder, PaymentMode: inst.PaymentMode,
}
resp.Config, err = s.decryptAndMaskConfig(inst.Config)
if err != nil {
@@ -110,10 +111,12 @@ func (s *PaymentConfigService) CreateProviderInstance(ctx context.Context, req C
if err != nil {
return nil, err
}
allowUserRefund := req.AllowUserRefund && req.RefundEnabled
return s.entClient.PaymentProviderInstance.Create().
SetProviderKey(req.ProviderKey).SetName(req.Name).SetConfig(enc).
SetSupportedTypes(typesStr).SetEnabled(req.Enabled).SetPaymentMode(req.PaymentMode).
SetSortOrder(req.SortOrder).SetLimits(req.Limits).SetRefundEnabled(req.RefundEnabled).
SetAllowUserRefund(allowUserRefund).
Save(ctx)
}
@@ -221,6 +224,21 @@ func (s *PaymentConfigService) UpdateProviderInstance(ctx context.Context, id in
}
if req.RefundEnabled != nil {
u.SetRefundEnabled(*req.RefundEnabled)
// Cascade: turning off refund_enabled also disables allow_user_refund
if !*req.RefundEnabled {
u.SetAllowUserRefund(false)
}
}
if req.AllowUserRefund != nil {
// Only allow enabling when refund_enabled is true
if *req.AllowUserRefund {
inst, err := s.entClient.PaymentProviderInstance.Get(ctx, id)
if err == nil && inst.RefundEnabled {
u.SetAllowUserRefund(true)
}
} else {
u.SetAllowUserRefund(false)
}
}
if req.PaymentMode != nil {
u.SetPaymentMode(*req.PaymentMode)
@@ -228,6 +246,23 @@ func (s *PaymentConfigService) UpdateProviderInstance(ctx context.Context, id in
return u.Save(ctx)
}
// GetUserRefundEligibleInstanceIDs returns provider instance IDs that allow user refund.
func (s *PaymentConfigService) GetUserRefundEligibleInstanceIDs(ctx context.Context) ([]string, error) {
instances, err := s.entClient.PaymentProviderInstance.Query().
Where(
paymentproviderinstance.AllowUserRefundEQ(true),
paymentproviderinstance.RefundEnabledEQ(true),
).Select(paymentproviderinstance.FieldID).All(ctx)
if err != nil {
return nil, err
}
ids := make([]string, 0, len(instances))
for _, inst := range instances {
ids = append(ids, strconv.FormatInt(int64(inst.ID), 10))
}
return ids, nil
}
func (s *PaymentConfigService) mergeConfig(ctx context.Context, id int64, newConfig map[string]string) (map[string]string, error) {
inst, err := s.entClient.PaymentProviderInstance.Get(ctx, id)
if err != nil {

View File

@@ -101,7 +101,7 @@ func TestIsSensitiveConfigField(t *testing.T) {
t.Parallel()
tests := []struct {
field string
field string
wantSen bool
}{
// Sensitive fields (contain key/secret/private/password/pkey patterns)

View File

@@ -105,26 +105,28 @@ type MethodLimitsResponse struct {
}
type CreateProviderInstanceRequest struct {
ProviderKey string `json:"provider_key"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Enabled bool `json:"enabled"`
PaymentMode string `json:"payment_mode"`
SortOrder int `json:"sort_order"`
Limits string `json:"limits"`
RefundEnabled bool `json:"refund_enabled"`
ProviderKey string `json:"provider_key"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Enabled bool `json:"enabled"`
PaymentMode string `json:"payment_mode"`
SortOrder int `json:"sort_order"`
Limits string `json:"limits"`
RefundEnabled bool `json:"refund_enabled"`
AllowUserRefund bool `json:"allow_user_refund"`
}
type UpdateProviderInstanceRequest struct {
Name *string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Enabled *bool `json:"enabled"`
PaymentMode *string `json:"payment_mode"`
SortOrder *int `json:"sort_order"`
Limits *string `json:"limits"`
RefundEnabled *bool `json:"refund_enabled"`
Name *string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes []string `json:"supported_types"`
Enabled *bool `json:"enabled"`
PaymentMode *string `json:"payment_mode"`
SortOrder *int `json:"sort_order"`
Limits *string `json:"limits"`
RefundEnabled *bool `json:"refund_enabled"`
AllowUserRefund *bool `json:"allow_user_refund"`
}
type CreatePlanRequest struct {
GroupID int64 `json:"group_id"`

View File

@@ -66,7 +66,7 @@ func TestSettingService_GetPublicSettings_ExposesRegistrationEmailSuffixWhitelis
func TestSettingService_GetPublicSettings_ExposesTablePreferences(t *testing.T) {
repo := &settingPublicRepoStub{
values: map[string]string{
SettingKeyTableDefaultPageSize: "50",
SettingKeyTableDefaultPageSize: "50",
SettingKeyTablePageSizeOptions: "[20,50,100]",
},
}

View File

@@ -208,7 +208,7 @@ func TestSettingService_UpdateSettings_TablePreferences(t *testing.T) {
svc := NewSettingService(repo, &config.Config{})
err := svc.UpdateSettings(context.Background(), &SystemSettings{
TableDefaultPageSize: 50,
TableDefaultPageSize: 50,
TablePageSizeOptions: []int{20, 50, 100},
})
require.NoError(t, err)
@@ -216,7 +216,7 @@ func TestSettingService_UpdateSettings_TablePreferences(t *testing.T) {
require.Equal(t, "[20,50,100]", repo.updates[SettingKeyTablePageSizeOptions])
err = svc.UpdateSettings(context.Background(), &SystemSettings{
TableDefaultPageSize: 1000,
TableDefaultPageSize: 1000,
TablePageSizeOptions: []int{20, 100},
})
require.NoError(t, err)

View File

@@ -108,8 +108,8 @@ type SystemSettings struct {
EnableCCHSigning bool // 是否对 billing header cch 进行签名(默认 false
// Balance low notification
BalanceLowNotifyEnabled bool
BalanceLowNotifyThreshold float64
BalanceLowNotifyEnabled bool
BalanceLowNotifyThreshold float64
BalanceLowNotifyRechargeURL string
// Account quota notification
@@ -155,10 +155,10 @@ type PublicSettings struct {
OIDCOAuthProviderName string
Version string
BalanceLowNotifyEnabled bool
AccountQuotaNotifyEnabled bool
BalanceLowNotifyThreshold float64
BalanceLowNotifyRechargeURL string
BalanceLowNotifyEnabled bool
AccountQuotaNotifyEnabled bool
BalanceLowNotifyThreshold float64
BalanceLowNotifyRechargeURL string
}
// StreamTimeoutSettings 流超时处理配置(仅控制超时后的处理方式,超时判定由网关配置控制)

View File

@@ -100,9 +100,22 @@ func valueOrZero(v *int64) int64 {
return *v
}
// AccountQuotaState holds the post-increment quota state returned by the DB transaction.
// All values are post-update (i.e., already include the increment).
type AccountQuotaState struct {
TotalUsed float64
TotalLimit float64
DailyUsed float64
DailyLimit float64
WeeklyUsed float64
WeeklyLimit float64
}
type UsageBillingApplyResult struct {
Applied bool
APIKeyQuotaExhausted bool
NewBalance *float64 // post-deduction balance (nil = no balance deduction)
QuotaState *AccountQuotaState // post-increment quota state (nil = no quota increment)
}
type UsageBillingRepository interface {

View File

@@ -32,7 +32,7 @@ type User struct {
// 余额不足通知
BalanceNotifyEnabled bool
BalanceNotifyThresholdType string // "fixed" (default) | "percentage"
BalanceNotifyThresholdType string // "fixed" (default) | "percentage"
BalanceNotifyThreshold *float64
BalanceNotifyExtraEmails []NotifyEmailEntry
TotalRecharged float64

View File

@@ -13,9 +13,9 @@ import (
)
var (
ErrUserNotFound = infraerrors.NotFound("USER_NOT_FOUND", "user not found")
ErrPasswordIncorrect = infraerrors.BadRequest("PASSWORD_INCORRECT", "current password is incorrect")
ErrInsufficientPerms = infraerrors.Forbidden("INSUFFICIENT_PERMISSIONS", "insufficient permissions")
ErrUserNotFound = infraerrors.NotFound("USER_NOT_FOUND", "user not found")
ErrPasswordIncorrect = infraerrors.BadRequest("PASSWORD_INCORRECT", "current password is incorrect")
ErrInsufficientPerms = infraerrors.Forbidden("INSUFFICIENT_PERMISSIONS", "insufficient permissions")
ErrNotifyCodeUserRateLimit = infraerrors.TooManyRequests("NOTIFY_CODE_USER_RATE_LIMIT", "too many verification codes requested, please try again later")
)