From 7b021906a2f64d37cf0eb932060f987905b8fc42 Mon Sep 17 00:00:00 2001 From: wucongxing8150 <815046773@qq.com> Date: Fri, 31 May 2024 17:21:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86=EF=BC=9A=E5=8F=91?= =?UTF-8?q?=E6=94=BE=E7=B3=BB=E7=BB=9F=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/controller/coupon.go | 91 +++++++++++++ api/dao/coupon.go | 18 +++ api/dao/couponGrant.go | 55 ++++++++ api/dao/popup.go | 64 +++++++++ api/dao/userCoupon.go | 125 ++++++++++++++++++ api/dao/userPatient.go | 9 ++ api/dto/UserCoupon.go | 20 ++- api/model/couponGrantRecord.go | 39 ++++++ api/model/popup.go | 40 ++++++ api/model/userCoupon.go | 17 +-- api/requests/coupon.go | 26 ++++ api/router/router.go | 17 +-- api/service/coupon.go | 234 +++++++++++++++++++++++++++++++++ api/service/messagePush.go | 36 +++++ 14 files changed, 767 insertions(+), 24 deletions(-) create mode 100644 api/dao/couponGrant.go create mode 100644 api/dao/popup.go create mode 100644 api/model/couponGrantRecord.go create mode 100644 api/model/popup.go create mode 100644 api/service/messagePush.go diff --git a/api/controller/coupon.go b/api/controller/coupon.go index 2d59413..ca3021c 100644 --- a/api/controller/coupon.go +++ b/api/controller/coupon.go @@ -188,3 +188,94 @@ func (r *Coupon) PutSystemCouponStatus(c *gin.Context) { responses.Ok(c) } + +// GetUserCouponPage 获取用户优惠卷列表-分页 +func (r *Coupon) GetUserCouponPage(c *gin.Context) { + couponRequest := requests.CouponRequest{} + req := couponRequest.GetUserCouponPage + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + if req.Page == 0 { + req.Page = 1 + } + + if req.PageSize == 0 { + req.PageSize = 20 + } + + userCouponDao := dao.UserCouponDao{} + userCoupon, total, err := userCouponDao.GetUserCouponPageSearch(req, req.Page, req.PageSize) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 处理返回值 + GetProductPlatformPageResponses := dto.GetUserCouponListDto(userCoupon) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + result := make(map[string]interface{}) + result["page"] = req.Page + result["page_size"] = req.PageSize + result["total"] = total + result["data"] = GetProductPlatformPageResponses + responses.OkWithData(result, c) +} + +// GrantSystemCoupon 发放系统优惠卷 +func (r *Coupon) GrantSystemCoupon(c *gin.Context) { + couponRequest := requests.CouponRequest{} + req := couponRequest.GrantSystemCoupon + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + id := c.Param("coupon_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + // 将 id 转换为 int64 类型 + couponId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + // 获取当前登陆用户id + userId := c.GetInt64("UserId") + if userId == 0 { + responses.FailWithMessage("角色错误", c) + return + } + + // 业务处理 + couponService := service.CouponService{} + _, err = couponService.GrantSystemCoupon(couponId, userId, req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} diff --git a/api/dao/coupon.go b/api/dao/coupon.go index 331b494..4783c67 100644 --- a/api/dao/coupon.go +++ b/api/dao/coupon.go @@ -165,3 +165,21 @@ func (r *CouponDao) GetCouponPageSearch(req requests.GetSystemCouponPage, page, } return m, totalRecords, 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("coupon_take_count", 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("coupon_take_count", gorm.Expr(field+" - ?", numeral)).Error + if err != nil { + return err + } + return nil +} diff --git a/api/dao/couponGrant.go b/api/dao/couponGrant.go new file mode 100644 index 0000000..815b33f --- /dev/null +++ b/api/dao/couponGrant.go @@ -0,0 +1,55 @@ +package dao + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" + "hospital-admin-api/api/model" + "hospital-admin-api/global" +) + +type CouponGrantDao struct { +} + +// GetCouponGrantById 获取数据-id +func (r *CouponGrantDao) GetCouponGrantById(orderServiceId int64) (m *model.CouponGrant, err error) { + err = global.Db.First(&m, orderServiceId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetCouponGrantPreloadById 获取数据-加载全部关联-id +func (r *CouponGrantDao) GetCouponGrantPreloadById(orderServiceId int64) (m *model.CouponGrant, err error) { + err = global.Db.Preload(clause.Associations).First(&m, orderServiceId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetCouponGrantByCouponId 获取数据-id +func (r *CouponGrantDao) GetCouponGrantByCouponId(couponId int64) (m *model.CouponGrant, err error) { + err = global.Db.Where("coupon_id = ?", couponId).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetCouponGrantList 获取列表 +func (r *CouponGrantDao) GetCouponGrantList(maps interface{}) (m []*model.CouponGrant, err error) { + err = global.Db.Where(maps).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddCouponGrant 新增 +func (r *CouponGrantDao) AddCouponGrant(tx *gorm.DB, model *model.CouponGrant) (*model.CouponGrant, error) { + if err := tx.Create(model).Error; err != nil { + return nil, err + } + return model, nil +} diff --git a/api/dao/popup.go b/api/dao/popup.go new file mode 100644 index 0000000..8105188 --- /dev/null +++ b/api/dao/popup.go @@ -0,0 +1,64 @@ +package dao + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" + "hospital-admin-api/api/model" + "hospital-admin-api/global" +) + +type PopupDao struct { +} + +// GetPopupById 获取数据-id +func (r *PopupDao) GetPopupById(popupId int64) (m *model.Popup, err error) { + err = global.Db.First(&m, popupId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetPopupPreloadById 获取数据-加载全部关联-id +func (r *PopupDao) GetPopupPreloadById(popupId int64) (m *model.Popup, err error) { + err = global.Db.Preload(clause.Associations).First(&m, popupId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// EditPopup 修改 +func (r *PopupDao) EditPopup(tx *gorm.DB, maps interface{}, data interface{}) error { + err := tx.Model(&model.Popup{}).Where(maps).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// EditPopupByOrderServicePackageId 修改-id +func (r *PopupDao) EditPopupByOrderServicePackageId(tx *gorm.DB, popupId int64, data interface{}) error { + err := tx.Model(&model.Popup{}).Where("popup_id = ?", popupId).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// GetPopupList 获取列表 +func (r *PopupDao) GetPopupList(maps interface{}) (m []*model.Popup, err error) { + err = global.Db.Where(maps).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddPopup 新增 +func (r *PopupDao) AddPopup(tx *gorm.DB, model *model.Popup) (*model.Popup, error) { + if err := tx.Create(model).Error; err != nil { + return nil, err + } + return model, nil +} diff --git a/api/dao/userCoupon.go b/api/dao/userCoupon.go index acdb8ab..f7964f2 100644 --- a/api/dao/userCoupon.go +++ b/api/dao/userCoupon.go @@ -4,7 +4,9 @@ import ( "gorm.io/gorm" "gorm.io/gorm/clause" "hospital-admin-api/api/model" + "hospital-admin-api/api/requests" "hospital-admin-api/global" + "strings" "time" ) @@ -73,6 +75,15 @@ func (r *UserCouponDao) GetUserCouponList(maps interface{}) (m []*model.UserCoup return m, nil } +// GetUserCoupon 获取 +func (r *UserCouponDao) GetUserCoupon(maps interface{}) (m *model.UserCoupon, err error) { + err = global.Db.Where(maps).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + // AddUserCoupon 新增用户优惠卷 func (r *UserCouponDao) AddUserCoupon(tx *gorm.DB, model *model.UserCoupon) (*model.UserCoupon, error) { if err := tx.Create(model).Error; err != nil { @@ -117,3 +128,117 @@ func (r *UserCouponDao) GetUserAllObjectTypeCoupon(userId int64, distributionObj } return m, nil } + +// GetUserCouponPageSearch 获取用户优惠卷列表-分页 +func (r *UserCouponDao) GetUserCouponPageSearch(req requests.GetUserCouponPage, page, pageSize int) (m []*model.UserCoupon, total int64, err error) { + var totalRecords int64 + + // 构建查询条件 + query := global.Db.Model(&model.UserCoupon{}) + + // 用户 + query = query.Preload("User", func(db *gorm.DB) *gorm.DB { + return db.Omit("user_password", "salt") + }) + + query = query.Preload("Coupon") + + // 优惠卷名称 + if req.CouponName != "" { + query = query.Where("coupon_name LIKE ?", "%"+req.CouponName+"%") + } + + // 优惠卷编号 + if req.CouponId != "" { + query = query.Where("coupon_id = ?", req.CouponId) + } + + // 使用状态 + if req.UserCouponStatus != nil { + query = query.Where("user_coupon_status = ?", req.UserCouponStatus) + } + + // 使用时间 + if req.CouponUseDate != "" { + couponUseDate := strings.Split(req.CouponUseDate, "&") + if len(couponUseDate) == 2 { + startTime, _ := time.Parse("2006-01-02", couponUseDate[0]) + endTime, _ := time.Parse("2006-01-02", couponUseDate[1]) + + endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second) + + query = query.Where("coupon_use_date BETWEEN ? AND ?", startTime, endTime) + } + } + + // 有效使用时间 + if req.ValidStartTime != "" { + validStartTime := strings.Split(req.ValidStartTime, "&") + if len(validStartTime) == 2 { + startTime, _ := time.Parse("2006-01-02", validStartTime[0]) + endTime, _ := time.Parse("2006-01-02", validStartTime[1]) + + endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second) + + query = query.Where("valid_start_time BETWEEN ? AND ?", startTime, endTime) + } + } + + // 过期使用时间 + if req.ValidEndTime != "" { + validEndTime := strings.Split(req.ValidEndTime, "&") + if len(validEndTime) == 2 { + startTime, _ := time.Parse("2006-01-02", validEndTime[0]) + endTime, _ := time.Parse("2006-01-02", validEndTime[1]) + + endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second) + + query = query.Where("valid_end_time BETWEEN ? AND ?", startTime, endTime) + } + } + + // 创建时间 + if req.CreatedAt != "" { + createdAt := strings.Split(req.CreatedAt, "&") + if len(createdAt) == 2 { + startTime, _ := time.Parse("2006-01-02", createdAt[0]) + endTime, _ := time.Parse("2006-01-02", createdAt[1]) + + endTime = endTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second) + + query = query.Where("created_at BETWEEN ? AND ?", startTime, endTime) + } + } + + // 手机号 + if req.Mobile != "" { + subQuery := global.Db.Model(&model.User{}). + Select("user_id"). + Where("mobile LIKE ?", "%"+req.Mobile+"%") + + query = query.Where(gorm.Expr("user_id IN (?)", subQuery)) + } + + // 用户名 + if req.UserName != "" { + subQuery := global.Db.Model(&model.UserPatient{}). + Select("user_id"). + Where("user_name LIKE ?", "%"+req.UserName+"%") + + query = query.Where(gorm.Expr("user_id IN (?)", subQuery)) + } + + // 排序 + query = query.Order("created_at desc") + + // 查询总数量 + if err := query.Count(&totalRecords).Error; err != nil { + return nil, 0, err + } + + err = query.Scopes(model.Paginate(page, pageSize)).Find(&m).Error + if err != nil { + return nil, 0, err + } + return m, totalRecords, nil +} diff --git a/api/dao/userPatient.go b/api/dao/userPatient.go index 6753c9d..1cd8193 100644 --- a/api/dao/userPatient.go +++ b/api/dao/userPatient.go @@ -235,3 +235,12 @@ func (r *UserPatientDao) GetUserPatientExportListSearch(req requests.UserPatient return m, nil } + +// GetUserPatientByUserId 获取患者数据-id +func (r *UserPatientDao) GetUserPatientByUserId(userId int64) (m *model.UserPatient, err error) { + err = global.Db.Where("user_id = ?", userId).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} diff --git a/api/dto/UserCoupon.go b/api/dto/UserCoupon.go index 60ab469..09ab35c 100644 --- a/api/dto/UserCoupon.go +++ b/api/dto/UserCoupon.go @@ -18,6 +18,7 @@ type UserCouponDto struct { CreatedAt model.LocalTime `json:"created_at"` // 创建时间 UpdatedAt model.LocalTime `json:"updated_at"` // 修改时间 Coupon *CouponDto `json:"coupon"` // 优惠卷 + UserName string `json:"user_name"` // 用户名称 } // GetUserCouponDto 用户优惠卷详情 @@ -28,7 +29,7 @@ func GetUserCouponDto(m *model.UserCoupon) *UserCouponDto { PatientId: fmt.Sprintf("%d", m.PatientId), CouponId: fmt.Sprintf("%d", m.CouponId), UserCouponStatus: m.UserCouponStatus, - CouponUseDate: model.LocalTime(m.CouponUseDate), + CouponUseDate: model.LocalTime(*m.CouponUseDate), ValidStartTime: model.LocalTime(m.ValidStartTime), ValidEndTime: model.LocalTime(m.ValidEndTime), CreatedAt: m.CreatedAt, @@ -49,18 +50,23 @@ func GetUserCouponListDto(m []*model.UserCoupon) []*UserCouponDto { PatientId: fmt.Sprintf("%d", v.PatientId), CouponId: fmt.Sprintf("%d", v.CouponId), UserCouponStatus: v.UserCouponStatus, - CouponUseDate: model.LocalTime(v.CouponUseDate), + CouponUseDate: model.LocalTime(*v.CouponUseDate), ValidStartTime: model.LocalTime(v.ValidStartTime), ValidEndTime: model.LocalTime(v.ValidEndTime), CreatedAt: v.CreatedAt, UpdatedAt: v.UpdatedAt, } - // 加载问诊订单数据 + // 加载优惠卷数据 if v.Coupon != nil { response = response.LoadCoupon(v.Coupon) } + // 加载用户属性 + if v.User != nil { + response = response.LoadUserAttr(v.User) + } + // 将转换后的结构体添加到新切片中 responses[i] = response } @@ -78,3 +84,11 @@ func (r *UserCouponDto) LoadCoupon(m *model.Coupon) *UserCouponDto { } return r } + +// LoadUserAttr 加载用户属性 +func (r *UserCouponDto) LoadUserAttr(m *model.User) *UserCouponDto { + if m != nil { + r.UserName = m.UserName + } + return r +} diff --git a/api/model/couponGrantRecord.go b/api/model/couponGrantRecord.go new file mode 100644 index 0000000..0a11d9b --- /dev/null +++ b/api/model/couponGrantRecord.go @@ -0,0 +1,39 @@ +package model + +import ( + "gorm.io/gorm" + "hospital-admin-api/global" + "time" +) + +// CouponGrant 优惠卷发放记录表 +type CouponGrant struct { + GrantId int64 `gorm:"column:grant_id;type:bigint(19);primary_key;comment:主键id" json:"grant_id"` + CouponId int64 `gorm:"column:coupon_id;type:bigint(19);comment:优惠卷id" json:"coupon_id"` + GrantType int `gorm:"column:grant_type;type:tinyint(1);default:1;comment:发放类型(1:具体用户 2:未拥有用户)" json:"grant_type"` + UserId int64 `gorm:"column:user_id;type:bigint(19);comment:用户id(发放类型为具体用户时存在)" json:"user_id"` + TotalQuantity int `gorm:"column:total_quantity;type:int(5);default:0;comment:目标发放数量" json:"total_quantity"` + GrantQuantity int `gorm:"column:grant_quantity;type:int(5);comment:已发放数量" json:"grant_quantity"` + GrantResult int `gorm:"column:grant_result;type:tinyint(1);default:2;comment:发放结果(1:成功 2:发放中 3:部分 4:失败)" json:"grant_result"` + StopReason string `gorm:"column:stop_reason;type:varchar(255);comment:停止原因" json:"stop_reason"` + AdminUserId int64 `gorm:"column:admin_user_id;type:bigint(19);comment:后台操作用户id" json:"admin_user_id"` + Model +} + +func (m *CouponGrant) TableName() string { + return "gdxz_coupon_grant" +} + +func (m *CouponGrant) BeforeCreate(tx *gorm.DB) error { + if m.GrantId == 0 { + m.GrantId = global.Snowflake.Generate().Int64() + } + + m.CreatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("CreatedAt", m.CreatedAt) + + m.UpdatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt) + + return nil +} diff --git a/api/model/popup.go b/api/model/popup.go new file mode 100644 index 0000000..c6fa302 --- /dev/null +++ b/api/model/popup.go @@ -0,0 +1,40 @@ +package model + +import ( + "gorm.io/gorm" + "hospital-admin-api/global" + "time" +) + +// Popup 弹窗表 +type Popup struct { + PopupId int64 `gorm:"column:popup_id;type:bigint(19);primary_key;comment:主键id" json:"popup_id"` + UserId int64 `gorm:"column:user_id;type:bigint(19);comment:用户id" json:"user_id"` + AppType int `gorm:"column:app_type;type:tinyint(4);comment:应用程序类型(1:小程序 2:app);NOT NULL" json:"app_type"` + ClientType int `gorm:"column:client_type;type:tinyint(4);comment:客户端类型(1:患者端 2:医生端 3:药师端);NOT NULL" json:"client_type"` + Status int `gorm:"column:status;type:tinyint(4);default:0;comment:状态(0:未弹 1:已弹)" json:"status"` + PopupType int `gorm:"column:popup_type;type:tinyint(4);comment:弹窗类型(1:结算费用规则 2:新优惠卷弹窗);NOT NULL" json:"popup_type"` + PopupTitle string `gorm:"column:popup_title;type:varchar(255);comment:标题" json:"popup_title"` + PopupContent string `gorm:"column:popup_content;type:varchar(1000);comment:内容" json:"popup_content"` + PopupImg string `gorm:"column:popup_img;type:varchar(255);comment:封面图片" json:"popup_img"` + PopupLink string `gorm:"column:popup_link;type:varchar(255);comment:跳转地址" json:"popup_link"` + Model +} + +func (m *Popup) TableName() string { + return "gdxz_popup" +} + +func (m *Popup) BeforeCreate(tx *gorm.DB) error { + if m.PopupId == 0 { + m.PopupId = global.Snowflake.Generate().Int64() + } + + m.CreatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("CreatedAt", m.CreatedAt) + + m.UpdatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt) + + return nil +} diff --git a/api/model/userCoupon.go b/api/model/userCoupon.go index c2baead..22c545f 100644 --- a/api/model/userCoupon.go +++ b/api/model/userCoupon.go @@ -8,16 +8,17 @@ import ( // UserCoupon 用户优惠卷表 type UserCoupon struct { - UserCouponId int64 `gorm:"column:user_coupon_id;type:bigint(19);primary_key;comment:主键id" json:"user_coupon_id"` - UserId int64 `gorm:"column:user_id;type:bigint(19);comment:用户id;NOT NULL" json:"user_id"` - PatientId int64 `gorm:"column:patient_id;type:bigint(19);comment:患者id" json:"patient_id"` - CouponId int64 `gorm:"column:coupon_id;type:bigint(19);comment:优惠卷id;NOT NULL" json:"coupon_id"` - UserCouponStatus int `gorm:"column:user_coupon_status;type:tinyint(1);default:0;comment:状态(0:未使用 1:已使用 3:已过期)" json:"user_coupon_status"` - CouponUseDate time.Time `gorm:"column:coupon_use_date;type:datetime;comment:使用时间" json:"coupon_use_date"` - ValidStartTime time.Time `gorm:"column:valid_start_time;type:datetime;comment:有效使用时间" json:"valid_start_time"` - ValidEndTime time.Time `gorm:"column:valid_end_time;type:datetime;comment:过期使用时间" json:"valid_end_time"` + UserCouponId int64 `gorm:"column:user_coupon_id;type:bigint(19);primary_key;comment:主键id" json:"user_coupon_id"` + UserId int64 `gorm:"column:user_id;type:bigint(19);comment:用户id;NOT NULL" json:"user_id"` + PatientId int64 `gorm:"column:patient_id;type:bigint(19);comment:患者id" json:"patient_id"` + CouponId int64 `gorm:"column:coupon_id;type:bigint(19);comment:优惠卷id;NOT NULL" json:"coupon_id"` + UserCouponStatus int `gorm:"column:user_coupon_status;type:tinyint(1);default:0;comment:状态(0:未使用 1:已使用 3:已过期)" json:"user_coupon_status"` + CouponUseDate *time.Time `gorm:"column:coupon_use_date;type:datetime;comment:使用时间" json:"coupon_use_date"` + ValidStartTime time.Time `gorm:"column:valid_start_time;type:datetime;comment:有效使用时间" json:"valid_start_time"` + ValidEndTime time.Time `gorm:"column:valid_end_time;type:datetime;comment:过期使用时间" json:"valid_end_time"` Model Coupon *Coupon `gorm:"foreignKey:CouponId;references:coupon_id" json:"coupon"` + User *User `gorm:"foreignKey:UserId;references:user_id" json:"user"` // 用户 } func (m *UserCoupon) TableName() string { diff --git a/api/requests/coupon.go b/api/requests/coupon.go index 64b38bc..91d91d8 100644 --- a/api/requests/coupon.go +++ b/api/requests/coupon.go @@ -5,6 +5,8 @@ type CouponRequest struct { AddSystemCoupon // 新增系统优惠卷 PutSystemCoupon // 修改系统优惠卷 PutSystemCouponStatus // 修改系统优惠卷状态 + GetUserCouponPage // 获取用户优惠卷列表-分页 + GrantSystemCoupon // 发放系统优惠卷 } // GetSystemCouponPage 获取系统优惠卷列表-分页 @@ -80,3 +82,27 @@ type PutSystemCoupon struct { type PutSystemCouponStatus struct { CouponStatus int `json:"coupon_status" form:"coupon_status" label:"状态" validate:"required,oneof=2 3 4"` // (1:正常 2:强制失效 3:结束 4:删除) } + +// GetUserCouponPage 获取用户优惠卷列表-分页 +type GetUserCouponPage struct { + Page int `json:"page" form:"page" label:"页码"` + PageSize int `json:"page_size" form:"page_size" label:"每页个数"` + CouponName string `json:"coupon_name" form:"coupon_name" label:"优惠卷名称"` // 优惠卷名称 + CouponId string `json:"coupon_id" form:"coupon_id" label:"优惠卷编号"` // 优惠卷名称 + UserCouponStatus *int `json:"user_coupon_status" form:"user_coupon_status" label:"使用状态(0:未使用 1:已使用 3:已过期)"` // 状态(1:正常 2:强制失效 3:结束 4:删除) + CouponUseDate string `json:"coupon_use_date" form:"coupon_use_date" label:"使用时间"` // 使用时间 + ValidStartTime string `json:"valid_start_time" form:"valid_start_time" label:"有效使用时间"` // 有效使用时间 + ValidEndTime string `json:"valid_end_time" form:"valid_end_time" label:"过期使用时间"` // 过期使用时间 + CreatedAt string `json:"created_at" form:"created_at" label:"创建时间"` // 创建时间 + Mobile string `json:"mobile" form:"mobile" label:"手机号"` + UserName string `json:"user_name" form:"user_name" label:"用户名"` +} + +// GrantSystemCoupon 发放系统优惠卷 +type GrantSystemCoupon struct { + Type int `json:"type" form:"type" label:"用户编号" validate:"required,oneof=1 2"` // 发放类型(1:具体用户 2:全部用户) + UserId string `json:"user_id" form:"user_id" label:"用户编号" validate:"number"` // 用户编号 + TotalQuantity int `json:"total_quantity" form:"total_quantity" label:"总发放数量" validate:"required,number,min=1"` // 总发放数量-发完即止 + SingleQuantity int `json:"single_quantity" form:"single_quantity" label:"个人可发放数量" validate:"required,number,min=1"` // 个人可发放数量-发完即止,依次发放,到达发放总数量后即停止 + IsForce *int `json:"is_follow_rules" form:"is_force_grant" label:"是否遵循优惠卷发放对象规则" validate:"oneof=0 1"` // 是否遵循优惠卷发放对象规则(0:否 1:是)(是:遵循优惠卷发放对象规则进行发放。否:不满足优惠卷发放对象规则也会发放一张) +} diff --git a/api/router/router.go b/api/router/router.go index 1e47da2..705d39d 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -740,25 +740,16 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 修改系统优惠卷状态 systemGroup.PUT("/status/:coupon_id", api.Coupon.PutSystemCouponStatus) + + // 发放系统优惠卷 + systemGroup.POST("/grant/:coupon_id", api.Coupon.GrantSystemCoupon) } // 用户优惠卷管理 userGroup := couponGroup.Group("/user") { // 获取用户优惠卷列表-分页 - userGroup.POST("/page", api.Product.GetProductPage) - - // 系统用户优惠卷详情 - userGroup.GET("/:product_id", api.Product.GetProduct) - - // 新增用户优惠卷 - userGroup.POST("", api.Product.AddProduct) - - // 修改用户优惠卷 - userGroup.PUT("/:product_id", api.Product.PutProduct) - - // 修改用户优惠卷状态 - userGroup.PUT("/status/:product_id", api.Product.PutProductStatus) + userGroup.POST("/page", api.Coupon.GetUserCouponPage) } } } diff --git a/api/service/coupon.go b/api/service/coupon.go index b8367cb..f6d0521 100644 --- a/api/service/coupon.go +++ b/api/service/coupon.go @@ -1,12 +1,14 @@ package service import ( + "encoding/json" "errors" "fmt" "hospital-admin-api/api/dao" "hospital-admin-api/api/dto" "hospital-admin-api/api/model" "hospital-admin-api/api/requests" + "hospital-admin-api/extend/rabbitMq" "hospital-admin-api/global" "hospital-admin-api/utils" "strconv" @@ -475,3 +477,235 @@ func (r *CouponService) PutSystemCouponStatus(couponId int64, req requests.PutSy tx.Commit() return true, nil } + +// GrantSystemCoupon 发放系统优惠卷 +func (r *CouponService) GrantSystemCoupon(couponId, adminUserId int64, req requests.GrantSystemCoupon) (bool, error) { + if req.Type == 2 { + return false, errors.New("暂时只支持具体用户发放") + } + + couponDao := dao.CouponDao{} + coupon, err := couponDao.GetCouponById(couponId) + if err != nil { + return false, err + } + + if coupon.CouponStatus != 1 { + return false, errors.New("优惠卷非正常状态,不支持发放") + } + + // 检测订单过期时间 + now := time.Now() + validEndTime := time.Time(*coupon.ValidEndTime) + if now.After(validEndTime) { + return false, errors.New("优惠卷已过期,不支持发放") + } + + // 检测优惠卷剩余数量 + remainingQuantity := coupon.CouponCount - coupon.CouponTakeCount + if remainingQuantity <= 0 { + return false, errors.New("优惠卷数量不足,无法发放") + } + + // 检测优惠卷可发放数量 + if req.TotalQuantity >= remainingQuantity { + return false, errors.New("优惠卷数量不足,无法发放") + } + + // 检测优惠卷过期时间 + now = now.Add(time.Minute * 10) + if coupon.ValidType == 1 { + // 1:绝对时效 + validStartTime := time.Time(*coupon.ValidStartTime) + if now.Before(validStartTime) { + return false, errors.New("优惠卷还未启用") + } + + validEndTime := time.Time(*coupon.ValidEndTime) + if now.After(validEndTime) { + return false, errors.New("优惠卷即将过期,不支持发放") + } + } + + // 获取优惠卷发放记录表 + couponGrantDao := dao.CouponGrantDao{} + + maps := make(map[string]interface{}) + maps["coupon_id"] = coupon.CouponId + maps["grant_result"] = 2 + couponGrants, _ := couponGrantDao.GetCouponGrantList(maps) + if len(couponGrants) > 0 { + return false, errors.New("请等待上次发放结束后再执行此操作") + } + + // 将 id 转换为 int64 类型 + userId, err := strconv.ParseInt(req.UserId, 10, 64) + if err != nil { + return false, errors.New("发放失败") + } + + userDao := dao.UserDao{} + user, _ := userDao.GetUserById(userId) + if user == nil { + return false, errors.New("用户错误") + } + + // 获取患者数据 + userPatientDao := dao.UserPatientDao{} + userPatient, _ := userPatientDao.GetUserPatientByUserId(userId) + if userPatient == nil { + return false, errors.New("用户错误") + } + + // 检测用户是否已领取该优惠卷 + userCouponDao := dao.UserCouponDao{} + + maps = make(map[string]interface{}) + maps["user_id"] = user.UserId + maps["coupon_id"] = coupon.CouponId + maps["user_coupon_status"] = 0 + userCoupons, _ := userCouponDao.GetUserCouponList(maps) + if len(userCoupons) >= req.SingleQuantity { + return false, errors.New("用户已有该优惠卷") + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + for i := 0; i < req.SingleQuantity; i++ { + // 添加用户优惠卷表 + UserCouponModel := &model.UserCoupon{ + UserId: user.UserId, + PatientId: userPatient.PatientId, + CouponId: couponId, + CouponUseDate: nil, + } + + // 有效类型(1:绝对时效,xxx-xxx时间段有效 2:相对时效 n天内有效) + if coupon.ValidType == 1 { + UserCouponModel.ValidStartTime = time.Time(*coupon.ValidStartTime) + UserCouponModel.ValidEndTime = time.Time(*coupon.ValidEndTime) + } + + if coupon.ValidType == 2 { + UserCouponModel.ValidStartTime = now + UserCouponModel.ValidEndTime = now.AddDate(0, 0, coupon.ValidDays) + } + + userCoupon, _ := userCouponDao.AddUserCoupon(tx, UserCouponModel) + if userCoupon == nil { + tx.Rollback() + return false, errors.New("发放失败") + } + + // 增加优惠卷发放数量 + err = couponDao.Inc(tx, couponId, "coupon_take_count", 1) + if err != nil { + tx.Rollback() + return false, errors.New("发放失败") + } + + // 添加弹窗表 + if coupon.IsPopup == 1 { + popupModel := &model.Popup{ + UserId: user.UserId, + AppType: 1, + ClientType: 1, + PopupType: 2, + PopupTitle: "红包福利", + PopupContent: "", + } + + popupContent := make(map[string]interface{}) + popupContent["user_coupon_id"] = fmt.Sprintf("%d", userCoupon.UserCouponId) + popupContent["coupon_price"] = coupon.CouponPrice + popupContent["application_scope"] = coupon.ApplicationScope + popupContent["inquiry_type"] = coupon.InquiryType + popupContent["valid_type"] = coupon.ValidType + popupContent["valid_days"] = coupon.ValidDays + popupContent["valid_start_time"] = coupon.ValidStartTime + popupContent["valid_end_time"] = coupon.ValidEndTime + + popupContentData, err := json.Marshal(popupContent) + if err != nil { + tx.Rollback() + return false, errors.New("发放失败") + } + + popupModel.PopupContent = string(popupContentData) + + popupDao := dao.PopupDao{} + popup, _ := popupDao.AddPopup(tx, popupModel) + if popup == nil { + tx.Rollback() + return false, errors.New("发放失败") + } + } + + // 增加优惠卷过期队列 + // 计算当天的结束时间 + year, month, day := now.Date() + location := now.Location() + endOfDay := time.Date(year, month, day, 23, 59, 59, 0, location) + if userCoupon.ValidEndTime.Before(endOfDay) { + // 需添加队列 + // 建立队列连接 + rabbitMQ, err := rabbitMq.NewRabbitMQClient() + if err != nil { + tx.Rollback() + return false, errors.New("发放失败") + } + + defer rabbitMQ.Close() + + data := make(map[string]interface{}) + data["user_coupon_id"] = fmt.Sprintf("%d", userCoupon.UserCouponId) + + delay := userCoupon.ValidEndTime.Sub(time.Now()) + + if delay < 10 { + delay = 10 * time.Second + } + + err = rabbitMQ.PublishWithDelay("user.coupon.expired.delay.queue", "amqp.delay.direct", "UserCouponExpired", data, delay) + if err != nil { + tx.Rollback() + return false, err + } + + go func() { + // 发送通知 + res, _ := PatientDistributeCoupon(coupon.CouponName, user.UserId) + if !res { + utils.LogJsonErr("CouponService-GrantSystemCoupon", "优惠卷通知发送失败") + } + }() + } + } + + // 添加优惠卷发放记录表 + couponGrantModel := &model.CouponGrant{ + CouponId: coupon.CouponId, + GrantType: req.Type, + UserId: userId, + TotalQuantity: req.TotalQuantity, + GrantQuantity: req.SingleQuantity, + GrantResult: 1, + StopReason: "", + AdminUserId: adminUserId, + } + + _, err = couponGrantDao.AddCouponGrant(tx, couponGrantModel) + if err != nil { + tx.Rollback() + return false, err + } + + tx.Commit() + return true, nil +} diff --git a/api/service/messagePush.go b/api/service/messagePush.go new file mode 100644 index 0000000..3d5b6f0 --- /dev/null +++ b/api/service/messagePush.go @@ -0,0 +1,36 @@ +package service + +import ( + "errors" + "fmt" + "hospital-admin-api/extend/rabbitMq" +) + +// PatientDistributeCoupon 患者-优惠劵发放-站内 +func PatientDistributeCoupon(couponName string, userId int64) (bool, error) { + // 建立队列连接 + rabbitMQ, err := rabbitMq.NewRabbitMQClient() + if err != nil { + return false, errors.New("内部错误") + } + + defer rabbitMQ.Close() + + data := make(map[string]interface{}) + data["user_id"] = fmt.Sprintf("%d", userId) + data["notice_type"] = 3 + data["notice_system_type"] = 2 + data["from_name"] = "肝胆小秘书" + data["notice_brief_title"] = "有新的优惠券已下发至您的账户,点击查看详情。" + data["notice_title"] = fmt.Sprintf("【%s】已到账", couponName) + data["notice_content"] = "有新的优惠劵已下发至您的账户中,点击查看详情!" + data["link_type"] = 7 + + err = rabbitMQ.Publish("send.station.message.queue", "amqp.direct", "SendStationMessage", data) + if err != nil { + return false, err + } + + return true, nil + +}