重构优惠券表结构与功能

This commit is contained in:
2026-04-09 14:58:20 +08:00
parent 3040b10eed
commit 7d7b979b66
16 changed files with 1012 additions and 199 deletions

View File

@@ -809,15 +809,6 @@ func ResourcePrice(c *fiber.Ctx) error {
}
// 获取套餐价格
// sku, err := s.Resource.GetSku(req.CreateResourceData.Code())
// if err != nil {
// return err
// }
// _, amount, discounted, couponApplied, err := s.Resource.GetPrice(sku, req.Count(), nil, nil)
// if err != nil {
// return err
// }
detail, err := req.TradeDetail(nil)
if err != nil {
return err

View File

@@ -9,21 +9,22 @@ import (
// Bill 账单表
type Bill struct {
core.Model
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
TradeID *int32 `json:"trade_id,omitempty" gorm:"column:trade_id"` // 订单ID
ResourceID *int32 `json:"resource_id,omitempty" gorm:"column:resource_id"` // 套餐ID
RefundID *int32 `json:"refund_id,omitempty" gorm:"column:refund_id"` // 退款ID
CouponID *int32 `json:"coupon_id,omitempty" gorm:"column:coupon_id"` // 优惠券ID
BillNo string `json:"bill_no" gorm:"column:bill_no"` // 易读账单号
Info *string `json:"info,omitempty" gorm:"column:info"` // 产品可读信息
Type BillType `json:"type" gorm:"column:type"` // 账单类型1-消费2-退款3-充值
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 应付金额
Actual decimal.Decimal `json:"actual" gorm:"column:actual"` // 实付金额
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
TradeID *int32 `json:"trade_id,omitempty" gorm:"column:trade_id"` // 订单ID
ResourceID *int32 `json:"resource_id,omitempty" gorm:"column:resource_id"` // 套餐ID
RefundID *int32 `json:"refund_id,omitempty" gorm:"column:refund_id"` // 退款ID
CouponUserID *int32 `json:"coupon_user_id,omitempty" gorm:"column:coupon_id"` // 优惠券发放ID
BillNo string `json:"bill_no" gorm:"column:bill_no"` // 易读账单号
Info *string `json:"info,omitempty" gorm:"column:info"` // 产品可读信息
Type BillType `json:"type" gorm:"column:type"` // 账单类型1-消费2-退款3-充值
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 应付金额
Actual decimal.Decimal `json:"actual" gorm:"column:actual"` // 实付金额
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Trade *Trade `json:"trade,omitempty" gorm:"foreignKey:TradeID"`
Resource *Resource `json:"resource,omitempty" gorm:"foreignKey:ResourceID"`
Refund *Refund `json:"refund,omitempty" gorm:"foreignKey:RefundID"`
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Trade *Trade `json:"trade,omitempty" gorm:"foreignKey:TradeID"`
Resource *Resource `json:"resource,omitempty" gorm:"foreignKey:ResourceID"`
Refund *Refund `json:"refund,omitempty" gorm:"foreignKey:RefundID"`
CouponUser *CouponUser `json:"coupon,omitempty" gorm:"foreignKey:CouponUserID"`
}
// BillType 账单类型枚举

View File

@@ -10,20 +10,29 @@ import (
// Coupon 优惠券表
type Coupon struct {
core.Model
UserID *int32 `json:"user_id,omitempty" gorm:"column:user_id"` // 用户ID
Code string `json:"code" gorm:"column:code"` // 优惠券代码
Remark *string `json:"remark,omitempty" gorm:"column:remark"` // 优惠券备注
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 优惠券金额
MinAmount decimal.Decimal `json:"min_amount" gorm:"column:min_amount"` // 最低消费金额
Status CouponStatus `json:"status" gorm:"column:status"` // 优惠券状态0-未使用1-已使用2-已过期
ExpireAt *time.Time `json:"expire_at,omitempty" gorm:"column:expire_at"` // 过期时间
Name string `json:"name" gorm:"column:name"` // 优惠券名称
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 优惠券金额
MinAmount decimal.Decimal `json:"min_amount" gorm:"column:min_amount"` // 最低消费金额
Count int32 `json:"count" gorm:"column:count"` // 优惠券数量
Status CouponStatus `json:"status" gorm:"column:status"` // 优惠券状态0-禁用1-正常
ExpireType CouponExpireType `json:"expire_type" gorm:"column:expire_type"` // 过期类型0-不过期1-固定日期2-相对日期(从发放时间算起)
ExpireAt *time.Time `json:"expire_at,omitempty" gorm:"column:expire_at"` // 过期时间,固定日期必填
ExpireIn *int `json:"expire_in,omitempty" gorm:"column:expire_in"` // 过期时长(天),相对日期必填
}
// CouponStatus 优惠券状态枚举
// CouponStatus 优惠券使用状态枚举
type CouponStatus int
const (
CouponStatusUnused CouponStatus = 0 // 未使
CouponStatusUsed CouponStatus = 1 // 已使用
CouponStatusExpired CouponStatus = 2 // 已过期
CouponStatusDisabled CouponStatus = 0 //
CouponStatusEnabled CouponStatus = 1 // 正常
)
// CouponExpireType 优惠券过期类型枚举
type CouponExpireType int
const (
CouponExpireTypeNever CouponExpireType = 0 // 不过期
CouponExpireTypeFixed CouponExpireType = 1 // 固定日期
CouponExpireTypeRelative CouponExpireType = 2 // 相对日期
)

25
web/models/coupon_user.go Normal file
View File

@@ -0,0 +1,25 @@
package models
import "time"
// CouponUser 优惠券发放表
type CouponUser struct {
ID int32 `json:"id" gorm:"column:id;primaryKey"` // 记录ID
CouponID int32 `json:"coupon_id" gorm:"column:coupon_id"` // 优惠券ID
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
Status CouponStatus `json:"status" gorm:"column:status"` // 使用状态0-未使用1-已使用
ExpireAt *time.Time `json:"expire_at,omitempty" gorm:"column:expire_at"` // 过期时间
UsedAt *time.Time `json:"used_at,omitempty" gorm:"column:used_at"` // 使用时间
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"` // 创建时间
Coupon *Coupon `json:"coupon,omitempty" gorm:"foreignKey:CouponID"`
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
}
// CouponUserStatus 优惠券发放状态枚举
type CouponUserStatus int
const (
CouponUserStatusUnused CouponUserStatus = 0 // 未使用
CouponUserStatusUsed CouponUserStatus = 1 // 已使用
)

View File

@@ -232,6 +232,27 @@ func newBalanceActivity(db *gorm.DB, opts ...gen.DOOption) balanceActivity {
}{
RelationField: field.NewRelation("Bill.Refund", "models.Refund"),
},
CouponUser: struct {
field.RelationField
Coupon struct {
field.RelationField
}
User struct {
field.RelationField
}
}{
RelationField: field.NewRelation("Bill.CouponUser", "models.CouponUser"),
Coupon: struct {
field.RelationField
}{
RelationField: field.NewRelation("Bill.CouponUser.Coupon", "models.Coupon"),
},
User: struct {
field.RelationField
}{
RelationField: field.NewRelation("Bill.CouponUser.User", "models.User"),
},
},
}
_balanceActivity.fillFieldMap()
@@ -561,6 +582,15 @@ type balanceActivityBelongsToBill struct {
Refund struct {
field.RelationField
}
CouponUser struct {
field.RelationField
Coupon struct {
field.RelationField
}
User struct {
field.RelationField
}
}
}
func (a balanceActivityBelongsToBill) Where(conds ...field.Expr) *balanceActivityBelongsToBill {

View File

@@ -35,7 +35,7 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
_bill.TradeID = field.NewInt32(tableName, "trade_id")
_bill.ResourceID = field.NewInt32(tableName, "resource_id")
_bill.RefundID = field.NewInt32(tableName, "refund_id")
_bill.CouponID = field.NewInt32(tableName, "coupon_id")
_bill.CouponUserID = field.NewInt32(tableName, "coupon_id")
_bill.BillNo = field.NewString(tableName, "bill_no")
_bill.Info = field.NewString(tableName, "info")
_bill.Type = field.NewInt(tableName, "type")
@@ -198,6 +198,22 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
RelationField: field.NewRelation("Refund", "models.Refund"),
}
_bill.CouponUser = billBelongsToCouponUser{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("CouponUser", "models.CouponUser"),
Coupon: struct {
field.RelationField
}{
RelationField: field.NewRelation("CouponUser.Coupon", "models.Coupon"),
},
User: struct {
field.RelationField
}{
RelationField: field.NewRelation("CouponUser.User", "models.User"),
},
}
_bill.fillFieldMap()
return _bill
@@ -206,22 +222,22 @@ func newBill(db *gorm.DB, opts ...gen.DOOption) bill {
type bill struct {
billDo
ALL field.Asterisk
ID field.Int32
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
UserID field.Int32
TradeID field.Int32
ResourceID field.Int32
RefundID field.Int32
CouponID field.Int32
BillNo field.String
Info field.String
Type field.Int
Amount field.Field
Actual field.Field
User billBelongsToUser
ALL field.Asterisk
ID field.Int32
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
UserID field.Int32
TradeID field.Int32
ResourceID field.Int32
RefundID field.Int32
CouponUserID field.Int32
BillNo field.String
Info field.String
Type field.Int
Amount field.Field
Actual field.Field
User billBelongsToUser
Trade billBelongsToTrade
@@ -229,6 +245,8 @@ type bill struct {
Refund billBelongsToRefund
CouponUser billBelongsToCouponUser
fieldMap map[string]field.Expr
}
@@ -252,7 +270,7 @@ func (b *bill) updateTableName(table string) *bill {
b.TradeID = field.NewInt32(table, "trade_id")
b.ResourceID = field.NewInt32(table, "resource_id")
b.RefundID = field.NewInt32(table, "refund_id")
b.CouponID = field.NewInt32(table, "coupon_id")
b.CouponUserID = field.NewInt32(table, "coupon_id")
b.BillNo = field.NewString(table, "bill_no")
b.Info = field.NewString(table, "info")
b.Type = field.NewInt(table, "type")
@@ -274,7 +292,7 @@ func (b *bill) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
}
func (b *bill) fillFieldMap() {
b.fieldMap = make(map[string]field.Expr, 18)
b.fieldMap = make(map[string]field.Expr, 19)
b.fieldMap["id"] = b.ID
b.fieldMap["created_at"] = b.CreatedAt
b.fieldMap["updated_at"] = b.UpdatedAt
@@ -283,7 +301,7 @@ func (b *bill) fillFieldMap() {
b.fieldMap["trade_id"] = b.TradeID
b.fieldMap["resource_id"] = b.ResourceID
b.fieldMap["refund_id"] = b.RefundID
b.fieldMap["coupon_id"] = b.CouponID
b.fieldMap["coupon_id"] = b.CouponUserID
b.fieldMap["bill_no"] = b.BillNo
b.fieldMap["info"] = b.Info
b.fieldMap["type"] = b.Type
@@ -302,6 +320,8 @@ func (b bill) clone(db *gorm.DB) bill {
b.Resource.db.Statement.ConnPool = db.Statement.ConnPool
b.Refund.db = db.Session(&gorm.Session{Initialized: true})
b.Refund.db.Statement.ConnPool = db.Statement.ConnPool
b.CouponUser.db = db.Session(&gorm.Session{Initialized: true})
b.CouponUser.db.Statement.ConnPool = db.Statement.ConnPool
return b
}
@@ -311,6 +331,7 @@ func (b bill) replaceDB(db *gorm.DB) bill {
b.Trade.db = db.Session(&gorm.Session{})
b.Resource.db = db.Session(&gorm.Session{})
b.Refund.db = db.Session(&gorm.Session{})
b.CouponUser.db = db.Session(&gorm.Session{})
return b
}
@@ -692,6 +713,94 @@ func (a billBelongsToRefundTx) Unscoped() *billBelongsToRefundTx {
return &a
}
type billBelongsToCouponUser struct {
db *gorm.DB
field.RelationField
Coupon struct {
field.RelationField
}
User struct {
field.RelationField
}
}
func (a billBelongsToCouponUser) Where(conds ...field.Expr) *billBelongsToCouponUser {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a billBelongsToCouponUser) WithContext(ctx context.Context) *billBelongsToCouponUser {
a.db = a.db.WithContext(ctx)
return &a
}
func (a billBelongsToCouponUser) Session(session *gorm.Session) *billBelongsToCouponUser {
a.db = a.db.Session(session)
return &a
}
func (a billBelongsToCouponUser) Model(m *models.Bill) *billBelongsToCouponUserTx {
return &billBelongsToCouponUserTx{a.db.Model(m).Association(a.Name())}
}
func (a billBelongsToCouponUser) Unscoped() *billBelongsToCouponUser {
a.db = a.db.Unscoped()
return &a
}
type billBelongsToCouponUserTx struct{ tx *gorm.Association }
func (a billBelongsToCouponUserTx) Find() (result *models.CouponUser, err error) {
return result, a.tx.Find(&result)
}
func (a billBelongsToCouponUserTx) Append(values ...*models.CouponUser) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a billBelongsToCouponUserTx) Replace(values ...*models.CouponUser) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a billBelongsToCouponUserTx) Delete(values ...*models.CouponUser) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a billBelongsToCouponUserTx) Clear() error {
return a.tx.Clear()
}
func (a billBelongsToCouponUserTx) Count() int64 {
return a.tx.Count()
}
func (a billBelongsToCouponUserTx) Unscoped() *billBelongsToCouponUserTx {
a.tx = a.tx.Unscoped()
return &a
}
type billDo struct{ gen.DO }
func (b billDo) Debug() *billDo {

View File

@@ -31,13 +31,14 @@ func newCoupon(db *gorm.DB, opts ...gen.DOOption) coupon {
_coupon.CreatedAt = field.NewTime(tableName, "created_at")
_coupon.UpdatedAt = field.NewTime(tableName, "updated_at")
_coupon.DeletedAt = field.NewField(tableName, "deleted_at")
_coupon.UserID = field.NewInt32(tableName, "user_id")
_coupon.Code = field.NewString(tableName, "code")
_coupon.Remark = field.NewString(tableName, "remark")
_coupon.Name = field.NewString(tableName, "name")
_coupon.Amount = field.NewField(tableName, "amount")
_coupon.MinAmount = field.NewField(tableName, "min_amount")
_coupon.Count_ = field.NewInt32(tableName, "count")
_coupon.Status = field.NewInt(tableName, "status")
_coupon.ExpireType = field.NewInt(tableName, "expire_type")
_coupon.ExpireAt = field.NewTime(tableName, "expire_at")
_coupon.ExpireIn = field.NewInt(tableName, "expire_in")
_coupon.fillFieldMap()
@@ -47,18 +48,19 @@ func newCoupon(db *gorm.DB, opts ...gen.DOOption) coupon {
type coupon struct {
couponDo
ALL field.Asterisk
ID field.Int32
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
UserID field.Int32
Code field.String
Remark field.String
Amount field.Field
MinAmount field.Field
Status field.Int
ExpireAt field.Time
ALL field.Asterisk
ID field.Int32
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Field
Name field.String
Amount field.Field
MinAmount field.Field
Count_ field.Int32
Status field.Int
ExpireType field.Int
ExpireAt field.Time
ExpireIn field.Int
fieldMap map[string]field.Expr
}
@@ -79,13 +81,14 @@ func (c *coupon) updateTableName(table string) *coupon {
c.CreatedAt = field.NewTime(table, "created_at")
c.UpdatedAt = field.NewTime(table, "updated_at")
c.DeletedAt = field.NewField(table, "deleted_at")
c.UserID = field.NewInt32(table, "user_id")
c.Code = field.NewString(table, "code")
c.Remark = field.NewString(table, "remark")
c.Name = field.NewString(table, "name")
c.Amount = field.NewField(table, "amount")
c.MinAmount = field.NewField(table, "min_amount")
c.Count_ = field.NewInt32(table, "count")
c.Status = field.NewInt(table, "status")
c.ExpireType = field.NewInt(table, "expire_type")
c.ExpireAt = field.NewTime(table, "expire_at")
c.ExpireIn = field.NewInt(table, "expire_in")
c.fillFieldMap()
@@ -102,18 +105,19 @@ func (c *coupon) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
}
func (c *coupon) fillFieldMap() {
c.fieldMap = make(map[string]field.Expr, 11)
c.fieldMap = make(map[string]field.Expr, 12)
c.fieldMap["id"] = c.ID
c.fieldMap["created_at"] = c.CreatedAt
c.fieldMap["updated_at"] = c.UpdatedAt
c.fieldMap["deleted_at"] = c.DeletedAt
c.fieldMap["user_id"] = c.UserID
c.fieldMap["code"] = c.Code
c.fieldMap["remark"] = c.Remark
c.fieldMap["name"] = c.Name
c.fieldMap["amount"] = c.Amount
c.fieldMap["min_amount"] = c.MinAmount
c.fieldMap["count"] = c.Count_
c.fieldMap["status"] = c.Status
c.fieldMap["expire_type"] = c.ExpireType
c.fieldMap["expire_at"] = c.ExpireAt
c.fieldMap["expire_in"] = c.ExpireIn
}
func (c coupon) clone(db *gorm.DB) coupon {

View File

@@ -0,0 +1,621 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package queries
import (
"context"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"platform/web/models"
)
func newCouponUser(db *gorm.DB, opts ...gen.DOOption) couponUser {
_couponUser := couponUser{}
_couponUser.couponUserDo.UseDB(db, opts...)
_couponUser.couponUserDo.UseModel(&models.CouponUser{})
tableName := _couponUser.couponUserDo.TableName()
_couponUser.ALL = field.NewAsterisk(tableName)
_couponUser.ID = field.NewInt32(tableName, "id")
_couponUser.CouponID = field.NewInt32(tableName, "coupon_id")
_couponUser.UserID = field.NewInt32(tableName, "user_id")
_couponUser.Status = field.NewInt(tableName, "status")
_couponUser.ExpireAt = field.NewTime(tableName, "expire_at")
_couponUser.UsedAt = field.NewTime(tableName, "used_at")
_couponUser.CreatedAt = field.NewTime(tableName, "created_at")
_couponUser.Coupon = couponUserBelongsToCoupon{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("Coupon", "models.Coupon"),
}
_couponUser.User = couponUserBelongsToUser{
db: db.Session(&gorm.Session{}),
RelationField: field.NewRelation("User", "models.User"),
Admin: struct {
field.RelationField
Roles struct {
field.RelationField
Permissions struct {
field.RelationField
Parent struct {
field.RelationField
}
Children struct {
field.RelationField
}
}
}
}{
RelationField: field.NewRelation("User.Admin", "models.Admin"),
Roles: struct {
field.RelationField
Permissions struct {
field.RelationField
Parent struct {
field.RelationField
}
Children struct {
field.RelationField
}
}
}{
RelationField: field.NewRelation("User.Admin.Roles", "models.AdminRole"),
Permissions: struct {
field.RelationField
Parent struct {
field.RelationField
}
Children struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Admin.Roles.Permissions", "models.Permission"),
Parent: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Admin.Roles.Permissions.Parent", "models.Permission"),
},
Children: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Admin.Roles.Permissions.Children", "models.Permission"),
},
},
},
},
Discount: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Discount", "models.ProductDiscount"),
},
Roles: struct {
field.RelationField
Permissions struct {
field.RelationField
}
}{
RelationField: field.NewRelation("User.Roles", "models.UserRole"),
Permissions: struct {
field.RelationField
}{
RelationField: field.NewRelation("User.Roles.Permissions", "models.Permission"),
},
},
}
_couponUser.fillFieldMap()
return _couponUser
}
type couponUser struct {
couponUserDo
ALL field.Asterisk
ID field.Int32
CouponID field.Int32
UserID field.Int32
Status field.Int
ExpireAt field.Time
UsedAt field.Time
CreatedAt field.Time
Coupon couponUserBelongsToCoupon
User couponUserBelongsToUser
fieldMap map[string]field.Expr
}
func (c couponUser) Table(newTableName string) *couponUser {
c.couponUserDo.UseTable(newTableName)
return c.updateTableName(newTableName)
}
func (c couponUser) As(alias string) *couponUser {
c.couponUserDo.DO = *(c.couponUserDo.As(alias).(*gen.DO))
return c.updateTableName(alias)
}
func (c *couponUser) updateTableName(table string) *couponUser {
c.ALL = field.NewAsterisk(table)
c.ID = field.NewInt32(table, "id")
c.CouponID = field.NewInt32(table, "coupon_id")
c.UserID = field.NewInt32(table, "user_id")
c.Status = field.NewInt(table, "status")
c.ExpireAt = field.NewTime(table, "expire_at")
c.UsedAt = field.NewTime(table, "used_at")
c.CreatedAt = field.NewTime(table, "created_at")
c.fillFieldMap()
return c
}
func (c *couponUser) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := c.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (c *couponUser) fillFieldMap() {
c.fieldMap = make(map[string]field.Expr, 9)
c.fieldMap["id"] = c.ID
c.fieldMap["coupon_id"] = c.CouponID
c.fieldMap["user_id"] = c.UserID
c.fieldMap["status"] = c.Status
c.fieldMap["expire_at"] = c.ExpireAt
c.fieldMap["used_at"] = c.UsedAt
c.fieldMap["created_at"] = c.CreatedAt
}
func (c couponUser) clone(db *gorm.DB) couponUser {
c.couponUserDo.ReplaceConnPool(db.Statement.ConnPool)
c.Coupon.db = db.Session(&gorm.Session{Initialized: true})
c.Coupon.db.Statement.ConnPool = db.Statement.ConnPool
c.User.db = db.Session(&gorm.Session{Initialized: true})
c.User.db.Statement.ConnPool = db.Statement.ConnPool
return c
}
func (c couponUser) replaceDB(db *gorm.DB) couponUser {
c.couponUserDo.ReplaceDB(db)
c.Coupon.db = db.Session(&gorm.Session{})
c.User.db = db.Session(&gorm.Session{})
return c
}
type couponUserBelongsToCoupon struct {
db *gorm.DB
field.RelationField
}
func (a couponUserBelongsToCoupon) Where(conds ...field.Expr) *couponUserBelongsToCoupon {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a couponUserBelongsToCoupon) WithContext(ctx context.Context) *couponUserBelongsToCoupon {
a.db = a.db.WithContext(ctx)
return &a
}
func (a couponUserBelongsToCoupon) Session(session *gorm.Session) *couponUserBelongsToCoupon {
a.db = a.db.Session(session)
return &a
}
func (a couponUserBelongsToCoupon) Model(m *models.CouponUser) *couponUserBelongsToCouponTx {
return &couponUserBelongsToCouponTx{a.db.Model(m).Association(a.Name())}
}
func (a couponUserBelongsToCoupon) Unscoped() *couponUserBelongsToCoupon {
a.db = a.db.Unscoped()
return &a
}
type couponUserBelongsToCouponTx struct{ tx *gorm.Association }
func (a couponUserBelongsToCouponTx) Find() (result *models.Coupon, err error) {
return result, a.tx.Find(&result)
}
func (a couponUserBelongsToCouponTx) Append(values ...*models.Coupon) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a couponUserBelongsToCouponTx) Replace(values ...*models.Coupon) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a couponUserBelongsToCouponTx) Delete(values ...*models.Coupon) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a couponUserBelongsToCouponTx) Clear() error {
return a.tx.Clear()
}
func (a couponUserBelongsToCouponTx) Count() int64 {
return a.tx.Count()
}
func (a couponUserBelongsToCouponTx) Unscoped() *couponUserBelongsToCouponTx {
a.tx = a.tx.Unscoped()
return &a
}
type couponUserBelongsToUser struct {
db *gorm.DB
field.RelationField
Admin struct {
field.RelationField
Roles struct {
field.RelationField
Permissions struct {
field.RelationField
Parent struct {
field.RelationField
}
Children struct {
field.RelationField
}
}
}
}
Discount struct {
field.RelationField
}
Roles struct {
field.RelationField
Permissions struct {
field.RelationField
}
}
}
func (a couponUserBelongsToUser) Where(conds ...field.Expr) *couponUserBelongsToUser {
if len(conds) == 0 {
return &a
}
exprs := make([]clause.Expression, 0, len(conds))
for _, cond := range conds {
exprs = append(exprs, cond.BeCond().(clause.Expression))
}
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
return &a
}
func (a couponUserBelongsToUser) WithContext(ctx context.Context) *couponUserBelongsToUser {
a.db = a.db.WithContext(ctx)
return &a
}
func (a couponUserBelongsToUser) Session(session *gorm.Session) *couponUserBelongsToUser {
a.db = a.db.Session(session)
return &a
}
func (a couponUserBelongsToUser) Model(m *models.CouponUser) *couponUserBelongsToUserTx {
return &couponUserBelongsToUserTx{a.db.Model(m).Association(a.Name())}
}
func (a couponUserBelongsToUser) Unscoped() *couponUserBelongsToUser {
a.db = a.db.Unscoped()
return &a
}
type couponUserBelongsToUserTx struct{ tx *gorm.Association }
func (a couponUserBelongsToUserTx) Find() (result *models.User, err error) {
return result, a.tx.Find(&result)
}
func (a couponUserBelongsToUserTx) Append(values ...*models.User) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Append(targetValues...)
}
func (a couponUserBelongsToUserTx) Replace(values ...*models.User) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Replace(targetValues...)
}
func (a couponUserBelongsToUserTx) Delete(values ...*models.User) (err error) {
targetValues := make([]interface{}, len(values))
for i, v := range values {
targetValues[i] = v
}
return a.tx.Delete(targetValues...)
}
func (a couponUserBelongsToUserTx) Clear() error {
return a.tx.Clear()
}
func (a couponUserBelongsToUserTx) Count() int64 {
return a.tx.Count()
}
func (a couponUserBelongsToUserTx) Unscoped() *couponUserBelongsToUserTx {
a.tx = a.tx.Unscoped()
return &a
}
type couponUserDo struct{ gen.DO }
func (c couponUserDo) Debug() *couponUserDo {
return c.withDO(c.DO.Debug())
}
func (c couponUserDo) WithContext(ctx context.Context) *couponUserDo {
return c.withDO(c.DO.WithContext(ctx))
}
func (c couponUserDo) ReadDB() *couponUserDo {
return c.Clauses(dbresolver.Read)
}
func (c couponUserDo) WriteDB() *couponUserDo {
return c.Clauses(dbresolver.Write)
}
func (c couponUserDo) Session(config *gorm.Session) *couponUserDo {
return c.withDO(c.DO.Session(config))
}
func (c couponUserDo) Clauses(conds ...clause.Expression) *couponUserDo {
return c.withDO(c.DO.Clauses(conds...))
}
func (c couponUserDo) Returning(value interface{}, columns ...string) *couponUserDo {
return c.withDO(c.DO.Returning(value, columns...))
}
func (c couponUserDo) Not(conds ...gen.Condition) *couponUserDo {
return c.withDO(c.DO.Not(conds...))
}
func (c couponUserDo) Or(conds ...gen.Condition) *couponUserDo {
return c.withDO(c.DO.Or(conds...))
}
func (c couponUserDo) Select(conds ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Select(conds...))
}
func (c couponUserDo) Where(conds ...gen.Condition) *couponUserDo {
return c.withDO(c.DO.Where(conds...))
}
func (c couponUserDo) Order(conds ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Order(conds...))
}
func (c couponUserDo) Distinct(cols ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Distinct(cols...))
}
func (c couponUserDo) Omit(cols ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Omit(cols...))
}
func (c couponUserDo) Join(table schema.Tabler, on ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Join(table, on...))
}
func (c couponUserDo) LeftJoin(table schema.Tabler, on ...field.Expr) *couponUserDo {
return c.withDO(c.DO.LeftJoin(table, on...))
}
func (c couponUserDo) RightJoin(table schema.Tabler, on ...field.Expr) *couponUserDo {
return c.withDO(c.DO.RightJoin(table, on...))
}
func (c couponUserDo) Group(cols ...field.Expr) *couponUserDo {
return c.withDO(c.DO.Group(cols...))
}
func (c couponUserDo) Having(conds ...gen.Condition) *couponUserDo {
return c.withDO(c.DO.Having(conds...))
}
func (c couponUserDo) Limit(limit int) *couponUserDo {
return c.withDO(c.DO.Limit(limit))
}
func (c couponUserDo) Offset(offset int) *couponUserDo {
return c.withDO(c.DO.Offset(offset))
}
func (c couponUserDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *couponUserDo {
return c.withDO(c.DO.Scopes(funcs...))
}
func (c couponUserDo) Unscoped() *couponUserDo {
return c.withDO(c.DO.Unscoped())
}
func (c couponUserDo) Create(values ...*models.CouponUser) error {
if len(values) == 0 {
return nil
}
return c.DO.Create(values)
}
func (c couponUserDo) CreateInBatches(values []*models.CouponUser, batchSize int) error {
return c.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (c couponUserDo) Save(values ...*models.CouponUser) error {
if len(values) == 0 {
return nil
}
return c.DO.Save(values)
}
func (c couponUserDo) First() (*models.CouponUser, error) {
if result, err := c.DO.First(); err != nil {
return nil, err
} else {
return result.(*models.CouponUser), nil
}
}
func (c couponUserDo) Take() (*models.CouponUser, error) {
if result, err := c.DO.Take(); err != nil {
return nil, err
} else {
return result.(*models.CouponUser), nil
}
}
func (c couponUserDo) Last() (*models.CouponUser, error) {
if result, err := c.DO.Last(); err != nil {
return nil, err
} else {
return result.(*models.CouponUser), nil
}
}
func (c couponUserDo) Find() ([]*models.CouponUser, error) {
result, err := c.DO.Find()
return result.([]*models.CouponUser), err
}
func (c couponUserDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.CouponUser, err error) {
buf := make([]*models.CouponUser, 0, batchSize)
err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (c couponUserDo) FindInBatches(result *[]*models.CouponUser, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return c.DO.FindInBatches(result, batchSize, fc)
}
func (c couponUserDo) Attrs(attrs ...field.AssignExpr) *couponUserDo {
return c.withDO(c.DO.Attrs(attrs...))
}
func (c couponUserDo) Assign(attrs ...field.AssignExpr) *couponUserDo {
return c.withDO(c.DO.Assign(attrs...))
}
func (c couponUserDo) Joins(fields ...field.RelationField) *couponUserDo {
for _, _f := range fields {
c = *c.withDO(c.DO.Joins(_f))
}
return &c
}
func (c couponUserDo) Preload(fields ...field.RelationField) *couponUserDo {
for _, _f := range fields {
c = *c.withDO(c.DO.Preload(_f))
}
return &c
}
func (c couponUserDo) FirstOrInit() (*models.CouponUser, error) {
if result, err := c.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*models.CouponUser), nil
}
}
func (c couponUserDo) FirstOrCreate() (*models.CouponUser, error) {
if result, err := c.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*models.CouponUser), nil
}
}
func (c couponUserDo) FindByPage(offset int, limit int) (result []*models.CouponUser, count int64, err error) {
result, err = c.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = c.Offset(-1).Limit(-1).Count()
return
}
func (c couponUserDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = c.Count()
if err != nil {
return
}
err = c.Offset(offset).Limit(limit).Scan(result)
return
}
func (c couponUserDo) Scan(result interface{}) (err error) {
return c.DO.Scan(result)
}
func (c couponUserDo) Delete(models ...*models.CouponUser) (result gen.ResultInfo, err error) {
return c.DO.Delete(models)
}
func (c *couponUserDo) withDO(do gen.Dao) *couponUserDo {
c.DO = *do.(*gen.DO)
return c
}

