- get and cancel promotion

This commit is contained in:
gazebo
2018-11-05 15:08:30 +08:00
parent 34c74cd40a
commit cf4bfb3dd8
5 changed files with 326 additions and 35 deletions

View File

@@ -32,11 +32,6 @@ const (
PromotionLimitedTimeMinPercentage = 80 PromotionLimitedTimeMinPercentage = 80
) )
const (
PromotionStatusCreated = 1
PromotionStatusEnded = 2
)
const ( const (
colSkuIDIndex = 0 colSkuIDIndex = 0
colSkuPriceIndex = 3 colSkuPriceIndex = 3
@@ -51,11 +46,16 @@ const (
MaxPromotionSkuCount = jdapi.MaxPromotionSkuCount MaxPromotionSkuCount = jdapi.MaxPromotionSkuCount
) )
const (
defSearchDays = 7
)
type SkuPrice struct { type SkuPrice struct {
SkuID int `json:"skuID"` SkuID int `json:"skuID"`
PriceType int `json:"priceType"` PriceType int `json:"priceType"`
Price int `json:"price"` // 分,这个不是单价 Price int `json:"price"` // 分,这个不是单价是这个sku的活动价
LimitSkuCount int `json:"limitSkuCount"` LimitSkuCount int `json:"limitSkuCount"`
IsLock int8 `json:"isLock"`
} }
type PromotionParams struct { type PromotionParams struct {
@@ -73,6 +73,14 @@ type tStoreSkuBindExt struct {
JdID int64 `orm:"column(jd_id)"` JdID int64 `orm:"column(jd_id)"`
} }
type tPromotionInfo struct {
model.Promotion
StoreIDStr string `orm:"column(store_id_str)" json:"-"`
SkuPriceStr string `orm:"column(sku_price_str)" json:"-"`
StoreIDs []int `orm:"-" json:"storeIDs"`
SkuPrices []*SkuPrice `orm:"-" json:"skuPrices"`
}
var ( var (
ErrEmptySkus = errors.New("空sku或指定的SKU没有被门店认领请检查") ErrEmptySkus = errors.New("空sku或指定的SKU没有被门店认领请检查")
) )
@@ -82,6 +90,7 @@ type JdPromotionHandler interface {
CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (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) CreatePromotionSku(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error)
ConfirmPromotion(infoId int64, outInfoId string) (err error) ConfirmPromotion(infoId int64, outInfoId string) (err error)
CancelPromotion(infoId int64, outInfoId string) (err error)
} }
type JdDirectDownHandler struct { type JdDirectDownHandler struct {
@@ -99,6 +108,9 @@ func (p *JdDirectDownHandler) CreatePromotionSku(infoId int64, outInfoId string,
func (p *JdDirectDownHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) { func (p *JdDirectDownHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.ConfirmPromotionSingle(infoId, outInfoId) return api.JdAPI.ConfirmPromotionSingle(infoId, outInfoId)
} }
func (p *JdDirectDownHandler) CancelPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.CancelPromotionSingle(infoId, outInfoId)
}
type JdLimitedTimeHandler struct { type JdLimitedTimeHandler struct {
} }
@@ -115,6 +127,9 @@ func (p *JdLimitedTimeHandler) CreatePromotionSku(infoId int64, outInfoId string
func (p *JdLimitedTimeHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) { func (p *JdLimitedTimeHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.ConfirmPromotionLimitTime(infoId, outInfoId) return api.JdAPI.ConfirmPromotionLimitTime(infoId, outInfoId)
} }
func (p *JdLimitedTimeHandler) CancelPromotion(infoId int64, outInfoId string) (err error) {
return api.JdAPI.CancelPromotionLimitTime(infoId, outInfoId)
}
type JdNullHandler struct { type JdNullHandler struct {
} }
@@ -131,6 +146,9 @@ func (p *JdNullHandler) CreatePromotionSku(infoId int64, outInfoId string, skus
func (p *JdNullHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) { func (p *JdNullHandler) ConfirmPromotion(infoId int64, outInfoId string) (err error) {
return nil return nil
} }
func (p *JdNullHandler) CancelPromotion(infoId int64, outInfoId string) (err error) {
return nil
}
func init() { func init() {
gob.Register(&PromotionParams{}) gob.Register(&PromotionParams{})
@@ -224,19 +242,19 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync bool, params
} }
promotion := &model.Promotion{ promotion := &model.Promotion{
Name: params.Name, Name: params.Name,
VendorID: model.VendorIDJD, Advertising: params.Advertising,
Type: params.Type, VendorID: model.VendorIDJD,
Status: PromotionStatusCreated, Type: params.Type,
SyncStatus: model.SyncFlagNewMask, Status: model.PromotionStatusLocalCreated,
BeginAt: params.BeginAt, BeginAt: params.BeginAt,
EndAt: params.EndAt, EndAt: params.EndAt,
} }
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
// } // }
promotion.Params = string(utils.MustMarshal(params)) // promotion.Params = string(utils.MustMarshal(params))
dao.Begin(db) dao.Begin(db)
defer func() { defer func() {
dao.Rollback(db) dao.Rollback(db)
@@ -246,18 +264,32 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync bool, params
return "", err return "", err
} }
var promotionHandler JdPromotionHandler for _, storeID := range params.StoreIDs {
if params.Type == PromotionTypeDirectDown { promotionStore := &model.PromotionStore{
promotionHandler = &JdDirectDownHandler{} PromotionID: promotion.ID,
} else if params.Type == PromotionTypeLimitedTime { StoreID: storeID,
promotionHandler = &JdLimitedTimeHandler{} }
} else { if err = dao.CreateEntity(db, promotionStore); err != nil {
panic(fmt.Sprintf("unknown promotion type:%d", params.Type)) return "", err
}
} }
if !globals.EnableStoreWrite { for _, skuPrice := range params.SkuPrices {
promotionHandler = &JdNullHandler{} promotionSku := &model.PromotionSku{
PromotionID: promotion.ID,
SkuID: skuPrice.SkuID,
PriceType: skuPrice.PriceType,
Price: skuPrice.Price,
LimitSkuCount: skuPrice.LimitSkuCount,
}
if err = dao.CreateEntity(db, promotionSku); err != nil {
return "", err
}
} }
promotionHandler := getPromotionHander(params.Type)
if promotionHandler == nil {
return "", errors.New("非法的促销类型")
}
infoId, err2 := promotionHandler.CreatePromotionInfos(params.Name, params.BeginAt, params.EndAt, utils.Int2Str(promotion.ID), params.Advertising) infoId, err2 := promotionHandler.CreatePromotionInfos(params.Name, params.BeginAt, params.EndAt, utils.Int2Str(promotion.ID), params.Advertising)
if err = err2; err != nil { if err = err2; err != nil {
return "", err return "", err
@@ -301,6 +333,14 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync bool, params
_, err = task2.GetResult(0) _, err = task2.GetResult(0)
} else if step == 3 { } else if step == 3 {
err = promotionHandler.ConfirmPromotion(infoId, "") err = promotionHandler.ConfirmPromotion(infoId, "")
if err == nil {
promotion.Status = model.PromotionStatusRemoteCreated
} else {
promotion.Status = model.PromotionStatusRemoteFailed
}
db := dao.GetDB()
dao.WrapUpdateULEntity(promotion, userName)
_, err = dao.UpdateEntity(db, promotion, "Status")
} }
return nil, err return nil, err
}, 4) }, 4)
@@ -362,6 +402,166 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync bool, params
// return CreateJdPromotion(ctx, true, isAsync, promotionParams, userName) // return CreateJdPromotion(ctx, true, isAsync, promotionParams, userName)
// } // }
func GetJdPromotions(ctx *jxcontext.Context, keyword string, params map[string]interface{}, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
sql := `
SELECT SQL_CALC_FOUND_ROWS
t1.id,
t1.created_at,
t1.updated_at,
t1.last_operator,
t1.vendor_id,
t1.name,
t1.type,
t1.status,
t1.vendor_promotion_id,
t1.begin_at,
t1.end_at,
t1.advertising,
CONCAT("[", GROUP_CONCAT(DISTINCT t2.store_id), "]") store_id_str,
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"skuID":', t3.sku_id, ', "priceType":', t3.price_type, ', "price":', t3.price, ', "limitSkuCount":', t3.limit_sku_count, ', "isLock":', t3.is_lock, '}')), "]") sku_price_str
FROM promotion t1
JOIN promotion_store t2 ON t1.id = t2.promotion_id
JOIN promotion_sku t3 ON t1.id = t3.promotion_id
WHERE t1.deleted_at = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
}
if keyword != "" {
keywordLike := "%" + keyword + "%"
sql += " AND ( t1.name LIKE ?"
sqlParams = append(sqlParams, keywordLike)
keywordInt := utils.Str2Int64WithDefault(keyword, 0)
if keywordInt > 0 {
sql += `
OR t1.id = ? OR t1.vendor_promotion_id = ?
OR (SELECT COUNT(*) FROM promotion_store tt1 WHERE tt1.promotion_id = t1.id AND tt1.store_id = ?) > 0
OR (SELECT COUNT(*) FROM promotion_sku tt1 WHERE tt1.promotion_id = t1.id AND tt1.sku_id = ?) > 0
`
sqlParams = append(sqlParams, keywordInt, keywordInt, keywordInt, keywordInt)
}
sql += ")"
}
if params["vendorID"] != nil {
sql += " AND t1.vendor_id = ?"
sqlParams = append(sqlParams, params["vendorID"].(int))
}
if params["promotionID"] != nil {
sql += " AND t1.id = ?"
sqlParams = append(sqlParams, params["promotionID"].(int))
}
if params["vendorPromotionID"] != nil {
sql += " AND t1.vendor_promotion_id = ?"
sqlParams = append(sqlParams, params["vendorPromotionID"].(int))
}
if params["name"] != nil {
sql += " AND t1.name LIKE ?"
sqlParams = append(sqlParams, "%"+params["name"].(string)+"%")
}
if params["beginAt"] != nil {
sql += " AND t1.begin_at <= ?"
sqlParams = append(sqlParams, utils.Str2Time(params["beginAt"].(string)))
}
if params["endAt"] != nil {
sql += " AND t1.end_at >= ?"
sqlParams = append(sqlParams, utils.Str2Time(params["endAt"].(string)))
}
days := defSearchDays
if params["days"] != nil {
days = params["days"].(int)
}
sql += " AND t1.created_at >= ?"
sqlParams = append(sqlParams, time.Now().Add(-time.Duration(days)*24*time.Hour))
if params["type"] != nil {
sql += " AND t1.type = ?"
sqlParams = append(sqlParams, params["type"].(int))
}
if params["storeID"] != nil {
sql += " AND (SELECT COUNT(*) FROM promotion_store tt1 WHERE tt1.promotion_id = t1.id AND tt1.store_id = ?) > 0"
sqlParams = append(sqlParams, params["storeID"].(int))
}
if params["skuID"] != nil {
sql += " AND (SELECT COUNT(*) FROM promotion_sku tt1 WHERE tt1.promotion_id = t1.id AND tt1.sku_id = ?) > 0"
sqlParams = append(sqlParams, params["skuID"].(int))
}
sql += `
GROUP BY
1,2,3,4,5,6,7,8,9,10,11,12
ORDER BY t1.id DESC
LIMIT ? OFFSET ?
`
pageSize = jxutils.FormalizePageSize(pageSize)
if offset < 0 {
offset = 0
}
sqlParams = append(sqlParams, pageSize, offset)
db := dao.GetDB()
dao.Begin(db)
defer func() {
dao.Rollback(db)
if r := recover(); r != nil {
panic(r)
}
}()
// globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false))
// globals.SugarLogger.Debug(sql)
var promotionList []*tPromotionInfo
if err = dao.GetRows(db, &promotionList, sql, sqlParams...); err == nil {
for _, v := range promotionList {
if v.StoreIDStr != "" {
if err = utils.UnmarshalUseNumber([]byte(v.StoreIDStr), &v.StoreIDs); err != nil {
return nil, err
}
}
if v.SkuPriceStr != "" {
if err = utils.UnmarshalUseNumber([]byte(v.SkuPriceStr), &v.SkuPrices); err != nil {
return nil, err
}
}
}
pagedInfo = &model.PagedInfo{}
countInfo := &struct{ Ct int }{}
if err = dao.GetRow(db, countInfo, "SELECT FOUND_ROWS() ct"); err == nil {
pagedInfo.TotalCount = countInfo.Ct
}
pagedInfo.Data = promotionList
}
dao.Commit(db)
return pagedInfo, err
}
func CancelJdPromotion(ctx *jxcontext.Context, promotionID int) (err error) {
db := dao.GetDB()
promotion := model.Promotion{}
promotion.ID = promotionID
if err = dao.GetEntity(db, promotion); err != nil {
return err
}
promotionHandler := getPromotionHander(promotion.Type)
if promotionHandler == nil {
return errors.New("非法的促销类型")
}
err = promotionHandler.CancelPromotion(utils.Str2Int64(promotion.VendorPromotionID), "")
return err
}
func excelStr2Time(timeStr string) (tm time.Time, err error) { func excelStr2Time(timeStr string) (tm time.Time, err error) {
return time.ParseInLocation("2006年1月2日15点4分5秒", timeStr, time.Local) return time.ParseInLocation("2006年1月2日15点4分5秒", timeStr, time.Local)
} }
func getPromotionHander(promotionType int) JdPromotionHandler {
var promotionHandler JdPromotionHandler
if promotionType == PromotionTypeDirectDown {
promotionHandler = &JdDirectDownHandler{}
} else if promotionType == PromotionTypeLimitedTime {
promotionHandler = &JdLimitedTimeHandler{}
} else {
// panic(fmt.Sprintf("unknown promotion type:%d", promotionType))
return nil
}
if !globals.EnableStoreWrite {
promotionHandler = &JdNullHandler{}
}
return promotionHandler
}

View File

@@ -4,18 +4,25 @@ import (
"time" "time"
) )
const (
PromotionStatusLocalCreated = 0 // 本地成功创建,
PromotionStatusRemoteFailed = 1 // 远程创建失败,
PromotionStatusRemoteCreated = 2 // 远程成功创建,
PromotionStatusCanceled = 3 // 被显示取消
PromotionStatusEnded = 4 // 已经超过活动时间,且被显示置为结束
)
type Promotion struct { type Promotion struct {
ModelIDCULD ModelIDCULD
VendorID int `orm:"column(vendor_id)"` VendorID int `orm:"column(vendor_id)"`
Name string `orm:"size(64)" json:"name"` Name string `orm:"size(64)" json:"name"`
Type int Advertising string `orm:"size(255)" json:"advertising"`
Status int Type int `json:"type"`
SyncStatus int Status int `json:"status"`
VendorPromotionID string `orm:"size(64);column(vendor_promotion_id);index" json:"vendorPromotionID"` VendorPromotionID string `orm:"size(64);column(vendor_promotion_id);index" json:"vendorPromotionID"`
BeginAt time.Time `orm:"type(datetime);index" json:"beginAt"` BeginAt time.Time `orm:"type(datetime);index" json:"beginAt"`
EndAt time.Time `orm:"type(datetime);index" json:"endAt"` EndAt time.Time `orm:"type(datetime);index" json:"endAt"`
Params string `orm:"type(text)" json:"params"`
} }
func (*Promotion) TableUnique() [][]string { func (*Promotion) TableUnique() [][]string {
@@ -23,3 +30,31 @@ func (*Promotion) TableUnique() [][]string {
[]string{"Name", "VendorID", "Type", "DeletedAt"}, []string{"Name", "VendorID", "Type", "DeletedAt"},
} }
} }
type PromotionStore struct {
ID int `orm:"column(id)" json:"id"`
PromotionID int `orm:"column(promotion_id)" json:"promotionID"`
StoreID int `orm:"column(store_id)" json:"storeID"`
}
func (*PromotionStore) TableUnique() [][]string {
return [][]string{
[]string{"PromotionID", "StoreID"},
}
}
type PromotionSku struct {
ID int `orm:"column(id)" json:"id"`
PromotionID int `orm:"column(promotion_id)" json:"promotionID"`
SkuID int `orm:"column(sku_id)" json:"skuID"`
PriceType int `json:"priceType"`
Price int `json:"price"` // 分,活动价,这个不是单价
LimitSkuCount int `json:"limitSkuCount"`
IsLock int8 `json:"isLock"` // 是否锁定门店商品信息
}
func (*PromotionSku) TableUnique() [][]string {
return [][]string{
[]string{"PromotionID", "SkuID"},
}
}

View File

@@ -19,8 +19,8 @@ type PromotionController struct {
// @Param token header string true "认证token" // @Param token header string true "认证token"
// @Param vendorID formData int true "厂商ID当前只支持京东0 " // @Param vendorID formData int true "厂商ID当前只支持京东0 "
// @Param name formData string true "促销名,必须唯一(所以名子上最好带上日期)" // @Param name formData string true "促销名,必须唯一(所以名子上最好带上日期)"
// @Param beginAt formData string true "开始时间" // @Param beginAt formData string true "开始日期"
// @Param endAt formData string true "结束时间" // @Param endAt formData string true "结束日期"
// @Param type formData int true "促销类型3直降4限时抢购" // @Param type formData int true "促销类型3直降4限时抢购"
// @Param storeIDs formData string true "json数据storeID列表[1,2,3]" // @Param storeIDs formData string true "json数据storeID列表[1,2,3]"
// @Param skuPrices formData string true "json数据价格信息列表" // @Param skuPrices formData string true "json数据价格信息列表"
@@ -99,3 +99,43 @@ func (c *PromotionController) SendAdvertingByGoodsOrder() {
return retVal, "", err return retVal, "", err
}) })
} }
// @Title 查询促销
// @Description 查询促销
// @Param token header string true "认证token"
// @Param keyword query string false "关键字"
// @Param vendorID query int false "厂商ID当前只支持京东0 "
// @Param promotionID query int false "活动id"
// @Param vendorPromotionID query int false "厂商活动id"
// @Param days query int false "多少天内创建的缺省7天"
// @Param name query string false "促销名,不完全匹配"
// @Param beginAt query string false "开始日期,包括"
// @Param endAt query string false "结束日期,包括"
// @Param type query int false "促销类型3直降4限时抢购"
// @Param storeID query int false "包含门店"
// @Param skuID query int false "包含sku"
// @Param offset query int false "活动列表起始序号以0开始缺省为0"
// @Param pageSize query int false "活动列表页大小缺省为50-1表示全部"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetPromotions [get]
func (c *PromotionController) GetPromotions() {
c.callGetPromotions(func(params *tPromotionGetPromotionsParams) (retVal interface{}, errCode string, err error) {
retVal, err = promotion.GetJdPromotions(params.Ctx, params.Keyword, params.MapData, params.Offset, params.PageSize)
return retVal, "", err
})
}
// @Title 查询促销
// @Description 查询促销
// @Param token header string true "认证token"
// @Param promotionID query int true "活动id"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /CancelPomotion [put]
func (c *PromotionController) CancelPomotion() {
c.callCancelPomotion(func(params *tPromotionCancelPomotionParams) (retVal interface{}, errCode string, err error) {
err = promotion.CancelJdPromotion(params.Ctx, params.PromotionID)
return retVal, "", err
})
}

View File

@@ -34,7 +34,7 @@ func Init() {
orm.RegisterModel(&model.SkuCategory{}) orm.RegisterModel(&model.SkuCategory{})
// orm.RegisterModel(&model.DurableTask{}, &model.DurableTaskItem{}) // orm.RegisterModel(&model.DurableTask{}, &model.DurableTaskItem{})
orm.RegisterModel(&model.Promotion{}) orm.RegisterModel(&model.Promotion{}, &model.PromotionStore{}, &model.PromotionSku{})
} }
// create table // create table
orm.RunSyncdb("default", false, true) orm.RunSyncdb("default", false, true)

View File

@@ -215,6 +215,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: "CancelPomotion",
Router: `/CancelPomotion`,
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: "CreatePromotion", Method: "CreatePromotion",
@@ -223,6 +231,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: "GetPromotions",
Router: `/GetPromotions`,
AllowHTTPMethods: []string{"get"},
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",