新功能(#74): 新增促销系统模型层

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
2026-05-26 22:11:02 -07:00
parent 5ebfe0a981
commit e61988d78f
14 changed files with 720 additions and 25 deletions
+106
View File
@@ -0,0 +1,106 @@
package promo_usage
import (
"context"
"errors"
"fmt"
"github.com/perfect-panel/server/pkg/cache"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)
var _ Model = (*customPromoUsageModel)(nil)
var cachePromoUsageIdPrefix = "cache:promo_usage:id:"
type (
Model interface {
promoUsageModel
customPromoUsageLogicModel
}
promoUsageModel interface {
Insert(ctx context.Context, data *PromoUsage, tx ...*gorm.DB) error
FindOne(ctx context.Context, id int64) (*PromoUsage, error)
Update(ctx context.Context, data *PromoUsage, tx ...*gorm.DB) error
Delete(ctx context.Context, id int64, tx ...*gorm.DB) error
Transaction(ctx context.Context, fn func(db *gorm.DB) error) error
}
customPromoUsageModel struct {
*defaultPromoUsageModel
}
defaultPromoUsageModel struct {
cache.CachedConn
table string
}
)
func newPromoUsageModel(db *gorm.DB, c *redis.Client) *defaultPromoUsageModel {
return &defaultPromoUsageModel{
CachedConn: cache.NewConn(db, c),
table: "`promo_usage`",
}
}
func (m *defaultPromoUsageModel) getCacheKeys(data *PromoUsage) []string {
if data == nil {
return []string{}
}
return []string{fmt.Sprintf("%s%v", cachePromoUsageIdPrefix, data.Id)}
}
func (m *defaultPromoUsageModel) Insert(ctx context.Context, data *PromoUsage, tx ...*gorm.DB) error {
return m.ExecCtx(ctx, func(conn *gorm.DB) error {
if len(tx) > 0 {
conn = tx[0]
}
return conn.Create(data).Error
}, m.getCacheKeys(data)...)
}
func (m *defaultPromoUsageModel) FindOne(ctx context.Context, id int64) (*PromoUsage, error) {
key := fmt.Sprintf("%s%v", cachePromoUsageIdPrefix, id)
var resp PromoUsage
err := m.QueryCtx(ctx, &resp, key, func(conn *gorm.DB, v interface{}) error {
return conn.Model(&PromoUsage{}).Where("`id` = ?", id).First(v).Error
})
if err != nil {
return nil, err
}
return &resp, nil
}
func (m *defaultPromoUsageModel) Update(ctx context.Context, data *PromoUsage, tx ...*gorm.DB) error {
old, err := m.FindOne(ctx, data.Id)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
return m.ExecCtx(ctx, func(conn *gorm.DB) error {
if len(tx) > 0 {
conn = tx[0]
}
return conn.Save(data).Error
}, m.getCacheKeys(old)...)
}
func (m *defaultPromoUsageModel) Delete(ctx context.Context, id int64, tx ...*gorm.DB) error {
data, err := m.FindOne(ctx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
return m.ExecCtx(ctx, func(conn *gorm.DB) error {
if len(tx) > 0 {
conn = tx[0]
}
return conn.Delete(&PromoUsage{}, id).Error
}, m.getCacheKeys(data)...)
}
func (m *defaultPromoUsageModel) Transaction(ctx context.Context, fn func(db *gorm.DB) error) error {
return m.TransactCtx(ctx, fn)
}
+71
View File
@@ -0,0 +1,71 @@
package promo_usage
import (
"context"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)
type customPromoUsageLogicModel interface {
FindByOrderNo(ctx context.Context, orderNo string) ([]*PromoUsage, error)
FindByUserAndRule(ctx context.Context, userId, promoRuleId int64) ([]*PromoUsage, error)
QueryListByPage(ctx context.Context, page, size int, userId, promoRuleId, subscribeId int64) (int64, []*PromoUsage, error)
}
func NewModel(conn *gorm.DB, c *redis.Client) Model {
return &customPromoUsageModel{
defaultPromoUsageModel: newPromoUsageModel(conn, c),
}
}
func (m *customPromoUsageModel) FindByOrderNo(ctx context.Context, orderNo string) ([]*PromoUsage, error) {
var list []*PromoUsage
err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
return conn.Model(&PromoUsage{}).
Where("order_no = ?", orderNo).
Order("id DESC").
Find(v).Error
})
return list, err
}
func (m *customPromoUsageModel) FindByUserAndRule(ctx context.Context, userId, promoRuleId int64) ([]*PromoUsage, error) {
var list []*PromoUsage
err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
return conn.Model(&PromoUsage{}).
Where("user_id = ? AND promo_rule_id = ?", userId, promoRuleId).
Order("id DESC").
Find(v).Error
})
return list, err
}
func (m *customPromoUsageModel) QueryListByPage(ctx context.Context, page, size int, userId, promoRuleId, subscribeId int64) (int64, []*PromoUsage, error) {
var list []*PromoUsage
var total int64
if page <= 0 {
page = 1
}
if size <= 0 {
size = 20
}
err := m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
db := conn.Model(&PromoUsage{})
if userId > 0 {
db = db.Where("user_id = ?", userId)
}
if promoRuleId > 0 {
db = db.Where("promo_rule_id = ?", promoRuleId)
}
if subscribeId > 0 {
db = db.Where("subscribe_id = ?", subscribeId)
}
if err := db.Count(&total).Error; err != nil {
return err
}
return db.Order("id DESC").Limit(size).Offset((page - 1) * size).Find(v).Error
})
return total, list, err
}
+17
View File
@@ -0,0 +1,17 @@
package promo_usage
import "time"
type PromoUsage struct {
Id int64 `gorm:"type:bigint unsigned;primaryKey"`
UserId int64 `gorm:"type:bigint unsigned;not null;index:idx_user_rule,priority:1;comment:User Id"`
PromoRuleId int64 `gorm:"type:bigint unsigned;not null;index:idx_user_rule,priority:2;comment:Promo Rule Id"`
SubscribeId int64 `gorm:"type:bigint unsigned;not null;comment:Subscribe Id"`
OrderNo string `gorm:"type:varchar(255);not null;default:'';index:idx_order_no;comment:Order No"`
PromoPrice int64 `gorm:"type:bigint;not null;default:0;comment:Promo Price"`
CreatedAt time.Time `gorm:"<-:create;comment:Create Time"`
}
func (PromoUsage) TableName() string {
return "promo_usage"
}