feat: add rebate data models
Add affiliate rebate configuration fields, option defaults, and rebate record persistence for the rebate workflow.
This commit is contained in:
parent
959ee42bcb
commit
16b2853d62
@ -288,6 +288,7 @@ func migrateDB() error {
|
||||
&ChannelMonitor{},
|
||||
&ChannelMonitorHistory{},
|
||||
&ChannelMonitorDailyRollup{},
|
||||
&RebateRecord{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -344,6 +345,7 @@ func migrateDBFast() error {
|
||||
{&ChannelMonitor{}, "ChannelMonitor"},
|
||||
{&ChannelMonitorHistory{}, "ChannelMonitorHistory"},
|
||||
{&ChannelMonitorDailyRollup{}, "ChannelMonitorDailyRollup"},
|
||||
{&RebateRecord{}, "RebateRecord"},
|
||||
}
|
||||
// 动态计算migration数量,确保errChan缓冲区足够大
|
||||
errChan := make(chan error, len(migrations))
|
||||
|
||||
@ -19,6 +19,12 @@ type Option struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
const (
|
||||
AffRebateRatePercentKey = "AffRebateRatePercent"
|
||||
AffRebateFrozenDaysKey = "AffRebateFrozenDays"
|
||||
AffRebateEnabledKey = "AffRebateEnabled"
|
||||
)
|
||||
|
||||
func AllOption() ([]*Option, error) {
|
||||
var options []*Option
|
||||
var err error
|
||||
@ -135,6 +141,9 @@ func InitOptionMap() {
|
||||
common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser)
|
||||
common.OptionMap["QuotaForInviter"] = strconv.Itoa(common.QuotaForInviter)
|
||||
common.OptionMap["QuotaForInvitee"] = strconv.Itoa(common.QuotaForInvitee)
|
||||
common.OptionMap[AffRebateRatePercentKey] = "0"
|
||||
common.OptionMap[AffRebateFrozenDaysKey] = "0"
|
||||
common.OptionMap[AffRebateEnabledKey] = strconv.FormatBool(false)
|
||||
common.OptionMap["QuotaRemindThreshold"] = strconv.Itoa(common.QuotaRemindThreshold)
|
||||
common.OptionMap["PreConsumedQuota"] = strconv.Itoa(common.PreConsumedQuota)
|
||||
common.OptionMap["ModelRequestRateLimitCount"] = strconv.Itoa(setting.ModelRequestRateLimitCount)
|
||||
|
||||
61
model/rebate_record.go
Normal file
61
model/rebate_record.go
Normal file
@ -0,0 +1,61 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type RebateRecord struct {
|
||||
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
|
||||
InviterId int `json:"inviter_id" gorm:"index;not null"`
|
||||
InviteeId int `json:"invitee_id" gorm:"index;not null"`
|
||||
OrderId int `json:"order_id" gorm:"index"`
|
||||
OrderType string `json:"order_type" gorm:"type:varchar(16);not null"`
|
||||
OrderAmount int `json:"order_amount" gorm:"not null"`
|
||||
RebateAmount int `json:"rebate_amount" gorm:"not null"`
|
||||
RatePercent int `json:"rate_percent" gorm:"not null"`
|
||||
Status string `json:"status" gorm:"type:varchar(16);not null;default:'frozen';index"`
|
||||
FrozenUntil *time.Time `json:"frozen_until" gorm:"index"`
|
||||
ReleasedAt *time.Time `json:"released_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
func (RebateRecord) TableName() string {
|
||||
return "rebate_records"
|
||||
}
|
||||
|
||||
func (r *RebateRecord) Insert() error {
|
||||
return DB.Create(r).Error
|
||||
}
|
||||
|
||||
func (r *RebateRecord) Update() error {
|
||||
return DB.Save(r).Error
|
||||
}
|
||||
|
||||
func GetFrozenRebatesDue() ([]RebateRecord, error) {
|
||||
var records []RebateRecord
|
||||
err := DB.Where("status = ? AND frozen_until IS NOT NULL AND frozen_until <= ?", "frozen", time.Now()).
|
||||
Order("id ASC").
|
||||
Find(&records).Error
|
||||
return records, err
|
||||
}
|
||||
|
||||
func GetRebateRecords(page int, pageSize int, status string, userId int) ([]RebateRecord, int64, error) {
|
||||
var records []RebateRecord
|
||||
var total int64
|
||||
query := DB.Model(&RebateRecord{})
|
||||
if status != "" {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
if userId > 0 {
|
||||
query = query.Where("inviter_id = ? OR invitee_id = ?", userId, userId)
|
||||
}
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 {
|
||||
pageSize = 20
|
||||
}
|
||||
err := query.Order("id DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records).Error
|
||||
return records, total, err
|
||||
}
|
||||
@ -22,37 +22,39 @@ const UserNameMaxLength = 20
|
||||
// User if you add sensitive fields, don't forget to clean them in setupLogin function.
|
||||
// Otherwise, the sensitive information will be saved on local storage in plain text!
|
||||
type User struct {
|
||||
Id int `json:"id"`
|
||||
Username string `json:"username" gorm:"unique;index" validate:"max=20"`
|
||||
Password string `json:"password" gorm:"not null;" validate:"min=8,max=20"`
|
||||
OriginalPassword string `json:"original_password" gorm:"-:all"` // this field is only for Password change verification, don't save it to database!
|
||||
DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
|
||||
Role int `json:"role" gorm:"type:int;default:1"` // admin, common
|
||||
Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
|
||||
Email string `json:"email" gorm:"index" validate:"max=50"`
|
||||
GitHubId string `json:"github_id" gorm:"column:github_id;index"`
|
||||
DiscordId string `json:"discord_id" gorm:"column:discord_id;index"`
|
||||
OidcId string `json:"oidc_id" gorm:"column:oidc_id;index"`
|
||||
WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
|
||||
TelegramId string `json:"telegram_id" gorm:"column:telegram_id;index"`
|
||||
VerificationCode string `json:"verification_code" gorm:"-:all"` // this field is only for Email verification, don't save it to database!
|
||||
AccessToken *string `json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"` // this token is for system management
|
||||
Quota int `json:"quota" gorm:"type:int;default:0"`
|
||||
UsedQuota int `json:"used_quota" gorm:"type:int;default:0;column:used_quota"` // used quota
|
||||
RequestCount int `json:"request_count" gorm:"type:int;default:0;"` // request number
|
||||
Group string `json:"group" gorm:"type:varchar(64);default:'default'"`
|
||||
AffCode string `json:"aff_code" gorm:"type:varchar(32);column:aff_code;uniqueIndex"`
|
||||
AffCount int `json:"aff_count" gorm:"type:int;default:0;column:aff_count"`
|
||||
AffQuota int `json:"aff_quota" gorm:"type:int;default:0;column:aff_quota"` // 邀请剩余额度
|
||||
AffHistoryQuota int `json:"aff_history_quota" gorm:"type:int;default:0;column:aff_history"` // 邀请历史额度
|
||||
InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
LinuxDOId string `json:"linux_do_id" gorm:"column:linux_do_id;index"`
|
||||
Setting string `json:"setting" gorm:"type:text;column:setting"`
|
||||
Remark string `json:"remark,omitempty" gorm:"type:varchar(255)" validate:"max=255"`
|
||||
StripeCustomer string `json:"stripe_customer" gorm:"type:varchar(64);column:stripe_customer;index"`
|
||||
CreatedAt int64 `json:"created_at" gorm:"autoCreateTime;column:created_at"`
|
||||
LastLoginAt int64 `json:"last_login_at" gorm:"default:0;column:last_login_at"`
|
||||
Id int `json:"id"`
|
||||
Username string `json:"username" gorm:"unique;index" validate:"max=20"`
|
||||
Password string `json:"password" gorm:"not null;" validate:"min=8,max=20"`
|
||||
OriginalPassword string `json:"original_password" gorm:"-:all"` // this field is only for Password change verification, don't save it to database!
|
||||
DisplayName string `json:"display_name" gorm:"index" validate:"max=20"`
|
||||
Role int `json:"role" gorm:"type:int;default:1"` // admin, common
|
||||
Status int `json:"status" gorm:"type:int;default:1"` // enabled, disabled
|
||||
Email string `json:"email" gorm:"index" validate:"max=50"`
|
||||
GitHubId string `json:"github_id" gorm:"column:github_id;index"`
|
||||
DiscordId string `json:"discord_id" gorm:"column:discord_id;index"`
|
||||
OidcId string `json:"oidc_id" gorm:"column:oidc_id;index"`
|
||||
WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
|
||||
TelegramId string `json:"telegram_id" gorm:"column:telegram_id;index"`
|
||||
VerificationCode string `json:"verification_code" gorm:"-:all"` // this field is only for Email verification, don't save it to database!
|
||||
AccessToken *string `json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"` // this token is for system management
|
||||
Quota int `json:"quota" gorm:"type:int;default:0"`
|
||||
UsedQuota int `json:"used_quota" gorm:"type:int;default:0;column:used_quota"` // used quota
|
||||
RequestCount int `json:"request_count" gorm:"type:int;default:0;"` // request number
|
||||
Group string `json:"group" gorm:"type:varchar(64);default:'default'"`
|
||||
AffCode string `json:"aff_code" gorm:"type:varchar(32);column:aff_code;uniqueIndex"`
|
||||
AffCount int `json:"aff_count" gorm:"type:int;default:0;column:aff_count"`
|
||||
AffQuota int `json:"aff_quota" gorm:"type:int;default:0;column:aff_quota"` // 邀请剩余额度
|
||||
AffHistoryQuota int `json:"aff_history_quota" gorm:"type:int;default:0;column:aff_history"` // 邀请历史额度
|
||||
AffRebateRatePercent int `json:"aff_rebate_rate_percent" gorm:"type:int;default:0"`
|
||||
AffRebateFrozenDays int `json:"aff_rebate_frozen_days" gorm:"type:int;default:0"`
|
||||
InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
LinuxDOId string `json:"linux_do_id" gorm:"column:linux_do_id;index"`
|
||||
Setting string `json:"setting" gorm:"type:text;column:setting"`
|
||||
Remark string `json:"remark,omitempty" gorm:"type:varchar(255)" validate:"max=255"`
|
||||
StripeCustomer string `json:"stripe_customer" gorm:"type:varchar(64);column:stripe_customer;index"`
|
||||
CreatedAt int64 `json:"created_at" gorm:"autoCreateTime;column:created_at"`
|
||||
LastLoginAt int64 `json:"last_login_at" gorm:"default:0;column:last_login_at"`
|
||||
}
|
||||
|
||||
func (user *User) ToBaseUser() *UserBase {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user