- move Cacher from globals to api

- vendorPromotionID for CreatePromotion
- LockPromotionSkus
This commit is contained in:
gazebo
2018-11-07 13:17:25 +08:00
parent ee9b84bd80
commit 9bb30affc4
12 changed files with 291 additions and 163 deletions

View File

@@ -6,7 +6,7 @@ import (
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api"
) )
const ( const (
@@ -52,7 +52,7 @@ func Login(id, loginType, secret string) (loginInfo *LoginInfo, err error) {
ExpiresIn: time.Now().Add(DefTokenDuration).Unix(), ExpiresIn: time.Now().Add(DefTokenDuration).Unix(),
Token: token, Token: token,
} }
globals.Cacher.Set(token, loginInfo, DefTokenDuration) api.Cacher.Set(token, loginInfo, DefTokenDuration)
return loginInfo, nil return loginInfo, nil
} }
} else { } else {
@@ -63,18 +63,18 @@ func Login(id, loginType, secret string) (loginInfo *LoginInfo, err error) {
func Logout(token string) (err error) { func Logout(token string) (err error) {
loginInfo := new(LoginInfo) loginInfo := new(LoginInfo)
if err = globals.Cacher.GetAs(token, loginInfo); err == nil { if err = api.Cacher.GetAs(token, loginInfo); err == nil {
if handler := authers[loginInfo.LoginType]; handler != nil { if handler := authers[loginInfo.LoginType]; handler != nil {
err = handler.Logout(loginInfo.ID) err = handler.Logout(loginInfo.ID)
} }
globals.Cacher.Del(token) api.Cacher.Del(token)
} }
return err return err
} }
func GetUserInfo(token string) (loginInfo *LoginInfo, err error) { func GetUserInfo(token string) (loginInfo *LoginInfo, err error) {
loginInfo = new(LoginInfo) loginInfo = new(LoginInfo)
if err = globals.Cacher.GetAs(token, loginInfo); err == nil { if err = api.Cacher.GetAs(token, loginInfo); err == nil {
return loginInfo, nil return loginInfo, nil
} }
return nil, model.ErrTokenIsInvalid return nil, model.ErrTokenIsInvalid

View File

@@ -7,6 +7,7 @@ import (
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/KenmyZhang/aliyun-communicate" "github.com/KenmyZhang/aliyun-communicate"
) )
@@ -23,7 +24,7 @@ func SendVerifyCode(mobileNumber string) error {
"code": code, "code": code,
}))) })))
if err == nil { if err == nil {
globals.Cacher.Set(mobileNumber, code, DefVerifyCodeDuration) api.Cacher.Set(mobileNumber, code, DefVerifyCodeDuration)
} else { } else {
globals.SugarLogger.Infof("SendVerifyCode mobileNumber:%s failed with error:%v", mobileNumber, err) globals.SugarLogger.Infof("SendVerifyCode mobileNumber:%s failed with error:%v", mobileNumber, err)
} }
@@ -33,9 +34,9 @@ func SendVerifyCode(mobileNumber string) error {
func VerifyCode(mobileNumber, code string) bool { func VerifyCode(mobileNumber, code string) bool {
globals.SugarLogger.Debugf("VerifyCode mobileNumber:%s, code:%s", mobileNumber, code) globals.SugarLogger.Debugf("VerifyCode mobileNumber:%s, code:%s", mobileNumber, code)
if value := globals.Cacher.Get(mobileNumber); value != nil { if value := api.Cacher.Get(mobileNumber); value != nil {
if code == value.(string) { if code == value.(string) {
globals.Cacher.Del(mobileNumber) api.Cacher.Del(mobileNumber)
return true return true
} }
} }

View File

@@ -54,7 +54,7 @@ func GetUserInfo(code string, state string) (token *UserInfoExt, err error) {
if err = err2; err == nil { if err = err2; err == nil {
pwd := utils.GetUUID() pwd := utils.GetUUID()
globals.SugarLogger.Debugf("GetUserInfo code:%s, pwd:%s", code, pwd) globals.SugarLogger.Debugf("GetUserInfo code:%s, pwd:%s", code, pwd)
globals.Cacher.Set(wxUserinfo.OpenID, pwd, DefTempPasswordDuration) api.Cacher.Set(wxUserinfo.OpenID, pwd, DefTempPasswordDuration)
return &UserInfoExt{ return &UserInfoExt{
UserInfo: *wxUserinfo, UserInfo: *wxUserinfo,
TempPassword: pwd, TempPassword: pwd,
@@ -70,13 +70,13 @@ func GetUserInfo(code string, state string) (token *UserInfoExt, err error) {
func (a *Auther) Login(openid, password string) (err error) { func (a *Auther) Login(openid, password string) (err error) {
globals.SugarLogger.Debugf("Login openid:%s, password:%s", openid, password) globals.SugarLogger.Debugf("Login openid:%s, password:%s", openid, password)
if value := globals.Cacher.Get(openid); value != nil { if value := api.Cacher.Get(openid); value != nil {
if password == value.(string) { if password == value.(string) {
// wxUser := &legacymodel.WeiXins{ // wxUser := &legacymodel.WeiXins{
// OpenID: openid, // OpenID: openid,
// } // }
// if err = dao.GetEntity(nil, wxUser, "OpenID"); err == nil { // if err = dao.GetEntity(nil, wxUser, "OpenID"); err == nil {
globals.Cacher.Del(openid) api.Cacher.Del(openid)
return nil return nil
// } // }
} }
@@ -87,14 +87,14 @@ func (a *Auther) Login(openid, password string) (err error) {
} }
func (a *Auther) Logout(openid string) error { func (a *Auther) Logout(openid string) error {
return globals.Cacher.Del(openid) return api.Cacher.Del(openid)
} }
func BindMobile(token, mobileNum, code, nickname string) (err error) { func BindMobile(token, mobileNum, code, nickname string) (err error) {
globals.SugarLogger.Debugf("BindMobile mobileNum:%s, code:%s, nickname:%s", mobileNum, code, nickname) globals.SugarLogger.Debugf("BindMobile mobileNum:%s, code:%s, nickname:%s", mobileNum, code, nickname)
loginInfo := new(auth.LoginInfo) loginInfo := new(auth.LoginInfo)
if err = globals.Cacher.GetAs(token, loginInfo); err == nil { if err = api.Cacher.GetAs(token, loginInfo); err == nil {
if mobile.VerifyCode(mobileNum, code) { if mobile.VerifyCode(mobileNum, code) {
user := &legacymodel.WeiXins{ user := &legacymodel.WeiXins{
OpenID: loginInfo.ID, OpenID: loginInfo.ID,

View File

@@ -197,90 +197,93 @@ func Init() {
scheduleRoutine() scheduleRoutine()
} }
func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueWhenError bool, params *PromotionParams, userName string) (hint string, err error) { func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueWhenError bool, vendorPromotionID string, params *PromotionParams, userName string) (hint string, err error) {
if len(params.SkuPrices) == 0 { if len(params.SkuPrices) == 0 {
return "", ErrEmptySkus return "", ErrEmptySkus
} }
db := dao.GetDB() db := dao.GetDB()
skuIDs := make([]int, len(params.SkuPrices)) modifyPricesList := make(map[int][]*jdapi.SkuPriceInfo)
skuPriceMap := make(map[int64]*SkuPrice) promotionPrices := make([]map[string]interface{}, len(params.StoreIDs)*len(params.SkuPrices))
for k, v := range params.SkuPrices { var jxStoreIDs []int
skuIDs[k] = v.SkuID
skuPriceMap[int64(v.SkuID)] = v if vendorPromotionID == "" {
} skuIDs := make([]int, len(params.SkuPrices))
sql := "" skuPriceMap := make(map[int64]*SkuPrice)
var sqlParam []interface{} for k, v := range params.SkuPrices {
if isIDJd { skuIDs[k] = v.SkuID
sql = ` skuPriceMap[int64(v.SkuID)] = v
}
sql := ""
var sqlParam []interface{}
if isIDJd {
sql = `
SELECT t1.*, t2.jd_id SELECT t1.*, t2.jd_id
FROM store_sku_bind t1 FROM store_sku_bind t1
JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ?
JOIN store_map t3 ON t1.store_id = t3.store_id AND t3.vendor_id = ? AND t3.deleted_at = ? JOIN store_map t3 ON t1.store_id = t3.store_id AND t3.vendor_id = ? AND t3.deleted_at = ?
WHERE t1.jd_sync_status = 0 AND t1.deleted_at = ? AND t2.jd_id IN ( WHERE t1.jd_sync_status = 0 AND t1.deleted_at = ? AND t2.jd_id IN (
` + dao.GenQuestionMarks(len(skuIDs)) + ") AND t3.vendor_store_id = ?" ` + dao.GenQuestionMarks(len(skuIDs)) + ") AND t3.vendor_store_id = ?"
sqlParam = append(sqlParam, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue) sqlParam = append(sqlParam, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue)
} else { } else {
sql = ` sql = `
SELECT t1.*, 0 jd_id SELECT t1.*, 0 jd_id
FROM store_sku_bind t1 FROM store_sku_bind t1
WHERE t1.jd_sync_status = 0 AND t1.deleted_at = ? AND t1.sku_id IN ( WHERE t1.jd_sync_status = 0 AND t1.deleted_at = ? AND t1.sku_id IN (
` + dao.GenQuestionMarks(len(skuIDs)) + ") AND t1.store_id = ?" ` + dao.GenQuestionMarks(len(skuIDs)) + ") AND t1.store_id = ?"
} }
sqlParam = append(sqlParam, utils.DefaultTimeValue, skuIDs) sqlParam = append(sqlParam, utils.DefaultTimeValue, skuIDs)
errMsg := "" errMsg := ""
modifyPricesList := make(map[int][]*jdapi.SkuPriceInfo) index := 0
promotionPrices := make([]map[string]interface{}, len(params.StoreIDs)*len(params.SkuPrices)) for _, storeID := range params.StoreIDs {
index := 0 var skuBinds []*tStoreSkuBindExt
var jxStoreIDs []int if err = dao.GetRows(db, &skuBinds, sql, append(sqlParam, storeID)...); err != nil {
for _, storeID := range params.StoreIDs { return "", err
var skuBinds []*tStoreSkuBindExt
if err = dao.GetRows(db, &skuBinds, sql, append(sqlParam, storeID)...); err != nil {
return "", err
}
for k, skuBind := range skuBinds {
if k == 0 {
jxStoreIDs = append(jxStoreIDs, skuBind.StoreID)
} }
mapSkuID := int64(skuBind.SkuID) for k, skuBind := range skuBinds {
if isIDJd { if k == 0 {
mapSkuID = skuBind.JdID jxStoreIDs = append(jxStoreIDs, skuBind.StoreID)
} }
promotionSkuPrice := skuPriceMap[mapSkuID] mapSkuID := int64(skuBind.SkuID)
if promotionSkuPrice.PriceType == PriceTypePercentage { if isIDJd {
promotionSkuPrice.Price = skuBind.Price * promotionSkuPrice.Price / 100 mapSkuID = skuBind.JdID
} }
if promotionSkuPrice.Price >= skuBind.Price { promotionSkuPrice := skuPriceMap[mapSkuID]
errMsg += fmt.Sprintf("促销价大于等于原价storeID:%d, skuID:%d\n", skuBind.StoreID, skuBind.SkuID) if promotionSkuPrice.PriceType == PriceTypePercentage {
} promotionSkuPrice.Price = skuBind.Price * promotionSkuPrice.Price / 100
if promotionSkuPrice.LimitSkuCount <= 0 { }
promotionSkuPrice.LimitSkuCount = DefaultLimitSkuCount if promotionSkuPrice.Price >= skuBind.Price {
} errMsg += fmt.Sprintf("促销价大于等于原价storeID:%d, skuID:%d\n", skuBind.StoreID, skuBind.SkuID)
if errMsg == "" { }
if params.Type == PromotionTypeLimitedTime { if promotionSkuPrice.LimitSkuCount <= 0 {
if skuBind.Price*PromotionLimitedTimeMinPercentage/100 < promotionSkuPrice.Price { promotionSkuPrice.LimitSkuCount = DefaultLimitSkuCount
modifyPricesList[skuBind.StoreID] = append(modifyPricesList[skuBind.StoreID], &jdapi.SkuPriceInfo{ }
OutSkuId: utils.Int2Str(skuBind.SkuID), if errMsg == "" {
Price: promotionSkuPrice.Price*100/PromotionLimitedTimeMinPercentage + 5, if params.Type == PromotionTypeLimitedTime {
}) if skuBind.Price*PromotionLimitedTimeMinPercentage/100 < promotionSkuPrice.Price {
modifyPricesList[skuBind.StoreID] = append(modifyPricesList[skuBind.StoreID], &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(skuBind.SkuID),
Price: promotionSkuPrice.Price*100/PromotionLimitedTimeMinPercentage + 5,
})
}
} }
promotionPrices[index] = map[string]interface{}{
jdapi.KeyOutStationNo: utils.Int2Str(skuBind.StoreID),
jdapi.KeyOutSkuId: utils.Int2Str(skuBind.SkuID),
jdapi.KeyPromotionPrice: promotionSkuPrice.Price,
jdapi.KeyLimitSkuCount: promotionSkuPrice.LimitSkuCount,
}
index++
} }
promotionPrices[index] = map[string]interface{}{
jdapi.KeyOutStationNo: utils.Int2Str(skuBind.StoreID),
jdapi.KeyOutSkuId: utils.Int2Str(skuBind.SkuID),
jdapi.KeyPromotionPrice: promotionSkuPrice.Price,
jdapi.KeyLimitSkuCount: promotionSkuPrice.LimitSkuCount,
}
index++
} }
} }
} if errMsg != "" {
if errMsg != "" { return "", errors.New(errMsg)
return "", errors.New(errMsg) }
} promotionPrices = promotionPrices[:index]
promotionPrices = promotionPrices[:index] if len(promotionPrices) == 0 {
if len(promotionPrices) == 0 { return "", ErrEmptySkus
return "", ErrEmptySkus }
} }
promotion := &model.Promotion{ promotion := &model.Promotion{
@@ -292,6 +295,9 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
BeginAt: params.BeginAt, BeginAt: params.BeginAt,
EndAt: params.EndAt, EndAt: params.EndAt,
} }
if vendorPromotionID != "" {
promotion.VendorPromotionID = vendorPromotionID
}
dao.WrapAddIDCULDEntity(promotion, userName) dao.WrapAddIDCULDEntity(promotion, userName)
// if promotion.Params, err = jxutils.SerializeData(params); err != nil { // if promotion.Params, err = jxutils.SerializeData(params); err != nil {
// return "", err // return "", err
@@ -331,78 +337,83 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
} }
} }
promotionHandler := getPromotionHander(params.Type) if vendorPromotionID == "" {
if promotionHandler == nil { promotionHandler := getPromotionHander(params.Type)
return "", errors.New("非法的促销类型") if promotionHandler == nil {
} return "", errors.New("非法的促销类型")
infoId, err2 := promotionHandler.CreatePromotionInfos(params.Name, params.BeginAt, params.EndAt, utils.Int2Str(promotion.ID), params.Advertising) }
if err = err2; err != nil { infoId, err2 := promotionHandler.CreatePromotionInfos(params.Name, params.BeginAt, params.EndAt, utils.Int2Str(promotion.ID), params.Advertising)
return "", err if err = err2; err != nil {
} return "", err
promotion.VendorPromotionID = utils.Int64ToStr(infoId) }
if _, err = dao.UpdateEntity(db, promotion); err != nil { promotion.VendorPromotionID = utils.Int64ToStr(infoId)
return "", err if _, err = dao.UpdateEntity(db, promotion); err != nil {
} return "", err
dao.Commit(db) }
dao.Commit(db)
rootTask := tasksch.NewSeqTask("CreateJdPromotion", userName, func(task *tasksch.SeqTask, step int, params2 ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("CreateJdPromotion", userName, func(task *tasksch.SeqTask, step int, params2 ...interface{}) (result interface{}, err error) {
if step == 0 { if step == 0 {
task1 := tasksch.NewParallelTask("CreateJdPromotion update sku price", nil, userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) { task1 := tasksch.NewParallelTask("CreateJdPromotion update sku price", nil, userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) {
storeID := batchItemList[0].(int) storeID := batchItemList[0].(int)
modifyPricesList := jxutils.SplitSlice(modifyPricesList[storeID], jdapi.MaxStoreSkuBatchSize) modifyPricesList := jxutils.SplitSlice(modifyPricesList[storeID], jdapi.MaxStoreSkuBatchSize)
for _, modifyPrices := range modifyPricesList { for _, modifyPrices := range modifyPricesList {
modifyPrices2 := make([]*jdapi.SkuPriceInfo, len(modifyPrices)) modifyPrices2 := make([]*jdapi.SkuPriceInfo, len(modifyPrices))
for k, v := range modifyPrices { for k, v := range modifyPrices {
modifyPrices2[k] = v.(*jdapi.SkuPriceInfo) modifyPrices2[k] = v.(*jdapi.SkuPriceInfo)
} }
if globals.EnableStoreWrite { if globals.EnableStoreWrite {
if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil { if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil {
return nil, err return nil, err
}
} }
} }
return nil, nil
}, jxStoreIDs)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
} else if step == 1 {
err = promotionHandler.CreatePromotionRules(infoId, "", 1, 1, 1, 1)
} else if step == 2 {
task2 := tasksch.NewParallelTask("CreateJdPromotion CreatePromotionSku", tasksch.NewParallelConfig().SetBatchSize(MaxPromotionSkuCount).SetIsContinueWhenError(isContinueWhenError), userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) {
skus := make([]map[string]interface{}, len(batchItemList))
for k, v := range batchItemList {
skus[k] = v.(map[string]interface{})
}
_, err = promotionHandler.CreatePromotionSku(infoId, "", skus)
return nil, err
}, promotionPrices)
task.AddChild(task2).Run()
_, err = task2.GetResult(0)
if isContinueWhenError && err != nil { // todo isContinueWhenError为true时强制忽略此步的错误
err = nil
} }
return nil, nil } else if step == 3 {
}, jxStoreIDs) err = promotionHandler.ConfirmPromotion(infoId, "")
task.AddChild(task1).Run() if err == nil {
_, err = task1.GetResult(0) promotion.Status = model.PromotionStatusRemoteCreated
} else if step == 1 { } else {
err = promotionHandler.CreatePromotionRules(infoId, "", 1, 1, 1, 1) promotion.Status = model.PromotionStatusRemoteFailed
} else if step == 2 { }
task2 := tasksch.NewParallelTask("CreateJdPromotion CreatePromotionSku", tasksch.NewParallelConfig().SetBatchSize(MaxPromotionSkuCount).SetIsContinueWhenError(isContinueWhenError), userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) { db := dao.GetDB()
skus := make([]map[string]interface{}, len(batchItemList)) if _, err = dao.UpdateEntityLogically(db, promotion, map[string]interface{}{
for k, v := range batchItemList { "Status": promotion.Status,
skus[k] = v.(map[string]interface{}) }, ctx.GetUserName(), nil); err == nil {
RefreshJdPromotionLockStatus(promotion.ID)
} }
_, err = promotionHandler.CreatePromotionSku(infoId, "", skus)
return nil, err
}, promotionPrices)
task.AddChild(task2).Run()
_, err = task2.GetResult(0)
if isContinueWhenError && err != nil { // todo isContinueWhenError为true时强制忽略此步的错误
err = nil
}
} else if step == 3 {
err = promotionHandler.ConfirmPromotion(infoId, "")
if err == nil {
promotion.Status = model.PromotionStatusRemoteCreated
} else {
promotion.Status = model.PromotionStatusRemoteFailed
}
db := dao.GetDB()
if _, err = dao.UpdateEntityLogically(db, promotion, map[string]interface{}{
"Status": promotion.Status,
}, ctx.GetUserName(), nil); err == nil {
RefreshJdPromotionLockStatus(promotion.ID)
} }
return nil, err
}, 4)
ctx.SetTaskOrAddChild(rootTask, nil)
tasksch.ManageTask(rootTask).Run()
if !isAsync {
_, err = rootTask.GetResult(0)
} }
return nil, err hint = rootTask.ID
}, 4) } else {
ctx.SetTaskOrAddChild(rootTask, nil) dao.Commit(db)
tasksch.ManageTask(rootTask).Run()
if !isAsync {
_, err = rootTask.GetResult(0)
} }
return rootTask.ID, err return hint, err
} }
// func CreatePromotionByExcel(ctx *jxcontext.Context, isAsync bool, promotionType int, fileHeader *multipart.FileHeader, userName string) (hint string, err error) { // func CreatePromotionByExcel(ctx *jxcontext.Context, isAsync bool, promotionType int, fileHeader *multipart.FileHeader, userName string) (hint string, err error) {
@@ -506,7 +517,7 @@ func GetJdPromotions(ctx *jxcontext.Context, keyword string, params map[string]i
} }
if params["vendorPromotionID"] != nil { if params["vendorPromotionID"] != nil {
sql += " AND t1.vendor_promotion_id = ?" sql += " AND t1.vendor_promotion_id = ?"
sqlParams = append(sqlParams, params["vendorPromotionID"].(int)) sqlParams = append(sqlParams, params["vendorPromotionID"].(string))
} }
if params["name"] != nil { if params["name"] != nil {
sql += " AND t1.name LIKE ?" sql += " AND t1.name LIKE ?"
@@ -651,6 +662,7 @@ func RefreshJdLockStoreSku() (err error) {
} }
return err return err
} }
storeskulock.ClearJdStoreSkuLock()
return RefreshJdPromotionItemListLockStatus(promotionItemList) return RefreshJdPromotionItemListLockStatus(promotionItemList)
} }
@@ -784,6 +796,33 @@ func RefreshJdPromotionLockStatus(promotionID int) (err error) {
return RefreshJdPromotionItemListLockStatus(promotionItemList) return RefreshJdPromotionItemListLockStatus(promotionItemList)
} }
func LockPromotionSkus(ctx *jxcontext.Context, promotionID int, isLock bool, skuIDs []int) (num int64, err error) {
sql := `
UPDATE promotion_sku t1
SET t1.is_lock = ?
WHERE t1.promotion_id = ?
`
intIsLock := 0
if isLock {
intIsLock = 1
}
sqlParams := []interface{}{
intIsLock,
promotionID,
}
if len(skuIDs) > 0 {
sql += " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuIDs)
}
db := dao.GetDB()
num, err = dao.ExecuteSQL(db, sql, sqlParams...)
if err == nil {
RefreshJdPromotionLockStatus(promotionID)
RefreshJdStoreSkuStock()
}
return num, err
}
func OnStoreStockMsg(msg *jdapi.CallbackStoreStockMsg) (retVal *jdapi.CallbackResponse) { func OnStoreStockMsg(msg *jdapi.CallbackStoreStockMsg) (retVal *jdapi.CallbackResponse) {
var err error var err error
globals.SugarLogger.Debugf("OnStoreStockMsg msg:%s", utils.Format4Output(msg, false)) globals.SugarLogger.Debugf("OnStoreStockMsg msg:%s", utils.Format4Output(msg, false))

View File

@@ -5,9 +5,10 @@ import (
) )
type ICacher interface { type ICacher interface {
FlushAll() error FlushKeys(prefix string) error
Set(key string, value interface{}, expiration time.Duration) error Set(key string, value interface{}, expiration time.Duration) error
Del(key string) error Del(key string) error
Get(key string) interface{} Get(key string) interface{}
GetAs(key string, ptr interface{}) error GetAs(key string, ptr interface{}) error
Keys(prefix string) ([]string, error)
} }

View File

@@ -25,8 +25,19 @@ func New(host string, port int, password string) *Cacher {
} }
} }
func (c *Cacher) FlushAll() error { func (c *Cacher) FlushKeys(prefix string) (err error) {
return c.client.FlushAll().Err() if prefix == "" {
return c.client.FlushAll().Err()
}
keys, err := c.Keys(prefix)
if err == nil {
for _, key := range keys {
if err = c.Del(key); err != nil {
break
}
}
}
return err
} }
func (c *Cacher) Set(key string, value interface{}, expiration time.Duration) error { func (c *Cacher) Set(key string, value interface{}, expiration time.Duration) error {
@@ -58,3 +69,7 @@ func (c *Cacher) GetAs(key string, ptr interface{}) error {
} }
return err return err
} }
func (c *Cacher) Keys(prefix string) ([]string, error) {
return c.client.Keys(prefix + "*").Result()
}

View File

@@ -3,12 +3,16 @@ package redis
import ( import (
"testing" "testing"
"git.rosy.net.cn/jx-callback/business/jxutils/cache"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/jx-callback/globals/beegodb" "git.rosy.net.cn/jx-callback/globals/beegodb"
"github.com/astaxie/beego" "github.com/astaxie/beego"
) )
var (
cacher cache.ICacher
)
func init() { func init() {
//E:/goprojects/src/git.rosy.net.cn/jx-callback/conf/app.conf //E:/goprojects/src/git.rosy.net.cn/jx-callback/conf/app.conf
///Users/xujianhua/go/src/git.rosy.net.cn/jx-callback/conf/app.conf ///Users/xujianhua/go/src/git.rosy.net.cn/jx-callback/conf/app.conf
@@ -17,7 +21,9 @@ func init() {
globals.Init() globals.Init()
beegodb.Init() beegodb.Init()
api.Init() // api.Init()
cacher = New("localhost", 6379, "")
} }
type FuckYou struct { type FuckYou struct {
@@ -25,8 +31,7 @@ type FuckYou struct {
} }
func TestIt(t *testing.T) { func TestIt(t *testing.T) {
cacher := New("localhost", 6379, "") cacher.FlushKeys("")
cacher.FlushAll()
if cacher.Get("key") != nil { if cacher.Get("key") != nil {
t.Fatal("should get nothing") t.Fatal("should get nothing")
} }
@@ -46,3 +51,35 @@ func TestIt(t *testing.T) {
t.Fatal("should get value") t.Fatal("should get value")
} }
} }
func TestKeys(t *testing.T) {
cacher.FlushKeys("")
keys, err := cacher.Keys("")
if err != nil {
t.Fatal(err)
}
if len(keys) != 0 {
t.Fatal("keys should be empty here")
}
cacher.Set("key1", 1, 0)
cacher.Set("key2", 2, 0)
cacher.Set("key22", 3, 0)
cacher.Set("key23", 4, 0)
cacher.Set("key24", 5, 0)
keys, err = cacher.Keys("")
if len(keys) != 5 {
t.Fatal("keys should be 5 here")
}
keys, err = cacher.Keys("key")
if len(keys) != 5 {
t.Fatal("keys should be 5 here")
}
keys, err = cacher.Keys("key2")
if len(keys) != 4 {
t.Fatal("keys should be 4 here")
}
keys, err = cacher.Keys("key22")
if len(keys) != 1 {
t.Fatal("keys should be 1 here")
}
}

View File

@@ -5,6 +5,7 @@ import (
"time" "time"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
) )
const ( const (
@@ -15,16 +16,20 @@ func LockJdStoreSku(jdStoreID string, jdSkuID int64, expire time.Time) {
globals.SugarLogger.Debug(expire, " ", time.Now()) globals.SugarLogger.Debug(expire, " ", time.Now())
duration := expire.Sub(time.Now()) duration := expire.Sub(time.Now())
if duration > 0 { if duration > 0 {
globals.Cacher.Set(genCacheKey(jdStoreID, jdSkuID), 1, duration) api.Cacher.Set(genCacheKey(jdStoreID, jdSkuID), 1, duration)
} }
} }
func UnlockJdStoreSku(jdStoreID string, jdSkuID int64) { func UnlockJdStoreSku(jdStoreID string, jdSkuID int64) {
globals.Cacher.Del(genCacheKey(jdStoreID, jdSkuID)) api.Cacher.Del(genCacheKey(jdStoreID, jdSkuID))
} }
func IsJdStoreSkuLocked(jdStoreID string, jdSkuID int64) bool { func IsJdStoreSkuLocked(jdStoreID string, jdSkuID int64) bool {
return globals.Cacher.Get(genCacheKey(jdStoreID, jdSkuID)) != nil return api.Cacher.Get(genCacheKey(jdStoreID, jdSkuID)) != nil
}
func ClearJdStoreSkuLock() {
api.Cacher.FlushKeys(cacheKeyPrefix)
} }
func genCacheKey(jdStoreID string, jdSkuID int64) string { func genCacheKey(jdStoreID string, jdSkuID int64) string {

View File

@@ -27,6 +27,7 @@ type PromotionController struct {
// @Param isAsync formData bool false "是否异步,缺省否(暂时只支持同步)" // @Param isAsync formData bool false "是否异步,缺省否(暂时只支持同步)"
// @Param isContinueWhenError formData bool false "单个同步失败是否继续缺省false" // @Param isContinueWhenError formData bool false "单个同步失败是否继续缺省false"
// @Param advertising formData string false "广告语" // @Param advertising formData string false "广告语"
// @Param vendorPromotionID formData string false "厂商活动id设置此字段表示关联京东活动并不会真正去创建"
// @Success 200 {object} controllers.CallResult // @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult
// @router /CreatePromotion [post] // @router /CreatePromotion [post]
@@ -52,7 +53,7 @@ func (c *PromotionController) CreatePromotion() {
} }
if err = utils.UnmarshalUseNumber([]byte(params.StoreIDs), &promotionParams.StoreIDs); err == nil { if err = utils.UnmarshalUseNumber([]byte(params.StoreIDs), &promotionParams.StoreIDs); err == nil {
if err = utils.UnmarshalUseNumber([]byte(params.SkuPrices), &promotionParams.SkuPrices); err == nil { if err = utils.UnmarshalUseNumber([]byte(params.SkuPrices), &promotionParams.SkuPrices); err == nil {
retVal, err = promotion.CreateJdPromotion(params.Ctx, false, params.IsAsync, params.IsContinueWhenError, promotionParams, params.Ctx.GetUserName()) retVal, err = promotion.CreateJdPromotion(params.Ctx, false, params.IsAsync, params.IsContinueWhenError, params.VendorPromotionID, promotionParams, params.Ctx.GetUserName())
} }
} }
return retVal, "", err return retVal, "", err
@@ -115,7 +116,7 @@ func (c *PromotionController) SendAdvertingByGoodsOrder() {
// @Param keyword query string false "关键字" // @Param keyword query string false "关键字"
// @Param vendorID query int false "厂商ID当前只支持京东0 " // @Param vendorID query int false "厂商ID当前只支持京东0 "
// @Param promotionID query int false "活动id" // @Param promotionID query int false "活动id"
// @Param vendorPromotionID query int false "厂商活动id" // @Param vendorPromotionID query string false "厂商活动id"
// @Param days query int false "多少天内创建的缺省7天" // @Param days query int false "多少天内创建的缺省7天"
// @Param name query string false "促销名,不完全匹配" // @Param name query string false "促销名,不完全匹配"
// @Param beginAt query string false "开始日期,包括" // @Param beginAt query string false "开始日期,包括"
@@ -135,10 +136,10 @@ func (c *PromotionController) GetPromotions() {
}) })
} }
// @Title 查询促销 // @Title 取消促销
// @Description 查询促销 // @Description 取消促销
// @Param token header string true "认证token" // @Param token header string true "认证token"
// @Param promotionID query int true "活动id" // @Param promotionID formData int true "活动id"
// @Success 200 {object} controllers.CallResult // @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult
// @router /CancelPromotion [put] // @router /CancelPromotion [put]
@@ -148,3 +149,25 @@ func (c *PromotionController) CancelPromotion() {
return retVal, "", err return retVal, "", err
}) })
} }
// @Title 锁定解锁活动SKU
// @Description 锁定解锁活动SKU
// @Param token header string true "认证token"
// @Param promotionID formData int true "活动id"
// @Param isLock formData bool true "活动id"
// @Param skuIDs formData string false "缺省全部"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /LockPromotionSkus [put]
func (c *PromotionController) LockPromotionSkus() {
c.callLockPromotionSkus(func(params *tPromotionLockPromotionSkusParams) (retVal interface{}, errCode string, err error) {
var skuIDs []int
if params.SkuIDs != "" {
if err = utils.UnmarshalUseNumber([]byte(params.SkuIDs), &skuIDs); err != nil {
return retVal, "", err
}
}
retVal, err = promotion.LockPromotionSkus(params.Ctx, params.PromotionID, params.IsLock, skuIDs)
return retVal, "", err
})
}

