320 lines
10 KiB
Go
320 lines
10 KiB
Go
package act
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
"git.rosy.net.cn/jx-callback/business/partner"
|
||
|
||
"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"
|
||
)
|
||
|
||
type ActOrderRuleParam struct {
|
||
SalePrice int64 `orm:"" json:"salePrice"` // 满的价格
|
||
DeductPrice int64 `orm:"" json:"deductPrice"` // 减的价格
|
||
}
|
||
|
||
type ActStoreSkuParam struct {
|
||
Action int // -1删除,1修改,2新增
|
||
|
||
StoreID int `orm:"column(store_id)" json:"storeID"`
|
||
SkuID int `orm:"column(sku_id)" json:"skuID"`
|
||
|
||
PricePercentage int `orm:"" json:"pricePercentage"` // 单品级活动用,SKU级的价格比例,非0覆盖Act中的PricePercentage
|
||
ActPrice int64 `orm:"" json:"actPrice"` // 单品级活动用,SKU级指定的价格,非0覆盖CustomPricePercentage与Act中的PricePercentage
|
||
|
||
Stock int `orm:"" json:"stock"` // 订单级活动用
|
||
}
|
||
|
||
type ActDetail struct {
|
||
model.Act2
|
||
}
|
||
|
||
func ActStoreSkuParam2Map(actStoreSku []*ActStoreSkuParam) (actStoreSkuMap map[int][]*ActStoreSkuParam) {
|
||
if len(actStoreSku) > 0 {
|
||
for _, v := range actStoreSku {
|
||
actStoreSkuMap[v.StoreID] = append(actStoreSkuMap[v.StoreID], v)
|
||
}
|
||
}
|
||
return actStoreSkuMap
|
||
}
|
||
|
||
func genStoreSkuMapKey(storeID, skuID int) int64 {
|
||
return int64(storeID) + int64(skuID)*1000000
|
||
}
|
||
|
||
func ActStoreSkuParam2Model(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actStoreSku []*ActStoreSkuParam) (actMapList []*model.ActMap, actStoreMapList []*model.ActStoreMap, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) {
|
||
if len(actStoreSku) > 0 {
|
||
storeIDMap := make(map[int]int)
|
||
skuIDMap := make(map[int]int)
|
||
storeSkuParamMap := make(map[int][]*ActStoreSkuParam)
|
||
for _, v := range actStoreSku {
|
||
storeIDMap[v.StoreID] = 1
|
||
skuIDMap[v.SkuID] = 1
|
||
storeSkuParamMap[v.StoreID] = append(storeSkuParamMap[v.StoreID], v)
|
||
}
|
||
db := dao.GetDB()
|
||
|
||
storeSkuList, err2 := dao.GetStoresSkusInfo(db, jxutils.IntMap2List(storeIDMap), jxutils.IntMap2List(skuIDMap))
|
||
if err = err2; err != nil {
|
||
return nil, nil, nil, nil, err
|
||
}
|
||
storeSkuMap := make(map[int64]*model.StoreSkuBind)
|
||
for _, v := range storeSkuList {
|
||
storeSkuMap[genStoreSkuMapKey(v.StoreID, v.SkuID)] = v
|
||
}
|
||
|
||
wholeValidVendorMap := make(map[int]int)
|
||
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[genStoreSkuMapKey(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||
validVendorMap[vendorID] = 1
|
||
validSkuMap[v.SkuID] = 1
|
||
actSkuMap := &model.ActStoreSkuMap{
|
||
ActID: act.ID,
|
||
StoreID: storeID,
|
||
SkuID: v.SkuID,
|
||
VendorID: vendorID,
|
||
|
||
SyncStatus: model.SyncFlagNewMask,
|
||
}
|
||
if v.ActPrice != 0 {
|
||
actSkuMap.ActualActPrice = v.ActPrice
|
||
} else {
|
||
percentage := act.PricePercentage
|
||
if v.PricePercentage != 0 {
|
||
percentage = v.PricePercentage
|
||
}
|
||
percentage = percentage * int(storeDetail.PricePercentage) / 100
|
||
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(storeSkuInfo.Price, percentage, 0))
|
||
}
|
||
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
|
||
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
|
||
}
|
||
}
|
||
} else if !dao.IsNoRowsError(err) {
|
||
return nil, nil, nil, nil, err
|
||
} else {
|
||
err = nil
|
||
}
|
||
}
|
||
|
||
for _, v := range oneStoreSkuParam {
|
||
if validSkuMap[v.SkuID] == 1 {
|
||
if storeSkuInfo := storeSkuMap[genStoreSkuMapKey(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||
storeSku := &model.ActStoreSku{
|
||
ActID: act.ID,
|
||
StoreID: v.StoreID,
|
||
SkuID: v.SkuID,
|
||
OriginalPrice: int64(storeSkuInfo.Price),
|
||
PricePercentage: v.PricePercentage,
|
||
ActPrice: v.ActPrice,
|
||
Stock: v.Stock,
|
||
}
|
||
dao.WrapAddIDCULDEntity(storeSku, ctx.GetUserName())
|
||
actStoreSkuList = append(actStoreSkuList, storeSku)
|
||
}
|
||
}
|
||
}
|
||
for vendorID := range validVendorMap {
|
||
wholeValidVendorMap[vendorID] = 1
|
||
actStoreMap := &model.ActStoreMap{
|
||
ActID: act.ID,
|
||
StoreID: storeID,
|
||
VendorID: vendorID,
|
||
|
||
SyncStatus: model.SyncFlagNewMask,
|
||
}
|
||
dao.WrapAddIDCULDEntity(actStoreMap, ctx.GetUserName())
|
||
actStoreMapList = append(actStoreMapList, actStoreMap)
|
||
}
|
||
}
|
||
for vendorID := range wholeValidVendorMap {
|
||
actMap := &model.ActMap{
|
||
ActID: act.ID,
|
||
VendorID: vendorID,
|
||
|
||
SyncStatus: model.SyncFlagNewMask,
|
||
}
|
||
dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName())
|
||
actMapList = append(actMapList, actMap)
|
||
}
|
||
}
|
||
return actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList, err
|
||
}
|
||
|
||
func CreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (actID int, err error) {
|
||
vendorIDMap := make(map[int]bool)
|
||
for _, v := range vendorIDs {
|
||
vendorIDMap[v] = true
|
||
}
|
||
db := dao.GetDB()
|
||
dao.WrapAddIDCULDEntity(act, ctx.GetUserName())
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil || err != nil {
|
||
dao.Rollback(db)
|
||
if r != nil {
|
||
panic(r)
|
||
}
|
||
}
|
||
}()
|
||
err = dao.CreateEntity(db, act)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, act, vendorIDs, actStoreSku)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
isEmptyAct := true
|
||
for _, list := range []interface{}{
|
||
actMapList, actStoreMapList, actStoreSkuList, actStoreSkuMapList,
|
||
} {
|
||
if len(utils.Interface2Slice(list)) > 0 {
|
||
err = dao.CreateMultiEntities(db, list)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
isEmptyAct = false
|
||
}
|
||
}
|
||
if isEmptyAct {
|
||
return 0, fmt.Errorf("没有门店及SKU满足需求,空操作")
|
||
}
|
||
dao.Commit(db)
|
||
return actID, err
|
||
}
|
||
|
||
func QueryActs(ctx *jxcontext.Context, actID int, keyword string, statusList []int, actTypeList []int, storeID, skuID int, beginAt, endAt time.Time) (actList []*model.Act, err error) {
|
||
return actList, err
|
||
}
|
||
|
||
func GetActDetail(ctx *jxcontext.Context, actID int) (actDetail *ActDetail, err error) {
|
||
return actDetail, err
|
||
}
|
||
|
||
// func GetAcVendorInfo(ctx *jxcontext.Context, actID int) (err error) {
|
||
// return err
|
||
// }
|
||
|
||
// func GetAcStoresVendorInfo(ctx *jxcontext.Context, actID int, storeIDs []int) (err error) {
|
||
// return err
|
||
// }
|
||
|
||
// func GetAcStoresSkusVendorInfo(ctx *jxcontext.Context, actID int, storeIDs, skuIDs []int) (err error) {
|
||
// return err
|
||
// }
|
||
|
||
func UpdateAct(ctx *jxcontext.Context, act *model.Act, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (err error) {
|
||
return err
|
||
}
|
||
|
||
func DeleteAct(ctx *jxcontext.Context, actID int) (err error) {
|
||
return err
|
||
}
|
||
|
||
func SyncAct(ctx *jxcontext.Context, actID int, vendorIDs, storeIDs, skuIDs []int) (err error) {
|
||
var actOrderRules []*model.ActOrderRule
|
||
db := dao.GetDB()
|
||
actMap, err := dao.GetActVendorInfo(db, actID, vendorIDs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
actStoreMap, err := dao.GetActStoreVendorInfo(db, actID, vendorIDs, storeIDs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, vendorIDs, storeIDs, skuIDs)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
var realVendorIDs []int
|
||
for vendorID := range actMap {
|
||
realVendorIDs = append(realVendorIDs, vendorID)
|
||
}
|
||
|
||
task := tasksch.NewParallelTask("SyncAct", nil, ctx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
vendorID := batchItemList[0].(int)
|
||
handler := partner.GetPurchasePlatformFromVendorID(vendorID)
|
||
if handler == nil {
|
||
err = fmt.Errorf("不被支持的vendorID:%d", vendorID)
|
||
} else {
|
||
act := actMap[vendorID]
|
||
actStore := actStoreMap[vendorID]
|
||
actStoreSku := actStoreSkuMap[vendorID]
|
||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(act, false))
|
||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(actStore, false))
|
||
// globals.SugarLogger.Debugf("%s", utils.Format4Output(actStoreSku, false))
|
||
if act != nil && actStore != nil && actStoreSku != nil {
|
||
if model.IsSyncStatusNeedDelete(act.SyncStatus) {
|
||
if !dao.IsVendorThingIDEmpty(act.VendorActID) {
|
||
}
|
||
} else if model.IsSyncStatusNeedCreate(act.SyncStatus) {
|
||
globals.SugarLogger.Debug("fuck")
|
||
err = handler.CreateAct(ctx, task, act, actOrderRules, actStore, actStoreSku)
|
||
} else /*if model.IsSyncStatusNeedUpdate(act.SyncStatus)*/ {
|
||
actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update := splitActStore(actStore)
|
||
err = handler.UpdateAct(ctx, task, act, actOrderRules, actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update, actStoreSku)
|
||
}
|
||
if err == nil {
|
||
actMap := &model.ActMap{}
|
||
actMap.ID = act.MapID
|
||
dao.UpdateEntityLogically(db, actMap, map[string]interface{}{
|
||
model.FieldSyncStatus: 0,
|
||
model.FieldVendorActID: act.VendorActID,
|
||
}, ctx.GetUserName(), nil)
|
||
for _, v := range actStore {
|
||
storeMap := model.ActStoreMap{}
|
||
storeMap.ID = v.MapID
|
||
dao.UpdateEntityLogically(db, storeMap, map[string]interface{}{
|
||
model.FieldSyncStatus: 0,
|
||
model.FieldVendorActID: v.VendorActID,
|
||
}, ctx.GetUserName(), nil)
|
||
}
|
||
for _, v := range actStoreSku {
|
||
storeSkuMap := model.ActStoreSkuMap{}
|
||
storeSkuMap.ID = v.MapID
|
||
dao.UpdateEntityLogically(db, storeSkuMap, map[string]interface{}{
|
||
model.FieldSyncStatus: 0,
|
||
model.FieldVendorActID: v.VendorActID,
|
||
}, ctx.GetUserName(), nil)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return nil, err
|
||
}, realVendorIDs)
|
||
tasksch.ManageTask(task).Run()
|
||
_, err = task.GetResult(0)
|
||
return err
|
||
}
|
||
|
||
func splitActStore(actStore []*model.ActStore2) (actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update []*model.ActStore2) {
|
||
for _, v := range actStore {
|
||
if model.IsSyncStatusNeedDelete(v.SyncStatus) {
|
||
if !dao.IsVendorThingIDEmpty(v.VendorActID) {
|
||
actStoreMap2Remove = append(actStoreMap2Remove, v)
|
||
}
|
||
} else if model.IsSyncStatusNeedCreate(v.SyncStatus) {
|
||
actStoreMap2Add = append(actStoreMap2Add, v)
|
||
} else if model.IsSyncStatusNeedUpdate(v.SyncStatus) {
|
||
actStoreMap2Update = append(actStoreMap2Update, v)
|
||
}
|
||
}
|
||
return actStoreMap2Remove, actStoreMap2Add, actStoreMap2Update
|
||
}
|