Files
jx-callback/business/jxstore/act/act.go
2019-09-12 16:55:11 +08:00

885 lines
29 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 act
import (
"fmt"
"math"
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/baseapi/utils/errlist"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/business/jxutils/jsonerr"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"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"
)
const (
DefActSkuStock = 200 // 缺省活动库存
maxDiscount4SkuSecKill = 99
minDiscount4SkuDirectDown = 0
)
type ActOrderRuleParam struct {
SalePrice int64 `orm:"" json:"salePrice"` // 满的价格
DeductPrice int64 `orm:"" json:"deductPrice"` // 减的价格
}
type ActStoreSkuParam struct {
model.ActStoreSku
ErrMsg string `json:"errMsg"`
}
type ActDetail struct {
model.Act2
}
type tPreCreateActVendorInfo struct {
VendorID int
VendorPrice int64 `orm:"" json:"vendorPrice"` // 单品级活动用,创建活动时商品的原始平台价
ActualActPrice int64 `orm:"" json:"actualActPrice"` // 单品级活动用,创建活动时商品的活动价格
}
type tPreCreateActStoreSku struct {
model.ActStoreSku
VendorInfoList []*tPreCreateActVendorInfo `json:"vendorInfoList"`
}
type tPreCreateActInfo struct {
model.Act
ValidVendorIDs []int
ActStoreSku []*tPreCreateActStoreSku `json:"actStoreSku"`
}
type ActManager struct {
}
var (
FixedActManager *ActManager
)
func init() {
FixedActManager = &ActManager{}
partner.InitActManager(FixedActManager)
}
func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Act, vendorIDs []int, actStoreSku []*ActStoreSkuParam) (validVendorIDs []int, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) {
wholeValidVendorMap := make(map[int]int)
if len(actStoreSku) > 0 {
storeIDMap := make(map[int]int)
skuIDMap := make(map[int]int)
storeSkuParamMap := make(map[int][]*ActStoreSkuParam)
var wrongSkuList []*ActStoreSkuParam
for _, v := range actStoreSku {
if act.Type == model.ActSkuFake && v.EarningPrice == 0 {
wrongSkuList = append(wrongSkuList, v)
} else {
storeIDMap[v.StoreID] = 1
skuIDMap[v.SkuID] = 1
storeSkuParamMap[v.StoreID] = append(storeSkuParamMap[v.StoreID], v)
}
}
if len(wrongSkuList) > 0 {
return nil, nil, nil, jsonerr.New(wrongSkuList, model.ErrCodeJsonActEarningPriceIsZero)
}
storeIDs := jxutils.IntMap2List(storeIDMap)
skuIDs := jxutils.IntMap2List(skuIDMap)
if !(len(vendorIDs) == 1 && vendorIDs[0] == model.VendorIDJD || act.Type == model.ActSkuFake) {
effectActStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, storeIDs, skuIDs, act.BeginAt, act.EndAt)
if err != nil {
globals.SugarLogger.Errorf("updateActPrice4StoreSkuNameNew can not get sku promotion info for error:%v", err)
return nil, nil, nil, err
}
if len(effectActStoreSkuList) > 0 {
return nil, nil, nil, jsonerr.New(effectActStoreSkuList, model.ErrCodeJsonActSkuConflict)
}
}
storeSkuList, err2 := dao.GetStoresSkusInfo(db, storeIDs, skuIDs)
if err = err2; err != nil {
return nil, nil, nil, err
}
storeSkuMap := make(map[int64]*model.StoreSkuBind)
for _, v := range storeSkuList {
storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v
}
for storeID, oneStoreSkuParam := range storeSkuParamMap {
validVendorMap := make(map[int]int)
validSkuMap := make(map[int]int)
for _, vendorID := range vendorIDs {
storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID)
if err = err2; err == nil {
for _, v := range oneStoreSkuParam {
if storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
validVendorMap[vendorID] = 1
validSkuMap[v.SkuID] = 1
pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, storeSkuInfo.Price, int(storeDetail.PricePercentage))
actSkuMap := &model.ActStoreSkuMap{
ActID: act.ID,
StoreID: storeID,
SkuID: v.SkuID,
VendorID: vendorID,
SyncStatus: model.SyncFlagNewMask,
VendorPrice: int64(jxutils.CaculateSkuVendorPrice(storeSkuInfo.Price, pricePercentage, 0)),
}
v.OriginalPrice = actSkuMap.VendorPrice
if act.Type == model.ActSkuFake {
actSkuMap.ActualActPrice = 0
} else {
if v.ActPrice != 0 {
actSkuMap.ActualActPrice = v.ActPrice
} else {
percentage := act.PricePercentage
if v.PricePercentage != 0 {
percentage = v.PricePercentage
}
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(int(actSkuMap.VendorPrice), percentage, 0))
if actSkuMap.ActualActPrice > 10 {
actSkuMap.ActualActPrice = int64(math.Round(float64(actSkuMap.ActualActPrice)/10) * 10)
}
}
if actSkuMap.ActualActPrice <= 0 {
actSkuMap.ActualActPrice = 1
}
}
if err2 := checkDiscountValidation(act.Type, int(actSkuMap.ActualActPrice*100/actSkuMap.VendorPrice)); err2 != nil {
v.ErrMsg = err2.Error()
wrongSkuList = append(wrongSkuList, v)
} else {
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
}
}
}
wholeValidVendorMap[vendorID] = 1
} else if !dao.IsNoRowsError(err) {
return nil, nil, nil, err
} else {
err = nil
}
}
if len(wrongSkuList) == 0 {
for _, v := range oneStoreSkuParam {
if validSkuMap[v.SkuID] == 1 { // todo 这里是否需要判断
if storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
storeSku := &v.ActStoreSku
storeSku.ActID = act.ID
storeSku.OriginalPrice = int64(storeSkuInfo.Price)
dao.WrapAddIDCULDEntity(storeSku, ctx.GetUserName())
actStoreSkuList = append(actStoreSkuList, storeSku)
}
}
}
}
}
if len(wrongSkuList) > 0 {
return nil, nil, nil, jsonerr.New(wrongSkuList, model.ErrCodeJsonActPriceTooLarger)
}
}
return jxutils.IntMap2List(wholeValidVendorMap), actStoreSkuList, actStoreSkuMapList, err
}
func addActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap) (err error) {
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
storeSkuMap := make(map[int64]int)
for _, v := range actStoreSkuList {
if v.Stock == 0 {
v.Stock = DefActSkuStock
}
err = dao.CreateEntity(db, v)
if err != nil {
dao.Rollback(db)
return err
}
storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v.ID
}
for _, v := range actStoreSkuMapList {
v.BindID = storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]
}
if len(actStoreSkuMapList) > 0 {
err = dao.CreateMultiEntities(db, actStoreSkuMapList)
if err != nil {
dao.Rollback(db)
return err
}
}
dao.Commit(db)
return err
}
func AddActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSku []*ActStoreSkuParam) (err error) {
actMap, err := dao.GetActVendorInfo(db, actID, nil)
if err != nil {
return err
}
vendorIDs := partner.GetVendorIDsFromActMap(actMap)
var act *model.Act
if len(vendorIDs) > 0 {
act = &actMap[vendorIDs[0]].Act
} else {
act = &model.Act{}
act.ID = actID
if err = dao.GetEntity(db, act); err != nil {
return err
}
}
if act.Status != model.ActStatusCreated || time.Now().Sub(act.EndAt) > 0 {
return fmt.Errorf("当前活动状态:%s不能进行此操作或已过期", model.ActStatusName[act.Status])
}
_, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, db, act, vendorIDs, actStoreSku)
if err != nil {
return err
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil {
return err
}
for _, act := range actMap {
if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act),
map[string]interface{}{
model.FieldSyncStatus: act.SyncStatus | model.SyncFlagModifiedMask,
}, ctx.GetUserName(), nil); err != nil {
return err
}
}
dao.Commit(db)
return err
}
func checkDiscountValidation(actType int, pricePercentage int) (err error) {
if actType == model.ActSkuDirectDown && (pricePercentage < minDiscount4SkuDirectDown || pricePercentage > 99) {
err = fmt.Errorf("%s活动折扣必须大于:%d, 且必须有折扣", model.ActTypeName[actType], minDiscount4SkuDirectDown)
} else if actType == model.ActSkuSecKill && pricePercentage > maxDiscount4SkuSecKill {
err = fmt.Errorf("%s活动折扣必须小于:%d", model.ActTypeName[actType], maxDiscount4SkuSecKill)
}
return err
}
func checkActValidation(act *model.Act, vendorIDs []int) (err error) {
errList := errlist.New()
if utils.IsTimeZero(act.BeginAt) || utils.IsTimeZero(act.EndAt) {
errList.AddErr(fmt.Errorf("活动开始与结束时间必须指定"))
} else if act.EndAt.Sub(act.BeginAt) < 0 {
errList.AddErr(fmt.Errorf("活动开始时间必须小于活动结束时间"))
}
vendorIDMap := make(map[int]int)
for _, vendorID := range vendorIDs {
vendorIDMap[vendorID] = 1
}
if act.Type == model.ActSkuDirectDown || act.Type == model.ActSkuSecKill {
if act.PricePercentage == 0 {
errList.AddErr(fmt.Errorf("必须指定缺省活动折扣"))
} else if err = checkDiscountValidation(act.Type, act.PricePercentage); err != nil {
errList.AddErr(err)
} else if act.Type == model.ActSkuSecKill && vendorIDMap[model.VendorIDMTWM] == 1 {
errList.AddErr(fmt.Errorf("%s平台不支持%s活动", model.VendorChineseNames[model.VendorIDMTWM], model.ActTypeName[model.ActSkuSecKill]))
}
} else if act.Type == model.ActSkuFake {
} else {
errList.AddErr(fmt.Errorf("当前只支持%s与%s活动", model.ActTypeName[model.ActSkuDirectDown], model.ActTypeName[model.ActSkuSecKill]))
}
err = errList.GetErrListAsOne()
return err
}
func setActDefault(act *model.Act) {
if act.LimitCount == 0 {
act.LimitCount = 1 // 缺省限购一份,如果确定不限,明确给一个很大的值
}
if act.LimitUser == 0 {
act.LimitUser = 1
}
act.Status = model.ActStatusCreated
}
func PreCreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (preCreateActInfo *tPreCreateActInfo, err error) {
if err = checkActValidation(act, vendorIDs); err != nil {
return nil, err
}
setActDefault(act)
db := dao.GetDB()
validVendorIDs, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, db, act, vendorIDs, actStoreSku)
if err != nil {
return nil, err
}
preCreateActInfo = &tPreCreateActInfo{
ValidVendorIDs: validVendorIDs,
}
storeSkuMap := make(map[int64]*tPreCreateActStoreSku)
for _, v := range actStoreSkuList {
tmp := &tPreCreateActStoreSku{
ActStoreSku: *v,
}
storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = tmp
preCreateActInfo.ActStoreSku = append(preCreateActInfo.ActStoreSku, tmp)
}
for _, v := range actStoreSkuMapList {
index := jxutils.Combine2Int(v.StoreID, v.SkuID)
storeSkuMap[index].VendorInfoList = append(storeSkuMap[index].VendorInfoList, &tPreCreateActVendorInfo{
VendorID: v.VendorID,
VendorPrice: v.VendorPrice,
ActualActPrice: v.ActualActPrice,
})
}
return preCreateActInfo, nil
}
func CreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam, isAsync bool) (hint string, err error) {
if err = checkActValidation(act, vendorIDs); err != nil {
return "", err
}
act.VendorMask = model.GetVendorMask(vendorIDs...)
setActDefault(act)
db := dao.GetDB()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
dao.WrapAddIDCULDEntity(act, ctx.GetUserName())
err = dao.CreateEntity(db, act)
if err != nil {
dao.Rollback(db)
return "", err
}
validVendorIDs, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, db, act, vendorIDs, actStoreSku)
if err != nil {
dao.Rollback(db)
return "", err
}
if len(validVendorIDs) == 0 {
dao.Rollback(db)
return "", fmt.Errorf("没有一个合法平台可以创建活动")
}
var actMapList []*model.ActMap
for _, vendorID := range validVendorIDs {
actMap := &model.ActMap{
ActID: act.ID,
VendorID: vendorID,
SyncStatus: model.SyncFlagNewMask,
}
dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName())
actMapList = append(actMapList, actMap)
}
if len(actMapList) > 0 {
err = dao.CreateMultiEntities(db, actMapList)
if err != nil {
dao.Rollback(db)
return "", err
}
}
if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil {
dao.Rollback(db)
return "", err
}
dao.Commit(db)
hint, err = SyncAct(ctx, nil, act.ID, nil, isAsync)
if !isAsync {
hint = utils.Int2Str(act.ID)
}
return hint, err
}
func vendorActInfo2Model(ctx *jxcontext.Context, db *dao.DaoDB, act2 *model.Act2, actStoreSku []*model.ActStoreSku2) (actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) {
vendorStoreIDMap := make(map[string]int)
vendorSkuIDMap := make(map[string]int)
for _, v := range actStoreSku {
vendorStoreIDMap[v.VendorStoreID] = 1
vendorSkuIDMap[v.VendorSkuID] = 1
}
// globals.SugarLogger.Debug(utils.Format4Output(vendorStoreIDMap, false))
// globals.SugarLogger.Debug(utils.Format4Output(vendorSkuIDMap, false))
vendorID := act2.VendorID
storeSkuList, err2 := dao.GetStoresSkusInfoByVendorInfo(db, vendorID, jxutils.StringMap2List(vendorStoreIDMap), jxutils.StringMap2List(vendorSkuIDMap))
if err = err2; err != nil {
return nil, nil, err
}
storeSkuMap := make(map[string]*dao.StoreSkuBindWithVendorInfo)
for _, v := range storeSkuList {
storeSkuMap[v.VendorStoreID+"/"+v.VendorSkuID] = v
}
storeSkuMap2 := make(map[int64]int)
for _, v := range actStoreSku {
if storeSkuInfo := storeSkuMap[v.VendorStoreID+"/"+v.VendorSkuID]; storeSkuInfo != nil {
index := jxutils.Combine2Int(storeSkuInfo.StoreID, storeSkuInfo.SkuID)
if storeSkuMap2[index] == 0 {
storeSkuMap2[index] = 1
actSku := &model.ActStoreSku{
ActID: act2.ID,
StoreID: storeSkuInfo.StoreID,
SkuID: storeSkuInfo.SkuID,
Stock: v.Stock,
ActPrice: v.ActualActPrice,
OriginalPrice: int64(storeSkuInfo.Price),
}
dao.WrapAddIDCULDEntity(actSku, ctx.GetUserName())
actStoreSkuList = append(actStoreSkuList, actSku)
actSkuMap := &model.ActStoreSkuMap{
ActID: act2.ID,
VendorActID: act2.VendorActID,
StoreID: storeSkuInfo.StoreID,
SkuID: storeSkuInfo.SkuID,
VendorID: vendorID,
SyncStatus: 0,
VendorPrice: 0,
ActualActPrice: v.ActualActPrice,
}
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
}
}
}
return actStoreSkuList, actStoreSkuMapList, err
}
func (a *ActManager) CreateActFromVendor(ctx *jxcontext.Context, act2 *model.Act2, actStoreSku []*model.ActStoreSku2) (actID int, err error) {
globals.SugarLogger.Debugf("CreateActFromVendor vendorID:%d, vendorActID:%s", act2.VendorID, act2.VendorActID)
db := dao.GetDB()
return createActFromVendor(ctx, db, act2, actStoreSku)
}
func createActFromVendor(ctx *jxcontext.Context, db *dao.DaoDB, act2 *model.Act2, actStoreSku []*model.ActStoreSku2) (actID int, err error) {
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
act := &act2.Act
act.VendorMask = model.GetVendorMask(act2.VendorID)
dao.WrapAddIDCULDEntity(act, ctx.GetUserName())
err = dao.CreateEntity(db, act)
if err != nil {
dao.Rollback(db)
return 0, err
}
actMap := &model.ActMap{
ActID: act.ID,
VendorID: act2.VendorID,
VendorActID: act2.VendorActID,
SyncStatus: 0,
}
dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName())
err = dao.CreateEntity(db, actMap)
if err != nil {
dao.Rollback(db)
return 0, err
}
actStoreSkuList, actStoreSkuMapList, err := vendorActInfo2Model(ctx, db, act2, actStoreSku)
if err != nil {
dao.Rollback(db)
return 0, err
}
if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil {
dao.Rollback(db)
return 0, err
}
dao.Commit(db)
return act.ID, nil
}
func (a *ActManager) IsVendorActExist(ctx *jxcontext.Context, vendorActID string, vendorID int) (isExist bool) {
db := dao.GetDB()
actMap := &model.ActMap{
VendorActID: vendorActID,
VendorID: vendorID,
}
actMap.DeletedAt = utils.DefaultTimeValue
if err := dao.GetEntity(db, actMap, "VendorActID", "VendorID", "DeletedAt"); err == nil {
isExist = true
}
return isExist
}
func QueryActs(ctx *jxcontext.Context, actID int, offset, pageSize int, syncStatus int, keyword string, vendorID int, statusList, actTypeList, createTypeList []int, storeID, skuID, cityCode int, beginAt, endAt, createdAtFrom, createdAtTo time.Time) (pagedInfo *dao.PagedActListInfo, err error) {
return dao.QueryActs(dao.GetDB(), actID, offset, pageSize, syncStatus, keyword, vendorID, statusList, actTypeList, createTypeList, storeID, skuID, cityCode, beginAt, endAt, createdAtFrom, createdAtTo)
}
func GetActStoreSkuInfo(ctx *jxcontext.Context, actID int, vendorIDs []int, keyword string, offset, pageSize int) (retVal interface{}, err error) {
db := dao.GetDB()
totalCount, actStoreSkuList, err := dao.GetActStoreSkuVendorList(db, actID, vendorIDs, nil, nil, keyword, offset, pageSize)
if err != nil {
return nil, err
}
for _, v := range actStoreSkuList {
v.SkuName = jxutils.ComposeSkuName(v.Prefix, v.SkuNameName, v.Comment, v.Unit, v.SpecQuality, v.SpecUnit, 0)
}
if pageSize > 0 && pageSize != model.UnlimitedPageSize {
pagedInfo := &model.PagedInfo{
TotalCount: totalCount,
Data: actStoreSkuList,
}
retVal = pagedInfo
} else {
retVal = actStoreSkuList
}
return retVal, err
}
func CancelAct(ctx *jxcontext.Context, actID int) (err error) {
db := dao.GetDB()
if err = DeleteActStoreSkuBind(ctx, db, actID, nil); err != nil {
return err
}
_, err = SyncAct(ctx, nil, actID, nil, false)
return err
}
// actStoreSkuParam为空不会删除act_store_sku但会删除act_store_sku_map
func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSkuParam []*ActStoreSkuParam) (err error) {
actMap, err := dao.GetActVendorInfo(db, actID, nil)
if err != nil {
return err
}
if len(actMap) == 0 {
return fmt.Errorf("找不到活动:%d或已被取消", actID)
}
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil)
if err != nil {
return err
}
act := actMap[partner.GetVendorIDsFromActMap(actMap)[0]]
if act.Status != model.ActStatusCreated || time.Now().Sub(act.EndAt) > 0 {
return fmt.Errorf("当前活动状态:%s不能进行此操作或已过期", model.ActStatusName[act.Status])
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
actStoreSkuParamMap := make(map[int64]*ActStoreSkuParam)
for _, v := range actStoreSkuParam {
actStoreSkuParamMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v
if _, err = dao.DeleteEntityLogically(db, &model.ActStoreSku{}, nil, ctx.GetUserName(),
map[string]interface{}{
model.FieldActID: actID,
model.FieldStoreID: v.StoreID,
model.FieldSkuID: v.SkuID,
}); err != nil {
return err
}
}
isNeedCancelAct := true
for vendorID, act := range actMap {
isDeleteAll := true
isDeleteAtLeastOne := false
if actStoreSkuParam != nil {
actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuMap[vendorID])
for storeID := range actStoreSkuMap {
for _, actStoreSku := range actStoreSkuMap[storeID] {
if actStoreSkuParam == nil || actStoreSkuParamMap[jxutils.Combine2Int(actStoreSku.StoreID, actStoreSku.SkuID)] != nil {
if act.Type == model.ActSkuFake {
_, err = dao.DeleteEntityLogically(db, &model.ActStoreSkuMap{}, nil, ctx.GetUserName(),
map[string]interface{}{
model.FieldActID: actID,
model.FieldStoreID: actStoreSku.StoreID,
model.FieldSkuID: actStoreSku.SkuID,
})
} else {
_, err = dao.UpdateEntityLogically(db, partner.ActStoreSku2ActStoreSkuMap(actStoreSku),
map[string]interface{}{
model.FieldSyncStatus: actStoreSku.SyncStatus | model.SyncFlagDeletedMask,
}, ctx.GetUserName(), nil)
}
if err != nil {
return err
}
isDeleteAtLeastOne = true
} else {
isNeedCancelAct = false
isDeleteAll = false
}
}
}
} else {
isDeleteAll = true
isDeleteAtLeastOne = true
}
if isDeleteAll || isDeleteAtLeastOne {
syncStatus := int8(model.SyncFlagModifiedMask)
if isDeleteAll {
syncStatus = model.SyncFlagDeletedMask
}
syncStatus |= act.SyncStatus
if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act),
map[string]interface{}{
model.FieldSyncStatus: syncStatus,
}, ctx.GetUserName(), nil); err != nil {
return err
}
}
if isDeleteAll != isNeedCancelAct {
globals.SugarLogger.Warnf("deleteActStoreBind, actID:%d isDeleteAll:%t != isNeedCancelAct:%t", act.ID, isDeleteAll, isNeedCancelAct)
}
}
if isNeedCancelAct {
act := &model.Act{}
act.ID = actID
if _, err = dao.UpdateEntityLogically(db, act,
map[string]interface{}{
model.FieldStatus: model.ActStatusCanceled,
}, ctx.GetUserName(), nil); err != nil {
return err
}
}
dao.Commit(db)
return err
}
// todo 当前逻辑要求传入活动的全部SKU信息以便低层做一些判断比如全部删除时要取消所以暂时删除storeIDs与skuIDs这两个参数
func SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, actID int, vendorIDs /*, storeIDs, skuIDs */ []int, isAsync bool) (hint string, err error) {
db := dao.GetDB()
actMap, err := dao.GetActVendorInfo(db, actID, vendorIDs)
if err != nil {
return "", err
}
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil)
if err != nil {
return "", err
}
if vendorIDs == nil {
vendorIDs = partner.GetVendorIDsFromActMap(actMap)
}
if len(vendorIDs) == 0 || actMap[vendorIDs[0]].Type == model.ActSkuFake {
return "", nil
}
task := tasksch.NewParallelTask("SyncAct", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
vendorID := batchItemList[0].(int)
if handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformActHandler); handler != nil {
tmpActMap := &model.ActMap{}
tmpActMap.ID = actMap[vendorID].MapID
if err = handler.SyncAct(ctx, nil, actMap[vendorID], nil, actStoreSkuMap[vendorID]); err == nil {
retVal = []int{1}
} else {
tmpActMap.Remark = utils.LimitUTF8StringLen(err.Error(), 1024)
}
// 保存最后一次同步错误信息
dao.UpdateEntity(db, tmpActMap, "Remark")
}
return retVal, err
}, vendorIDs)
tasksch.HandleTask(task, parentTask, true).Run()
if !isAsync {
result, err2 := task.GetResult(0)
if err = err2; err == nil {
hint = utils.Int2Str(len(result))
}
} else {
hint = task.GetID()
}
return hint, err
}
func RefreshPageActs(ctx *jxcontext.Context, vendorIDs []int, createdFrom time.Time, isAsync bool) (hint string, err error) {
task := tasksch.NewParallelTask("RefreshPageActs", nil, ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
vendorID := batchItemList[0].(int)
if handler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformPageActHandler); handler != nil {
db := dao.GetDB()
actList, err2 := handler.GetPageActList(ctx, createdFrom)
globals.SugarLogger.Debug(utils.Format4Output(actList, false))
if err = err2; err != nil {
return nil, err
}
// actInfo, err2 := dao.QueryActs(db, 0, 0, -1, -1, "", vendorID, nil, []int{model.ActCreateTypeSpider},
// nil, 0, 0, 0, utils.DefaultTimeValue, utils.DefaultTimeValue, createdFrom, utils.DefaultTimeValue)
vendorActIDs, err2 := dao.GetExistVendorActIDs(db, vendorID)
if err = err2; err != nil {
return nil, err
}
localActMap := jxutils.StringList2Map(vendorActIDs)
// localActMap := make(map[string]*dao.ActVendorInfo)
// for _, v := range vendorActIDs {
// if v.VendorList[0].VendorActID != "" {
// localActMap[v.VendorList[0].VendorActID] = v
// }
// }
var needAddActList []*model.Act2
// var needUpdateActList []*model.Act
for _, v := range actList {
localAct := localActMap[v.VendorActID]
if localAct == 0 {
if v.Status == model.ActStatusCreated {
needAddActList = append(needAddActList, v)
}
}
// else if v.Status != localAct.Status {
// localAct.Status = v.Status
// needUpdateActList = append(needUpdateActList, &localAct.Act)
// }
}
subTask := tasksch.NewParallelTask("RefreshPageAct Sub", nil, ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
act2 := batchItemList[0].(*model.Act2)
actStoreSkuList, err := handler.GetPageActSkuList(ctx, act2.VendorActID)
if err == nil {
retVal = actStoreSkuList
}
return retVal, err
}, needAddActList)
tasksch.AddChild(task, subTask).Run()
skuList, err2 := subTask.GetResult(0)
if err = err2; err != nil {
return nil, err
}
needAddActSkuMap := make(map[string][]*model.ActStoreSku2)
for _, v := range skuList {
actStoreSku := v.(*model.ActStoreSku2)
needAddActSkuMap[actStoreSku.VendorActID] = append(needAddActSkuMap[actStoreSku.VendorActID], actStoreSku)
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
for _, v := range needAddActList {
if len(needAddActSkuMap[v.VendorActID]) > 0 {
if _, err = createActFromVendor(ctx, db, v, needAddActSkuMap[v.VendorActID]); err != nil {
return nil, err
}
}
}
// for _, v := range needUpdateActList {
// if _, err = dao.UpdateEntity(db, v, model.FieldStatus); err != nil {
// return nil, err
// }
// }
dao.Commit(db)
}
return retVal, err
}, vendorIDs)
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
hint = "1"
_, err = task.GetResult(0)
} else {
hint = task.GetID()
}
return hint, err
}
func DeleteSkusFromAct(ctx *jxcontext.Context, vendorID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
actMap := make(map[int]*model.Act)
for _, skuID := range skuIDs {
pagedInfo, err2 := dao.QueryActs(db, 0, 0, -1, -1, "", vendorID, []int{model.ActStatusCreated}, []int{model.ActSkuDirectDown, model.ActSkuSecKill}, nil, 0, skuID, 0,
utils.DefaultTimeValue, utils.DefaultTimeValue, time.Now().Add(-24*30*3*time.Hour), utils.DefaultTimeValue)
if err = err2; err != nil {
return "", err
}
// globals.SugarLogger.Debug(utils.Format4Output(pagedInfo, false))
for _, v := range pagedInfo.Data {
actMap[v.Act.ID] = &v.Act
}
}
if len(actMap) == 0 {
return "", nil
}
skuIDMap := jxutils.IntList2Map(skuIDs)
var actIDList []int
for k := range actMap {
actIDList = append(actIDList, k)
}
task := tasksch.NewParallelTask("将SKU从所有活动中删除", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
actID := batchItemList[0].(int)
_, actStoreSkuList, err := dao.GetActStoreSkuVendorList(db, actID, []int{-1}, nil, skuIDs, "", 0, -1)
if err == nil {
// db := dao.GetDB()
var deleteList []*ActStoreSkuParam
for _, v := range actStoreSkuList {
if skuIDMap[v.SkuID] == 1 {
deleteList = append(deleteList, &ActStoreSkuParam{
ActStoreSku: model.ActStoreSku{
StoreID: v.StoreID,
SkuID: v.SkuID,
},
})
}
}
if len(deleteList) > 0 {
// globals.SugarLogger.Debug(utils.Format4Output(deleteList, false))
if err = DeleteActStoreSkuBind(ctx, db, actID, deleteList); err == nil {
if _, err = SyncAct(ctx, task, actID, nil, false); err == nil {
retVal = deleteList
}
}
}
}
return retVal, err
}, actIDList)
tasksch.HandleTask(task, nil, true).Run()
if isAsync {
hint = task.GetID()
} else {
resultList, err2 := task.GetResult(0)
if err = err2; err == nil {
hint = utils.Int2Str(len(resultList))
}
}
return hint, err
}