From 978dadf14e8469f4fb68cb0bc8d134da95c97cae Mon Sep 17 00:00:00 2001 From: wucongxing8150 <815046773@qq.com> Date: Tue, 13 Aug 2024 08:51:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=8F=91=E6=94=BE?= =?UTF-8?q?=E4=BC=98=E6=83=A0=E5=8D=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/amqp/consumer/CouponExpire.go | 2 +- api/crontab/SystemCouponExpire.go | 2 +- api/dao/Coupon.go | 18 +++++ api/dto/Coupon.go | 38 +++++----- api/model/Coupon.go | 34 ++++----- api/service/Coupon.go | 116 ++++++++++++++++++++++++++++++ api/service/UserCoupon.go | 2 +- utils/tz.go | 24 +++++++ 8 files changed, 197 insertions(+), 39 deletions(-) create mode 100644 api/service/Coupon.go create mode 100644 utils/tz.go diff --git a/api/amqp/consumer/CouponExpire.go b/api/amqp/consumer/CouponExpire.go index b247f2e..78d6118 100644 --- a/api/amqp/consumer/CouponExpire.go +++ b/api/amqp/consumer/CouponExpire.go @@ -71,7 +71,7 @@ func CouponExpire(msg amqp091.Delivery) { // 检测优惠卷过期时间 now := time.Now() - validEndTime := time.Time(coupon.ValidEndTime) + validEndTime := time.Time(*coupon.ValidEndTime) diffTime := validEndTime.Sub(now) if diffTime >= 60*time.Second { // 重新添加入队列 diff --git a/api/crontab/SystemCouponExpire.go b/api/crontab/SystemCouponExpire.go index 7edf7d8..4de344a 100644 --- a/api/crontab/SystemCouponExpire.go +++ b/api/crontab/SystemCouponExpire.go @@ -19,7 +19,7 @@ func SystemCouponExpire() { for _, coupon := range coupons { // 计算过期时间 - validEndTime := time.Time(coupon.ValidEndTime) + validEndTime := time.Time(*coupon.ValidEndTime) delay := validEndTime.Sub(time.Now()) if delay < 5*time.Second { diff --git a/api/dao/Coupon.go b/api/dao/Coupon.go index e318f07..0b0121d 100644 --- a/api/dao/Coupon.go +++ b/api/dao/Coupon.go @@ -115,3 +115,21 @@ func (r *CouponDao) GetCouponListByValidTime(maps interface{}, startTime, endTim } return m, nil } + +// Inc 自增 +func (r *CouponDao) Inc(tx *gorm.DB, couponId int64, field string, numeral int) error { + err := tx.Model(&model.Coupon{}).Where("coupon_id = ?", couponId).UpdateColumn(field, gorm.Expr(field+" + ?", numeral)).Error + if err != nil { + return err + } + return nil +} + +// Dec 自减 +func (r *CouponDao) Dec(tx *gorm.DB, couponId int64, field string, numeral int) error { + err := tx.Model(&model.Coupon{}).Where("coupon_id = ?", couponId).UpdateColumn(field, gorm.Expr(field+" - ?", numeral)).Error + if err != nil { + return err + } + return nil +} diff --git a/api/dto/Coupon.go b/api/dto/Coupon.go index bdf9eb3..abbd3b3 100644 --- a/api/dto/Coupon.go +++ b/api/dto/Coupon.go @@ -7,25 +7,25 @@ import ( ) type CouponDto struct { - CouponId string `json:"coupon_id"` // 主键id - CouponName string `json:"coupon_name"` // 优惠券名称 - CouponType int `json:"coupon_type"` // 优惠券类型(1:无门槛 2:满减) - CouponStatus int `json:"coupon_status"` // 状态(1:正常 2:强制失效 3:结束 4:删除) - ApplicationScope int `json:"application_scope"` // 适用范围(1:全场通用) - IsMutex int `json:"is_mutex"` // 是否互斥(0:否 1:是) - CouponCount int `json:"coupon_count"` // 发放数量 - CouponTakeCount int `json:"coupon_take_count"` // 已领取数量 - CouponUsedCount int `json:"coupon_used_count"` // 已使用数量 - CouponPrice float64 `json:"coupon_price"` // 优惠券金额 - WithAmount float64 `json:"with_amount"` // 符合满减标准金额(优惠券类型为满减时使用) - ValidType int `json:"valid_type"` // 有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效) - ValidDays int `json:"valid_days"` // 自领取之日起有效天数 - ValidStartTime model.LocalTime `json:"valid_start_time"` // 开始使用时间 - ValidEndTime model.LocalTime `json:"valid_end_time"` // 结束使用时间 - SystemMemberIds []*string `json:"system_member_ids"` // 会员id(适用范围为会员时生效,如果此项为null,则表示所有会员通用) - CouponDesc string `json:"coupon_desc"` // 优惠券描述 - CreatedAt model.LocalTime `json:"created_at"` // 创建时间 - UpdatedAt model.LocalTime `json:"updated_at"` // 更新时间 + CouponId string `json:"coupon_id"` // 主键id + CouponName string `json:"coupon_name"` // 优惠券名称 + CouponType int `json:"coupon_type"` // 优惠券类型(1:无门槛 2:满减) + CouponStatus int `json:"coupon_status"` // 状态(1:正常 2:强制失效 3:结束 4:删除) + ApplicationScope int `json:"application_scope"` // 适用范围(1:全场通用) + IsMutex int `json:"is_mutex"` // 是否互斥(0:否 1:是) + CouponCount int `json:"coupon_count"` // 发放数量 + CouponTakeCount int `json:"coupon_take_count"` // 已领取数量 + CouponUsedCount int `json:"coupon_used_count"` // 已使用数量 + CouponPrice float64 `json:"coupon_price"` // 优惠券金额 + WithAmount float64 `json:"with_amount"` // 符合满减标准金额(优惠券类型为满减时使用) + ValidType int `json:"valid_type"` // 有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效) + ValidDays int `json:"valid_days"` // 自领取之日起有效天数 + ValidStartTime *model.LocalTime `json:"valid_start_time"` // 开始使用时间 + ValidEndTime *model.LocalTime `json:"valid_end_time"` // 结束使用时间 + SystemMemberIds []*string `json:"system_member_ids"` // 会员id(适用范围为会员时生效,如果此项为null,则表示所有会员通用) + CouponDesc string `json:"coupon_desc"` // 优惠券描述 + CreatedAt model.LocalTime `json:"created_at"` // 创建时间 + UpdatedAt model.LocalTime `json:"updated_at"` // 更新时间 } // GetCouponDto 优惠卷详情 diff --git a/api/model/Coupon.go b/api/model/Coupon.go index 2ceee05..9d1486f 100644 --- a/api/model/Coupon.go +++ b/api/model/Coupon.go @@ -7,23 +7,23 @@ import ( ) type Coupon struct { - CouponId int64 `gorm:"column:coupon_id;type:bigint(19);primary_key;comment:主键id" json:"coupon_id"` - CouponName string `gorm:"column:coupon_name;type:varchar(255);comment:优惠卷名称" json:"coupon_name"` - CouponType int `gorm:"column:coupon_type;type:varchar(255);comment:优惠卷类型(1:无门槛 2:满减)" json:"coupon_type"` - CouponStatus int `gorm:"column:coupon_status;type:tinyint(1);default:1;comment:状态(1:正常 2:强制失效 3:结束 4:删除)" json:"coupon_status"` - ApplicationScope int `gorm:"column:application_scope;type:tinyint(1);default:1;comment:适用范围(1:全场通用 2:单项 3:会员)" json:"application_scope"` - IsMutex int `gorm:"column:is_mutex;type:tinyint(1);default:1;comment:是否互斥(0:否 1:是)互斥情况下无法和其他优惠卷同时使用" json:"is_mutex"` - CouponCount int `gorm:"column:coupon_count;type:int(10);default:1;comment:发放数量;NOT NULL" json:"coupon_count"` - CouponTakeCount int `gorm:"column:coupon_take_count;type:int(10);comment:已领取数量" json:"coupon_take_count"` - CouponUsedCount int `gorm:"column:coupon_used_count;type:int(10);default:0;comment:已使用数量" json:"coupon_used_count"` - CouponPrice float64 `gorm:"column:coupon_price;type:decimal(10,2) unsigned;default:0.00;comment:优惠卷金额" json:"coupon_price"` - WithAmount float64 `gorm:"column:with_amount;type:decimal(10,2);comment:符合满减标准金额(优惠卷类型为满减时使用)" json:"with_amount"` - ValidType int `gorm:"column:valid_type;type:tinyint(1);comment:有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效);NOT NULL" json:"valid_type"` - ValidDays int `gorm:"column:valid_days;type:int(3);comment:自领取之日起有效天数" json:"valid_days"` - ValidStartTime LocalTime `gorm:"column:valid_start_time;type:datetime;comment:开始使用时间" json:"valid_start_time"` - ValidEndTime LocalTime `gorm:"column:valid_end_time;type:datetime;comment:结束使用时间" json:"valid_end_time"` - SystemMemberIds string `gorm:"column:system_member_ids;type:bigint(19);comment:会员id(适用范围为会员时生效,如果此项为null,则表示所有会员通用)" json:"system_member_ids"` - CouponDesc string `gorm:"column:coupon_desc;type:varchar(200);comment:优惠卷描述" json:"coupon_desc"` + CouponId int64 `gorm:"column:coupon_id;type:bigint(19);primary_key;comment:主键id" json:"coupon_id"` + CouponName string `gorm:"column:coupon_name;type:varchar(255);comment:优惠卷名称" json:"coupon_name"` + CouponType int `gorm:"column:coupon_type;type:varchar(255);comment:优惠卷类型(1:无门槛 2:满减)" json:"coupon_type"` + CouponStatus int `gorm:"column:coupon_status;type:tinyint(1);default:1;comment:状态(1:正常 2:强制失效 3:结束 4:删除)" json:"coupon_status"` + ApplicationScope int `gorm:"column:application_scope;type:tinyint(1);default:1;comment:适用范围(1:全场通用 2:单项 3:会员)" json:"application_scope"` + IsMutex int `gorm:"column:is_mutex;type:tinyint(1);default:1;comment:是否互斥(0:否 1:是)互斥情况下无法和其他优惠卷同时使用" json:"is_mutex"` + CouponCount int `gorm:"column:coupon_count;type:int(10);default:1;comment:发放数量;NOT NULL" json:"coupon_count"` + CouponTakeCount int `gorm:"column:coupon_take_count;type:int(10);comment:已领取数量" json:"coupon_take_count"` + CouponUsedCount int `gorm:"column:coupon_used_count;type:int(10);default:0;comment:已使用数量" json:"coupon_used_count"` + CouponPrice float64 `gorm:"column:coupon_price;type:decimal(10,2) unsigned;default:0.00;comment:优惠卷金额" json:"coupon_price"` + WithAmount float64 `gorm:"column:with_amount;type:decimal(10,2);comment:符合满减标准金额(优惠卷类型为满减时使用)" json:"with_amount"` + ValidType int `gorm:"column:valid_type;type:tinyint(1);comment:有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效);NOT NULL" json:"valid_type"` + ValidDays int `gorm:"column:valid_days;type:int(3);comment:自领取之日起有效天数" json:"valid_days"` + ValidStartTime *LocalTime `gorm:"column:valid_start_time;type:datetime;comment:开始使用时间" json:"valid_start_time"` + ValidEndTime *LocalTime `gorm:"column:valid_end_time;type:datetime;comment:结束使用时间" json:"valid_end_time"` + SystemMemberIds string `gorm:"column:system_member_ids;type:bigint(19);comment:会员id(适用范围为会员时生效,如果此项为null,则表示所有会员通用)" json:"system_member_ids"` + CouponDesc string `gorm:"column:coupon_desc;type:varchar(200);comment:优惠卷描述" json:"coupon_desc"` Model } diff --git a/api/service/Coupon.go b/api/service/Coupon.go new file mode 100644 index 0000000..49c771a --- /dev/null +++ b/api/service/Coupon.go @@ -0,0 +1,116 @@ +package service + +import ( + "fmt" + "gorm.io/gorm" + "hepa-calc-api/api/dao" + "hepa-calc-api/api/model" + "hepa-calc-api/extend/rabbitMq" + "time" +) + +type CouponService struct { +} + +// GrantUserCoupon 发放优惠卷 +func (r *CouponService) GrantUserCoupon(tx *gorm.DB, userId, couponId int64, grantQuantity int) bool { + // 获取优惠卷数据 + couponDao := dao.CouponDao{} + coupon, err := couponDao.GetCouponById(couponId) + if err != nil { + return false + } + + // 判断优惠卷状态 + if coupon.CouponStatus != 1 { + return true + } + + // 判断优惠卷过期时间 + if coupon.ValidType == 1 { + now := time.Now().Add(10 * 60 * time.Second) + validEndTime := time.Time(*coupon.ValidEndTime) + if validEndTime.Before(now) { + return false + } + } + + // 判断优惠卷数量是否充足 + if coupon.CouponCount <= coupon.CouponTakeCount { + return false + } + + // 检测剩余数量 + remainingQuantity := coupon.CouponCount - coupon.CouponTakeCount + if remainingQuantity <= grantQuantity { + return false + } + + // 添加用户优惠卷表 + userCoupon := &model.UserCoupon{ + UserId: userId, + CouponId: couponId, + UserCouponStatus: 0, + IsWindows: 0, + CouponUseDate: nil, + } + + if coupon.ValidType == 1 { + // 有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效) + userCoupon.ValidStartTime = coupon.ValidStartTime + userCoupon.ValidEndTime = coupon.ValidEndTime + } else { + validStartTime := model.LocalTime(time.Now()) + userCoupon.ValidStartTime = &validStartTime + + validEndTime := model.LocalTime(time.Now().Add(time.Duration(coupon.ValidDays) * 24 * time.Hour)) + userCoupon.ValidEndTime = &validEndTime + } + + userCouponDao := dao.UserCouponDao{} + userCoupon, err = userCouponDao.AddUserCoupon(tx, userCoupon) + if err != nil { + return false + } + + // 增加优惠卷发放数量 + err = couponDao.Inc(tx, couponId, "coupon_take_count", grantQuantity) + if err != nil { + return false + } + + // 增加过期队列 + if coupon.ValidType == 1 { + validEndTime := time.Time(*userCoupon.ValidEndTime) + + // 计算当天的结束时间 + now := time.Now() + year, month, day := now.Date() + location := now.Location() + endOfDay := time.Date(year, month, day, 23, 59, 59, 0, location) + if validEndTime.Before(endOfDay) { + delay := validEndTime.Sub(time.Now()) + if delay < 5*time.Second { + delay = 5 * time.Second + } + + // 添加处理优惠卷过期队列 + data := make(map[string]interface{}) + data["coupon_id"] = fmt.Sprintf("%d", coupon.CouponId) + + p := rabbitMq.PublishS{ + QueueName: "user.coupon.expired.delay.queue", + ExchangeName: "amqp.delay.direct", + RoutingKey: "UserCouponExpired", + Message: data, + Delay: delay, + } + err := p.PublishWithDelay() + if err != nil { + return false + } + } + } + + return true +} diff --git a/api/service/UserCoupon.go b/api/service/UserCoupon.go index 78652e9..2967fa8 100644 --- a/api/service/UserCoupon.go +++ b/api/service/UserCoupon.go @@ -77,7 +77,7 @@ func (r *UserCouponService) CheckUserCoupon(m *model.UserCoupon, id int64, order // 检测优惠劵过期时间 if m.Coupon.ValidType == 1 { - validEndTime = time.Time(m.Coupon.ValidEndTime) + validEndTime = time.Time(*m.Coupon.ValidEndTime) if validEndTime.Before(now) { return false, errors.New("优惠卷已过期,无法使用") } diff --git a/utils/tz.go b/utils/tz.go new file mode 100644 index 0000000..1792a48 --- /dev/null +++ b/utils/tz.go @@ -0,0 +1,24 @@ +package utils + +import ( + "hepa-calc-api/api/model" + "time" +) + +// StrToLocalTime 字符串时间转localtime +func StrToLocalTime(s string) (*model.LocalTime, error) { + // 获取本地时区 + location, err := time.LoadLocation("Local") + if err != nil { + return nil, err + } + + timeParse, err := time.ParseInLocation("2006-01-02 15:04:05", s, location) + if err != nil { + return nil, err + } + + t := model.LocalTime(timeParse) + + return &t, nil +}