View File

@@ -9,6 +9,8 @@ import (
"git.rosy.net.cn/baseapi/platformapi/mtpsapi" "git.rosy.net.cn/baseapi/platformapi/mtpsapi"
"git.rosy.net.cn/baseapi/platformapi/weixinapi" "git.rosy.net.cn/baseapi/platformapi/weixinapi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/cache"
"git.rosy.net.cn/jx-callback/business/jxutils/cache/redis"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
@@ -24,6 +26,8 @@ var (
WeixinAPI *weixinapi.API WeixinAPI *weixinapi.API
AutonaviAPI *autonavi.API AutonaviAPI *autonavi.API
QiniuAPI *qbox.Mac QiniuAPI *qbox.Mac
Cacher cache.ICacher
) )
func Init() { func Init() {
@@ -47,6 +51,7 @@ func Init() {
if !beego.AppConfig.DefaultBool("disableEbai", false) { if !beego.AppConfig.DefaultBool("disableEbai", false) {
EbaiAPI = ebaiapi.New(beego.AppConfig.String("ebaiSource"), beego.AppConfig.String("ebaiSecret")) EbaiAPI = ebaiapi.New(beego.AppConfig.String("ebaiSource"), beego.AppConfig.String("ebaiSecret"))
} }
Cacher = redis.New(beego.AppConfig.DefaultString("redisHost", "localhost"), beego.AppConfig.DefaultInt("redisPort", 0), beego.AppConfig.DefaultString("redisPassword", ""))
} }
func initElm() { func initElm() {

View File

@@ -2,8 +2,6 @@ package globals
import ( import (
"git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi"
"git.rosy.net.cn/jx-callback/business/jxutils/cache"
"git.rosy.net.cn/jx-callback/business/jxutils/cache/redis"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/astaxie/beego/logs" "github.com/astaxie/beego/logs"
_ "github.com/go-sql-driver/mysql" // import your used driver _ "github.com/go-sql-driver/mysql" // import your used driver
@@ -22,8 +20,6 @@ var (
SugarLogger *zap.SugaredLogger SugarLogger *zap.SugaredLogger
Cacher cache.ICacher
AliKey string AliKey string
AliSecret string AliSecret string
@@ -51,8 +47,6 @@ func Init() {
ReallySendWeixinMsg = beego.BConfig.RunMode == "prod" ReallySendWeixinMsg = beego.BConfig.RunMode == "prod"
ReallyCallPlatformAPI = true ReallyCallPlatformAPI = true
Cacher = redis.New(beego.AppConfig.DefaultString("redisHost", "localhost"), beego.AppConfig.DefaultInt("redisPort", 0), beego.AppConfig.DefaultString("redisPassword", ""))
AliKey = beego.AppConfig.DefaultString("aliKey", "") AliKey = beego.AppConfig.DefaultString("aliKey", "")
AliSecret = beego.AppConfig.DefaultString("aliSecret", "") AliSecret = beego.AppConfig.DefaultString("aliSecret", "")

View File

@@ -239,6 +239,14 @@ func init() {
MethodParams: param.Make(), MethodParams: param.Make(),
Params: nil}) Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"],
beego.ControllerComments{
Method: "LockPromotionSkus",
Router: `/LockPromotionSkus`,
AllowHTTPMethods: []string{"put"},
MethodParams: param.Make(),
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"], beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PromotionController"],
beego.ControllerComments{ beego.ControllerComments{
Method: "SendAdvertingByGoodsOrder", Method: "SendAdvertingByGoodsOrder",