|
@@ -1,37 +1,63 @@
|
|
package entity
|
|
package entity
|
|
|
|
|
|
import (
|
|
import (
|
|
- "app.yhyue.com/moapp/jybase/common"
|
|
|
|
- "app.yhyue.com/moapp/jybase/date"
|
|
|
|
- "app.yhyue.com/moapp/jybase/encrypt"
|
|
|
|
- "app.yhyue.com/moapp/jybase/redis"
|
|
|
|
- "fmt"
|
|
|
|
- "gopkg.in/mgo.v2/bson"
|
|
|
|
- "jy/src/jfw/modules/subscribepay/src/config"
|
|
|
|
- "jy/src/jfw/modules/subscribepay/src/util"
|
|
|
|
- "log"
|
|
|
|
- "strings"
|
|
|
|
- "sync"
|
|
|
|
|
|
+ "app.yhyue.com/moapp/jybase/common"
|
|
|
|
+ "app.yhyue.com/moapp/jybase/date"
|
|
|
|
+ "app.yhyue.com/moapp/jybase/encrypt"
|
|
|
|
+ "app.yhyue.com/moapp/jybase/redis"
|
|
|
|
+ "fmt"
|
|
|
|
+ "jy/src/jfw/modules/subscribepay/src/config"
|
|
|
|
+ "jy/src/jfw/modules/subscribepay/src/util"
|
|
|
|
+ "log"
|
|
|
|
+ "sync"
|
|
|
|
+ "time"
|
|
)
|
|
)
|
|
|
|
|
|
const (
|
|
const (
|
|
TableEquityInfo = "jyactivities.equity_info" // 营销权益信息表
|
|
TableEquityInfo = "jyactivities.equity_info" // 营销权益信息表
|
|
//TableEquityActive = "jyactivities.equity_active" // 营销权益活动表 P477和权益码兑换表合成一张表
|
|
//TableEquityActive = "jyactivities.equity_active" // 营销权益活动表 P477和权益码兑换表合成一张表
|
|
- TableEquityActive = "jyactivities.activity_info" // 营销权益活动表
|
|
|
|
- TableOrder = "jianyu.dataexport_order" // 订单表
|
|
|
|
- TableLotteryPrizeOrder = "jyactivities.lottery_prize_order" // 下单后抽奖活动关联订单信息表
|
|
|
|
- TablebasePosition = "base_service.base_position" // 用户职位表
|
|
|
|
- valueStateGifted = 1 // 已赠送状态值
|
|
|
|
- valueMoldMonth = 0 // 月度
|
|
|
|
- valueMoldYear = 1 // 年度
|
|
|
|
- valueOrderTypeCreate = 1 // 超级订阅订单类型: 购买
|
|
|
|
- valueOrderTypeRenew = 2 // 续费
|
|
|
|
- valueOrderTypeUpgrade = 3 // 升级
|
|
|
|
- valueCycleUnitYear = 1 // 周期单位为年
|
|
|
|
- valueAreaCountAll = -1 // 全国
|
|
|
|
|
|
+ TableEquityActive = "jyactivities.activity_info" // 营销权益活动表
|
|
|
|
+ TableOrder = "jianyu.dataexport_order" // 订单表
|
|
|
|
+ TableLotteryPrizeOrder = "jyactivities.lottery_prize_order" // 下单后抽奖活动关联订单信息表
|
|
|
|
+ TableLotteryProducInfo = "jyactivities.product_info" // 活动奖励对应的剑鱼产品说明表
|
|
|
|
+ TableLotteryProductRule = "jyactivities.product_rule" // 赠送规则iddoc
|
|
|
|
+ TableLotteryUserCount = "jyactivities.lottery_user_account" // 用户中奖信息表
|
|
|
|
+ TableLotteryPrizeInfo = "jyactivities.lottery_prize_info" // 奖品信息配置表
|
|
|
|
+ TablebasePosition = "base_service.base_position" // 用户职位表
|
|
|
|
+ valueStateGifted = 1 // 已赠送状态值
|
|
|
|
+ valueMoldMonth = 0 // 月度
|
|
|
|
+ valueMoldYear = 1 // 年度
|
|
|
|
+ valueOrderTypeCreate = 1 // 超级订阅订单类型: 购买
|
|
|
|
+ valueOrderTypeRenew = 2 // 续费
|
|
|
|
+ valueOrderTypeUpgrade = 3 // 升级
|
|
|
|
+ valueCycleUnitYear = 1 // 周期单位为年
|
|
|
|
+ valueCycleUnitMonth = 2 // 周期单位为月
|
|
|
|
+ valueCycleUnitDay = 3 // 周期单位为天
|
|
|
|
+ valueCycleUnitQuarter = 4 // 周期单位为季
|
|
|
|
+ valueAreaCountAll = -1 // 全国
|
|
|
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// mold_wide_cycle : id
|
|
|
|
+var ActivityProductInfoMap = map[string]int{}
|
|
|
|
+
|
|
|
|
+// 为了初始化产品信息到内存
|
|
|
|
+func init() {
|
|
|
|
+ query := fmt.Sprintf("SELECT * FROM %s where state=0;", TableLotteryProducInfo)
|
|
|
|
+ rs := util.BaseMysql.SelectBySql(query)
|
|
|
|
+ if rs == nil || len(*rs) == 0 {
|
|
|
|
+ log.Println("jyactivities.product_info 未获取到数据")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ for i := 0; i < len(*rs); i++ {
|
|
|
|
+ id := (*rs)[i]["id"]
|
|
|
|
+ mold := (*rs)[i]["mold"]
|
|
|
|
+ wide := (*rs)[i]["wide"]
|
|
|
|
+ cycle := (*rs)[i]["cycle"]
|
|
|
|
+ ActivityProductInfoMap[fmt.Sprintf("%v_%v_%v", mold, wide, cycle)] = common.IntAll(id)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
var equityStockLock = sync.Mutex{} // 赠送视频权益码库存锁
|
|
var equityStockLock = sync.Mutex{} // 赠送视频权益码库存锁
|
|
// EquityActive 赠送视频会员活动
|
|
// EquityActive 赠送视频会员活动
|
|
type EquityActive struct {
|
|
type EquityActive struct {
|
|
@@ -40,8 +66,8 @@ type EquityActive struct {
|
|
positionId int // 职位id
|
|
positionId int // 职位id
|
|
Phone string // 手机号 用于发短信
|
|
Phone string // 手机号 用于发短信
|
|
OrderCode string // 订单号
|
|
OrderCode string // 订单号
|
|
- OrderType int // 1购买 2升级 3续费
|
|
|
|
- CycleUnit int // 单位 1-年
|
|
|
|
|
|
+ OrderType int // 1购买 2续费 3升级
|
|
|
|
+ CycleUnit int // 单位 1-年 2-月 3-天 4-季
|
|
CycleCount int // 数量
|
|
CycleCount int // 数量
|
|
AreaCount int // -1 是全国
|
|
AreaCount int // -1 是全国
|
|
ProductType string // 消息中的产品类型
|
|
ProductType string // 消息中的产品类型
|
|
@@ -53,7 +79,7 @@ type EquityActive struct {
|
|
// GiftVip 赠送腾讯视频会员
|
|
// GiftVip 赠送腾讯视频会员
|
|
func (e *EquityActive) GiftVip() {
|
|
func (e *EquityActive) GiftVip() {
|
|
//1. 判断活动是否开启
|
|
//1. 判断活动是否开启
|
|
- open, activeId, activeName := e.activityStart()
|
|
|
|
|
|
+ open, activeId, _ := e.activityStart()
|
|
if !open || activeId <= 0 {
|
|
if !open || activeId <= 0 {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
@@ -63,17 +89,17 @@ func (e *EquityActive) GiftVip() {
|
|
log.Println("equityActive 未获取到有效的mgoId", e.OrderCode)
|
|
log.Println("equityActive 未获取到有效的mgoId", e.OrderCode)
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- //2. 判断是否符合赠送条件
|
|
|
|
- ok, mold := e.matchOrder()
|
|
|
|
- if !ok {
|
|
|
|
|
|
+ //2. 判断是否符合活动配置的产品id
|
|
|
|
+ productInfoId := e.matchOrder()
|
|
|
|
+ if productInfoId <= 0 {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
equityStockLock.Lock()
|
|
equityStockLock.Lock()
|
|
defer func() {
|
|
defer func() {
|
|
equityStockLock.Unlock()
|
|
equityStockLock.Unlock()
|
|
}()
|
|
}()
|
|
- //3. 判断库存
|
|
|
|
- e.processEquityInfo(activeName, activeId, mold)
|
|
|
|
|
|
+ //3. 1-判该产品id 是否有对应库存 2-更新用户待获取订单表 3-符合条件则发送消息
|
|
|
|
+ e.processEquityInfo(activeId, productInfoId)
|
|
}
|
|
}
|
|
|
|
|
|
// txActivityStart 判断活动是否开启 开启则返回活动id
|
|
// txActivityStart 判断活动是否开启 开启则返回活动id
|
|
@@ -91,105 +117,53 @@ func (e *EquityActive) activityStart() (open bool, id int, name string) {
|
|
}
|
|
}
|
|
|
|
|
|
// 判断订单是否符合条件
|
|
// 判断订单是否符合条件
|
|
-func (e *EquityActive) matchOrder() (ok bool, mold int) {
|
|
|
|
- //(购买||续费)
|
|
|
|
- if (e.OrderType == valueOrderTypeCreate || e.OrderType == valueOrderTypeRenew) && e.CycleCount > 0 {
|
|
|
|
- // 判断购买是否为年度订单
|
|
|
|
- if e.CycleUnit != valueCycleUnitYear {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- // 为年度订单则判断是否为全国
|
|
|
|
- if e.AreaCount == valueAreaCountAll {
|
|
|
|
- ok = true
|
|
|
|
- mold = valueMoldYear //全国赠送1年
|
|
|
|
- } else {
|
|
|
|
- ok = true
|
|
|
|
- mold = valueMoldMonth //非全国赠送1月
|
|
|
|
- }
|
|
|
|
- //其他不赠送
|
|
|
|
- return
|
|
|
|
- } else if e.OrderType == valueOrderTypeUpgrade {
|
|
|
|
- // 升级
|
|
|
|
- // 判断是否是年度会员 不是年度会员则不赠送 是则赠送1月
|
|
|
|
- if e.isYearVip() {
|
|
|
|
- ok = true
|
|
|
|
- mold = valueMoldMonth
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return
|
|
|
|
|
|
+func (e *EquityActive) matchOrder() (productInfoId int) {
|
|
|
|
+ // mold '类型:1:购买;2:续费;3:升级',
|
|
|
|
+ //`wide` int(1) DEFAULT '0' COMMENT '是否全国:默认0:非全国;1:全国',
|
|
|
|
+ //`cycle` int(1) DEFAULT '0' COMMENT '下单周期:1:月;2:季;3:年',
|
|
|
|
+ // 1. 获取product_info_id
|
|
|
|
+ mold := e.OrderType
|
|
|
|
+ wide := common.If(e.AreaCount == -1, -1, 0)
|
|
|
|
+ cycle := e.CycleUnit
|
|
|
|
+ key := fmt.Sprintf("%v_%v_%v", mold, wide, cycle)
|
|
|
|
+ return ActivityProductInfoMap[key]
|
|
}
|
|
}
|
|
|
|
|
|
-// 处理库存
|
|
|
|
-func (e *EquityActive) processEquityInfo(activeName string, activeId, mold int) {
|
|
|
|
- count := 0
|
|
|
|
- tx, err := util.Mysql.DB.Begin()
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("equityActive db Begin:", err)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- now := date.NowFormat(date.Date_Full_Layout)
|
|
|
|
- countQuery := fmt.Sprintf("SELECT count(*) FROM %s where state= 0 and mold=? and active_id=? and ex_end_time>?;", TableEquityInfo)
|
|
|
|
- rows, err := tx.Query(countQuery, mold, activeId, now)
|
|
|
|
- if err != nil || rows == nil {
|
|
|
|
- log.Println("获取剩余库存数量失败:", err, rows, e.OrderCode)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- defer rows.Close()
|
|
|
|
- for rows.Next() {
|
|
|
|
- err = rows.Scan(&count)
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("遍历剩余库存数量失败:", err, rows)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if count <= 0 {
|
|
|
|
- log.Println("库存剩余为0:", countQuery, mold, activeId, now)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- query := fmt.Sprintf("SELECT id,name,code,date_format(ex_end_time,'%%Y-%%m-%%d') as ex_end_time FROM %s where state= 0 and mold=? and active_id=? and ex_end_time>? limit 1 for update;", TableEquityInfo)
|
|
|
|
- data, err := tx.Query(query, mold, activeId, now)
|
|
|
|
- if err != nil || data == nil {
|
|
|
|
- tx.Rollback()
|
|
|
|
- log.Println("获取视频权益码信息失败:", err, data, e.OrderCode)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- eId, name, code, exEndTime := 0, "", "", ""
|
|
|
|
- defer data.Close()
|
|
|
|
- for data.Next() {
|
|
|
|
- err = data.Scan(&eId, &name, &code, &exEndTime)
|
|
|
|
- }
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("获取视频权益码失败:", err, data, e.OrderCode)
|
|
|
|
- tx.Rollback()
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- threshold, b := config.Config.EquityActive.MailAlarm.Threshold[fmt.Sprintf("%v", mold)]
|
|
|
|
- if count < 1 || eId <= 0 {
|
|
|
|
- tx.Rollback()
|
|
|
|
- // 没有库存
|
|
|
|
- if b {
|
|
|
|
- go e.sendAlarmMail(activeName, activeId, threshold.Name, mold, 0)
|
|
|
|
- }
|
|
|
|
|
|
+//// 2. 根据product_info_id 获取对应奖品信息是否有库存
|
|
|
|
+
|
|
|
|
+// 存 lottery_user_account 发消息
|
|
|
|
+func (e *EquityActive) processEquityInfo(activeId, productInfoId int) {
|
|
|
|
+ //判断库存
|
|
|
|
+ q := fmt.Sprintf("SELECT sum(b.inventory) as inventory ,min(a.cycle) as cycle FROM %s a left join %s b on(a.prize_id=b.id) where a.state=0 and b.state=0 and a.product_info_id=? and a.active_id=?;", TableLotteryProductRule, TableLotteryPrizeInfo)
|
|
|
|
+ rs := util.BaseMysql.SelectBySql(q, productInfoId, activeId)
|
|
|
|
+ if rs == nil || len(*rs) == 0 {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- if b && int(count)-1 <= threshold.Value {
|
|
|
|
- // 发库存告警时这减去1是因为这一次消耗一个
|
|
|
|
- go e.sendAlarmMail(activeName, activeId, threshold.Name, mold, int(count)-1)
|
|
|
|
- }
|
|
|
|
- update := fmt.Sprintf("update %s set order_code=?,state=?,update_time=? where id=? ", TableEquityInfo)
|
|
|
|
- _, err = tx.Exec(update, e.OrderCode, valueStateGifted, date.NowFormat(date.Date_Full_Layout), eId)
|
|
|
|
- if err != nil {
|
|
|
|
- tx.Rollback()
|
|
|
|
- log.Println("更新视频权益码失败", e.OrderCode, eId, err)
|
|
|
|
|
|
+ inventory := common.IntAll((*rs)[0]["inventory"])
|
|
|
|
+ if inventory <= 0 { // 判断库存
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- err = tx.Commit()
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("视频权益码commit失败", e.OrderCode, eId, err)
|
|
|
|
- return
|
|
|
|
|
|
+ cycle := common.IntAll((*rs)[0]["cycle"])
|
|
|
|
+ if cycle <= 0 {
|
|
|
|
+ cycle = 90
|
|
}
|
|
}
|
|
- //6. 发送短信、站内信
|
|
|
|
- go e.sendVipMsg(name, code, exEndTime)
|
|
|
|
|
|
+ now := time.Now()
|
|
|
|
+ // 计算过期时间
|
|
|
|
+ expires := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local).AddDate(0, 0, cycle)
|
|
|
|
+ // 存记录
|
|
|
|
+ util.BaseMysql.Insert(TableLotteryUserCount, map[string]interface{}{
|
|
|
|
+ "active_id": activeId,
|
|
|
|
+ "phone": e.Phone,
|
|
|
|
+ "position_id": e.positionId,
|
|
|
|
+ "mgo_user_id": e.mgoId,
|
|
|
|
+ "order_code": e.OrderCode,
|
|
|
|
+ "create_time": date.NowFormat(date.Date_Full_Layout),
|
|
|
|
+ "update_time": date.NowFormat(date.Date_Full_Layout),
|
|
|
|
+ "expires": date.FormatDate(&expires, date.Date_Full_Layout),
|
|
|
|
+ "product_info_id": productInfoId,
|
|
|
|
+ })
|
|
|
|
+ // 站内信
|
|
|
|
+ go e.sendVipMsg(date.FormatDate(&expires, date.Date_Short_Layout))
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
@@ -208,42 +182,11 @@ func (e *EquityActive) setUserID() {
|
|
if phone != "" {
|
|
if phone != "" {
|
|
e.Phone = phone
|
|
e.Phone = phone
|
|
}
|
|
}
|
|
- // 如果没有redis取到说明是代用户下单的订单
|
|
|
|
- // 代用户下单的现在只有个人版的 所以可以直接从订单里面取用户mgoId
|
|
|
|
- // 但是需要再判断业绩归属部门
|
|
|
|
- if e.mgoId == "" && bson.IsObjectIdHex(e.UserId) && e.SaleDep != "" {
|
|
|
|
- if _, ok := config.Config.EquityActive.SaleDep[e.SaleDep]; ok {
|
|
|
|
- e.mgoId = e.UserId
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// 支付后发送抽奖消息 获取用户id
|
|
|
|
-func (e *EquityActive) setUserIDPayRaffle() {
|
|
|
|
- orderKey := fmt.Sprintf("order_%s", e.OrderCode)
|
|
|
|
- rs := redis.Get("other", orderKey)
|
|
|
|
- info := common.ObjToMap(rs)
|
|
|
|
- phone := ""
|
|
|
|
- if info != nil && len(*info) > 0 {
|
|
|
|
- log.Println("PayRaffle 获取到redis保存的用户身份信息:", orderKey, info)
|
|
|
|
- e.mgoId = common.ObjToString((*info)["mgoId"])
|
|
|
|
- e.positionId = common.IntAll((*info)["positionId"])
|
|
|
|
- phone = common.ObjToString((*info)["phone"])
|
|
|
|
- }
|
|
|
|
- if phone != "" {
|
|
|
|
- e.Phone = phone
|
|
|
|
- }
|
|
|
|
- // 如果没有redis取到说明是代用户下单的订单
|
|
|
|
- // 代用户下单的现在只有个人版的 所以可以直接从订单里面取用户mgoId
|
|
|
|
- if e.mgoId == "" && bson.IsObjectIdHex(e.UserId) {
|
|
|
|
- e.mgoId = e.UserId
|
|
|
|
- }
|
|
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
// 发送消息
|
|
// 发送消息
|
|
-func (e *EquityActive) sendVipMsg(eName, code, ex_end_time string) {
|
|
|
|
|
|
+func (e *EquityActive) sendVipMsg(ex_end_time string) {
|
|
// 发送短信
|
|
// 发送短信
|
|
// 04 短信模板:用户{1}您好,购买{2}产品赠送您{3},请前往{4}进行兑换解锁福利。
|
|
// 04 短信模板:用户{1}您好,购买{2}产品赠送您{3},请前往{4}进行兑换解锁福利。
|
|
// 手机号处理
|
|
// 手机号处理
|
|
@@ -272,8 +215,8 @@ func (e *EquityActive) sendVipMsg(eName, code, ex_end_time string) {
|
|
p := util.MessageParam{
|
|
p := util.MessageParam{
|
|
UserIds: e.mgoId,
|
|
UserIds: e.mgoId,
|
|
PositionIds: fmt.Sprintf("%v", e.positionId),
|
|
PositionIds: fmt.Sprintf("%v", e.positionId),
|
|
- Title: fmt.Sprintf(siteMsg.Title, eName),
|
|
|
|
- Content: fmt.Sprintf(siteMsg.Content, e.ProductType, eName, code, ex_end_time, e.ProductType, eName, code),
|
|
|
|
|
|
+ Title: fmt.Sprintf(siteMsg.Title),
|
|
|
|
+ Content: fmt.Sprintf(siteMsg.Content, e.ProductType, ex_end_time, e.ProductType),
|
|
MsgType: siteMsg.MsgType,
|
|
MsgType: siteMsg.MsgType,
|
|
SendMode: 2,
|
|
SendMode: 2,
|
|
Link: siteMsg.Link,
|
|
Link: siteMsg.Link,
|
|
@@ -285,18 +228,6 @@ func (e *EquityActive) sendVipMsg(eName, code, ex_end_time string) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-// 库存告警
|
|
|
|
-func (e *EquityActive) sendAlarmMail(activeName string, activeId int, name string, mold, count int) {
|
|
|
|
- ma := config.Config.EquityActive.MailAlarm
|
|
|
|
- if len(ma.To) == 0 {
|
|
|
|
- log.Println("未配置视频会员权益码活动库存告警邮箱")
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- to := strings.Join(ma.To, ",")
|
|
|
|
- content := fmt.Sprintf("活动:%s(活动id:%d),%s权益(mold:%d)当前库存:%d", activeName, activeId, name, mold, count)
|
|
|
|
- util.SendRetryMailMany(ma.ReTry, to, ma.Title, content, "", "", config.GmailAuth)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
// 判断是否年度会员
|
|
// 判断是否年度会员
|
|
func (e *EquityActive) isYearVip() bool {
|
|
func (e *EquityActive) isYearVip() bool {
|
|
query := fmt.Sprintf("select count(*) from %s where user_id=? and order_status=1 and product_type =? and (timestampdiff(day,vip_starttime,vip_endtime)>=365) order by create_time desc limit 1", TableOrder)
|
|
query := fmt.Sprintf("select count(*) from %s where user_id=? and order_status=1 and product_type =? and (timestampdiff(day,vip_starttime,vip_endtime)>=365) order by create_time desc limit 1", TableOrder)
|