package v1 import ( "encoding/json" "errors" "fmt" "hospital-open-api/api/dao" dtoV1 "hospital-open-api/api/dto/v1" "hospital-open-api/api/model" requestsV1 "hospital-open-api/api/requests/v1" "hospital-open-api/api/service" "hospital-open-api/extend/rabbitMq" "hospital-open-api/global" "hospital-open-api/utils" "strconv" "time" ) // CouponService 优惠卷 type CouponService struct { } // ReceiveCoupon 领取优惠卷 func (r *CouponService) ReceiveCoupon(req requestsV1.ReceiveCoupon) (g *dtoV1.ReceiveCouponDto, err error) { // 获取用户数据 userDao := dao.UserDao{} maps := make(map[string]interface{}) maps["mobile"] = req.Mobile maps["user_type"] = 1 user, _ := userDao.GetUser(maps) if user == nil { g = &dtoV1.ReceiveCouponDto{ Status: 2, Message: "未注册互联网医院患者端", Data: nil, } return g, nil } // 获取患者数据 userPatientDao := dao.UserPatientDao{} userPatient, _ := userPatientDao.GetUserPatientByUserId(user.UserId) if userPatient == nil { g = &dtoV1.ReceiveCouponDto{ Status: 2, Message: "未注册互联网医院患者端", Data: nil, } return g, err } // 将 id 转换为 int64 类型 couponId, err := strconv.ParseInt(req.CouponId, 10, 64) if err != nil { return g, errors.New("内部错误") } // 获取优惠卷数据 couponDao := dao.CouponDao{} coupon, _ := couponDao.GetCouponById(couponId) if coupon == nil { return nil, errors.New("非法优惠卷") } // 检测优惠卷状态 if coupon.CouponStatus != 1 { return nil, errors.New("存在错误优惠卷") } // 检测发放优惠卷数量 if req.Quantity <= 0 { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷数量错误", Data: nil, } return g, nil } // 检测优惠卷剩余数量 remainingQuantity := coupon.CouponCount - coupon.CouponTakeCount if remainingQuantity <= 0 { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷数量不足,领取失败", Data: nil, } return g, nil } if remainingQuantity < req.Quantity { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷数量不足,领取失败", Data: nil, } return g, nil } // 获取当前时间 now := time.Now() // 检测优惠卷过期时间 if coupon.ValidType == 1 { // 1:绝对时效 validStartTime := time.Time(coupon.ValidStartTime) if now.Before(validStartTime) { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷还未启用", Data: nil, } return g, nil } validEndTime := time.Time(coupon.ValidEndTime) if now.After(validEndTime) { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷已过期", Data: nil, } return g, nil } // 即将过期检测 now = now.Add(time.Minute * 10) // 1:绝对时效 validStartTime = time.Time(coupon.ValidStartTime) if now.Before(validStartTime) { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷还未启用", Data: nil, } return g, nil } validEndTime = time.Time(coupon.ValidEndTime) if now.After(validEndTime) { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "优惠卷即将过期", Data: nil, } return g, nil } } // 检测优惠卷过期时间 now = now.Add(time.Minute * 10) if coupon.ValidType == 1 { } // 检测用户是否已领取该优惠卷 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) > 0 { g = &dtoV1.ReceiveCouponDto{ Status: 0, Message: "重复领取", Data: nil, } return g, nil } // 开始事务 tx := global.Db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 添加用户优惠卷表 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 nil, errors.New("发放失败") } // 增加优惠卷发放数量 err = couponDao.Inc(tx, couponId, "coupon_take_count", req.Quantity) if err != nil { tx.Rollback() return nil, 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 nil, errors.New("发放失败") } popupModel.PopupContent = string(popupContentData) popupDao := dao.PopupDao{} popup, _ := popupDao.AddPopup(tx, popupModel) if popup == nil { tx.Rollback() return nil, 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 g, 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 nil, err } go func() { // 发送通知 res, _ := service.PatientDistributeCoupon(coupon.CouponName, user.UserId) if !res { utils.LogJsonError("优惠卷通知发送失败") } }() } tx.Commit() g = &dtoV1.ReceiveCouponDto{ Status: 1, Message: "成功", Data: nil, } return g, nil }