From 7d7b979b661c6e759193dac518186dd3e1dbc82c Mon Sep 17 00:00:00 2001 From: luorijun Date: Thu, 9 Apr 2026 14:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BC=98=E6=83=A0=E5=88=B8?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E4=B8=8E=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/gen/main.go | 1 + scripts/sql/init.sql | 76 ++-- web/handlers/resource.go | 9 - web/models/bill.go | 29 +- web/models/coupon.go | 31 +- web/models/coupon_user.go | 25 ++ web/queries/balance_activity.gen.go | 30 ++ web/queries/bill.gen.go | 149 ++++++- web/queries/coupon.gen.go | 48 ++- web/queries/coupon_user.gen.go | 621 ++++++++++++++++++++++++++++ web/queries/gen.go | 8 + web/services/bill.go | 18 +- web/services/coupon.go | 109 +++-- web/services/resource.go | 36 +- web/services/trade.go | 20 +- web/services/user.go | 1 - 16 files changed, 1012 insertions(+), 199 deletions(-) create mode 100644 web/models/coupon_user.go create mode 100644 web/queries/coupon_user.gen.go diff --git a/cmd/gen/main.go b/cmd/gen/main.go index b9c0743..21f5fe4 100644 --- a/cmd/gen/main.go +++ b/cmd/gen/main.go @@ -66,6 +66,7 @@ func main() { m.Inquiry{}, m.ProductDiscount{}, m.BalanceActivity{}, + m.CouponUser{}, ) g.Execute() } diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql index b82d2cc..b5f65c9 100644 --- a/scripts/sql/init.sql +++ b/scripts/sql/init.sql @@ -989,7 +989,7 @@ create table bill ( trade_id int, resource_id int, refund_id int, - coupon_id int, + coupon_user_id int, bill_no text not null, info text, type int not null, @@ -1004,7 +1004,7 @@ create index idx_bill_user_id on bill (user_id) where deleted_at is null; create index idx_bill_trade_id on bill (trade_id) where deleted_at is null; create index idx_bill_resource_id on bill (resource_id) where deleted_at is null; create index idx_bill_refund_id on bill (refund_id) where deleted_at is null; -create index idx_bill_coupon_id on bill (coupon_id) where deleted_at is null; +create index idx_bill_coupon_id on bill (coupon_user_id) where deleted_at is null; create index idx_bill_created_at on bill (created_at) where deleted_at is null; -- bill表字段注释 @@ -1014,6 +1014,7 @@ comment on column bill.user_id is '用户ID'; comment on column bill.trade_id is '订单ID'; comment on column bill.resource_id is '套餐ID'; comment on column bill.refund_id is '退款ID'; +comment on column bill.coupon_user_id is '优惠券发放ID'; comment on column bill.bill_no is '易读账单号'; comment on column bill.info is '产品可读信息'; comment on column bill.type is '账单类型:1-消费,2-退款,3-充值'; @@ -1056,36 +1057,59 @@ comment on column balance_activity.created_at is '创建时间'; -- coupon 优惠券 drop table if exists coupon cascade; create table coupon ( - id int generated by default as identity primary key, - user_id int, - code text not null, - remark text, - amount decimal(12, 2) not null default 0, - min_amount decimal(12, 2) not null default 0, - status int not null default 0, - expire_at timestamptz, - created_at timestamptz default current_timestamp, - updated_at timestamptz default current_timestamp, - deleted_at timestamptz + id int generated by default as identity primary key, + name text not null, + amount decimal(12, 2) not null default 0, + min_amount decimal(12, 2) not null default 0, + count int not null default 0, + status int not null default 1, + expire_type int not null default 0, + expire_at timestamptz, + expire_in int, + created_at timestamptz default current_timestamp, + updated_at timestamptz default current_timestamp, + deleted_at timestamptz ); -create index idx_coupon_user_id on coupon (user_id) where deleted_at is null; -create index idx_coupon_code on coupon (code) where deleted_at is null; -create index idx_coupon_created_at on coupon (created_at) where deleted_at is null; -- coupon表字段注释 comment on table coupon is '优惠券表'; comment on column coupon.id is '优惠券ID'; -comment on column coupon.user_id is '用户ID'; -comment on column coupon.code is '优惠券代码'; -comment on column coupon.remark is '优惠券备注'; +comment on column coupon.name is '优惠券名称'; comment on column coupon.amount is '优惠券金额'; comment on column coupon.min_amount is '最低消费金额'; -comment on column coupon.status is '优惠券状态:0-未使用,1-已使用,2-已过期'; -comment on column coupon.expire_at is '过期时间'; +comment on column coupon.count is '优惠券数量'; +comment on column coupon.status is '优惠券状态:0-禁用,1-正常'; +comment on column coupon.expire_type is '过期类型:0-不过期,1-固定日期,2-相对日期(从发放时间算起)'; +comment on column coupon.expire_at is '过期时间,固定日期必填'; +comment on column coupon.expire_in is '过期时长(天),相对日期必填'; comment on column coupon.created_at is '创建时间'; comment on column coupon.updated_at is '更新时间'; comment on column coupon.deleted_at is '删除时间'; +-- coupon_user 优惠券发放 +drop table if exists coupon_user cascade; +create table coupon_user ( + id int generated by default as identity primary key, + coupon_id int not null, + user_id int not null, + status int not null default 0, + expire_at timestamptz, + used_at timestamptz, + created_at timestamptz default current_timestamp +); +create index idx_coupon_user_coupon_id on coupon_user (coupon_id); +create index idx_coupon_user_user_id on coupon_user (user_id); + +-- coupon_user表字段注释 +comment on table coupon_user is '优惠券发放表'; +comment on column coupon_user.id is '记录ID'; +comment on column coupon_user.coupon_id is '优惠券ID'; +comment on column coupon_user.user_id is '用户ID'; +comment on column coupon_user.status is '使用状态:0-未使用,1-已使用'; +comment on column coupon_user.expire_at is '过期时间'; +comment on column coupon_user.used_at is '使用时间'; +comment on column coupon_user.created_at is '创建时间'; + -- endregion -- ==================== @@ -1190,11 +1214,13 @@ alter table bill alter table bill add constraint fk_bill_refund_id foreign key (refund_id) references refund (id) on delete set null; alter table bill - add constraint fk_bill_coupon_id foreign key (coupon_id) references coupon (id) on delete set null; + add constraint fk_bill_coupon_id foreign key (coupon_user_id) references coupon_user (id) on delete set null; --- coupon表外键 -alter table coupon - add constraint fk_coupon_user_id foreign key (user_id) references "user" (id) on delete cascade; +-- coupon_user表外键 +alter table coupon_user + add constraint fk_coupon_user_user_id foreign key (user_id) references "user" (id) on delete cascade; +alter table coupon_user + add constraint fk_coupon_user_coupon_id foreign key (coupon_id) references coupon (id) on delete cascade; -- product_sku表外键 alter table product_sku diff --git a/web/handlers/resource.go b/web/handlers/resource.go index efc8f56..c26e41b 100644 --- a/web/handlers/resource.go +++ b/web/handlers/resource.go @@ -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 diff --git a/web/models/bill.go b/web/models/bill.go index 2444409..177ac66 100644 --- a/web/models/bill.go +++ b/web/models/bill.go @@ -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 账单类型枚举 diff --git a/web/models/coupon.go b/web/models/coupon.go index 9a91acc..e5238d6 100644 --- a/web/models/coupon.go +++ b/web/models/coupon.go @@ -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 // 相对日期 ) diff --git a/web/models/coupon_user.go b/web/models/coupon_user.go new file mode 100644 index 0000000..582d052 --- /dev/null +++ b/web/models/coupon_user.go @@ -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 // 已使用 +) diff --git a/web/queries/balance_activity.gen.go b/web/queries/balance_activity.gen.go index 1ebdad2..afe4a88 100644 --- a/web/queries/balance_activity.gen.go +++ b/web/queries/balance_activity.gen.go @@ -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 { diff --git a/web/queries/bill.gen.go b/web/queries/bill.gen.go index 266a94c..ce0c62e 100644 --- a/web/queries/bill.gen.go +++ b/web/queries/bill.gen.go @@ -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 { diff --git a/web/queries/coupon.gen.go b/web/queries/coupon.gen.go index 9e5f7c7..d823d04 100644 --- a/web/queries/coupon.gen.go +++ b/web/queries/coupon.gen.go @@ -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 { diff --git a/web/queries/coupon_user.gen.go b/web/queries/coupon_user.gen.go new file mode 100644 index 0000000..36e22cc --- /dev/null +++ b/web/queries/coupon_user.gen.go @@ -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 +} diff --git a/web/queries/gen.go b/web/queries/gen.go index 7e25714..60bc218 100644 --- a/web/queries/gen.go +++ b/web/queries/gen.go @@ -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), diff --git a/web/services/bill.go b/web/services/bill.go index f75c3ed..ec12517 100644 --- a/web/services/bill.go +++ b/web/services/bill.go @@ -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, }) } diff --git a/web/services/coupon.go b/web/services/coupon.go index 6e29198..b0c38ed 100644 --- a/web/services/coupon.go +++ b/web/services/coupon.go @@ -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 } diff --git a/web/services/resource.go b/web/services/resource.go index 2a69bf5..0a29d61 100644 --- a/web/services/resource.go +++ b/web/services/resource.go @@ -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 } diff --git a/web/services/trade.go b/web/services/trade.go index bdc3295..8a27a26 100644 --- a/web/services/trade.go +++ b/web/services/trade.go @@ -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 diff --git a/web/services/user.go b/web/services/user.go index 1a94770..30c011c 100644 --- a/web/services/user.go +++ b/web/services/user.go @@ -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 }