382 lines
12 KiB
Go
382 lines
12 KiB
Go
package act
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"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/globals"
|
||
|
||
"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 (
|
||
ActionTypeNA = 0
|
||
)
|
||
|
||
type ActOrderRuleParam struct {
|
||
SalePrice int64 `orm:"" json:"salePrice"` // 满的价格
|
||
DeductPrice int64 `orm:"" json:"deductPrice"` // 减的价格
|
||
}
|
||
|
||
type ActStoreSkuParam struct {
|
||
model.ActStoreSku
|
||
|
||
Action int // -1删除,1修改,2新增
|
||
}
|
||
|
||
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 := &v.ActStoreSku
|
||
storeSku.ActID = act.ID
|
||
storeSku.OriginalPrice = int64(storeSkuInfo.Price)
|
||
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 {
|
||
dao.Rollback(db)
|
||
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 {
|
||
dao.Rollback(db)
|
||
return 0, err
|
||
}
|
||
isEmptyAct = false
|
||
}
|
||
}
|
||
if isEmptyAct {
|
||
dao.Rollback(db)
|
||
return 0, fmt.Errorf("没有门店及SKU满足需求,空操作")
|
||
}
|
||
dao.Commit(db)
|
||
actID = act.ID
|
||
err = SyncAct(ctx, actID, nil, nil, nil)
|
||
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 parseActStoreSkuParam(actStoreSku []*ActStoreSkuParam) {
|
||
|
||
}
|
||
|
||
func UpdateAct(ctx *jxcontext.Context, act *model.Act, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam) (err error) {
|
||
return err
|
||
}
|
||
|
||
func CancelAct(ctx *jxcontext.Context, actID int) (err error) {
|
||
db := dao.GetDB()
|
||
act := &model.Act{}
|
||
act.ID = actID
|
||
if err = dao.GetEntity(db, act); err != nil {
|
||
return err
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
|
||
dao.UpdateEntityLogically(db, act, map[string]interface{}{
|
||
model.FieldStatus: model.ActStatusCanceled,
|
||
}, ctx.GetUserName(), nil)
|
||
_, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &model.ActMap{}, nil, ctx.GetUserName(), map[string]interface{}{
|
||
model.FieldActID: actID,
|
||
}, model.FieldSyncStatus, model.SyncFlagModifiedMask)
|
||
if err == nil {
|
||
dao.Commit(db)
|
||
globals.SugarLogger.Debugf("CancelAct track:%s", ctx.GetTrackInfo())
|
||
err = SyncAct(ctx, actID, nil, nil, nil)
|
||
} else {
|
||
dao.Rollback(db)
|
||
}
|
||
return err
|
||
}
|
||
|
||
func DeleteActStoreBind(ctx *jxcontext.Context, actID int, actStoreSku []*ActStoreSkuParam) (err error) {
|
||
storeIDMap := make(map[int]int)
|
||
skuIDMap := make(map[int]int)
|
||
actStoreSkuParamMap := make(map[int64]*ActStoreSkuParam)
|
||
for _, v := range actStoreSku {
|
||
storeIDMap[v.StoreID] = 1
|
||
skuIDMap[v.SkuID] = 1
|
||
actStoreSkuParamMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v
|
||
}
|
||
|
||
db := dao.GetDB()
|
||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, jxutils.IntMap2List(storeIDMap), jxutils.IntMap2List(skuIDMap))
|
||
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)
|
||
}
|
||
}
|
||
}()
|
||
for _, v := range actStoreSkuMap {
|
||
for _, storeSku := range v {
|
||
storeSku.SyncStatus |= model.SyncFlagDeletedMask
|
||
if param := actStoreSkuParamMap[jxutils.Combine2Int(storeSku.StoreID, storeSku.SkuID)]; param != nil {
|
||
if _, err = dao.UpdateEntity(db, storeSku); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
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.IsSyncStatusNeedCreate(act.SyncStatus) {
|
||
err = handler.CreateAct(ctx, task, act, actOrderRules, actStore, actStoreSku)
|
||
} else if model.IsSyncStatusNeedUpdate(act.SyncStatus) {
|
||
if act.Status == model.ActStatusCanceled {
|
||
err = handler.CancelAct(ctx, task, act, actStore, actStoreSku)
|
||
} else {
|
||
// 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
|
||
}
|