Files
jx-callback/business/jxstore/promotion/jd_promotion.go
2018-10-13 20:28:20 +08:00

237 lines
8.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package promotion
import (
"encoding/gob"
"errors"
"fmt"
"time"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals/api"
)
const (
PromotionTypeNormal = 1
PromotionTypeDirectDown = 3
PromotionTypeLimitedTime = 4
)
const (
PriceTypePrice = 1 // 绝对价格
PriceTypePercentage = 2 // 百分比
)
const (
PromotionLimitedTimeMinPercentage = 80
)
const (
PromotionStatusCreated = 1
PromotionStatusEnded = 2
)
type SkuPrice struct {
SkuID int `json:"skuID"`
PriceType int `json:"priceType"`
Price int `json:"price"` // 分,这个不是单价
}
type PromotionParams struct {
Name string
Advertising string
Type int
BeginAt time.Time
EndAt time.Time
StoreIDs []int
SkuPrices []*SkuPrice
}
var (
ErrEmptySkus = errors.New("空sku")
)
type JdPromotionHandler interface {
CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error)
CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error)
CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error)
ConfirmPromotion(infoId int64, outInfoId string) (err error)
}
type JdDirectDownHandler struct {
}
func (p *JdDirectDownHandler) CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
return api.JdAPI.CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising)
}
func (p *JdDirectDownHandler) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
return api.JdAPI.CreatePromotionRules(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily)
}
func (p *JdDirectDownHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
return api.JdAPI.CreatePromotionSkuSingle(infoId, outInfoId, skus)
}
func (p *JdDirectDownHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.ConfirmPromotionSingle(infoId, outInfoId)
}
type JdLimitedTimeHandler struct {
}
func (p *JdLimitedTimeHandler) CreatePromotionInfos(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
return api.JdAPI.CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising)
}
func (p *JdLimitedTimeHandler) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
return api.JdAPI.CreatePromotionRules(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily)
}
func (p *JdLimitedTimeHandler) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
return api.JdAPI.CreatePromotionSkuLimitTime(infoId, outInfoId, skus)
}
func (p *JdLimitedTimeHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.ConfirmPromotionLimitTime(infoId, outInfoId)
}
func init() {
gob.Register(&PromotionParams{})
gob.Register([]*SkuPrice{})
}
func CreateJdPromotion(isAsync bool, params *PromotionParams, userName string) (hint string, err error) {
if len(params.SkuPrices) == 0 {
return "", ErrEmptySkus
}
db := dao.GetDB()
skuIDs := make([]int, len(params.SkuPrices))
skuPriceMap := make(map[int]*SkuPrice)
for k, v := range params.SkuPrices {
skuIDs[k] = v.SkuID
skuPriceMap[v.SkuID] = v
}
sql := `
SELECT t1.*
FROM store_sku_bind t1
WHERE t1.jd_sync_status = 0 AND t1.deleted_at = ? AND t1.store_id = ? AND t1.sku_id IN (
` + dao.GenQuestionMarks(len(skuIDs)) + ")"
errMsg := ""
modifyPricesList := make(map[int][]*jdapi.SkuPriceInfo)
promotionPrices := make([]map[string]interface{}, len(params.StoreIDs)*len(params.SkuPrices))
index := 0
for _, storeID := range params.StoreIDs {
var skuBinds []*model.StoreSkuBind
if err = dao.GetRows(db, &skuBinds, sql, utils.DefaultTimeValue, storeID, skuIDs); err != nil {
return "", err
}
for _, skuBind := range skuBinds {
promotionSkuPrice := skuPriceMap[skuBind.SkuID]
if promotionSkuPrice.PriceType == PriceTypePercentage {
promotionSkuPrice.Price = skuBind.Price * promotionSkuPrice.Price / 100
}
if promotionSkuPrice.Price >= skuBind.Price {
errMsg += fmt.Sprintf("促销价大于等于原价storeID:%d, skuID:%d\n", storeID, skuBind.SkuID)
}
if errMsg == "" {
if params.Type == PromotionTypeLimitedTime {
if skuBind.Price*PromotionLimitedTimeMinPercentage/100 < promotionSkuPrice.Price {
modifyPricesList[storeID] = append(modifyPricesList[storeID], &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(skuBind.SkuID),
Price: promotionSkuPrice.Price*100/PromotionLimitedTimeMinPercentage + 1,
})
}
}
promotionPrices[index] = map[string]interface{}{
jdapi.KeyOutStationNo: utils.Int2Str(storeID),
jdapi.KeyOutSkuId: utils.Int2Str(skuBind.SkuID),
jdapi.KeyPromotionPrice: promotionSkuPrice.Price,
}
index++
}
}
}
promotionPrices = promotionPrices[:index]
if len(promotionPrices) == 0 {
return "", ErrEmptySkus
}
if errMsg != "" {
return "", errors.New(errMsg)
}
promotion := &model.Promotion{
Name: params.Name,
VendorID: model.VendorIDJD,
Type: params.Type,
Status: PromotionStatusCreated,
SyncStatus: model.SyncFlagNewMask,
BeginAt: params.BeginAt,
EndAt: params.EndAt,
}
dao.WrapAddIDCULDEntity(promotion, userName)
if promotion.Params, err = jxutils.SerializeData(params); err != nil {
return "", err
}
dao.Begin(db)
defer func() {
dao.Rollback(db)
}()
if err = dao.CreateEntity(db, promotion); err != nil {
return "", err
}
var promotionHandler JdPromotionHandler
if params.Type == PromotionTypeDirectDown {
promotionHandler = &JdDirectDownHandler{}
} else if params.Type == PromotionTypeLimitedTime {
promotionHandler = &JdLimitedTimeHandler{}
} else {
panic(fmt.Sprintf("unknown promotion type:%d", params.Type))
}
infoId, err2 := promotionHandler.CreatePromotionInfos(params.Name, params.BeginAt, params.EndAt, utils.Int2Str(promotion.ID), params.Advertising)
if err = err2; err != nil {
return "", err
}
promotion.VendorPromotionID = utils.Int64ToStr(infoId)
if _, err = dao.UpdateEntity(db, promotion); err != nil {
return "", err
}
dao.Commit(db)
task := tasksch.RunTask("CreateJdPromotion update sku price", false, nil, 0, 1, userName, func(batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
storeID := batchItemList[0].(int)
modifyPricesList := jxutils.SplitSlice(modifyPricesList[storeID], jdapi.MaxStoreSkuBatchSize)
for _, modifyPrices := range modifyPricesList {
modifyPrices2 := make([]*jdapi.SkuPriceInfo, len(modifyPrices))
for k, v := range modifyPrices {
modifyPrices2[k] = v.(*jdapi.SkuPriceInfo)
}
if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil {
return nil, err
}
}
return nil, nil
}, params.StoreIDs)
if _, err = task.GetResult(0); err != nil {
return "", err
}
if err = promotionHandler.CreatePromotionRules(infoId, "", 1, 1, 1, 1); err != nil {
return "", err
}
task = tasksch.RunManagedTask("CreateJdPromotion CreatePromotionSku", false, nil, 0, jdapi.MaxPromotionSkuCount, userName, func(batchItemList []interface{}, params ...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)
if _, err = task.GetResult(0); err != nil {
return "", err
}
err = promotionHandler.ConfirmPromotion(infoId, "")
return "", err
}