View File

@@ -25,6 +25,7 @@ var (
Channel *channel
Client *client
Coupon *coupon
CouponUser *couponUser
Edge *edge
Inquiry *inquiry
LinkAdminRole *linkAdminRole
@@ -63,6 +64,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
Channel = &Q.Channel
Client = &Q.Client
Coupon = &Q.Coupon
CouponUser = &Q.CouponUser
Edge = &Q.Edge
Inquiry = &Q.Inquiry
LinkAdminRole = &Q.LinkAdminRole
@@ -102,6 +104,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
Channel: newChannel(db, opts...),
Client: newClient(db, opts...),
Coupon: newCoupon(db, opts...),
CouponUser: newCouponUser(db, opts...),
Edge: newEdge(db, opts...),
Inquiry: newInquiry(db, opts...),
LinkAdminRole: newLinkAdminRole(db, opts...),
@@ -142,6 +145,7 @@ type Query struct {
Channel channel
Client client
Coupon coupon
CouponUser couponUser
Edge edge
Inquiry inquiry
LinkAdminRole linkAdminRole
@@ -183,6 +187,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
Channel: q.Channel.clone(db),
Client: q.Client.clone(db),
Coupon: q.Coupon.clone(db),
CouponUser: q.CouponUser.clone(db),
Edge: q.Edge.clone(db),
Inquiry: q.Inquiry.clone(db),
LinkAdminRole: q.LinkAdminRole.clone(db),
@@ -231,6 +236,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
Channel: q.Channel.replaceDB(db),
Client: q.Client.replaceDB(db),
Coupon: q.Coupon.replaceDB(db),
CouponUser: q.CouponUser.replaceDB(db),
Edge: q.Edge.replaceDB(db),
Inquiry: q.Inquiry.replaceDB(db),
LinkAdminRole: q.LinkAdminRole.replaceDB(db),
@@ -269,6 +275,7 @@ type queryCtx struct {
Channel *channelDo
Client *clientDo
Coupon *couponDo
CouponUser *couponUserDo
Edge *edgeDo
Inquiry *inquiryDo
LinkAdminRole *linkAdminRoleDo
@@ -307,6 +314,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
Channel: q.Channel.WithContext(ctx),
Client: q.Client.WithContext(ctx),
Coupon: q.Coupon.WithContext(ctx),
CouponUser: q.CouponUser.WithContext(ctx),
Edge: q.Edge.WithContext(ctx),
Inquiry: q.Inquiry.WithContext(ctx),
LinkAdminRole: q.LinkAdminRole.WithContext(ctx),

View File

@@ -23,14 +23,14 @@ func (s *billService) CreateForBalance(q *q.Query, uid, tradeId int32, detail *T
func (s *billService) CreateForResource(q *q.Query, uid, resourceId int32, tradeId *int32, detail *TradeDetail) error {
return q.Bill.Create(&m.Bill{
UserID: uid,
BillNo: ID.GenReadable("bil"),
ResourceID: &resourceId,
TradeID: tradeId,
CouponID: detail.CouponId,
Type: m.BillTypeConsume,
Info: &detail.Subject,
Amount: detail.Amount,
Actual: detail.Actual,
UserID: uid,
BillNo: ID.GenReadable("bil"),
ResourceID: &resourceId,
TradeID: tradeId,
CouponUserID: detail.CouponUserId,
Type: m.BillTypeConsume,
Info: &detail.Subject,
Amount: detail.Amount,
Actual: detail.Actual,
})
}

View File

@@ -3,6 +3,7 @@ package services
import (
"errors"
"fmt"
"platform/pkg/u"
"platform/web/core"
m "platform/web/models"
q "platform/web/queries"
@@ -27,36 +28,32 @@ func (s *couponService) Page(req *core.PageReq) (result []*m.Coupon, count int64
func (s *couponService) Create(data CreateCouponData) error {
return q.Coupon.Create(&m.Coupon{
UserID: data.UserID,
Code: data.Code,
Remark: data.Remark,
Amount: data.Amount,
MinAmount: data.MinAmount,
Status: m.CouponStatusUnused,
ExpireAt: data.ExpireAt,
Name: data.Name,
Amount: data.Amount,
MinAmount: data.MinAmount,
Count: int32(u.Else(data.Count, 1)),
Status: u.Else(data.Status, m.CouponStatusEnabled),
ExpireType: u.Else(data.ExpireType, m.CouponExpireTypeNever),
ExpireAt: data.ExpireAt,
ExpireIn: data.ExpireIn,
})
}
type CreateCouponData struct {
UserID *int32 `json:"user_id"`
Code string `json:"code" validate:"required"`
Remark *string `json:"remark"`
Amount decimal.Decimal `json:"amount" validate:"required"`
MinAmount decimal.Decimal `json:"min_amount"`
ExpireAt *time.Time `json:"expire_at"`
Name string `json:"name" validate:"required"`
Amount decimal.Decimal `json:"amount" validate:"required"`
MinAmount decimal.Decimal `json:"min_amount"`
Count *int `json:"count"`
Status *m.CouponStatus `json:"status"`
ExpireType *m.CouponExpireType `json:"expire_type"`
ExpireAt *time.Time `json:"expire_at"`
ExpireIn *int `json:"expire_in"`
}
func (s *couponService) Update(data UpdateCouponData) error {
do := make([]field.AssignExpr, 0)
if data.UserID != nil {
do = append(do, q.Coupon.UserID.Value(*data.UserID))
}
if data.Code != nil {
do = append(do, q.Coupon.Code.Value(*data.Code))
}
if data.Remark != nil {
do = append(do, q.Coupon.Remark.Value(*data.Remark))
if data.Name != nil {
do = append(do, q.Coupon.Name.Value(*data.Name))
}
if data.Amount != nil {
do = append(do, q.Coupon.Amount.Value(*data.Amount))
@@ -64,26 +61,36 @@ func (s *couponService) Update(data UpdateCouponData) error {
if data.MinAmount != nil {
do = append(do, q.Coupon.MinAmount.Value(*data.MinAmount))
}
if data.Count != nil {
do = append(do, q.Coupon.Count_.Value(int32(*data.Count)))
}
if data.Status != nil {
do = append(do, q.Coupon.Status.Value(int(*data.Status)))
}
if data.ExpireType != nil {
do = append(do, q.Coupon.ExpireType.Value(int(*data.ExpireType)))
}
if data.ExpireAt != nil {
do = append(do, q.Coupon.ExpireAt.Value(*data.ExpireAt))
}
if data.ExpireIn != nil {
do = append(do, q.Coupon.ExpireIn.Value(*data.ExpireIn))
}
_, err := q.Coupon.Where(q.Coupon.ID.Eq(data.ID)).UpdateSimple(do...)
return err
}
type UpdateCouponData struct {
ID int32 `json:"id" validate:"required"`
UserID *int32 `json:"user_id"`
Code *string `json:"code"`
Remark *string `json:"remark"`
Amount *decimal.Decimal `json:"amount"`
MinAmount *decimal.Decimal `json:"min_amount"`
Status *m.CouponStatus `json:"status"`
ExpireAt *time.Time `json:"expire_at"`
ID int32 `json:"id" validate:"required"`
Name *string `json:"name"`
Amount *decimal.Decimal `json:"amount"`
MinAmount *decimal.Decimal `json:"min_amount"`
Count *int `json:"count"`
Status *m.CouponStatus `json:"status"`
ExpireType *m.CouponExpireType `json:"expire_type"`
ExpireAt *time.Time `json:"expire_at"`
ExpireIn *int `json:"expire_in"`
}
func (s *couponService) Delete(id int32) error {
@@ -91,14 +98,14 @@ func (s *couponService) Delete(id int32) error {
return err
}
func (s *couponService) GetCouponAvailableByCode(code string, amount decimal.Decimal, uid *int32) (*m.Coupon, error) {
// GetUserCoupon 获取用户的指定优惠券
func (s *couponService) GetUserCoupon(uid int32, cuid int32, amount decimal.Decimal) (*m.CouponUser, error) {
// 获取优惠券
coupon, err := q.Coupon.Where(
q.Coupon.Code.Eq(code),
q.Coupon.Status.Eq(int(m.CouponStatusUnused)),
q.Coupon.
Where(q.Coupon.ExpireAt.Gt(time.Now())).
Or(q.Coupon.ExpireAt.IsNull()),
assigned, err := q.CouponUser.Joins(q.CouponUser.Coupon).Where(
q.CouponUser.ID.Eq(cuid),
q.CouponUser.UserID.Eq(uid),
q.CouponUser.Status.Eq(int(m.CouponUserStatusUnused)),
q.CouponUser.ExpireAt.Gt(time.Now()),
).Take()
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, core.NewBizErr("优惠券不存在或已失效")
@@ -108,32 +115,22 @@ func (s *couponService) GetCouponAvailableByCode(code string, amount decimal.Dec
}
// 检查最小使用额度
if amount.Cmp(coupon.MinAmount) < 0 {
return nil, core.NewBizErr(fmt.Sprintf("使用此优惠券的最小额度为 %s", coupon.MinAmount))
if amount.Cmp(assigned.Coupon.MinAmount) < 0 {
return nil, core.NewBizErr(fmt.Sprintf("使用此优惠券的最小额度为 %s", assigned.Coupon.MinAmount))
}
// 检查所属
if coupon.UserID != nil {
if uid == nil {
return nil, core.NewBizErr("检查优惠券所属用户失败")
}
if *coupon.UserID != *uid {
return nil, core.NewBizErr("优惠券不属于当前用户")
}
}
return coupon, nil
return assigned, nil
}
func (s *couponService) UseCoupon(q *q.Query, id int32) error {
_, err := q.Coupon.
func (s *couponService) UseCoupon(q *q.Query, cuid int32) error {
_, err := q.CouponUser.
Where(
q.Coupon.ID.Eq(id),
q.Coupon.Status.Eq(int(m.CouponStatusUnused)),
q.Coupon.ExpireAt.Gt(time.Now()),
q.CouponUser.ID.Eq(cuid),
q.CouponUser.Status.Eq(int(m.CouponUserStatusUnused)),
).
UpdateSimple(
q.Coupon.Status.Value(int(m.CouponStatusUsed)),
q.CouponUser.Status.Value(int(m.CouponUserStatusUsed)),
q.CouponUser.UsedAt.Value(time.Now()),
)
return err
}

View File

@@ -46,8 +46,8 @@ func (s *resourceService) CreateResourceByBalance(user *m.User, data *CreateReso
}
// 核销优惠券
if detail.CouponId != nil {
err = Coupon.UseCoupon(q, *detail.CouponId)
if detail.CouponUserId != nil {
err = Coupon.UseCoupon(q, *detail.CouponUserId)
if err != nil {
return core.NewServErr("核销优惠券失败", err)
}
@@ -144,7 +144,7 @@ type UpdateResourceData struct {
Active *bool `json:"active"`
}
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, couponCode *string) (*m.ProductSku, *m.ProductDiscount, *m.Coupon, decimal.Decimal, decimal.Decimal, error) {
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, error) {
sku, err := q.ProductSku.
Joins(q.ProductSku.Discount).
@@ -180,20 +180,15 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
discounted := amount.Mul(discountRate)
// 优惠价
uid := (*int32)(nil)
if user != nil {
uid = &user.ID
}
coupon := (*m.Coupon)(nil)
coupon := (*m.CouponUser)(nil)
couponApplied := discounted.Copy()
if couponCode != nil {
if user != nil && cuid != nil {
var err error
coupon, err = Coupon.GetCouponAvailableByCode(*couponCode, discounted, uid)
coupon, err = Coupon.GetUserCoupon(user.ID, *cuid, discounted)
if err != nil {
return nil, nil, nil, decimal.Zero, decimal.Zero, err
}
couponApplied = discounted.Sub(coupon.Amount)
couponApplied = discounted.Sub(coupon.Coupon.Amount)
}
// 约束到最低价格
@@ -208,10 +203,10 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
}
type CreateResourceData struct {
Type m.ResourceType `json:"type" validate:"required"`
Short *CreateShortResourceData `json:"short,omitempty"`
Long *CreateLongResourceData `json:"long,omitempty"`
CouponCode *string `json:"coupon,omitempty"`
Type m.ResourceType `json:"type" validate:"required"`
Short *CreateShortResourceData `json:"short,omitempty"`
Long *CreateLongResourceData `json:"long,omitempty"`
CouponId *int32 `json:"coupon,omitempty"`
}
type CreateShortResourceData struct {
@@ -265,7 +260,7 @@ func (data *CreateResourceData) Code() string {
}
func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error) {
sku, discount, coupon, amount, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponCode)
sku, discount, coupon, amount, actual, err := Resource.CalcPrice(data.Code(), data.Count(), user, data.CouponId)
if err != nil {
return nil, err
}
@@ -274,17 +269,16 @@ func (data *CreateResourceData) TradeDetail(user *m.User) (*TradeDetail, error)
if discount != nil {
discountId = &discount.ID
}
var couponId *int32 = nil
var couponUserId *int32 = nil
if coupon != nil {
couponId = &coupon.ID
couponUserId = &coupon.ID
}
return &TradeDetail{
data,
m.TradeTypePurchase,
sku.Name,
amount, actual,
discountId, discount,
couponId, coupon,
discountId, couponUserId,
}, nil
}

View File

@@ -332,8 +332,8 @@ func (s *tradeService) OnCompleteTrade(user *m.User, interNo string, outerNo str
}
// 核销优惠券
if detail.CouponId != nil {
err = Coupon.UseCoupon(q, *detail.CouponId)
if detail.CouponUserId != nil {
err = Coupon.UseCoupon(q, *detail.CouponUserId)
if err != nil {
return core.NewServErr("核销优惠券失败", err)
}
@@ -614,15 +614,13 @@ type ProductData interface {
}
type TradeDetail struct {
Product ProductData `json:"product"`
Type m.TradeType `json:"type"`
Subject string `json:"subject"`
Amount decimal.Decimal `json:"amount"`
Actual decimal.Decimal `json:"actual"`
DiscountId *int32 `json:"discount_id,omitempty"`
Discount *m.ProductDiscount `json:"-"` // 不应缓存
CouponId *int32 `json:"coupon_id,omitempty"`
Coupon *m.Coupon `json:"-"` // 不应缓存
Product ProductData `json:"product"`
Type m.TradeType `json:"type"`
Subject string `json:"subject"`
Amount decimal.Decimal `json:"amount"`
Actual decimal.Decimal `json:"actual"`
DiscountId *int32 `json:"discount_id,omitempty"`
CouponUserId *int32 `json:"coupon_id,omitempty"`
}
type TradeErr string

View File

@@ -94,7 +94,6 @@ func (data *UpdateBalanceData) TradeDetail(user *m.User) (*TradeDetail, error) {
fmt.Sprintf("账户充值 - %s元", amount.StringFixed(2)),
amount, amount,
nil, nil,
nil, nil,
}, nil
}