- refactor jxcontent and tasksch (remove dependency from jxcontent to tasksch)

- send dingding msg to user when async task finished
This commit is contained in:
gazebo
2019-03-22 15:04:28 +08:00
parent 0f5445020a
commit 25ac631c5c
31 changed files with 1527 additions and 1488 deletions

View File

@@ -387,3 +387,7 @@ func DisableUser(userID, operatorUserName string) (err error) {
} }
return err return err
} }
func GetUserBindAuthInfo(userID string) (authList []*model.AuthBind, err error) {
return dao.GetUserBindAuthInfo(dao.GetDB(), userID)
}

View File

@@ -41,7 +41,7 @@ func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs []
} }
dao.Commit(db) dao.Commit(db)
rootTask := tasksch.NewParallelTask("SendStoreMessage", nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("SendStoreMessage", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
db := dao.GetDB() db := dao.GetDB()
msgStatus := batchItemList[0].(*model.MessageStatus) msgStatus := batchItemList[0].(*model.MessageStatus)
if err = weixinmsg.NotifyStoreMessage(msgStatus.StoreID, msgStatus.MessageID, msgStatus.ID, msg.Title, msg.Content); err == nil { if err = weixinmsg.NotifyStoreMessage(msgStatus.StoreID, msgStatus.MessageID, msgStatus.ID, msg.Title, msg.Content); err == nil {

View File

@@ -750,40 +750,40 @@ func RefreshMissingDadaStores(ctx *jxcontext.Context, storeID int, isAsync, isCo
if err != nil { if err != nil {
return "", err return "", err
} }
task := tasksch.NewParallelTask("RefreshMissingDadaStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("RefreshMissingDadaStores", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
storeDetail := batchItemList[0].(*dao.StoreDetail2) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
_, err = api.DadaAPI.ShopDetail(utils.Int2Str(storeDetail.ID)) storeDetail := batchItemList[0].(*dao.StoreDetail2)
if err != nil { _, err = api.DadaAPI.ShopDetail(utils.Int2Str(storeDetail.ID))
if codeErr, ok := err.(*utils.ErrorWithCode); ok && codeErr.IntCode() == dadaapi.ResponseCodeShopNotExist { if err != nil {
_, err = api.DadaAPI.ShopAdd(utils.Int2Str(storeDetail.ID), composeDadaStoreName(storeDetail), dadaapi.BusinessTypeConvStore, storeDetail.CityName, if codeErr, ok := err.(*utils.ErrorWithCode); ok && codeErr.IntCode() == dadaapi.ResponseCodeShopNotExist {
storeDetail.DistrictName, storeDetail.Address, jxutils.IntCoordinate2Standard(storeDetail.Lng), jxutils.IntCoordinate2Standard(storeDetail.Lat), _, err = api.DadaAPI.ShopAdd(utils.Int2Str(storeDetail.ID), composeDadaStoreName(storeDetail), dadaapi.BusinessTypeConvStore, storeDetail.CityName,
storeDetail.Tel1, storeDetail.Tel1, nil) storeDetail.DistrictName, storeDetail.Address, jxutils.IntCoordinate2Standard(storeDetail.Lng), jxutils.IntCoordinate2Standard(storeDetail.Lat),
storeDetail.Tel1, storeDetail.Tel1, nil)
}
} else {
params := map[string]interface{}{
"station_name": composeDadaStoreName(storeDetail),
"business": dadaapi.BusinessTypeConvStore,
"city_name": storeDetail.CityName,
"area_name": storeDetail.DistrictName,
"station_address": storeDetail.Address,
"lng": jxutils.IntCoordinate2Standard(storeDetail.Lng),
"lat": jxutils.IntCoordinate2Standard(storeDetail.Lat),
"contact_name": storeDetail.Tel1,
"phone": storeDetail.Tel1,
}
err = api.DadaAPI.ShopUpdate(utils.Int2Str(storeDetail.ID), params)
} }
} else { if err == nil {
params := map[string]interface{}{ db := dao.GetDB()
"station_name": composeDadaStoreName(storeDetail), _, err = AddStoreCourierMap(ctx, db, storeDetail.ID, model.VendorIDDada, &model.StoreCourierMap{
"business": dadaapi.BusinessTypeConvStore, VendorStoreID: utils.Int2Str(storeDetail.ID),
"city_name": storeDetail.CityName, Status: model.StoreStatusOpened,
"area_name": storeDetail.DistrictName, })
"station_address": storeDetail.Address,
"lng": jxutils.IntCoordinate2Standard(storeDetail.Lng),
"lat": jxutils.IntCoordinate2Standard(storeDetail.Lat),
"contact_name": storeDetail.Tel1,
"phone": storeDetail.Tel1,
} }
err = api.DadaAPI.ShopUpdate(utils.Int2Str(storeDetail.ID), params) return nil, err
} }, storeList)
if err == nil { tasksch.HandleTask(task, nil, true).Run()
db := dao.GetDB()
_, err = AddStoreCourierMap(ctx, db, storeDetail.ID, model.VendorIDDada, &model.StoreCourierMap{
VendorStoreID: utils.Int2Str(storeDetail.ID),
Status: model.StoreStatusOpened,
})
}
return nil, err
}, storeList)
ctx.SetTaskOrAddChild(task, nil)
tasksch.ManageTask(task).Run()
hint = task.ID hint = task.ID
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)

View File

@@ -130,29 +130,29 @@ func (v *VendorSync) GetSingleStoreHandler(vendorID int) partner.ISingleStoreHan
func (v *VendorSync) syncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, multiStoresHandler partner.IMultipleStoresHandler, db *dao.DaoDB, cats []*model.SkuCategory, userName string) (err error) { func (v *VendorSync) syncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, multiStoresHandler partner.IMultipleStoresHandler, db *dao.DaoDB, cats []*model.SkuCategory, userName string) (err error) {
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()]) syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
task := tasksch.NewParallelTask("syncCategories", nil, userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.NewParallelTask("syncCategories", nil, ctx,
cat := batchItemList[0].(*model.SkuCategory) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
updateFields := []string{syncStatusFieldName} cat := batchItemList[0].(*model.SkuCategory)
syncStatus := jxutils.GetObjFieldByName(cat, syncStatusFieldName).(int8) updateFields := []string{syncStatusFieldName}
if (syncStatus & model.SyncFlagDeletedMask) != 0 { //删除 syncStatus := jxutils.GetObjFieldByName(cat, syncStatusFieldName).(int8)
err = multiStoresHandler.DeleteCategory(db, cat, userName) if (syncStatus & model.SyncFlagDeletedMask) != 0 { //删除
} else if (syncStatus & model.SyncFlagNewMask) != 0 { // 新增 err = multiStoresHandler.DeleteCategory(db, cat, userName)
err = multiStoresHandler.CreateCategory(db, cat, userName) } else if (syncStatus & model.SyncFlagNewMask) != 0 { // 新增
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()])) err = multiStoresHandler.CreateCategory(db, cat, userName)
} else if (syncStatus & model.SyncFlagModifiedMask) != 0 { // 修改 updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
err = multiStoresHandler.UpdateCategory(db, cat, userName) } else if (syncStatus & model.SyncFlagModifiedMask) != 0 { // 修改
if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.IntCode() == -3 { err = multiStoresHandler.UpdateCategory(db, cat, userName)
err = nil if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.IntCode() == -3 {
err = nil
}
} }
} if err == nil {
if err == nil { jxutils.SetObjFieldByName(cat, syncStatusFieldName, int8(0))
jxutils.SetObjFieldByName(cat, syncStatusFieldName, int8(0)) _, err = dao.UpdateEntity(db, cat, updateFields...)
_, err = dao.UpdateEntity(db, cat, updateFields...) }
} return nil, err
return nil, err }, cats)
}, cats) tasksch.HandleTask(task, parentTask, false).Run()
ctx.SetTaskOrAddChild(task, parentTask)
task.Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
return err return err
} }
@@ -212,14 +212,15 @@ func (v *VendorSync) SyncStore(ctx *jxcontext.Context, db *dao.DaoDB, vendorID,
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
handler := v.GetStoreHandler(loopMapInfo.VendorID) handler := v.GetStoreHandler(loopMapInfo.VendorID)
if len(loopMapInfo.StoreMapList) > 1 { if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewParallelTask(fmt.Sprintf("SyncStore loop store %s", model.VendorChineseNames[loopMapInfo.VendorID]), nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { loopStoreTask := tasksch.NewParallelTask(fmt.Sprintf("SyncStore loop store %s", model.VendorChineseNames[loopMapInfo.VendorID]), nil, ctx,
storeMap := batchItemList[0].(*model.StoreMap) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if err = handler.UpdateStore(db, storeMap.StoreID, userName); err == nil { storeMap := batchItemList[0].(*model.StoreMap)
storeMap.SyncStatus = 0 if err = handler.UpdateStore(db, storeMap.StoreID, userName); err == nil {
_, err = dao.UpdateEntity(db, storeMap, model.FieldSyncStatus) storeMap.SyncStatus = 0
} _, err = dao.UpdateEntity(db, storeMap, model.FieldSyncStatus)
return nil, err }
}, loopMapInfo.StoreMapList) return nil, err
}, loopMapInfo.StoreMapList)
t.AddChild(loopStoreTask).Run() t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0) _, err = loopStoreTask.GetResult(0)
return nil, err return nil, err
@@ -262,51 +263,52 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
err := dao.GetRows(db, &skuNameList, sql, sqlParams...) err := dao.GetRows(db, &skuNameList, sql, sqlParams...)
if err == nil && len(skuNameList) > 0 { if err == nil && len(skuNameList) > 0 {
// todo 同一skuName下的sku顺序处理的原因是京东SPU特殊类型必须要序列化同步才能正常处理, db可能会有多线程问题 // todo 同一skuName下的sku顺序处理的原因是京东SPU特殊类型必须要序列化同步才能正常处理, db可能会有多线程问题
task := tasksch.NewParallelTask("SyncSku loop sku", tasksch.NewParallelConfig().SetParallelCount(10).SetIsContinueWhenError(isContinueWhenError), userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.NewParallelTask("SyncSku loop sku", tasksch.NewParallelConfig().SetParallelCount(10).SetIsContinueWhenError(isContinueWhenError), ctx,
skuName := batchItemList[0].(*model.SkuName) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var skuList []*model.Sku skuName := batchItemList[0].(*model.SkuName)
if err = dao.GetRows(db, &skuList, fmt.Sprintf(` var skuList []*model.Sku
if err = dao.GetRows(db, &skuList, fmt.Sprintf(`
SELECT * SELECT *
FROM sku FROM sku
WHERE name_id = ? AND %s_sync_status <> 0 WHERE name_id = ? AND %s_sync_status <> 0
ORDER BY IF(spec_unit IN('kg', 'L'), 1000, 1) * spec_quality ORDER BY IF(spec_unit IN('kg', 'L'), 1000, 1) * spec_quality
`, dbField), skuName.ID); err == nil && len(skuList) > 0 { `, dbField), skuName.ID); err == nil && len(skuList) > 0 {
for _, sku := range skuList { for _, sku := range skuList {
syncStatus := jxutils.GetObjFieldByName(sku, syncStatusFieldName).(int8) syncStatus := jxutils.GetObjFieldByName(sku, syncStatusFieldName).(int8)
if (skuID == -1 || skuID == sku.ID) && (syncStatus != 0) { if (skuID == -1 || skuID == sku.ID) && (syncStatus != 0) {
updateFields := []string{syncStatusFieldName} updateFields := []string{syncStatusFieldName}
if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除 if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除
err = multiStoresHandler.DeleteSku(db, sku, userName) err = multiStoresHandler.DeleteSku(db, sku, userName)
} else if syncStatus&model.SyncFlagNewMask != 0 { // 新增 } else if syncStatus&model.SyncFlagNewMask != 0 { // 新增
if err = multiStoresHandler.CreateSku(db, sku, userName); err == nil { if err = multiStoresHandler.CreateSku(db, sku, userName); err == nil {
var tmpStruct struct { var tmpStruct struct {
MaxIndex int MaxIndex int
}
// todo hard code 得到京东spu中sku的顺序以方便以后修改销售属性这个必须要每次重新从数据库取
if dao.GetRow(db, &tmpStruct, "SELECT MAX(sku_index) max_index FROM sku WHERE name_id = ? AND jd_id > 0 AND jd_id < 4024012631406 ", sku.NameID) == nil {
sku.SkuIndex = tmpStruct.MaxIndex + 1
updateFields = append(updateFields, "SkuIndex")
}
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
} }
// todo hard code 得到京东spu中sku的顺序以方便以后修改销售属性这个必须要每次重新从数据库取 } else if syncStatus&model.SyncFlagModifiedMask != 0 { // 修改
if dao.GetRow(db, &tmpStruct, "SELECT MAX(sku_index) max_index FROM sku WHERE name_id = ? AND jd_id > 0 AND jd_id < 4024012631406 ", sku.NameID) == nil { err = multiStoresHandler.UpdateSku(db, sku, userName)
sku.SkuIndex = tmpStruct.MaxIndex + 1
updateFields = append(updateFields, "SkuIndex")
}
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[multiStoresHandler.GetVendorID()]))
} }
} else if syncStatus&model.SyncFlagModifiedMask != 0 { // 修改 if err == nil {
err = multiStoresHandler.UpdateSku(db, sku, userName) jxutils.SetObjFieldByName(sku, syncStatusFieldName, int8(0))
} if _, err = dao.UpdateEntity(db, sku, updateFields...); err != nil {
if err == nil { break
jxutils.SetObjFieldByName(sku, syncStatusFieldName, int8(0)) }
if _, err = dao.UpdateEntity(db, sku, updateFields...); err != nil {
break
} }
} }
} }
} }
} if err == nil {
if err == nil { jxutils.SetObjFieldByName(skuName, syncStatusFieldName, int8(0))
jxutils.SetObjFieldByName(skuName, syncStatusFieldName, int8(0)) _, err = dao.UpdateEntity(db, skuName, syncStatusFieldName)
_, err = dao.UpdateEntity(db, skuName, syncStatusFieldName) }
} return nil, err
return nil, err }, skuNameList)
}, skuNameList)
t.AddChild(task).Run() t.AddChild(task).Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
@@ -320,11 +322,12 @@ func (v *VendorSync) SyncStoresCategory(ctx *jxcontext.Context, db *dao.DaoDB, v
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
if handler := v.GetSingleStoreHandler(loopMapInfo.VendorID); handler != nil { if handler := v.GetSingleStoreHandler(loopMapInfo.VendorID); handler != nil {
if len(loopMapInfo.StoreMapList) > 1 { if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewSeqTask("SyncStoresCategory loop stores", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { loopStoreTask := tasksch.NewSeqTask("SyncStoresCategory loop stores", ctx,
storeID := loopMapInfo.StoreMapList[step].StoreID func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
_, err = handler.SyncStoreCategory(ctx, task, storeID, false) storeID := loopMapInfo.StoreMapList[step].StoreID
return nil, err _, err = handler.SyncStoreCategory(ctx, task, storeID, false)
}, len(loopMapInfo.StoreMapList)) return nil, err
}, len(loopMapInfo.StoreMapList))
t.AddChild(loopStoreTask).Run() t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0) _, err = loopStoreTask.GetResult(0)
return nil, err return nil, err
@@ -342,16 +345,17 @@ func (v *VendorSync) SyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendo
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil { if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
if len(loopMapInfo.StoreMapList) > 1 { if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewSeqTask("SyncStoresSkus相同平台循环门店", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { loopStoreTask := tasksch.NewSeqTask("SyncStoresSkus相同平台循环门店", ctx,
storeID := loopMapInfo.StoreMapList[step].StoreID func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
if _, err = handler.SyncStoreSkus(ctx, task, storeID, skuIDs, false, isContinueWhenError); err != nil { storeID := loopMapInfo.StoreMapList[step].StoreID
globals.SugarLogger.Debugf("SyncStoresSkus failed1 store:%d failed with error:%v", storeID, err) if _, err = handler.SyncStoreSkus(ctx, task, storeID, skuIDs, false, isContinueWhenError); err != nil {
if isContinueWhenError { globals.SugarLogger.Debugf("SyncStoresSkus failed1 store:%d failed with error:%v", storeID, err)
err = nil if isContinueWhenError {
err = nil
}
} }
} return nil, err
return nil, err }, len(loopMapInfo.StoreMapList))
}, len(loopMapInfo.StoreMapList))
t.AddChild(loopStoreTask).Run() t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0) _, err = loopStoreTask.GetResult(0)
return nil, err return nil, err
@@ -368,11 +372,12 @@ func (v *VendorSync) FullSyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, v
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil { if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
if len(loopMapInfo.StoreMapList) > 1 { if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewSeqTask("FullSyncStoresSkus相同平台循环门店", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { loopStoreTask := tasksch.NewSeqTask("FullSyncStoresSkus相同平台循环门店", ctx,
storeID := loopMapInfo.StoreMapList[step].StoreID func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
_, err = handler.FullSyncStoreSkus(ctx, task, storeID, false, isContinueWhenError) storeID := loopMapInfo.StoreMapList[step].StoreID
return nil, err _, err = handler.FullSyncStoreSkus(ctx, task, storeID, false, isContinueWhenError)
}, len(loopMapInfo.StoreMapList)) return nil, err
}, len(loopMapInfo.StoreMapList))
t.AddChild(loopStoreTask).Run() t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0) _, err = loopStoreTask.GetResult(0)
return nil, err return nil, err
@@ -389,11 +394,12 @@ func (v *VendorSync) DeleteRemoteStoreSkus(ctx *jxcontext.Context, db *dao.DaoDB
loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) loopMapInfo := batchItemList[0].(*LoopStoreMapInfo)
if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil { if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil {
if len(loopMapInfo.StoreMapList) > 1 { if len(loopMapInfo.StoreMapList) > 1 {
loopStoreTask := tasksch.NewSeqTask("DeleteRemoteStoreSkus相同平台循环门店", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { loopStoreTask := tasksch.NewSeqTask("DeleteRemoteStoreSkus相同平台循环门店", ctx,
storeID := loopMapInfo.StoreMapList[step].StoreID func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
_, err = handler.DeleteRemoteStoreSkus(ctx, task, storeID, false, isContinueWhenError) storeID := loopMapInfo.StoreMapList[step].StoreID
return nil, err _, err = handler.DeleteRemoteStoreSkus(ctx, task, storeID, false, isContinueWhenError)
}, len(loopMapInfo.StoreMapList)) return nil, err
}, len(loopMapInfo.StoreMapList))
t.AddChild(loopStoreTask).Run() t.AddChild(loopStoreTask).Run()
_, err = loopStoreTask.GetResult(0) _, err = loopStoreTask.GetResult(0)
return nil, err return nil, err
@@ -443,9 +449,8 @@ func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskNa
} }
index++ index++
} }
task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx.GetUserName(), handler, loopInfoList) task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, loopInfoList)
ctx.SetTaskOrAddChild(task, nil) tasksch.HandleTask(task, nil, true).Run()
tasksch.ManageTask(task).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
@@ -453,62 +458,28 @@ func (v *VendorSync) LoopStoresMap(ctx *jxcontext.Context, db *dao.DaoDB, taskNa
} }
func (v *VendorSync) LoopMultiStoresVendors(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync bool, userName string, handler tasksch.WorkFunc) (hint string, err error) { func (v *VendorSync) LoopMultiStoresVendors(ctx *jxcontext.Context, db *dao.DaoDB, taskName string, isAsync bool, userName string, handler tasksch.WorkFunc) (hint string, err error) {
task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), userName, handler, v.MultiStoreVendorIDs) task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, handler, v.MultiStoreVendorIDs)
ctx.SetTaskOrAddChild(task, nil) tasksch.HandleTask(task, nil, true).Run()
tasksch.ManageTask(task).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
return task.ID, makeSyncError(err) return task.ID, makeSyncError(err)
} }
// func (v *VendorSync) LoopStoreVendors(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs []int, taskName string, isAsync bool, userName string, handler tasksch.WorkFunc) (hint string, err error) {
// if taskName == "" {
// taskName = "LoopStoreVendors"
// }
// var vendorIDMap map[int]int
// if len(vendorIDs) != 0 {
// vendorIDMap = make(map[int]int)
// for _, v := range vendorIDs {
// vendorIDMap[v] = 1
// }
// }
// allHandlers := make([]int, len(v.MultiStoreVendorIDs)+len(v.SingleStoreVendorIDs))
// copy(allHandlers, v.MultiStoreVendorIDs)
// copy(allHandlers[len(v.MultiStoreVendorIDs):], v.SingleStoreVendorIDs)
// if vendorIDMap != nil {
// count := 0
// for _, v := range allHandlers {
// if vendorIDMap[v] == 1 {
// allHandlers[count] = v
// count++
// }
// }
// allHandlers = allHandlers[:count]
// }
// task := tasksch.NewParallelTask(taskName, nil, userName, handler, allHandlers)
// ctx.SetTaskOrAddChild(task, nil)
// tasksch.ManageTask(task).Run()
// if !isAsync {
// _, err = task.GetResult(0)
// }
// return task.ID, err
// }
func (v *VendorSync) RefreshAllSkusID(ctx *jxcontext.Context, isAsync bool, vendorIDs []int, storeIDs []int) (hint string, err error) { func (v *VendorSync) RefreshAllSkusID(ctx *jxcontext.Context, isAsync bool, vendorIDs []int, storeIDs []int) (hint string, err error) {
task := tasksch.NewParallelTask("RefreshAllSkusID", nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("RefreshAllSkusID", nil, ctx,
vendorID := batchItemList[0].(int) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if handler := v.GetStoreHandler(vendorID); handler != nil { vendorID := batchItemList[0].(int)
if multiHandler, ok := handler.(partner.IMultipleStoresHandler); ok { if handler := v.GetStoreHandler(vendorID); handler != nil {
_, err = multiHandler.RefreshAllSkusID(ctx, task, false) if multiHandler, ok := handler.(partner.IMultipleStoresHandler); ok {
} else if singleHandler, ok := handler.(partner.ISingleStoreHandler); ok { _, err = multiHandler.RefreshAllSkusID(ctx, task, false)
_, err = singleHandler.RefreshStoresAllSkusID(ctx, task, false, storeIDs) } else if singleHandler, ok := handler.(partner.ISingleStoreHandler); ok {
_, err = singleHandler.RefreshStoresAllSkusID(ctx, task, false, storeIDs)
}
} }
} return nil, err
return nil, err }, vendorIDs)
}, vendorIDs) tasksch.HandleTask(task, nil, true).Run()
ctx.SetTaskOrAddChild(task, nil)
tasksch.ManageTask(task).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
@@ -516,15 +487,15 @@ func (v *VendorSync) RefreshAllSkusID(ctx *jxcontext.Context, isAsync bool, vend
} }
func (v *VendorSync) RefreshAllStoresID(ctx *jxcontext.Context, isAsync bool, vendorIDs []int) (hint string, err error) { func (v *VendorSync) RefreshAllStoresID(ctx *jxcontext.Context, isAsync bool, vendorIDs []int) (hint string, err error) {
task := tasksch.NewParallelTask("RefreshAllStoresID", nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("RefreshAllStoresID", nil, ctx,
vendorID := batchItemList[0].(int) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if handler := v.GetStoreHandler(vendorID); handler != nil { vendorID := batchItemList[0].(int)
_, err = handler.RefreshAllStoresID(ctx, task, false) if handler := v.GetStoreHandler(vendorID); handler != nil {
} _, err = handler.RefreshAllStoresID(ctx, task, false)
return nil, err }
}, vendorIDs) return nil, err
ctx.SetTaskOrAddChild(task, nil) }, vendorIDs)
tasksch.ManageTask(task).Run() tasksch.HandleTask(task, nil, true).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }

View File

@@ -100,7 +100,7 @@ func RegisterUser(user *model.User, mobileVerifyCode string, inAuthInfo *auth2.A
func GetUserBindAuthInfo(ctx *jxcontext.Context) (authList []*model.AuthBind, err error) { func GetUserBindAuthInfo(ctx *jxcontext.Context) (authList []*model.AuthBind, err error) {
authInfo, err := ctx.GetV2AuthInfo() authInfo, err := ctx.GetV2AuthInfo()
if err == nil { if err == nil {
return dao.GetUserBindAuthInfo(dao.GetDB(), authInfo.GetID()) return auth2.GetUserBindAuthInfo(authInfo.GetID())
} }
return nil, err return nil, err
} }

View File

@@ -52,51 +52,51 @@ func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, ti
} }
upToken := putPolicy.UploadToken(api.QiniuAPI) upToken := putPolicy.UploadToken(api.QiniuAPI)
cfg := &storage.Config{} cfg := &storage.Config{}
task := tasksch.NewParallelTask("SendFilesToStores", tasksch.NewParallelConfig().SetIsContinueWhenError(true), userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("SendFilesToStores", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
fileInfo := batchItemList[0].(*tUploadFileInfo) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
fileHeader := fileInfo.FileHeader fileInfo := batchItemList[0].(*tUploadFileInfo)
storeID := fileInfo.StoreID fileHeader := fileInfo.FileHeader
file, err := fileHeader.Open() storeID := fileInfo.StoreID
globals.SugarLogger.Debugf("SendFilesToStores upload file:%s", fileHeader.Filename) file, err := fileHeader.Open()
if err == nil { globals.SugarLogger.Debugf("SendFilesToStores upload file:%s", fileHeader.Filename)
ret := storage.PutRet{}
key := "storeBill_" + utils.Int2Str(storeID) + "_" + strings.ToLower(utils.GetUUID()) + path.Ext(fileHeader.Filename)
formUploader := storage.NewFormUploader(cfg)
for i := 0; i < 3; i++ {
if err = formUploader.Put(context.Background(), &ret, upToken, key, file, fileHeader.Size, nil); err == nil {
break
}
}
file.Close()
if err == nil { if err == nil {
db := dao.GetDB() ret := storage.PutRet{}
billRec := &legacymodel.StoreBill{ key := "storeBill_" + utils.Int2Str(storeID) + "_" + strings.ToLower(utils.GetUUID()) + path.Ext(fileHeader.Filename)
Date: time.Now(), formUploader := storage.NewFormUploader(cfg)
Url: jxutils.ComposeQiniuResURL(ret.Key), for i := 0; i < 3; i++ {
StoreId: storeID, if err = formUploader.Put(context.Background(), &ret, upToken, key, file, fileHeader.Size, nil); err == nil {
BillName: fileHeader.Filename, break
ShopName: shopName, }
BillTitle: title, }
} file.Close()
if err = dao.CreateEntity(db, billRec); err == nil { if err == nil {
err = weixinmsg.NotifySaleBill(storeID, title, shopName, "http://www.jxc4.com/billshow/?path="+billRec.Url) db := dao.GetDB()
if err != nil { billRec := &legacymodel.StoreBill{
globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err) Date: time.Now(),
Url: jxutils.ComposeQiniuResURL(ret.Key),
StoreId: storeID,
BillName: fileHeader.Filename,
ShopName: shopName,
BillTitle: title,
}
if err = dao.CreateEntity(db, billRec); err == nil {
err = weixinmsg.NotifySaleBill(storeID, title, shopName, "http://www.jxc4.com/billshow/?path="+billRec.Url)
if err != nil {
globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err)
}
err = nil // 忽略微信发送错误
} else {
globals.SugarLogger.Warnf("SendFilesToStores CreateEntity file:%s error:%v", fileHeader.Filename, err)
} }
err = nil // 忽略微信发送错误
} else { } else {
globals.SugarLogger.Warnf("SendFilesToStores CreateEntity file:%s error:%v", fileHeader.Filename, err) globals.SugarLogger.Warnf("SendFilesToStores file:%s failed with error:%v", fileHeader.Filename, err)
} }
} else { } else {
globals.SugarLogger.Warnf("SendFilesToStores file:%s failed with error:%v", fileHeader.Filename, err) globals.SugarLogger.Warnf("SendFilesToStores open file:%s failed with error:%v", fileHeader.Filename, err)
} }
} else { return retVal, err
globals.SugarLogger.Warnf("SendFilesToStores open file:%s failed with error:%v", fileHeader.Filename, err) }, fileList)
} tasksch.HandleTask(task, nil, true).Run()
return retVal, err
}, fileList)
ctx.SetTaskOrAddChild(task, nil)
tasksch.ManageTask(task).Run()
hint = task.ID hint = task.ID
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)

View File

@@ -147,22 +147,23 @@ func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError b
return "", err return "", err
} }
task := tasksch.NewParallelTask("InitSkuName calculate md5", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("InitSkuName calculate md5", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
skuName := batchItemList[0].(*model.SkuName) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if skuName.ImgHashCode == "" || isForce { skuName := batchItemList[0].(*model.SkuName)
response, err := http.Get(skuName.Img) if skuName.ImgHashCode == "" || isForce {
if err == nil { response, err := http.Get(skuName.Img)
defer response.Body.Close() if err == nil {
data, err2 := ioutil.ReadAll(response.Body) defer response.Body.Close()
if err = err2; err == nil { data, err2 := ioutil.ReadAll(response.Body)
skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data)) if err = err2; err == nil {
db := dao.GetDB() skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data))
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode") db := dao.GetDB()
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode")
}
} }
} }
} return nil, err
return nil, err }, skuNameList)
}, skuNameList)
tasksch.ManageTask(task).Run() tasksch.ManageTask(task).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
@@ -207,17 +208,18 @@ func UploadWeimobImg4SkuName(ctx *jxcontext.Context, nameIDs []int, isAsync, isC
if err != nil { if err != nil {
return "", err return "", err
} }
rootTask := tasksch.NewParallelTask("UploadWeimobImg4SkuName", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("UploadWeimobImg4SkuName", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx,
skuName := batchItemList[0].(*model.SkuName) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if skuName.Img != "" && skuName.ImgWeimob == "" { skuName := batchItemList[0].(*model.SkuName)
if globals.EnableWscStoreWrite { if skuName.Img != "" && skuName.ImgWeimob == "" {
if skuName.ImgWeimob, err = api.WeimobAPI.UploadImgByURL(skuName.Img, ""); err == nil { if globals.EnableWscStoreWrite {
_, err = dao.UpdateEntity(db, skuName, "ImgWeimob") if skuName.ImgWeimob, err = api.WeimobAPI.UploadImgByURL(skuName.Img, ""); err == nil {
_, err = dao.UpdateEntity(db, skuName, "ImgWeimob")
}
} }
} }
} return nil, err
return nil, err }, skuNameList)
}, skuNameList)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
@@ -350,76 +352,77 @@ func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, i
} }
cfg := &storage.Config{} cfg := &storage.Config{}
upToken := putPolicy.UploadToken(api.QiniuAPI) upToken := putPolicy.UploadToken(api.QiniuAPI)
rootTask := tasksch.NewSeqTask("BuildSkuFromEbaiStore", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("BuildSkuFromEbaiStore", ctx,
var catID string func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
cat := skuCatList[step] var catID string
skuNameExtList := allSkuInfo2[cat] cat := skuCatList[step]
catID, err = addShopCategory(0, cat.Name, int(cat.Level), cat.Seq, ctx.GetUserName()) skuNameExtList := allSkuInfo2[cat]
if err == nil { catID, err = addShopCategory(0, cat.Name, int(cat.Level), cat.Seq, ctx.GetUserName())
shopCategories := []int64{utils.Str2Int64(catID)} if err == nil {
for _, skuNameExt := range skuNameExtList { shopCategories := []int64{utils.Str2Int64(catID)}
var imgContent []byte for _, skuNameExt := range skuNameExtList {
skuNameExt.CategoryID = cat.ID var imgContent []byte
skuNameExt.Img = strings.Replace(skuNameExt.Img, "https://", "http://", 1) skuNameExt.CategoryID = cat.ID
if imgContent, _, err = jxutils.DownloadFileByURL(skuNameExt.Img); err != nil { skuNameExt.Img = strings.Replace(skuNameExt.Img, "https://", "http://", 1)
globals.SugarLogger.Infof("download pic %s failed with error:%v", skuNameExt.Img, err) if imgContent, _, err = jxutils.DownloadFileByURL(skuNameExt.Img); err != nil {
if !isContinueWhenError { globals.SugarLogger.Infof("download pic %s failed with error:%v", skuNameExt.Img, err)
return nil, err
}
err = nil
continue
}
formUploader := storage.NewFormUploader(cfg)
ret := storage.PutRet{}
key := jxutils.GenPicFileName(".jpeg")
for i := 0; i < 3; i++ {
if err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(imgContent), int64(len(imgContent)), nil); err == nil {
break
}
}
if err != nil {
globals.SugarLogger.Infof("upload pic %s failed with error:%v", skuNameExt.Img, err)
if !isContinueWhenError {
return nil, err
}
err = nil
continue
}
qiniuImgURL := "http://image.jxc4.com/" + key + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800"
for _, sku := range skuNameExt.Skus {
jdCatID := 22410 // 其他国产水果
if cat.Name == "进口水果" {
jdCatID = 20342 // 其他进口水果
}
price := sku.LinkID
sku.LinkID = 0
skuName := jxutils.ComposeSkuName(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameLen)
fixedStatus := 1
if sku.Status != model.SkuStatusNormal {
fixedStatus = 2
}
var vendorSkuID string
vendorSkuID, err = addSku(utils.Int2Str(startOutSkuID), jdCatID, shopCategories, jd.DefBrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{qiniuImgURL}, fixedStatus, true, nil)
if err == nil {
globals.SugarLogger.Debugf("vendorSkuID=%s", vendorSkuID)
} else {
globals.SugarLogger.Infof("create %s failed with error:%v", skuName, err)
if !isContinueWhenError { if !isContinueWhenError {
return nil, err return nil, err
} }
err = nil err = nil
continue
}
formUploader := storage.NewFormUploader(cfg)
ret := storage.PutRet{}
key := jxutils.GenPicFileName(".jpeg")
for i := 0; i < 3; i++ {
if err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(imgContent), int64(len(imgContent)), nil); err == nil {
break
}
}
if err != nil {
globals.SugarLogger.Infof("upload pic %s failed with error:%v", skuNameExt.Img, err)
if !isContinueWhenError {
return nil, err
}
err = nil
continue
}
qiniuImgURL := "http://image.jxc4.com/" + key + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800"
for _, sku := range skuNameExt.Skus {
jdCatID := 22410 // 其他国产水果
if cat.Name == "进口水果" {
jdCatID = 20342 // 其他进口水果
}
price := sku.LinkID
sku.LinkID = 0
skuName := jxutils.ComposeSkuName(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameLen)
fixedStatus := 1
if sku.Status != model.SkuStatusNormal {
fixedStatus = 2
}
var vendorSkuID string
vendorSkuID, err = addSku(utils.Int2Str(startOutSkuID), jdCatID, shopCategories, jd.DefBrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{qiniuImgURL}, fixedStatus, true, nil)
if err == nil {
globals.SugarLogger.Debugf("vendorSkuID=%s", vendorSkuID)
} else {
globals.SugarLogger.Infof("create %s failed with error:%v", skuName, err)
if !isContinueWhenError {
return nil, err
}
err = nil
}
// fmt.Printf("%s,[%s]%s-%f-%s, %s, %s\n", cat.Name, skuNameExt.Prefix, skuNameExt.Name, skuNameExt.SpecQuality, skuNameExt.SpecUnit, qiniuImgURL, skuName)
startOutSkuID++
// rootTask.Cancel()
// return nil, nil
} }
// fmt.Printf("%s,[%s]%s-%f-%s, %s, %s\n", cat.Name, skuNameExt.Prefix, skuNameExt.Name, skuNameExt.SpecQuality, skuNameExt.SpecUnit, qiniuImgURL, skuName)
startOutSkuID++
// rootTask.Cancel()
// return nil, nil
} }
} else {
return nil, err
} }
} else {
return nil, err return nil, err
} }, len(skuCatList))
return nil, err
}, len(skuCatList))
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)

View File

@@ -424,64 +424,66 @@ func CreateJdPromotion(ctx *jxcontext.Context, isIDJd bool, isAsync, isContinueW
} }
dao.Commit(db) dao.Commit(db)
rootTask := tasksch.NewSeqTask("CreateJdPromotion", userName, func(task *tasksch.SeqTask, step int, params2 ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("CreateJdPromotion", ctx,
if step == 0 { func(task *tasksch.SeqTask, step int, params2 ...interface{}) (result interface{}, err error) {
task1 := tasksch.NewParallelTask("CreateJdPromotion update sku price", nil, userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) { if step == 0 {
storeID := batchItemList[0].(int) task1 := tasksch.NewParallelTask("CreateJdPromotion update sku price", nil, ctx,
modifyPricesList := jxutils.SplitSlice(modifyPricesList[storeID], jdapi.MaxStoreSkuBatchSize) func(t *tasksch.ParallelTask, batchItemList []interface{}, params2 ...interface{}) (retVal interface{}, err error) {
for _, modifyPrices := range modifyPricesList { storeID := batchItemList[0].(int)
modifyPrices2 := make([]*jdapi.SkuPriceInfo, len(modifyPrices)) modifyPricesList := jxutils.SplitSlice(modifyPricesList[storeID], jdapi.MaxStoreSkuBatchSize)
for k, v := range modifyPrices { for _, modifyPrices := range modifyPricesList {
modifyPrices2[k] = v.(*jdapi.SkuPriceInfo) modifyPrices2 := make([]*jdapi.SkuPriceInfo, len(modifyPrices))
} for k, v := range modifyPrices {
if globals.EnableStoreWrite { modifyPrices2[k] = v.(*jdapi.SkuPriceInfo)
if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil { }
return nil, err if globals.EnableStoreWrite {
if _, err = api.JdAPI.UpdateVendorStationPrice(utils.Int2Str(storeID), "", modifyPrices2); err != nil {
return nil, err
}
}
} }
return nil, nil
}, jxStoreIDs)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
} else if step == 1 {
err = promotionHandler.CreatePromotionRules(infoId, "", limitDevice, limitPin, limitCount, limitDaily)
} else if step == 2 {
task2 := tasksch.NewParallelTask("CreateJdPromotion CreatePromotionSku", tasksch.NewParallelConfig().SetBatchSize(MaxPromotionSkuCount).SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params2 ...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)
task.AddChild(task2).Run()
_, err = task2.GetResult(0)
if isContinueWhenError && err != nil { // todo isContinueWhenError为true时强制忽略此步的错误
err = nil
}
} else if step == 3 {
err = promotionHandler.ConfirmPromotion(infoId, "")
if err == nil {
db := dao.GetDB()
if _, err = dao.UpdateEntityLogically(db, promotion, map[string]interface{}{
model.FieldStatus: model.PromotionStatusRemoteCreated,
}, ctx.GetUserName(), nil); err == nil {
RefreshJdPromotionLockStatus(ctx, promotion.ID)
} }
} }
return nil, nil
}, jxStoreIDs)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
} else if step == 1 {
err = promotionHandler.CreatePromotionRules(infoId, "", limitDevice, limitPin, limitCount, limitDaily)
} else if step == 2 {
task2 := tasksch.NewParallelTask("CreateJdPromotion CreatePromotionSku", tasksch.NewParallelConfig().SetBatchSize(MaxPromotionSkuCount).SetIsContinueWhenError(isContinueWhenError), userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params2 ...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)
task.AddChild(task2).Run()
_, err = task2.GetResult(0)
if isContinueWhenError && err != nil { // todo isContinueWhenError为true时强制忽略此步的错误
err = nil
} }
} else if step == 3 { if err != nil {
err = promotionHandler.ConfirmPromotion(infoId, "")
if err == nil {
db := dao.GetDB() db := dao.GetDB()
if _, err = dao.UpdateEntityLogically(db, promotion, map[string]interface{}{ dao.UpdateEntityLogically(db, promotion, map[string]interface{}{
model.FieldStatus: model.PromotionStatusRemoteCreated, model.FieldStatus: model.PromotionStatusRemoteFailed,
}, ctx.GetUserName(), nil); err == nil { model.FieldRemark: err.Error(),
RefreshJdPromotionLockStatus(ctx, promotion.ID) }, ctx.GetUserName(), nil)
}
} }
} return nil, err
if err != nil { }, 4)
db := dao.GetDB() tasksch.HandleTask(rootTask, nil, true).Run()
dao.UpdateEntityLogically(db, promotion, map[string]interface{}{
model.FieldStatus: model.PromotionStatusRemoteFailed,
model.FieldRemark: err.Error(),
}, ctx.GetUserName(), nil)
}
return nil, err
}, 4)
ctx.SetTaskOrAddChild(rootTask, nil)
tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
} }
@@ -745,32 +747,33 @@ func RefreshJdStoreSkuStock(promotionID int, skuIDs []int) (err error) {
} }
globals.SugarLogger.Debugf("RefreshJdStoreSkuStock promotionID:%d, len(promotionItemList)=%d", promotionID, len(promotionItemList)) globals.SugarLogger.Debugf("RefreshJdStoreSkuStock promotionID:%d, len(promotionItemList)=%d", promotionID, len(promotionItemList))
if len(promotionItemList) > 0 { if len(promotionItemList) > 0 {
task := tasksch.NewParallelTask("RefreshJdStoreSkuStock", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(true), "schedule", func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("RefreshJdStoreSkuStock", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(true), jxcontext.AdminCtx,
stockList := make([]*jdapi.SkuStock, 0) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
stationNo := batchItemList[0].(*tPromotionItemInfo).JdStoreID stockList := make([]*jdapi.SkuStock, 0)
for _, v := range batchItemList { stationNo := batchItemList[0].(*tPromotionItemInfo).JdStoreID
promotionItem := v.(*tPromotionItemInfo) for _, v := range batchItemList {
if promotionItem.JdStoreID != stationNo { promotionItem := v.(*tPromotionItemInfo)
// globals.SugarLogger.Debugf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys stationNo:%s, stockList:%s", stationNo, utils.Format4Output(stockList, false)) if promotionItem.JdStoreID != stationNo {
_, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, stockList, userName) // globals.SugarLogger.Debugf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys stationNo:%s, stockList:%s", stationNo, utils.Format4Output(stockList, false))
if err != nil { _, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, stockList, userName)
globals.SugarLogger.Warnf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys failed with error:%v", err) if err != nil {
globals.SugarLogger.Warnf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys failed with error:%v", err)
}
stockList = make([]*jdapi.SkuStock, 0)
stationNo = promotionItem.JdStoreID
} }
stockList = make([]*jdapi.SkuStock, 0) stockList = append(stockList, &jdapi.SkuStock{
stationNo = promotionItem.JdStoreID OutSkuId: utils.Int2Str(promotionItem.SkuID),
StockQty: model.MaxStoreSkuStockQty,
})
} }
stockList = append(stockList, &jdapi.SkuStock{ // globals.SugarLogger.Debugf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys stationNo:%s, stockList:%s", stationNo, utils.Format4Output(stockList, false))
OutSkuId: utils.Int2Str(promotionItem.SkuID), _, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, stockList, userName)
StockQty: model.MaxStoreSkuStockQty, if err != nil {
}) globals.SugarLogger.Warnf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys failed with error:%v", err)
} }
// globals.SugarLogger.Debugf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys stationNo:%s, stockList:%s", stationNo, utils.Format4Output(stockList, false)) return nil, err
_, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, stockList, userName) }, promotionItemList)
if err != nil {
globals.SugarLogger.Warnf("RefreshJdStoreSkuStock BatchUpdateCurrentQtys failed with error:%v", err)
}
return nil, err
}, promotionItemList)
task.Run() task.Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }

View File

@@ -65,22 +65,22 @@ func SendAdvertingByGoodsOrder(ctx *jxcontext.Context, advertising string, days
mobileNumbers = append(mobileNumbers, "18180948107") mobileNumbers = append(mobileNumbers, "18180948107")
smsClient := aliyunsmsclient.New("http://dysmsapi.aliyuncs.com/") smsClient := aliyunsmsclient.New("http://dysmsapi.aliyuncs.com/")
task := tasksch.NewParallelTask("SendAdvertingByGoodsOrder", tasksch.NewParallelConfig().SetBatchSize(MaxBatchSize), userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("SendAdvertingByGoodsOrder", tasksch.NewParallelConfig().SetBatchSize(MaxBatchSize), ctx,
numbers := make([]string, len(batchItemList)) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
for k, v := range batchItemList { numbers := make([]string, len(batchItemList))
numbers[k] = v.(string) for k, v := range batchItemList {
} numbers[k] = v.(string)
numberStr := strings.Join(numbers, ",") }
_, err = smsClient.Execute(globals.AliKey, globals.AliSecret, numberStr, "京西菜市", "SMS_109345355", string(utils.MustMarshal(map[string]interface{}{ numberStr := strings.Join(numbers, ",")
"code": "code", _, err = smsClient.Execute(globals.AliKey, globals.AliSecret, numberStr, "京西菜市", "SMS_109345355", string(utils.MustMarshal(map[string]interface{}{
}))) "code": "code",
if err != nil { })))
globals.SugarLogger.Infof("SendAdvertingByGoodsOrder numbers:%s failed with error:%v", numberStr, err) if err != nil {
} globals.SugarLogger.Infof("SendAdvertingByGoodsOrder numbers:%s failed with error:%v", numberStr, err)
return nil, err }
}, mobileNumbers) return nil, err
ctx.SetTaskOrAddChild(task, nil) }, mobileNumbers)
tasksch.ManageTask(task).Run() tasksch.HandleTask(task, nil, true).Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)

View File

@@ -138,11 +138,12 @@ func Convert2JDSPU(ctx *jxcontext.Context, count int, isAsync, isContinueWhenErr
if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil { if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil {
return "", err return "", err
} }
rootTask := tasksch.NewParallelTask("Convert2JDSPU", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("Convert2JDSPU", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
skuName := batchItemList[0].(*model.SkuName) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
_, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName()) skuName := batchItemList[0].(*model.SkuName)
return nil, err _, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName())
}, skuNameList) return nil, err
}, skuNameList)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
@@ -283,8 +284,9 @@ func Change2JDSPU4Store(ctx *jxcontext.Context, storeIDs []int, step int, isAsyn
func TransferLegacyJdOrder(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { func TransferLegacyJdOrder(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
sqlBatchCount := 1000 sqlBatchCount := 1000
rootTask := tasksch.NewSeqTask("TransferLegacyJdOrder", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("TransferLegacyJdOrder", ctx,
sql := ` func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
sql := `
SELECT t1.* SELECT t1.*
FROM jdorder t1 FROM jdorder t1
LEFT JOIN goods_order_original t2 ON t2.vendor_order_id = t1.vendor_order_id LEFT JOIN goods_order_original t2 ON t2.vendor_order_id = t1.vendor_order_id
@@ -292,58 +294,59 @@ func TransferLegacyJdOrder(ctx *jxcontext.Context, isAsync, isContinueWhenError
ORDER BY t1.orderstatustime ORDER BY t1.orderstatustime
LIMIT ? LIMIT ?
` `
db := dao.GetDB() db := dao.GetDB()
var jdOrderList []*legacymodel2.Jdorder var jdOrderList []*legacymodel2.Jdorder
if err = dao.GetRows(db, &jdOrderList, sql, sqlBatchCount); err != nil { if err = dao.GetRows(db, &jdOrderList, sql, sqlBatchCount); err != nil {
return nil, err return nil, err
} }
if len(jdOrderList) > 0 { if len(jdOrderList) > 0 {
task := tasksch.NewParallelTask("TransferLegacyJdOrder2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetBatchSize(40), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("TransferLegacyJdOrder2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetBatchSize(40), ctx,
var orderDetailList []*model.GoodsOrderOriginal func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
for _, v := range batchItemList { var orderDetailList []*model.GoodsOrderOriginal
jdOrder := v.(*legacymodel2.Jdorder) for _, v := range batchItemList {
var detail map[string]interface{} jdOrder := v.(*legacymodel2.Jdorder)
if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(jdOrder.Data, "\n", "", -1), "\r", "", -1)), &detail); err != nil { var detail map[string]interface{}
return nil, err if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(jdOrder.Data, "\n", "", -1), "\r", "", -1)), &detail); err != nil {
} return nil, err
resultList := detail["result"].(map[string]interface{})["resultList"].([]interface{})
if len(resultList) > 0 {
originalData := resultList[0].(map[string]interface{})
orgCode := originalData["orgCode"].(string)
if orgCode == "320406" {
orderPurchaseTime := utils.Interface2String(originalData["orderPurchaseTime"])
if orderPurchaseTime == "" {
globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal order:%s", jdOrder.VendorOrderID)
orderPurchaseTime = utils.Interface2String(originalData["orderStartTime"])
} }
if orderPurchaseTime != "" { resultList := detail["result"].(map[string]interface{})["resultList"].([]interface{})
orderDetail := &model.GoodsOrderOriginal{ if len(resultList) > 0 {
VendorOrderID: jdOrder.VendorOrderID, originalData := resultList[0].(map[string]interface{})
VendorID: model.VendorIDJD, orgCode := originalData["orgCode"].(string)
AccountNo: orgCode, if orgCode == "320406" {
OrderCreatedAt: utils.Str2Time(orderPurchaseTime), orderPurchaseTime := utils.Interface2String(originalData["orderPurchaseTime"])
OriginalData: string(utils.MustMarshal(originalData)), if orderPurchaseTime == "" {
globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal order:%s", jdOrder.VendorOrderID)
orderPurchaseTime = utils.Interface2String(originalData["orderStartTime"])
}
if orderPurchaseTime != "" {
orderDetail := &model.GoodsOrderOriginal{
VendorOrderID: jdOrder.VendorOrderID,
VendorID: model.VendorIDJD,
AccountNo: orgCode,
OrderCreatedAt: utils.Str2Time(orderPurchaseTime),
OriginalData: string(utils.MustMarshal(originalData)),
}
orderDetailList = append(orderDetailList, orderDetail)
} else {
globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal2 order:%s", jdOrder.VendorOrderID)
}
} }
orderDetailList = append(orderDetailList, orderDetail)
} else {
globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal2 order:%s", jdOrder.VendorOrderID)
} }
} }
} if len(orderDetailList) > 0 {
} err = dao.CreateMultiEntities(db, orderDetailList)
if len(orderDetailList) > 0 { }
err = dao.CreateMultiEntities(db, orderDetailList) return nil, err
} }, jdOrderList)
return nil, err // rootTask.AddChild(task).Run()
}, jdOrderList) task.Run()
// rootTask.AddChild(task).Run() _, err = task.GetResult(0)
task.Run() } else {
_, err = task.GetResult(0) rootTask.Cancel()
} else { }
rootTask.Cancel() return nil, err
} }, math.MaxInt32)
return nil, err
}, math.MaxInt32)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -484,38 +487,39 @@ func PullJdOrder(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, is
gapList[k] = k gapList[k] = k
} }
rootTask := tasksch.NewParallelTask("PullJdOrder", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(20), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("PullJdOrder", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(20), ctx,
gapIndex := batchItemList[0].(int) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
hourIndex := gapIndex * hourGap gapIndex := batchItemList[0].(int)
subFromTime := fromTime.Add(time.Duration(hourIndex) * time.Hour) hourIndex := gapIndex * hourGap
subToTime := fromTime.Add(time.Duration(hourIndex+hourGap) * time.Hour) subFromTime := fromTime.Add(time.Duration(hourIndex) * time.Hour)
if subToTime.Sub(toTime) > 0 { subToTime := fromTime.Add(time.Duration(hourIndex+hourGap) * time.Hour)
subToTime = toTime if subToTime.Sub(toTime) > 0 {
} subToTime = toTime
if true { //gapIndex < gapCount-1 { }
subToTime = subToTime.Add(-1 * time.Second) // 减一秒 if true { //gapIndex < gapCount-1 {
} subToTime = subToTime.Add(-1 * time.Second) // 减一秒
commonParams := map[string]interface{}{ }
jdapi.KeyPageSize: pageSize, commonParams := map[string]interface{}{
"orderPurchaseTime_begin": utils.Time2Str(subFromTime), jdapi.KeyPageSize: pageSize,
"orderPurchaseTime_end": utils.Time2Str(subToTime), "orderPurchaseTime_begin": utils.Time2Str(subFromTime),
} "orderPurchaseTime_end": utils.Time2Str(subToTime),
// globals.SugarLogger.Debugf("PullJdOrder, commonParams=%s", utils.Format4Output(commonParams, false)) }
orderList, totalCount, err := api.JdAPI.OrderQuery(commonParams) // globals.SugarLogger.Debugf("PullJdOrder, commonParams=%s", utils.Format4Output(commonParams, false))
if err != nil { orderList, totalCount, err := api.JdAPI.OrderQuery(commonParams)
return "", err if err != nil {
} return "", err
storeOrderList, err := api.JdAPI.GetStoreOrderInfoList(utils.Time2Str(subFromTime), utils.Time2Str(subToTime)) }
if err != nil { storeOrderList, err := api.JdAPI.GetStoreOrderInfoList(utils.Time2Str(subFromTime), utils.Time2Str(subToTime))
} if err != nil {
if err = saveJdOrderList(existJdIDMap, orderList, storeOrderList); err != nil { }
return "", err if err = saveJdOrderList(existJdIDMap, orderList, storeOrderList); err != nil {
} return "", err
if false { }
globals.SugarLogger.Debugf("subFromTime:%s, subToTime:%s, totalCount:%d, len(orderList):%d", utils.Time2Str(subFromTime), utils.Time2Str(subToTime), totalCount, len(orderList)) if false {
} globals.SugarLogger.Debugf("subFromTime:%s, subToTime:%s, totalCount:%d, len(orderList):%d", utils.Time2Str(subFromTime), utils.Time2Str(subToTime), totalCount, len(orderList))
return nil, err }
}, gapList) return nil, err
}, gapList)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
@@ -562,17 +566,18 @@ func DeleteWrongSpu(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (
if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil { if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil {
return "", err return "", err
} }
rootTask := tasksch.NewSeqTask("DeleteWrongSpu", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("DeleteWrongSpu", ctx,
mapData := map[string]interface{}{ func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
"name": skuNameList[step].Name, mapData := map[string]interface{}{
} "name": skuNameList[step].Name,
_, err = cms.UpdateSkuName(ctx, skuNameList[step].ID, mapData, ctx.GetUserName()) }
if err != nil { _, err = cms.UpdateSkuName(ctx, skuNameList[step].ID, mapData, ctx.GetUserName())
globals.SugarLogger.Debugf("DeleteWrongSpu failed nameid:%d, name:%s, with error:%v", skuNameList[step].ID, skuNameList[step].Name, err) if err != nil {
err = nil // 强制忽略错误 globals.SugarLogger.Debugf("DeleteWrongSpu failed nameid:%d, name:%s, with error:%v", skuNameList[step].ID, skuNameList[step].Name, err)
} err = nil // 强制忽略错误
return nil, err }
}, len(skuNameList)) return nil, err
}, len(skuNameList))
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
@@ -590,8 +595,9 @@ type GoodsOrderOriginalEx struct {
func CreateOrderFromOriginal(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { func CreateOrderFromOriginal(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
sqlBatchCount := 5000 sqlBatchCount := 5000
rootTask := tasksch.NewSeqTask("CreateOrderFromOriginal", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("CreateOrderFromOriginal", ctx,
sql := ` func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
sql := `
SELECT t1.*, t3.order_status SELECT t1.*, t3.order_status
FROM goods_order_original t1 FROM goods_order_original t1
LEFT JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id LEFT JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id
@@ -599,58 +605,59 @@ func CreateOrderFromOriginal(ctx *jxcontext.Context, isAsync, isContinueWhenErro
WHERE t2.id IS NULL WHERE t2.id IS NULL
LIMIT ?; LIMIT ?;
` `
rawDB := orm.NewOrm() rawDB := orm.NewOrm()
db := dao.WrapDB(rawDB) db := dao.WrapDB(rawDB)
var orderList []*GoodsOrderOriginalEx var orderList []*GoodsOrderOriginalEx
if err = dao.GetRows(db, &orderList, sql, sqlBatchCount); err != nil { if err = dao.GetRows(db, &orderList, sql, sqlBatchCount); err != nil {
return nil, err
}
if len(orderList) > 0 {
task := tasksch.NewParallelTask("CreateOrderFromOriginal", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(1), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
orderOriginal := batchItemList[0].(*GoodsOrderOriginalEx)
globals.SugarLogger.Debugf("CreateOrderFromOriginal processing orderID:%s", orderOriginal.VendorOrderID)
if handler := partner.GetPurchasePlatformFromVendorID(orderOriginal.VendorID); handler != nil {
var detail map[string]interface{}
if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(orderOriginal.OriginalData, "\n", "", -1), "\r", "", -1)), &detail); err != nil {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
return nil, err
}
order := handler.Map2Order(detail)
if order.Status < model.OrderStatusEndBegin {
if orderOriginal.OrderStatus == 3 {
order.Status = model.OrderStatusFinished
} else if orderOriginal.OrderStatus == 7 {
order.Status = model.OrderStatusCanceled
} else {
order2, err2 := handler.GetOrder(order.VendorOrderID)
if err = err2; err == nil {
order.Status = order2.Status
} else {
err = nil // ignore get status error
}
}
}
if err == nil {
rawDB := orm.NewOrm()
if _, err = orderman.FixedOrderManager.SaveOrder(order, false, rawDB); err != nil {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
}
} else {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
}
} else {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s", orderOriginal.VendorOrderID)
}
return nil, err return nil, err
}, orderList) }
// rootTask.AddChild(task).Run() if len(orderList) > 0 {
task.Run() task := tasksch.NewParallelTask("CreateOrderFromOriginal", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(1), ctx,
_, err = task.GetResult(0) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
} else { orderOriginal := batchItemList[0].(*GoodsOrderOriginalEx)
rootTask.Cancel() globals.SugarLogger.Debugf("CreateOrderFromOriginal processing orderID:%s", orderOriginal.VendorOrderID)
} if handler := partner.GetPurchasePlatformFromVendorID(orderOriginal.VendorID); handler != nil {
return nil, err var detail map[string]interface{}
}, math.MaxInt32) if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(orderOriginal.OriginalData, "\n", "", -1), "\r", "", -1)), &detail); err != nil {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
return nil, err
}
order := handler.Map2Order(detail)
if order.Status < model.OrderStatusEndBegin {
if orderOriginal.OrderStatus == 3 {
order.Status = model.OrderStatusFinished
} else if orderOriginal.OrderStatus == 7 {
order.Status = model.OrderStatusCanceled
} else {
order2, err2 := handler.GetOrder(order.VendorOrderID)
if err = err2; err == nil {
order.Status = order2.Status
} else {
err = nil // ignore get status error
}
}
}
if err == nil {
rawDB := orm.NewOrm()
if _, err = orderman.FixedOrderManager.SaveOrder(order, false, rawDB); err != nil {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
}
} else {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s, error:%v", orderOriginal.VendorOrderID, err)
}
} else {
globals.SugarLogger.Debugf("CreateOrderFromOriginal abnormal orderID:%s", orderOriginal.VendorOrderID)
}
return nil, err
}, orderList)
// rootTask.AddChild(task).Run()
task.Run()
_, err = task.GetResult(0)
} else {
rootTask.Cancel()
}
return nil, err
}, math.MaxInt32)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -688,91 +695,93 @@ func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isA
return "", fmt.Errorf("待转换的skuName为空") return "", fmt.Errorf("待转换的skuName为空")
} }
batchSize := 40 batchSize := 40
rootTask := tasksch.NewSeqTask("TransformJdSpu2Sku", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("TransformJdSpu2Sku", ctx,
var ( func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
locker sync.Mutex var (
skuIDs []int locker sync.Mutex
) skuIDs []int
lastIndex := (step + 1) * batchSize )
if lastIndex > len(skuNameList) { lastIndex := (step + 1) * batchSize
lastIndex = len(skuNameList) if lastIndex > len(skuNameList) {
} lastIndex = len(skuNameList)
batchSkNameList := skuNameList[step*batchSize : lastIndex] }
subTask := tasksch.NewParallelTask(fmt.Sprintf("TransformJdSpu2Sku:%d", step), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(subTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { batchSkNameList := skuNameList[step*batchSize : lastIndex]
skuName := batchItemList[0].(*model.SkuName) subTask := tasksch.NewParallelTask(fmt.Sprintf("TransformJdSpu2Sku:%d", step), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
if !jxutils.IsFakeID(skuName.JdID) { func(subTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
sql = ` skuName := batchItemList[0].(*model.SkuName)
if !jxutils.IsFakeID(skuName.JdID) {
sql = `
SELECT * SELECT *
FROM sku FROM sku
WHERE name_id = ? AND deleted_at = ? AND status <> ?; WHERE name_id = ? AND deleted_at = ? AND status <> ?;
` `
sqlParams := []interface{}{ sqlParams := []interface{}{
skuName.ID, skuName.ID,
utils.DefaultTimeValue, utils.DefaultTimeValue,
model.SkuStatusDeleted, model.SkuStatusDeleted,
} }
var skuList []*model.Sku var skuList []*model.Sku
if err = dao.GetRows(db, &skuList, sql, sqlParams...); err != nil { if err = dao.GetRows(db, &skuList, sql, sqlParams...); err != nil {
return "", err return "", err
} }
globals.SugarLogger.Debugf("TransformJdSpu2Sku skuList:%s", utils.Format4Output(skuList, false)) globals.SugarLogger.Debugf("TransformJdSpu2Sku skuList:%s", utils.Format4Output(skuList, false))
if len(skuList) > 0 { if len(skuList) > 0 {
for _, sku := range skuList { for _, sku := range skuList {
locker.Lock() locker.Lock()
skuIDs = append(skuIDs, sku.ID) skuIDs = append(skuIDs, sku.ID)
locker.Unlock() locker.Unlock()
if !jxutils.IsFakeID(sku.JdID) { if !jxutils.IsFakeID(sku.JdID) {
if globals.EnableStoreWrite { if globals.EnableStoreWrite {
if err = api.JdAPI.UpdateSkuBaseInfo(utils.Int2Str(skuName.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)); err != nil { if err = api.JdAPI.UpdateSkuBaseInfo(utils.Int2Str(skuName.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)); err != nil {
break break
}
}
} }
} }
} }
} if err == nil && globals.EnableStoreWrite {
} if err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil {
if err == nil && globals.EnableStoreWrite { err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
if err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil { }
err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)) }
} if err == nil {
} skuName.IsSpu = 0
if err == nil { skuName.JdID = 0
skuName.IsSpu = 0 if _, err = dao.UpdateEntity(db, skuName, "IsSpu", "JdID"); err == nil {
skuName.JdID = 0 sql := `
if _, err = dao.UpdateEntity(db, skuName, "IsSpu", "JdID"); err == nil {
sql := `
UPDATE sku t1 UPDATE sku t1
SET SET
t1.jd_sync_status = ?, t1.jd_sync_status = ?,
t1.jd_id = 0 t1.jd_id = 0
WHERE t1.name_id = ? AND t1.deleted_at = ? AND t1.status <> ? WHERE t1.name_id = ? AND t1.deleted_at = ? AND t1.status <> ?
` `
sqlParams := []interface{}{ sqlParams := []interface{}{
model.SyncFlagNewMask, model.SyncFlagNewMask,
skuName.ID, skuName.ID,
utils.DefaultTimeValue, utils.DefaultTimeValue,
model.SkuStatusDeleted, model.SkuStatusDeleted,
} }
if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err == nil { if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err == nil {
_, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName()) _, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName())
}
}
} }
} else {
globals.SugarLogger.Debugf("TransformJdSpu2Sku skuName:%d is fake", skuName.ID)
}
return nil, err
}, batchSkNameList)
rootTask.AddChild(subTask).Run()
if _, err = subTask.GetResult(0); err == nil {
if len(skuIDs) > 0 {
if _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, -1, skuIDs, model.SyncFlagModifiedMask|model.SyncFlagPriceMask|model.SyncFlagSaleMask); err == nil {
time.Sleep(20 * time.Second)
_, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, nil, skuIDs, false, isContinueWhenError)
} }
} }
} else {
globals.SugarLogger.Debugf("TransformJdSpu2Sku skuName:%d is fake", skuName.ID)
} }
return nil, err return nil, err
}, batchSkNameList) }, (len(skuNameList)-1)/batchSize+1)
rootTask.AddChild(subTask).Run()
if _, err = subTask.GetResult(0); err == nil {
if len(skuIDs) > 0 {
if _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, -1, skuIDs, model.SyncFlagModifiedMask|model.SyncFlagPriceMask|model.SyncFlagSaleMask); err == nil {
time.Sleep(20 * time.Second)
_, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, nil, skuIDs, false, isContinueWhenError)
}
}
}
return nil, err
}, (len(skuNameList)-1)/batchSize+1)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -795,21 +804,22 @@ func ReProcessJdBadComment(ctx *jxcontext.Context, isForce, isAsync, isContinueW
var commentList []*legacymodel.JxBadComments var commentList []*legacymodel.JxBadComments
if err = dao.GetRows(db, &commentList, sql); err == nil { if err = dao.GetRows(db, &commentList, sql); err == nil {
if len(commentList) > 0 { if len(commentList) > 0 {
rootTask := tasksch.NewParallelTask("ReProcessJdBadComment", nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("ReProcessJdBadComment", nil, ctx,
badComment := batchItemList[0].(*legacymodel.JxBadComments) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
comment1, _ := unmarshalCommentText(badComment.Msg) badComment := batchItemList[0].(*legacymodel.JxBadComments)
comment2, _ := unmarshalCommentText(badComment.UpdatedMsg) comment1, _ := unmarshalCommentText(badComment.Msg)
if len(comment1) > 0 { comment2, _ := unmarshalCommentText(badComment.UpdatedMsg)
badComment.Createtime = utils.Timestamp2Str(utils.MustInterface2Int64(comment1["createTime"].(map[string]interface{})["time"]) / 1000) if len(comment1) > 0 {
badComment.Msg = string(utils.MustMarshal(comment1)) badComment.Createtime = utils.Timestamp2Str(utils.MustInterface2Int64(comment1["createTime"].(map[string]interface{})["time"]) / 1000)
if len(comment2) > 0 { badComment.Msg = string(utils.MustMarshal(comment1))
badComment.Updatetime = utils.Timestamp2Str(utils.MustInterface2Int64(comment2["createTime"].(map[string]interface{})["time"]) / 1000) if len(comment2) > 0 {
badComment.UpdatedMsg = string(utils.MustMarshal(comment2)) badComment.Updatetime = utils.Timestamp2Str(utils.MustInterface2Int64(comment2["createTime"].(map[string]interface{})["time"]) / 1000)
badComment.UpdatedMsg = string(utils.MustMarshal(comment2))
}
_, err = dao.UpdateEntity(db, badComment)
} }
_, err = dao.UpdateEntity(db, badComment) return nil, err
} }, commentList)
return nil, err
}, commentList)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -856,15 +866,16 @@ func RefreshEbaiBadComment(ctx *jxcontext.Context, fromTime, toTime time.Time, i
} }
days := int(toTime.Sub(fromTime)/(24*time.Hour) + 1) days := int(toTime.Sub(fromTime)/(24*time.Hour) + 1)
globals.SugarLogger.Debugf("RefreshEbaiBadComment fromTime:%s, toTime:%s, days:%d", utils.Time2Str(fromTime), utils.Time2Str(toTime), days) globals.SugarLogger.Debugf("RefreshEbaiBadComment fromTime:%s, toTime:%s, days:%d", utils.Time2Str(fromTime), utils.Time2Str(toTime), days)
rootTask := tasksch.NewSeqTask("RefreshEbaiBadComment", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("RefreshEbaiBadComment", ctx,
batchFromTime := fromTime.Add(time.Duration(step) * 24 * time.Hour) func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
batchToTime := batchFromTime.Add(24*time.Hour - time.Second) batchFromTime := fromTime.Add(time.Duration(step) * 24 * time.Hour)
if batchToTime.Sub(toTime) > 0 { batchToTime := batchFromTime.Add(24*time.Hour - time.Second)
batchToTime = toTime if batchToTime.Sub(toTime) > 0 {
} batchToTime = toTime
err = ebai.CurPurchaseHandler.RefreshComment(batchFromTime, batchToTime) }
return nil, err err = ebai.CurPurchaseHandler.RefreshComment(batchFromTime, batchToTime)
}, days) return nil, err
}, days)
tasksch.ManageTask(rootTask).Run() tasksch.ManageTask(rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)

View File

@@ -3,12 +3,10 @@ package jxcontext
import ( import (
"errors" "errors"
"net/http" "net/http"
"sync"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/auth2" "git.rosy.net.cn/jx-callback/business/auth2"
"git.rosy.net.cn/jx-callback/business/jxcallback/auth" "git.rosy.net.cn/jx-callback/business/jxcallback/auth"
"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"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego" "github.com/astaxie/beego"
@@ -21,14 +19,12 @@ type IAuther interface {
} }
type Context struct { type Context struct {
rootTask tasksch.ITask
token string token string
accessUUID string accessUUID string
userInfo IAuther //*auth.LoginInfo userInfo IAuther //*auth.LoginInfo
w http.ResponseWriter w http.ResponseWriter
r *http.Request r *http.Request
mapData map[interface{}]interface{} mapData map[interface{}]interface{}
locker sync.RWMutex
} }
const ( const (
@@ -43,9 +39,8 @@ func init() {
AdminCtx = NewWithUserName(nil, model.AdminName, nil, nil) AdminCtx = NewWithUserName(nil, model.AdminName, nil, nil)
} }
func NewWithUserName(rootTask tasksch.ITask, userName string, w http.ResponseWriter, r *http.Request) (ctx *Context) { func NewWithUserName(notUsed interface{}, userName string, w http.ResponseWriter, r *http.Request) (ctx *Context) {
ctx = &Context{ ctx = &Context{
rootTask: rootTask,
token: userName, token: userName,
w: w, w: w,
r: r, r: r,
@@ -55,9 +50,8 @@ func NewWithUserName(rootTask tasksch.ITask, userName string, w http.ResponseWri
return ctx return ctx
} }
func New(rootTask tasksch.ITask, token string, w http.ResponseWriter, r *http.Request) (ctx *Context, errCode string, err error) { func New(notUsed interface{}, token string, w http.ResponseWriter, r *http.Request) (ctx *Context, errCode string, err error) {
ctx = &Context{ ctx = &Context{
rootTask: rootTask,
token: token, token: token,
w: w, w: w,
r: r, r: r,
@@ -141,34 +135,6 @@ func (ctx *Context) GetV2AuthInfo() (authInfo *auth2.AuthInfo, err error) {
return nil, auth2.ErrNeedV2Token return nil, auth2.ErrNeedV2Token
} }
func (ctx *Context) GetRootTask() tasksch.ITask {
ctx.locker.RLock()
defer ctx.locker.RUnlock()
return ctx.rootTask
}
func (ctx *Context) SetTaskOrAddChild(task tasksch.ITask, parentTask tasksch.ITask) bool {
if parentTask != nil {
parentTask.AddChild(task)
} else {
parentTask = task
}
ctx.locker.RLock()
if ctx.rootTask == nil {
ctx.locker.RUnlock()
ctx.locker.Lock()
if ctx.rootTask == nil {
ctx.rootTask = parentTask
}
ctx.locker.Unlock()
return true
}
ctx.locker.RUnlock()
return false
}
func (ctx *Context) GetResponseWriter() http.ResponseWriter { func (ctx *Context) GetResponseWriter() http.ResponseWriter {
return ctx.w return ctx.w
} }
@@ -176,17 +142,3 @@ func (ctx *Context) GetResponseWriter() http.ResponseWriter {
func (ctx *Context) GetRequest() *http.Request { func (ctx *Context) GetRequest() *http.Request {
return ctx.r return ctx.r
} }
func (ctx *Context) SetValue(key, value interface{}) {
ctx.locker.Lock()
defer ctx.locker.Unlock()
ctx.mapData[key] = value
}
func (ctx *Context) GetValue(key interface{}) interface{} {
ctx.locker.RLock()
defer ctx.locker.RUnlock()
return ctx.mapData[key]
}

View File

@@ -0,0 +1,24 @@
package msg
import (
"git.rosy.net.cn/jx-callback/business/auth2"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/dingding"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
)
func SendUserMessage(userID, title, content string) (err error) {
authList, err := auth2.GetUserBindAuthInfo(userID)
if err == nil {
for _, auth := range authList {
if auth.Type == dingding.AuthTypeStaff {
err = api.DingDingAPI.CorpAsyncSendSimple(auth.AuthID, content)
break
}
}
}
if err != nil {
globals.SugarLogger.Infof("SendUserMessage userID:%s, title:%s, content:%s failed with error:%v", userID, title, content, err)
}
return err
}

View File

@@ -6,6 +6,7 @@ import (
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
) )
@@ -18,6 +19,8 @@ type WorkFunc func(task *ParallelTask, batchItemList []interface{}, params ...in
type ResultHandlerFunc func(taskName string, result []interface{}, err error) type ResultHandlerFunc func(taskName string, result []interface{}, err error)
type ParallelConfig struct { type ParallelConfig struct {
// ParentTask ITask
// IsAsync bool
ParallelCount int ParallelCount int
BatchSize int BatchSize int
IsContinueWhenError bool IsContinueWhenError bool
@@ -41,9 +44,11 @@ var (
func NewParallelConfig() *ParallelConfig { func NewParallelConfig() *ParallelConfig {
return &ParallelConfig{ return &ParallelConfig{
// ParentTask: parentTask,
// IsAsync: false,
IsContinueWhenError: false,
ParallelCount: DefParallelCount, ParallelCount: DefParallelCount,
BatchSize: 1, BatchSize: 1,
IsContinueWhenError: false,
ResultHandler: nil, ResultHandler: nil,
} }
} }
@@ -63,12 +68,17 @@ func (c *ParallelConfig) SetIsContinueWhenError(isContinueWhenError bool) *Paral
return c return c
} }
// func (c *ParallelConfig) SetIsAsync(isAsync bool) *ParallelConfig {
// c.IsAsync = isAsync
// return c
// }
func (c *ParallelConfig) SetResultHandler(resultHandler ResultHandlerFunc) *ParallelConfig { func (c *ParallelConfig) SetResultHandler(resultHandler ResultHandlerFunc) *ParallelConfig {
c.ResultHandler = resultHandler c.ResultHandler = resultHandler
return c return c
} }
func NewParallelTask(taskName string, config *ParallelConfig, userName string, worker WorkFunc, itemList interface{}, params ...interface{}) *ParallelTask { func NewParallelTask(taskName string, config *ParallelConfig, ctx *jxcontext.Context, worker WorkFunc, itemList interface{}, params ...interface{}) *ParallelTask {
if config == nil { if config == nil {
config = NewParallelConfig() config = NewParallelConfig()
} }
@@ -91,7 +101,7 @@ func NewParallelTask(taskName string, config *ParallelConfig, userName string, w
worker: worker, worker: worker,
jobList: jobList, jobList: jobList,
} }
task.Init(config.ParallelCount, config.BatchSize, config.IsContinueWhenError, params, taskName, userName, len(realItemList), jobListLen) task.Init(config.ParallelCount, config.BatchSize, config.IsContinueWhenError, params, taskName, ctx, len(realItemList), jobListLen)
return task return task
} }

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
) )
func TestRunParallelTask(t *testing.T) { func TestRunParallelTask(t *testing.T) {
@@ -14,16 +15,17 @@ func TestRunParallelTask(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7), "autotest", func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7), jxcontext.AdminCtx,
sleepSecond := rand.Intn(5) func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
t.Logf("sleep %d seconds", sleepSecond) sleepSecond := rand.Intn(5)
time.Sleep(time.Duration(sleepSecond) * time.Second) t.Logf("sleep %d seconds", sleepSecond)
retSlice := make([]string, len(batchItemList)) time.Sleep(time.Duration(sleepSecond) * time.Second)
for k := range retSlice { retSlice := make([]string, len(batchItemList))
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) for k := range retSlice {
} retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
return retSlice, nil }
}, itemList, "a", "b", 1, 2) return retSlice, nil
}, itemList, "a", "b", 1, 2)
task.Run() task.Run()
result, err := task.GetResult(1 * time.Microsecond) result, err := task.GetResult(1 * time.Microsecond)
if err == nil || task.GetStatus() != TaskStatusWorking { if err == nil || task.GetStatus() != TaskStatusWorking {
@@ -45,16 +47,17 @@ func TestCancelParallelTask(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7), "autotest", func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7), jxcontext.AdminCtx,
sleepSecond := rand.Intn(5) func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
fmt.Printf("sleep %d seconds\n", sleepSecond) sleepSecond := rand.Intn(5)
time.Sleep(time.Duration(sleepSecond) * time.Second) fmt.Printf("sleep %d seconds\n", sleepSecond)
retSlice := make([]string, len(batchItemList)) time.Sleep(time.Duration(sleepSecond) * time.Second)
for k := range retSlice { retSlice := make([]string, len(batchItemList))
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) for k := range retSlice {
} retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
return retSlice, nil }
}, itemList, "a", "b", 1, 2) return retSlice, nil
}, itemList, "a", "b", 1, 2)
task.Run() task.Run()
// time.Sleep(time.Second * 6) // time.Sleep(time.Second * 6)
fmt.Printf("finishedItemCount:%d, finishedJobCount:%d\n", task.GetFinishedItemCount(), task.GetFinishedJobCount()) fmt.Printf("finishedItemCount:%d, finishedJobCount:%d\n", task.GetFinishedItemCount(), task.GetFinishedJobCount())
@@ -71,19 +74,20 @@ func TestRunParallelTaskPartialSuccess(t *testing.T) {
for k := range itemList { for k := range itemList {
itemList[k] = k itemList[k] = k
} }
task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7).SetIsContinueWhenError(true), "autotest", func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := NewParallelTask("test", NewParallelConfig().SetParallelCount(100).SetBatchSize(7).SetIsContinueWhenError(true), jxcontext.AdminCtx,
sleepSecond := rand.Intn(5) func(task *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
t.Logf("sleep %d seconds", sleepSecond) sleepSecond := rand.Intn(5)
time.Sleep(time.Duration(sleepSecond) * time.Second) t.Logf("sleep %d seconds", sleepSecond)
retSlice := make([]string, len(batchItemList)) time.Sleep(time.Duration(sleepSecond) * time.Second)
for k := range retSlice { retSlice := make([]string, len(batchItemList))
retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2) for k := range retSlice {
} retSlice[k] = "hello:" + utils.Int2Str(batchItemList[k].(int)*2)
if rand.Intn(2) == 1 { }
return nil, fmt.Errorf("test:%d", batchItemList[0].(int)) if rand.Intn(2) == 1 {
} return nil, fmt.Errorf("test:%d", batchItemList[0].(int))
return retSlice, nil }
}, itemList, "a", "b", 1, 2) return retSlice, nil
}, itemList, "a", "b", 1, 2)
task.Run() task.Run()
result, err := task.GetResult(1 * time.Microsecond) result, err := task.GetResult(1 * time.Microsecond)
if err == nil || task.GetStatus() != TaskStatusWorking { if err == nil || task.GetStatus() != TaskStatusWorking {

View File

@@ -4,6 +4,7 @@ import (
"time" "time"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
) )
@@ -19,11 +20,11 @@ type SeqTask struct {
worker SeqWorkFunc worker SeqWorkFunc
} }
func NewSeqTask(taskName string, userName string, worker SeqWorkFunc, stepCount int, params ...interface{}) *SeqTask { func NewSeqTask(taskName string, ctx *jxcontext.Context, worker SeqWorkFunc, stepCount int, params ...interface{}) *SeqTask {
task := &SeqTask{ task := &SeqTask{
worker: worker, worker: worker,
} }
task.Init(1, 1, false, params, taskName, userName, stepCount, stepCount) task.Init(1, 1, false, params, taskName, ctx, stepCount, stepCount)
return task return task
} }

View File

@@ -7,38 +7,41 @@ import (
"time" "time"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
) )
func TestRunSeqTask(t *testing.T) { func TestRunSeqTask(t *testing.T) {
var seqTask ITask var seqTask ITask
seqTask = NewSeqTask("TestSeqTask", "autotest", func(task *SeqTask, step int, params ...interface{}) (result interface{}, err error) { seqTask = NewSeqTask("TestSeqTask", jxcontext.AdminCtx,
switch step { func(task *SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
fmt.Println("ONE") case 0:
task2 := NewParallelTask("hello", nil, "xjh", func(parallelTask *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { fmt.Println("ONE")
i := batchItemList[0].(int) task2 := NewParallelTask("hello", nil, jxcontext.AdminCtx,
time.Sleep(2 * time.Second) func(parallelTask *ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
fmt.Println(i * 2) i := batchItemList[0].(int)
return nil, nil time.Sleep(2 * time.Second)
}, []int{1, 2, 3}) fmt.Println(i * 2)
seqTask.AddChild(task2) return nil, nil
time.Sleep(time.Duration(rand.Intn(3)) * time.Second) }, []int{1, 2, 3})
task2.Run() seqTask.AddChild(task2)
case 1: time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
fmt.Println("TWO") task2.Run()
time.Sleep(time.Duration(rand.Intn(3)) * time.Second) case 1:
case 2: fmt.Println("TWO")
fmt.Println("THREE") time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
time.Sleep(time.Duration(rand.Intn(3)) * time.Second) case 2:
case 3: fmt.Println("THREE")
fmt.Println("FOUR") time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
time.Sleep(time.Duration(rand.Intn(3)) * time.Second) case 3:
case 4: fmt.Println("FOUR")
fmt.Println("FIVE") time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
time.Sleep(time.Duration(rand.Intn(3)) * time.Second) case 4:
} fmt.Println("FIVE")
return []string{"1"}, nil time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
}, 5) }
return []string{"1"}, nil
}, 5)
seqTask.Run() seqTask.Run()
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)

View File

@@ -8,6 +8,8 @@ import (
"time" "time"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/msg"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
) )
@@ -97,14 +99,17 @@ type BaseTask struct {
Children TaskList `json:"children"` Children TaskList `json:"children"`
Err error `json:"err"` Err error `json:"err"`
detailErrMsgList []string `json:"-"` detailErrMsgList []string
finishChan chan int finishChan chan struct{}
C <-chan int `json:"-"` C <-chan struct{} `json:"-"`
params []interface{} params []interface{}
quitChan chan int quitChan chan int
locker sync.RWMutex locker sync.RWMutex
parent ITask parent ITask
ctx *jxcontext.Context
isGetResultCalled bool
} }
func (s TaskList) Len() int { func (s TaskList) Len() int {
@@ -121,7 +126,7 @@ func (s TaskList) Swap(i, j int) {
s[j] = tmp s[j] = tmp
} }
func (t *BaseTask) Init(parallelCount, batchSize int, isContinueWhenError bool, params []interface{}, name, userName string, totalItemCount, totalJobCount int) { func (t *BaseTask) Init(parallelCount, batchSize int, isContinueWhenError bool, params []interface{}, name string, ctx *jxcontext.Context, totalItemCount, totalJobCount int) {
t.ID = utils.GetUUID() t.ID = utils.GetUUID()
t.ParallelCount = parallelCount t.ParallelCount = parallelCount
t.BatchSize = batchSize t.BatchSize = batchSize
@@ -129,13 +134,14 @@ func (t *BaseTask) Init(parallelCount, batchSize int, isContinueWhenError bool,
t.params = params t.params = params
t.Name = name t.Name = name
t.CreatedAt = time.Now() t.CreatedAt = time.Now()
t.CreatedBy = userName t.ctx = ctx
t.CreatedBy = ctx.GetUserName()
t.UpdatedAt = t.CreatedAt t.UpdatedAt = t.CreatedAt
t.TerminatedAt = utils.DefaultTimeValue t.TerminatedAt = utils.DefaultTimeValue
t.TotalItemCount = totalItemCount t.TotalItemCount = totalItemCount
t.TotalJobCount = totalJobCount t.TotalJobCount = totalJobCount
t.quitChan = make(chan int) t.quitChan = make(chan int)
t.finishChan = make(chan int) t.finishChan = make(chan struct{})
t.Status = TaskStatusWorking t.Status = TaskStatusWorking
t.C = t.finishChan t.C = t.finishChan
@@ -155,6 +161,7 @@ func (t *BaseTask) GetResult(duration time.Duration) (retVal []interface{}, err
timer := time.NewTimer(duration) timer := time.NewTimer(duration)
select { select {
case <-t.finishChan: case <-t.finishChan:
t.isGetResultCalled = true
timer.Stop() timer.Stop()
return t.Result, t.Err return t.Result, t.Err
case <-timer.C: case <-timer.C:
@@ -249,6 +256,14 @@ func AddChild(parentTask ITask, task ITask) ITask {
return task return task
} }
func HandleTask(task, parentTask ITask, isMangeIt bool) ITask {
AddChild(task, parentTask)
if parentTask == nil && isMangeIt {
ManageTask(task)
}
return task
}
///////// /////////
func (t *BaseTask) MarshalJSON() ([]byte, error) { func (t *BaseTask) MarshalJSON() ([]byte, error) {
@@ -280,6 +295,18 @@ func (t *BaseTask) run(taskHandler func()) {
} }
close(t.finishChan) close(t.finishChan)
time.Sleep(10 * time.Millisecond) // 等待GetResult中的isGetResultCalled赋值
if !t.isGetResultCalled && t.parent == nil && len(GetTasks(t.ID, TaskStatusBegin, TaskStatusEnd, 24, "")) == 0 {
if authInfo, err := t.ctx.GetV2AuthInfo(); err == nil { // 这里应该是不管登录类型,直接以可能的方式发消息
var content string
if t.Status == TaskStatusFinished {
content = fmt.Sprintf("你的异步任务[%s]执行成功完成", t.Name)
} else {
content = fmt.Sprintf("你的异步任务[%s]执行失败,%s", t.Name, t.Err.Error())
}
msg.SendUserMessage(authInfo.UserID, "异步任务完成", content)
}
}
}) })
} }
} }

View File

@@ -52,3 +52,18 @@ func GetAuthBindsByAuthID2(db *DaoDB, authID2 string, typeList []string) (authBi
err = GetRows(db, &authBinds, sql, sqlParams...) err = GetRows(db, &authBinds, sql, sqlParams...)
return authBinds, err return authBinds, err
} }
func GetUserBindAuthInfo(db *DaoDB, userID string) (authList []*model.AuthBind, err error) {
sql := `
SELECT *
FROM auth_bind t1
WHERE t1.deleted_at = ? AND t1.status = ? AND t1.user_id = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
model.UserStatusNormal,
userID,
}
err = GetRows(db, &authList, sql, sqlParams...)
return authList, err
}

View File

@@ -23,18 +23,3 @@ func GetUserByID(db *DaoDB, fieldName, fieldValue string) (user *model.User, err
err = GetRow(db, &user, sql, sqlParams...) err = GetRow(db, &user, sql, sqlParams...)
return user, err return user, err
} }
func GetUserBindAuthInfo(db *DaoDB, userID string) (authList []*model.AuthBind, err error) {
sql := `
SELECT *
FROM auth_bind t1
WHERE t1.deleted_at = ? AND t1.status = ? AND t1.user_id = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue,
model.UserStatusNormal,
userID,
}
err = GetRows(db, &authList, sql, sqlParams...)
return authList, err
}

View File

@@ -3,6 +3,7 @@ package ebai
import ( import (
"git.rosy.net.cn/baseapi/platformapi/ebaiapi" "git.rosy.net.cn/baseapi/platformapi/ebaiapi"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
"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/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api"
@@ -11,30 +12,31 @@ import (
func (p *PurchaseHandler) UpdatePlaces() (err error) { func (p *PurchaseHandler) UpdatePlaces() (err error) {
provinces, err := api.EbaiAPI.CommonShopCities(0) provinces, err := api.EbaiAPI.CommonShopCities(0)
if err == nil { if err == nil {
task := tasksch.NewParallelTask("UpdatePlaces", nil, "test", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("UpdatePlaces", nil, jxcontext.AdminCtx,
province := batchItemList[0].(*ebaiapi.CityInfo) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
retSlice := make([]*ebaiapi.CityInfo, 0) province := batchItemList[0].(*ebaiapi.CityInfo)
if province.IsOpen != 0 { retSlice := make([]*ebaiapi.CityInfo, 0)
retSlice = append(retSlice, province) if province.IsOpen != 0 {
cities, err := api.EbaiAPI.CommonShopCities(province.ID) retSlice = append(retSlice, province)
for _, city := range cities { cities, err := api.EbaiAPI.CommonShopCities(province.ID)
if city.IsOpen != 0 { for _, city := range cities {
retSlice = append(retSlice, city) if city.IsOpen != 0 {
districts, err2 := api.EbaiAPI.CommonShopCities(city.ID) retSlice = append(retSlice, city)
if err = err2; err == nil { districts, err2 := api.EbaiAPI.CommonShopCities(city.ID)
for _, district := range districts { if err = err2; err == nil {
if district.IsOpen != 0 { for _, district := range districts {
retSlice = append(retSlice, district) if district.IsOpen != 0 {
retSlice = append(retSlice, district)
}
} }
} else {
break
} }
} else {
break
} }
} }
} }
} return retSlice, err
return retSlice, err }, provinces)
}, provinces)
task.Run() task.Run()
places, err2 := task.GetResult(0) places, err2 := task.GetResult(0)
if err = err2; err == nil { if err = err2; err == nil {

View File

@@ -338,17 +338,17 @@ func (c *PurchaseHandler) RefreshRealMobile(ctx *jxcontext.Context, fromTime, to
var orderList []*model.GoodsOrder var orderList []*model.GoodsOrder
db := dao.GetDB() db := dao.GetDB()
if err = dao.GetRows(db, &orderList, sql, sqlParams...); err == nil && len(orderList) > 0 { if err = dao.GetRows(db, &orderList, sql, sqlParams...); err == nil && len(orderList) > 0 {
task := tasksch.NewParallelTask("ebai RefreshRealMobile", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("ebai RefreshRealMobile", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
order := batchItemList[0].(*model.GoodsOrder) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
mobile, err2 := api.EbaiAPI.GetRealMobile4Order(order.VendorOrderID) order := batchItemList[0].(*model.GoodsOrder)
if err = err2; err == nil && !jxutils.IsMobileFake(mobile) && strings.Index(order.ConsigneeMobile, mobile) == -1 { mobile, err2 := api.EbaiAPI.GetRealMobile4Order(order.VendorOrderID)
order.ConsigneeMobile2 = mobile if err = err2; err == nil && !jxutils.IsMobileFake(mobile) && strings.Index(order.ConsigneeMobile, mobile) == -1 {
_, err = dao.UpdateEntity(db, order, "ConsigneeMobile2") order.ConsigneeMobile2 = mobile
} _, err = dao.UpdateEntity(db, order, "ConsigneeMobile2")
return nil, err }
}, orderList) return nil, err
ctx.SetTaskOrAddChild(task, nil) }, orderList)
tasksch.ManageTask(task).Run() tasksch.HandleTask(task, nil, true).Run()
hint = task.ID hint = task.ID
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)

View File

@@ -216,44 +216,45 @@ func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask
const stepCount = 3 const stepCount = 3
var stores []*tEbaiStoreInfo var stores []*tEbaiStoreInfo
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("ebai RefreshAllStoresID", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("ebai RefreshAllStoresID", ctx,
switch step { func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = dao.GetRows(db, &stores, ` case 0:
err = dao.GetRows(db, &stores, `
SELECT t1.*, t2.vendor_store_id SELECT t1.*, t2.vendor_store_id
FROM store t1 FROM store t1
JOIN store_map t2 ON t1.id = t2.store_id AND t2.deleted_at = ? AND t2.vendor_id = ? JOIN store_map t2 ON t1.id = t2.store_id AND t2.deleted_at = ? AND t2.vendor_id = ?
WHERE t1.deleted_at = ? WHERE t1.deleted_at = ?
`, utils.DefaultTimeValue, model.VendorIDEBAI, utils.DefaultTimeValue) `, utils.DefaultTimeValue, model.VendorIDEBAI, utils.DefaultTimeValue)
default: default:
taskName := "ebai RefreshAllStoresID update to custom id" taskName := "ebai RefreshAllStoresID update to custom id"
if step != stepCount-1 { if step != stepCount-1 {
taskName = "ebai RefreshAllStoresID update to uuid" taskName = "ebai RefreshAllStoresID update to uuid"
}
task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetBatchSize(batchSize), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
baiduShopIDs := make([]string, len(batchItemList))
shopIDs := make([]string, len(batchItemList))
for k, v := range batchItemList {
store := v.(*tEbaiStoreInfo)
baiduShopIDs[k] = store.VendorStoreID
shopIDs[k] = utils.Int2Str(store.ID)
if step != stepCount-1 {
shopIDs[k] = utils.GetUUID()
}
}
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
err = api.EbaiAPI.ShopIDBatchUpdate(baiduShopIDs, shopIDs)
}
return nil, err
}, stores)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
} }
task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetBatchSize(batchSize), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { return nil, err
baiduShopIDs := make([]string, len(batchItemList)) }, stepCount)
shopIDs := make([]string, len(batchItemList))
for k, v := range batchItemList {
store := v.(*tEbaiStoreInfo)
baiduShopIDs[k] = store.VendorStoreID
shopIDs[k] = utils.Int2Str(store.ID)
if step != stepCount-1 {
shopIDs[k] = utils.GetUUID()
}
}
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
err = api.EbaiAPI.ShopIDBatchUpdate(baiduShopIDs, shopIDs)
}
return nil, err
}, stores)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
}
return nil, err
}, stepCount)
ctx.SetTaskOrAddChild(rootTask, parentTask) tasksch.HandleTask(rootTask, parentTask, false).Run()
rootTask.Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
} }

View File

@@ -144,29 +144,30 @@ func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask t
globals.SugarLogger.Debugf("FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) globals.SugarLogger.Debugf("FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName)
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("FullSyncStoreSkus", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("FullSyncStoreSkus", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil) case 0:
// 强制忽略删除SKU错误 err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
if isContinueWhenError { // 强制忽略删除SKU错误
err = nil if isContinueWhenError {
err = nil
}
case 1:
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
}
case 3:
err = p.SyncLocalStoreCategory(db, storeID, userName)
case 4:
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
case 5:
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError)
} }
case 1: return nil, err
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask) }, 6)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
}
case 3:
err = p.SyncLocalStoreCategory(db, storeID, userName)
case 4:
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
case 5:
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError)
}
return nil, err
}, 6)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -180,24 +181,25 @@ func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTa
db := dao.GetDB() db := dao.GetDB()
var errDeleteSku error var errDeleteSku error
rootTask := tasksch.NewSeqTask("DeleteRemoteStoreSkus", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("DeleteRemoteStoreSkus", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil) case 0:
errDeleteSku = err err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
// 强制忽略删除SKU错误 errDeleteSku = err
if isContinueWhenError { // 强制忽略删除SKU错误
err = nil if isContinueWhenError {
err = nil
}
case 1:
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
}
} }
case 1: return nil, err
_, err = p.setStoreSkuSyncStatus(ctx, db, storeID, nil, model.SyncFlagNewMask) }, 3)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, storeID, nil, model.SyncFlagNewMask)
}
}
return nil, err
}, 3)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -215,58 +217,60 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
var storeSkuInfoList []*tStoreSkuFullInfo var storeSkuInfoList []*tStoreSkuFullInfo
var num int64 var num int64
strStoreID := utils.Int2Str(storeID) strStoreID := utils.Int2Str(storeID)
rootTask := tasksch.NewSeqTask("SyncStoreSkus饿百1", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("SyncStoreSkus饿百1", ctx,
if step == 0 { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
db := dao.GetDB() if step == 0 {
for i := 0; i < 3; i++ { db := dao.GetDB()
if storeSkuInfoList, err = p.getDirtyStoreSkus(db, storeID, skuIDs); err != nil { for i := 0; i < 3; i++ {
return nil, err if storeSkuInfoList, err = p.getDirtyStoreSkus(db, storeID, skuIDs); err != nil {
} return nil, err
if num, err = p.createCatByStoreSkus(ctx, rootTask, db, storeID, storeSkuInfoList); err != nil { }
return nil, err if num, err = p.createCatByStoreSkus(ctx, rootTask, db, storeID, storeSkuInfoList); err != nil {
} return nil, err
if num == 0 { }
break if num == 0 {
} break
}
if num != 0 {
globals.SugarLogger.Infof("SyncStoreSkus 不能创建商品所需的类别, storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName)
return nil, errors.New("不能创建商品所需的类别")
}
} else if step == 1 {
task := tasksch.NewParallelTask("SyncStoreSkus饿百2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
storeSku := batchItemList[0].(*tStoreSkuFullInfo)
updateFields := []string{model.FieldEbaiSyncStatus}
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
if storeSku.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 {
err = api.EbaiAPI.SkuDelete(strStoreID, utils.Int64ToStr(storeSku.EbaiID))
} else if storeSku.EbaiSyncStatus&model.SyncFlagNewMask != 0 {
// globals.SugarLogger.Debug(utils.Format4Output(genSkuParamsFromStoreSkuInfo(storeSku), false))
// todo 适当处理重复(即已经创建)的情况
if storeSku.EbaiID, err = api.EbaiAPI.SkuCreate(strStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
updateFields = append(updateFields, model.FieldEbaiID)
}
} else if storeSku.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 {
if jxutils.IsFakeID(storeSku.EbaiID) {
err = fmt.Errorf("京西数据异常,修改一个没有创建的饿百商品:%d, store:%s", storeSku.SkuID, strStoreID)
} else {
if _, err = api.EbaiAPI.SkuUpdate(strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
// err = api.EbaiAPI.SkuShopCategoryMap(strStoreID, storeSku.EbaiID, utils.Int64ToStr(storeSku.CatEbaiID))
}
}
} }
} }
if err == nil { if num != 0 {
storeSku.EbaiSyncStatus = 0 globals.SugarLogger.Infof("SyncStoreSkus 不能创建商品所需的类别, storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName)
_, err = dao.UpdateEntity(nil, &storeSku.StoreSkuBind, updateFields...) return nil, errors.New("不能创建商品所需的类别")
} }
return nil, err } else if step == 1 {
}, storeSkuInfoList) task := tasksch.NewParallelTask("SyncStoreSkus饿百2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
tasksch.AddChild(rootTask, task).Run() func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
_, err = task.GetResult(0) storeSku := batchItemList[0].(*tStoreSkuFullInfo)
} updateFields := []string{model.FieldEbaiSyncStatus}
return nil, err if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
}, 2) if storeSku.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 {
err = api.EbaiAPI.SkuDelete(strStoreID, utils.Int64ToStr(storeSku.EbaiID))
} else if storeSku.EbaiSyncStatus&model.SyncFlagNewMask != 0 {
// globals.SugarLogger.Debug(utils.Format4Output(genSkuParamsFromStoreSkuInfo(storeSku), false))
// todo 适当处理重复(即已经创建)的情况
if storeSku.EbaiID, err = api.EbaiAPI.SkuCreate(strStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
updateFields = append(updateFields, model.FieldEbaiID)
}
} else if storeSku.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 {
if jxutils.IsFakeID(storeSku.EbaiID) {
err = fmt.Errorf("京西数据异常,修改一个没有创建的饿百商品:%d, store:%s", storeSku.SkuID, strStoreID)
} else {
if _, err = api.EbaiAPI.SkuUpdate(strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(storeSku)); err == nil {
// err = api.EbaiAPI.SkuShopCategoryMap(strStoreID, storeSku.EbaiID, utils.Int64ToStr(storeSku.CatEbaiID))
}
}
}
}
if err == nil {
storeSku.EbaiSyncStatus = 0
_, err = dao.UpdateEntity(nil, &storeSku.StoreSkuBind, updateFields...)
}
return nil, err
}, storeSkuInfoList)
tasksch.AddChild(rootTask, task).Run()
_, err = task.GetResult(0)
}
return nil, err
}, 2)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -274,7 +278,7 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
return rootTask.ID, err return rootTask.ID, err
} }
func (p *PurchaseHandler) GetAllRemoteSkus(storeID int) (skus []map[string]interface{}, err error) { func (p *PurchaseHandler) GetAllRemoteSkus(ctx *jxcontext.Context, storeID int, parentTask tasksch.ITask) (skus []map[string]interface{}, err error) {
page1, err := api.EbaiAPI.SkuList(utils.Int2Str(storeID), utils.Params2Map("pagesize", MaxPageSize)) page1, err := api.EbaiAPI.SkuList(utils.Int2Str(storeID), utils.Params2Map("pagesize", MaxPageSize))
if err == nil { if err == nil {
skus = append(skus, page1.List...) skus = append(skus, page1.List...)
@@ -283,19 +287,20 @@ func (p *PurchaseHandler) GetAllRemoteSkus(storeID int) (skus []map[string]inter
for i := 2; i <= page1.Pages; i++ { for i := 2; i <= page1.Pages; i++ {
pages[i-2] = i pages[i-2] = i
} }
task := tasksch.NewParallelTask("GetAllRemoteSkus", nil, "", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("GetAllRemoteSkus", nil, ctx,
callParams := map[string]interface{}{ func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
"pagesize": MaxPageSize, callParams := map[string]interface{}{
"page": batchItemList[0], "pagesize": MaxPageSize,
} "page": batchItemList[0],
pageSku, err2 := api.EbaiAPI.SkuList(utils.Int2Str(storeID), callParams) }
if err2 == nil { pageSku, err2 := api.EbaiAPI.SkuList(utils.Int2Str(storeID), callParams)
return pageSku.List, err2 if err2 == nil {
} return pageSku.List, err2
globals.SugarLogger.Debug(utils.Format4Output(callParams, false)) }
return nil, err2 globals.SugarLogger.Debug(utils.Format4Output(callParams, false))
}, pages) return nil, err2
task.Run() }, pages)
tasksch.HandleTask(task, parentTask, false).Run()
result, err2 := task.GetResult(0) result, err2 := task.GetResult(0)
if err = err2; err == nil { if err = err2; err == nil {
for _, v := range result { for _, v := range result {
@@ -311,7 +316,7 @@ func (p *PurchaseHandler) DeleteRemoteSkus(ctx *jxcontext.Context, parentTask ta
globals.SugarLogger.Debugf("DeleteRemoteSkus饿百 storeID:%d", storeID) globals.SugarLogger.Debugf("DeleteRemoteSkus饿百 storeID:%d", storeID)
if vendorSkuIDs == nil { if vendorSkuIDs == nil {
result, err2 := p.GetAllRemoteSkus(storeID) result, err2 := p.GetAllRemoteSkus(ctx, storeID, parentTask)
if err = err2; err == nil { if err = err2; err == nil {
vendorSkuIDs = make([]string, len(result)) vendorSkuIDs = make([]string, len(result))
for k, v := range result { for k, v := range result {
@@ -319,16 +324,17 @@ func (p *PurchaseHandler) DeleteRemoteSkus(ctx *jxcontext.Context, parentTask ta
} }
} }
} }
task := tasksch.NewParallelTask("DeleteRemoteSkus", tasksch.NewParallelConfig().SetBatchSize(100).SetIsContinueWhenError(true), "", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("DeleteRemoteSkus", tasksch.NewParallelConfig().SetBatchSize(100).SetIsContinueWhenError(true), ctx,
strList := make([]string, len(batchItemList)) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
for k, v := range batchItemList { strList := make([]string, len(batchItemList))
strList[k] = v.(string) for k, v := range batchItemList {
} strList[k] = v.(string)
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite { }
err = api.EbaiAPI.SkuDelete(utils.Int2Str(storeID), strings.Join(strList, ",")) if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
} err = api.EbaiAPI.SkuDelete(utils.Int2Str(storeID), strings.Join(strList, ","))
return nil, err }
}, vendorSkuIDs) return nil, err
}, vendorSkuIDs)
tasksch.AddChild(parentTask, task).Run() tasksch.AddChild(parentTask, task).Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
return err return err
@@ -347,12 +353,13 @@ func (p *PurchaseHandler) DeleteRemoteCategories(ctx *jxcontext.Context, parentT
} }
} }
} }
task := tasksch.NewParallelTask("DeleteRemoteCategories", tasksch.NewParallelConfig().SetIsContinueWhenError(true), "", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("DeleteRemoteCategories", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite { func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
err = api.EbaiAPI.ShopCategoryDelete(strStoreID, batchItemList[0].(int64)) if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
} err = api.EbaiAPI.ShopCategoryDelete(strStoreID, batchItemList[0].(int64))
return nil, err }
}, vendorCatIDs) return nil, err
}, vendorCatIDs)
tasksch.AddChild(parentTask, task).Run() tasksch.AddChild(parentTask, task).Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
return err return err
@@ -465,9 +472,10 @@ func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask t
globals.SugarLogger.Debugf("SyncOneStoreCategories storeID:%d, userName:%s", storeID, userName) globals.SugarLogger.Debugf("SyncOneStoreCategories storeID:%d, userName:%s", storeID, userName)
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("ebai SyncStoreCategory", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("ebai SyncStoreCategory", ctx,
level := step + 1 func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
sql := ` level := step + 1
sql := `
SELECT t2.*, t1.name, t1.parent_id, t1.level, t1.type, t1.seq, t2p.ebai_id parent_ebai_id SELECT t2.*, t1.name, t1.parent_id, t1.level, t1.type, t1.seq, t2p.ebai_id parent_ebai_id
FROM sku_category t1 FROM sku_category t1
LEFT JOIN sku_category t1p ON t1.parent_id = t1p.id LEFT JOIN sku_category t1p ON t1.parent_id = t1p.id
@@ -475,45 +483,46 @@ func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask t
LEFT JOIN store_sku_category_map t2p ON t1p.id = t2p.category_id AND t2p.store_id = ? AND t2p.deleted_at = ? LEFT JOIN store_sku_category_map t2p ON t1p.id = t2p.category_id AND t2p.store_id = ? AND t2p.deleted_at = ?
WHERE t1.level = ? AND t1.deleted_at = ? WHERE t1.level = ? AND t1.deleted_at = ?
` `
var catList []*tStoreCatInfo var catList []*tStoreCatInfo
sqlParams := []interface{}{ sqlParams := []interface{}{
storeID, storeID,
storeID, storeID,
utils.DefaultTimeValue, utils.DefaultTimeValue,
level, level,
utils.DefaultTimeValue, utils.DefaultTimeValue,
} }
if err = dao.GetRows(db, &catList, sql, sqlParams...); err == nil { if err = dao.GetRows(db, &catList, sql, sqlParams...); err == nil {
strStoreID := utils.Int2Str(storeID) strStoreID := utils.Int2Str(storeID)
task := tasksch.NewParallelTask("SyncStoreCategory", nil, userName, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("SyncStoreCategory", nil, ctx,
updateFields := []string{model.FieldEbaiSyncStatus} func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
catInfo := batchItemList[0].(*tStoreCatInfo) updateFields := []string{model.FieldEbaiSyncStatus}
// globals.SugarLogger.Debug(utils.Format4Output(catInfo, false)) catInfo := batchItemList[0].(*tStoreCatInfo)
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite { // globals.SugarLogger.Debug(utils.Format4Output(catInfo, false))
if catInfo.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
err = api.EbaiAPI.ShopCategoryDelete(strStoreID, catInfo.EbaiID) if catInfo.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除
} else if catInfo.EbaiSyncStatus&model.SyncFlagNewMask != 0 { // 新增 err = api.EbaiAPI.ShopCategoryDelete(strStoreID, catInfo.EbaiID)
ebaiID, err2 := api.EbaiAPI.ShopCategoryCreate(strStoreID, catInfo.ParentEbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq)) } else if catInfo.EbaiSyncStatus&model.SyncFlagNewMask != 0 { // 新增
if err = err2; err == nil { ebaiID, err2 := api.EbaiAPI.ShopCategoryCreate(strStoreID, catInfo.ParentEbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq))
catInfo.EbaiID = ebaiID if err = err2; err == nil {
updateFields = append(updateFields, model.FieldEbaiID) catInfo.EbaiID = ebaiID
updateFields = append(updateFields, model.FieldEbaiID)
}
} else if catInfo.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改
err = api.EbaiAPI.ShopCategoryUpdate(strStoreID, catInfo.EbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq))
}
} }
} else if catInfo.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改 if err == nil {
err = api.EbaiAPI.ShopCategoryUpdate(strStoreID, catInfo.EbaiID, formatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq)) db2 := dao.GetDB()
} catInfo.EbaiSyncStatus = 0
} _, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
if err == nil { }
db2 := dao.GetDB() return nil, err
catInfo.EbaiSyncStatus = 0 }, catList)
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...) rootTask.AddChild(task).Run()
} _, err = task.GetResult(0)
return nil, err }
}, catList) return nil, err
rootTask.AddChild(task).Run() }, 2)
_, err = task.GetResult(0)
}
return nil, err
}, 2)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)

View File

@@ -36,7 +36,7 @@ func TestSyncOneStoreCategoriesFromLocal2Remote(t *testing.T) {
} }
func TestGetAllRemoteSkus(t *testing.T) { func TestGetAllRemoteSkus(t *testing.T) {
result, err := new(PurchaseHandler).GetAllRemoteSkus(testShopID) result, err := new(PurchaseHandler).GetAllRemoteSkus(jxcontext.AdminCtx, testShopID, nil)
if err != nil { if err != nil {
t.Fatal(err.Error()) t.Fatal(err.Error())
} else { } else {

View File

@@ -302,44 +302,45 @@ func (p *PurchaseHandler) RefreshAllSkusID(ctx *jxcontext.Context, parentTask ta
var skuPairs []*jdapi.SkuIDPair var skuPairs []*jdapi.SkuIDPair
const stepCount = 2 const stepCount = 2
rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = dao.GetRows(db, &skuPairs, ` case 0:
err = dao.GetRows(db, &skuPairs, `
SELECT t1.id out_sku_id, t1.jd_id sku_id SELECT t1.id out_sku_id, t1.jd_id sku_id
FROM sku t1 FROM sku t1
WHERE t1.deleted_at = ? WHERE t1.deleted_at = ?
`, utils.DefaultTimeValue) `, utils.DefaultTimeValue)
default: default:
taskName := "RefreshAllSkusID update id" taskName := "RefreshAllSkusID update id"
if step != stepCount-1 { if step != stepCount-1 {
taskName = "RefreshAllSkusID update uuid" taskName = "RefreshAllSkusID update uuid"
}
task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx,
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList))
for k, v := range batchItemList {
pair := v.(*jdapi.SkuIDPair)
skuPairs[k] = &jdapi.SkuIDPair{
SkuId: pair.SkuId,
OutSkuId: pair.OutSkuId,
}
if step != stepCount-1 {
skuPairs[k].OutSkuId = utils.GetUUID()
}
}
globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
if globals.EnableStoreWrite {
_, err = api.JdAPI.BatchUpdateOutSkuId(skuPairs)
}
return nil, err
}, skuPairs)
rootTask.AddChild(task1).Run()
_, err = task1.GetResult(0)
} }
task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx.GetUserName(), func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { return nil, err
skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList)) }, stepCount)
for k, v := range batchItemList { tasksch.HandleTask(rootTask, parentTask, false).Run()
pair := v.(*jdapi.SkuIDPair)
skuPairs[k] = &jdapi.SkuIDPair{
SkuId: pair.SkuId,
OutSkuId: pair.OutSkuId,
}
if step != stepCount-1 {
skuPairs[k].OutSkuId = utils.GetUUID()
}
}
globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
if globals.EnableStoreWrite {
_, err = api.JdAPI.BatchUpdateOutSkuId(skuPairs)
}
return nil, err
}, skuPairs)
rootTask.AddChild(task1).Run()
_, err = task1.GetResult(0)
}
return nil, err
}, stepCount)
ctx.SetTaskOrAddChild(rootTask, parentTask)
rootTask.Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
} }

View File

@@ -209,41 +209,42 @@ func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask
const stepCount = 3 const stepCount = 3
var stores []*tJdStoreInfo var stores []*tJdStoreInfo
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("jd RefreshAllStoresID", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("jd RefreshAllStoresID", ctx,
switch step { func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = dao.GetRows(db, &stores, ` case 0:
err = dao.GetRows(db, &stores, `
SELECT t1.*, t2.vendor_store_id SELECT t1.*, t2.vendor_store_id
FROM store t1 FROM store t1
JOIN store_map t2 ON t1.id = t2.store_id AND t2.deleted_at = ? AND t2.vendor_id = ? JOIN store_map t2 ON t1.id = t2.store_id AND t2.deleted_at = ? AND t2.vendor_id = ?
WHERE t1.deleted_at = ? WHERE t1.deleted_at = ?
`, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue) `, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue)
default: default:
taskName := "jd RefreshAllStoresID update outSystemId" taskName := "jd RefreshAllStoresID update outSystemId"
if step != stepCount-1 {
taskName = "jd RefreshAllStoresID update to uuid"
}
task1 := tasksch.NewParallelTask(taskName, nil, ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
store := batchItemList[0].(*tJdStoreInfo)
storeParams := map[string]interface{}{
"outSystemId": utils.Int2Str(int(store.ID)),
}
if step != stepCount-1 { if step != stepCount-1 {
storeParams["outSystemId"] = utils.GetUUID() taskName = "jd RefreshAllStoresID update to uuid"
} }
if true { //globals.EnableStoreWrite { task1 := tasksch.NewParallelTask(taskName, nil, ctx,
err = api.JdAPI.UpdateStoreInfo4Open(store.VendorStoreID, ctx.GetUserName(), storeParams) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
} store := batchItemList[0].(*tJdStoreInfo)
return nil, err storeParams := map[string]interface{}{
}, stores) "outSystemId": utils.Int2Str(int(store.ID)),
task.AddChild(task1).Run() }
_, err = task1.GetResult(0) if step != stepCount-1 {
} storeParams["outSystemId"] = utils.GetUUID()
return nil, err }
}, stepCount) if true { //globals.EnableStoreWrite {
err = api.JdAPI.UpdateStoreInfo4Open(store.VendorStoreID, ctx.GetUserName(), storeParams)
}
return nil, err
}, stores)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
}
return nil, err
}, stepCount)
ctx.SetTaskOrAddChild(rootTask, parentTask) tasksch.HandleTask(rootTask, parentTask, false).Run()
rootTask.Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
} }

View File

@@ -54,106 +54,106 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
if err = dao.GetRows(db, &storeSkus, sql, append(sqlParams, sqlWhereParams...)...); err != nil { if err = dao.GetRows(db, &storeSkus, sql, append(sqlParams, sqlWhereParams...)...); err != nil {
return "", err return "", err
} }
task := tasksch.NewParallelTask("SyncStoresSkus京东", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("SyncStoresSkus京东", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(isContinueWhenError), ctx,
var skuPriceInfoList []*jdapi.SkuPriceInfo func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
var skuVendibilityList []*jdapi.StockVendibility var skuPriceInfoList []*jdapi.SkuPriceInfo
var skuStockList []*jdapi.SkuStock var skuVendibilityList []*jdapi.StockVendibility
stationNo := batchItemList[0].(*tStoreSkuBindExt).VendorStoreID var skuStockList []*jdapi.SkuStock
var batchSkuIDs []int stationNo := batchItemList[0].(*tStoreSkuBindExt).VendorStoreID
for _, v := range batchItemList { var batchSkuIDs []int
storeSku := v.(*tStoreSkuBindExt) for _, v := range batchItemList {
alreadyAddStock := false storeSku := v.(*tStoreSkuBindExt)
if storeSku.JdSyncStatus&model.SyncFlagChangedMask != 0 { alreadyAddStock := false
batchSkuIDs = append(batchSkuIDs, storeSku.SkuID) if storeSku.JdSyncStatus&model.SyncFlagChangedMask != 0 {
if storeSku.JdSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 { // 关注或取消关注 batchSkuIDs = append(batchSkuIDs, storeSku.SkuID)
stock := &jdapi.SkuStock{ if storeSku.JdSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 { // 关注或取消关注
OutSkuId: utils.Int2Str(storeSku.SkuID),
StockQty: model.MaxStoreSkuStockQty,
}
if storeSku.DeletedAt != utils.DefaultTimeValue {
stock.StockQty = 0
} else {
alreadyAddStock = true
}
if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuStockList = append(skuStockList, stock)
}
}
if storeSku.JdSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(storeSku.SkuID),
Price: jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage),
})
}
if storeSku.JdSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
vendibility := &jdapi.StockVendibility{
OutSkuId: utils.Int2Str(storeSku.SkuID),
DoSale: true,
}
if storeSku.Status != model.StoreSkuBindStatusNormal {
vendibility.DoSale = false
} else if !alreadyAddStock { // 如果是设置可售则自动将库存加满
stock := &jdapi.SkuStock{ stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.SkuID), OutSkuId: utils.Int2Str(storeSku.SkuID),
StockQty: model.MaxStoreSkuStockQty, StockQty: model.MaxStoreSkuStockQty,
} }
skuStockList = append(skuStockList, stock) if storeSku.DeletedAt != utils.DefaultTimeValue {
stock.StockQty = 0
} else {
alreadyAddStock = true
}
if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuStockList = append(skuStockList, stock)
}
} }
if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { if storeSku.JdSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
skuVendibilityList = append(skuVendibilityList, vendibility) skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(storeSku.SkuID),
Price: jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage),
})
}
if storeSku.JdSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
vendibility := &jdapi.StockVendibility{
OutSkuId: utils.Int2Str(storeSku.SkuID),
DoSale: true,
}
if storeSku.Status != model.StoreSkuBindStatusNormal {
vendibility.DoSale = false
} else if !alreadyAddStock { // 如果是设置可售则自动将库存加满
stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.SkuID),
StockQty: model.MaxStoreSkuStockQty,
}
skuStockList = append(skuStockList, stock)
}
if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuVendibilityList = append(skuVendibilityList, vendibility)
}
} }
} }
} }
} syncMask := 0
syncMask := 0 errList := []error{}
errList := []error{} if globals.EnableStoreWrite {
if globals.EnableStoreWrite { // todo 以下可以优化为并行操作
// todo 以下可以优化为并行操作 globals.SugarLogger.Debug(utils.Format4Output(skuVendibilityList, false), utils.Format4Output(skuPriceInfoList, false), utils.Format4Output(skuStockList, false))
globals.SugarLogger.Debug(utils.Format4Output(skuVendibilityList, false), utils.Format4Output(skuPriceInfoList, false), utils.Format4Output(skuStockList, false)) if len(skuVendibilityList) > 0 {
if len(skuVendibilityList) > 0 { if _, err = api.JdAPI.BatchUpdateVendibility("", stationNo, skuVendibilityList, ctx.GetUserName()); err == nil {
if _, err = api.JdAPI.BatchUpdateVendibility("", stationNo, skuVendibilityList, ctx.GetUserName()); err == nil { syncMask |= model.SyncFlagSaleMask
syncMask |= model.SyncFlagSaleMask } else {
} else { errList = append(errList, err)
errList = append(errList, err) }
}
if (err == nil || isContinueWhenError) && len(skuStockList) > 0 {
if _, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, skuStockList, ctx.GetUserName()); err == nil {
syncMask |= model.SyncFlagNewMask | model.SyncFlagDeletedMask
} else {
errList = append(errList, err)
}
}
if (err == nil || isContinueWhenError) && len(skuPriceInfoList) > 0 {
if _, err = api.JdAPI.UpdateVendorStationPrice("", stationNo, skuPriceInfoList); err == nil {
syncMask |= model.SyncFlagPriceMask
} else {
errList = append(errList, err)
}
} }
} }
if (err == nil || isContinueWhenError) && len(skuStockList) > 0 { if len(errList) == 0 {
if _, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, skuStockList, ctx.GetUserName()); err == nil { syncMask = -1
syncMask |= model.SyncFlagNewMask | model.SyncFlagDeletedMask
} else {
errList = append(errList, err)
}
} }
if (err == nil || isContinueWhenError) && len(skuPriceInfoList) > 0 { if syncMask != 0 && len(batchSkuIDs) > 0 {
if _, err = api.JdAPI.UpdateVendorStationPrice("", stationNo, skuPriceInfoList); err == nil { db := dao.GetDB() // 多线程问题
syncMask |= model.SyncFlagPriceMask sql := `
} else {
errList = append(errList, err)
}
}
}
if len(errList) == 0 {
syncMask = -1
}
if syncMask != 0 && len(batchSkuIDs) > 0 {
db := dao.GetDB() // 多线程问题
sql := `
UPDATE store_sku_bind t1 UPDATE store_sku_bind t1
SET t1.jd_sync_status = t1.jd_sync_status & ? SET t1.jd_sync_status = t1.jd_sync_status & ?
` + sqlWhere0 + " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(batchSkuIDs)) + ")" ` + sqlWhere0 + " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(batchSkuIDs)) + ")"
if _, err = dao.ExecuteSQL(db, sql, ^syncMask, storeID, batchSkuIDs); err != nil { if _, err = dao.ExecuteSQL(db, sql, ^syncMask, storeID, batchSkuIDs); err != nil {
errList = append(errList, err) errList = append(errList, err)
}
} }
} if len(errList) == 1 {
if len(errList) == 1 { err = errList[0]
err = errList[0] } else if len(errList) > 1 {
} else if len(errList) > 1 { err = fmt.Errorf("%v", errList)
err = fmt.Errorf("%v", errList) }
} return nil, err
return nil, err }, storeSkus)
}, storeSkus) tasksch.HandleTask(task, parentTask, false).Run()
ctx.SetTaskOrAddChild(task, parentTask)
task.Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }
@@ -185,83 +185,83 @@ func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasks
return "", err return "", err
} }
stationNo := storeDetail.VendorStoreID stationNo := storeDetail.VendorStoreID
task := tasksch.NewParallelTask("SyncStoresSkus京东", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) { task := tasksch.NewParallelTask("SyncStoresSkus京东", tasksch.NewParallelConfig().SetBatchSize(jdapi.MaxStoreSkuBatchSize).SetIsContinueWhenError(isContinueWhenError), ctx,
var skuPriceInfoList []*jdapi.SkuPriceInfo func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
var skuVendibilityList []*jdapi.StockVendibility var skuPriceInfoList []*jdapi.SkuPriceInfo
var skuStockList []*jdapi.SkuStock var skuVendibilityList []*jdapi.StockVendibility
var batchSkuIDs []int var skuStockList []*jdapi.SkuStock
for _, v := range batchItemList { var batchSkuIDs []int
storeSku := v.(*dao.StoreSkuSyncInfo) for _, v := range batchItemList {
alreadyAddStock := false storeSku := v.(*dao.StoreSkuSyncInfo)
if storeSku.SkuSyncStatus&model.SyncFlagChangedMask != 0 || storeSku.BindID == 0 { alreadyAddStock := false
if storeSku.BindID != 0 { if storeSku.SkuSyncStatus&model.SyncFlagChangedMask != 0 || storeSku.BindID == 0 {
batchSkuIDs = append(batchSkuIDs, storeSku.BindID) if storeSku.BindID != 0 {
} batchSkuIDs = append(batchSkuIDs, storeSku.BindID)
if storeSku.SkuSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 || storeSku.BindID == 0 { // 关注或取消关注
stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.ID),
StockQty: model.MaxStoreSkuStockQty,
} }
if storeSku.DeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 { if storeSku.SkuSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 || storeSku.BindID == 0 { // 关注或取消关注
stock.StockQty = 0
} else {
alreadyAddStock = true
}
if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuStockList = append(skuStockList, stock)
}
}
if storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(storeSku.ID),
Price: jxutils.CaculateSkuVendorPrice(int(storeSku.Price), int(storeDetail.PricePercentage)),
})
}
if storeSku.SkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
vendibility := &jdapi.StockVendibility{
OutSkuId: utils.Int2Str(storeSku.ID),
DoSale: true,
}
if storeSku.StoreSkuStatus != model.StoreSkuBindStatusNormal {
vendibility.DoSale = false
} else if !alreadyAddStock { // 如果是设置可售则自动将库存加满
stock := &jdapi.SkuStock{ stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.ID), OutSkuId: utils.Int2Str(storeSku.ID),
StockQty: model.MaxStoreSkuStockQty, StockQty: model.MaxStoreSkuStockQty,
} }
skuStockList = append(skuStockList, stock) if storeSku.DeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 {
stock.StockQty = 0
} else {
alreadyAddStock = true
}
if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuStockList = append(skuStockList, stock)
}
} }
if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { if storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
skuVendibilityList = append(skuVendibilityList, vendibility) skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
OutSkuId: utils.Int2Str(storeSku.ID),
Price: jxutils.CaculateSkuVendorPrice(int(storeSku.Price), int(storeDetail.PricePercentage)),
})
}
if storeSku.SkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
vendibility := &jdapi.StockVendibility{
OutSkuId: utils.Int2Str(storeSku.ID),
DoSale: true,
}
if storeSku.StoreSkuStatus != model.StoreSkuBindStatusNormal {
vendibility.DoSale = false
} else if !alreadyAddStock { // 如果是设置可售则自动将库存加满
stock := &jdapi.SkuStock{
OutSkuId: utils.Int2Str(storeSku.ID),
StockQty: model.MaxStoreSkuStockQty,
}
skuStockList = append(skuStockList, stock)
}
if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) {
skuVendibilityList = append(skuVendibilityList, vendibility)
}
} }
} }
} }
} globals.SugarLogger.Debugf("jd syncStoreSkus sync detail, storeID:%d, skuVendibilityList:%s, skuPriceInfoList:%s, skuStockList:%s", storeID, utils.Format4Output(skuVendibilityList, true), utils.Format4Output(skuPriceInfoList, true), utils.Format4Output(skuStockList, true))
globals.SugarLogger.Debugf("jd syncStoreSkus sync detail, storeID:%d, skuVendibilityList:%s, skuPriceInfoList:%s, skuStockList:%s", storeID, utils.Format4Output(skuVendibilityList, true), utils.Format4Output(skuPriceInfoList, true), utils.Format4Output(skuStockList, true)) if globals.EnableStoreWrite {
if globals.EnableStoreWrite { // todo 以下可以优化为并行操作
// todo 以下可以优化为并行操作 if len(skuVendibilityList) > 0 {
if len(skuVendibilityList) > 0 { _, err = api.JdAPI.BatchUpdateVendibility("", stationNo, skuVendibilityList, ctx.GetUserName())
_, err = api.JdAPI.BatchUpdateVendibility("", stationNo, skuVendibilityList, ctx.GetUserName()) }
if err == nil && len(skuStockList) > 0 {
_, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, skuStockList, ctx.GetUserName())
}
if err == nil && len(skuPriceInfoList) > 0 {
_, err = api.JdAPI.UpdateVendorStationPrice("", stationNo, skuPriceInfoList)
}
} }
if err == nil && len(skuStockList) > 0 { if err == nil && len(batchSkuIDs) > 0 {
_, err = api.JdAPI.BatchUpdateCurrentQtys("", stationNo, skuStockList, ctx.GetUserName()) db := dao.GetDB() // 多线程问题
} sql := `
if err == nil && len(skuPriceInfoList) > 0 {
_, err = api.JdAPI.UpdateVendorStationPrice("", stationNo, skuPriceInfoList)
}
}
if err == nil && len(batchSkuIDs) > 0 {
db := dao.GetDB() // 多线程问题
sql := `
UPDATE store_sku_bind t1 UPDATE store_sku_bind t1
SET t1.jd_sync_status = 0 SET t1.jd_sync_status = 0
WHERE t1.id IN (` + dao.GenQuestionMarks(len(batchSkuIDs)) + ")" WHERE t1.id IN (` + dao.GenQuestionMarks(len(batchSkuIDs)) + ")"
_, err = dao.ExecuteSQL(db, sql, batchSkuIDs) _, err = dao.ExecuteSQL(db, sql, batchSkuIDs)
} }
return nil, err return nil, err
}, skus) }, skus)
ctx.SetTaskOrAddChild(task, parentTask) tasksch.HandleTask(task, parentTask, false).Run()
task.Run()
if !isAsync { if !isAsync {
_, err = task.GetResult(0) _, err = task.GetResult(0)
} }

View File

@@ -17,7 +17,6 @@ import (
// hint如果是异步返回的是任务ID如果是同步返回是本次需要同步的目录数 // hint如果是异步返回的是任务ID如果是同步返回是本次需要同步的目录数
func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) {
userName := ctx.GetUserName()
num := 0 num := 0
db := dao.GetDB() db := dao.GetDB()
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM)
@@ -25,57 +24,59 @@ func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask t
return hint, err return hint, err
} }
vendorStoreID := storeDetail.VendorStoreID vendorStoreID := storeDetail.VendorStoreID
rootTask := tasksch.NewSeqTask("美团外卖SyncStoreCategory step1", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("美团外卖SyncStoreCategory step1", ctx,
level := step + 1 func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
catList, err := dao.GetStoreCategories(db, model.VendorIDMTWM, storeID, level) level := step + 1
if len(catList) > 0 { catList, err := dao.GetStoreCategories(db, model.VendorIDMTWM, storeID, level)
num += len(catList) if len(catList) > 0 {
task := tasksch.NewParallelTask(fmt.Sprintf("美团外卖SyncStoreCategory step2, level=%d", level), nil, userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { num += len(catList)
updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDMTWM])} task := tasksch.NewParallelTask(fmt.Sprintf("美团外卖SyncStoreCategory step2, level=%d", level), nil, ctx,
catInfo := batchItemList[0].(*dao.StoreCatSyncInfo) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite { updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDMTWM])}
if catInfo.MtwmSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 catInfo := batchItemList[0].(*dao.StoreCatSyncInfo)
globals.SugarLogger.Debugf("RetailCatDelete vendorStoreID:%s, MtwmID:%s", vendorStoreID, catInfo.MtwmID) if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catInfo.MtwmID) if catInfo.MtwmSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除
} else if catInfo.MtwmSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增 globals.SugarLogger.Debugf("RetailCatDelete vendorStoreID:%s, MtwmID:%s", vendorStoreID, catInfo.MtwmID)
catName := catInfo.CatName err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catInfo.MtwmID)
subCatName := "" } else if catInfo.MtwmSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增
originName := "" catName := catInfo.CatName
if catInfo.MtwmSyncStatus&model.SyncFlagNewMask == 0 { subCatName := ""
originName = catInfo.MtwmID originName := ""
} if catInfo.MtwmSyncStatus&model.SyncFlagNewMask == 0 {
if level == 2 { originName = catInfo.MtwmID
originName = catInfo.ParentCatName }
catName = catInfo.ParentCatName if level == 2 {
subCatName = catInfo.CatName originName = catInfo.ParentCatName
if catInfo.MtwmSyncStatus&model.SyncFlagNewMask == 0 { catName = catInfo.ParentCatName
originName = catInfo.MtwmID subCatName = catInfo.CatName
catName = catInfo.CatName if catInfo.MtwmSyncStatus&model.SyncFlagNewMask == 0 {
subCatName = "" originName = catInfo.MtwmID
catName = catInfo.CatName
subCatName = ""
}
}
if catName == "" {
panic("catName is empty")
}
globals.SugarLogger.Debugf("RetailCatUpdate vendorStoreID:%s, originName:%s, catName:%s, subCatName:%s, seq:%d", vendorStoreID, originName, catName, subCatName, catInfo.Seq)
if err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, originName, catName, subCatName, catInfo.Seq); err == nil {
catInfo.MtwmID = catInfo.CatName
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDMTWM]))
}
} }
} }
if catName == "" { if err == nil {
panic("catName is empty") db2 := dao.GetDB()
catInfo.MtwmSyncStatus = 0
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
} }
globals.SugarLogger.Debugf("RetailCatUpdate vendorStoreID:%s, originName:%s, catName:%s, subCatName:%s, seq:%d", vendorStoreID, originName, catName, subCatName, catInfo.Seq) return nil, err
if err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, originName, catName, subCatName, catInfo.Seq); err == nil { }, catList)
catInfo.MtwmID = catInfo.CatName rootTask.AddChild(task).Run()
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDMTWM])) _, err = task.GetResult(0)
} }
} return nil, err
} }, 2)
if err == nil {
db2 := dao.GetDB()
catInfo.MtwmSyncStatus = 0
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
}
return nil, err
}, catList)
rootTask.AddChild(task).Run()
_, err = task.GetResult(0)
}
return nil, err
}, 2)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
hint = utils.Int2Str(num) hint = utils.Int2Str(num)
@@ -235,56 +236,57 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
} }
// globals.SugarLogger.Debug(utils.Format4Output(skus, false)) // globals.SugarLogger.Debug(utils.Format4Output(skus, false))
vendorStoreID := storeDetail.VendorStoreID vendorStoreID := storeDetail.VendorStoreID
rootTask := tasksch.NewParallelTask("美团外卖SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("美团外卖SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
foodDataList := make([]map[string]interface{}, len(batchItemList)) func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
// for k, v := range batchItemList { foodDataList := make([]map[string]interface{}, len(batchItemList))
v := batchItemList[0] // for k, v := range batchItemList {
skuItem := v.(*dao.StoreSkuSyncInfo) v := batchItemList[0]
if skuItem.SkuSyncStatus&model.SyncFlagDeletedMask != 0 { skuItem := v.(*dao.StoreSkuSyncInfo)
err = api.MtwmAPI.RetailDelete(vendorStoreID, utils.Int2Str(skuItem.ID)) if skuItem.SkuSyncStatus&model.SyncFlagDeletedMask != 0 {
} else if skuItem.SkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask) != 0 { err = api.MtwmAPI.RetailDelete(vendorStoreID, utils.Int2Str(skuItem.ID))
foodData := make(map[string]interface{}) } else if skuItem.SkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask) != 0 {
foodDataList[0] = foodData foodData := make(map[string]interface{})
foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(skuItem.ID) foodDataList[0] = foodData
foodData["name"] = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30) foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(skuItem.ID)
foodData["description"] = skuItem.Comment foodData["name"] = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30)
foodData["price"] = jxutils.IntPrice2Standard(int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage)))) foodData["description"] = skuItem.Comment
foodData["min_order_count"] = 1 foodData["price"] = jxutils.IntPrice2Standard(int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage))))
foodData["unit"] = skuItem.Unit foodData["min_order_count"] = 1
foodData["box_num"] = 0 foodData["unit"] = skuItem.Unit
foodData["box_price"] = 0.0 foodData["box_num"] = 0
foodData["category_name"] = skuItem.VendorCatID foodData["box_price"] = 0.0
foodData["is_sold_out"] = skuStatusJX2Mtwm(jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus)) foodData["category_name"] = skuItem.VendorCatID
foodData["picture"] = skuItem.Img foodData["is_sold_out"] = skuStatusJX2Mtwm(jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus))
if skuItem.VendorVendorCatID != 0 { foodData["picture"] = skuItem.Img
foodData["tag_id"] = utils.Int64ToStr(skuItem.VendorVendorCatID) if skuItem.VendorVendorCatID != 0 {
} else { foodData["tag_id"] = utils.Int64ToStr(skuItem.VendorVendorCatID)
// foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) } else {
// foodData["tag_id"] = utils.Int64ToStr(defVendorCatID)
}
skus := []map[string]interface{}{
map[string]interface{}{
"sku_id": foodData[mtwmapi.KeyAppFoodCode],
"spec": jxutils.ComposeSkuSpec(skuItem.SpecQuality, skuItem.SpecUnit),
"price": foodData["price"],
"stock": "*",
"upc": skuItem.Upc,
},
}
if foodData["tag_id"] != nil {
skus[0]["weight"] = skuItem.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用
}
foodData["skus"] = skus
if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.RetailBatchInitData(vendorStoreID, foodDataList)
}
} }
skus := []map[string]interface{}{ if err == nil {
map[string]interface{}{ storeSkuBind := &model.StoreSkuBind{}
"sku_id": foodData[mtwmapi.KeyAppFoodCode], storeSkuBind.ID = skuItem.BindID
"spec": jxutils.ComposeSkuSpec(skuItem.SpecQuality, skuItem.SpecUnit), _, err = dao.UpdateEntity(nil, storeSkuBind, model.FieldMtwmSyncStatus)
"price": foodData["price"],
"stock": "*",
"upc": skuItem.Upc,
},
} }
if foodData["tag_id"] != nil { return nil, err
skus[0]["weight"] = skuItem.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 }, skus)
}
foodData["skus"] = skus
if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.RetailBatchInitData(vendorStoreID, foodDataList)
}
}
if err == nil {
storeSkuBind := &model.StoreSkuBind{}
storeSkuBind.ID = skuItem.BindID
_, err = dao.UpdateEntity(nil, storeSkuBind, model.FieldMtwmSyncStatus)
}
return nil, err
}, skus)
if parentTask != nil { if parentTask != nil {
parentTask.AddChild(rootTask) parentTask.AddChild(rootTask)
} }
@@ -307,28 +309,29 @@ func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask t
globals.SugarLogger.Debugf("mtwm FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) globals.SugarLogger.Debugf("mtwm FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName)
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("美团外卖FullSyncStoreSkus", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("美团外卖FullSyncStoreSkus", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil) case 0:
if isContinueWhenError { err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
err = nil if isContinueWhenError {
err = nil
}
case 1:
_, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
}
case 3:
_, err = p.SyncLocalStoreCategory(ctx, db, storeID, true)
case 4:
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
case 5:
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError)
} }
case 1: return nil, err
_, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask) }, 6)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
}
case 3:
_, err = p.SyncLocalStoreCategory(ctx, db, storeID, true)
case 4:
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
case 5:
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError)
}
return nil, err
}, 6)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
@@ -351,13 +354,14 @@ func (p *PurchaseHandler) DeleteRemoteSkus(ctx *jxcontext.Context, parentTask ta
return err return err
} }
vendorStoreID := storeDetail.VendorStoreID vendorStoreID := storeDetail.VendorStoreID
task := tasksch.NewParallelTask("mtwm DeleteRemoteSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(true), "", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { task := tasksch.NewParallelTask("mtwm DeleteRemoteSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite { func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
// globals.SugarLogger.Debugf("mtwm RetailDelete vendorStoreID:%s, sku:%s", vendorStoreID, batchItemList[0].(string)) if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite {
err = api.MtwmAPI.RetailDelete(vendorStoreID, batchItemList[0].(string)) // globals.SugarLogger.Debugf("mtwm RetailDelete vendorStoreID:%s, sku:%s", vendorStoreID, batchItemList[0].(string))
} err = api.MtwmAPI.RetailDelete(vendorStoreID, batchItemList[0].(string))
return nil, err }
}, vendorSkuIDs) return nil, err
}, vendorSkuIDs)
tasksch.AddChild(parentTask, task).Run() tasksch.AddChild(parentTask, task).Run()
_, err = task.GetResult(0) _, err = task.GetResult(0)
return err return err
@@ -402,25 +406,27 @@ func (p *PurchaseHandler) DeleteRemoteCategories(ctx *jxcontext.Context, parentT
} }
} }
} }
rootTask := tasksch.NewSeqTask("mtwm DeleteRemoteCategories", "", func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("mtwm DeleteRemoteCategories", ctx,
var catIDs []string func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
if step == 0 { var catIDs []string
catIDs = vendorCatIDs2 if step == 0 {
} else { catIDs = vendorCatIDs2
catIDs = vendorCatIDs } else {
} catIDs = vendorCatIDs
if len(catIDs) > 0 { }
task := tasksch.NewParallelTask("mtwm DeleteRemoteCategories paralle", tasksch.NewParallelConfig().SetIsContinueWhenError(true), "", func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { if len(catIDs) > 0 {
if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite { task := tasksch.NewParallelTask("mtwm DeleteRemoteCategories paralle", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
err = api.MtwmAPI.RetailCatDelete(vendorStoreID, batchItemList[0].(string)) func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
} if globals.EnableStoreWrite && globals.EnableMtwmStoreWrite {
return nil, err err = api.MtwmAPI.RetailCatDelete(vendorStoreID, batchItemList[0].(string))
}, catIDs) }
rootTask.AddChild(task).Run() return nil, err
_, err = task.GetResult(0) }, catIDs)
} rootTask.AddChild(task).Run()
return nil, err _, err = task.GetResult(0)
}, 2) }
return nil, err
}, 2)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)
return err return err
@@ -432,24 +438,25 @@ func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTa
db := dao.GetDB() db := dao.GetDB()
var errDeleteSku error var errDeleteSku error
rootTask := tasksch.NewSeqTask("mtwm DeleteRemoteStoreSkus", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("mtwm DeleteRemoteStoreSkus", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil) case 0:
errDeleteSku = err err = p.DeleteRemoteSkus(ctx, rootTask, storeID, nil)
// 强制忽略删除SKU错误 errDeleteSku = err
if isContinueWhenError { // 强制忽略删除SKU错误
err = nil if isContinueWhenError {
err = nil
}
case 1:
_, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
}
} }
case 1: return nil, err
_, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask) }, 3)
case 2:
if err = p.DeleteRemoteCategories(ctx, rootTask, storeID, nil); err == nil {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, storeID, nil, model.SyncFlagNewMask)
}
}
return nil, err
}, 3)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)

View File

@@ -24,47 +24,48 @@ const (
) )
func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) {
userName := ctx.GetUserName()
strStoreID := utils.Int2Str(storeID) strStoreID := utils.Int2Str(storeID)
num := 0 num := 0
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("微盟微商城SyncStoreCategory step1", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("微盟微商城SyncStoreCategory step1", ctx,
level := step + 1 func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
catList, err := dao.GetStoreCategories(db, model.VendorIDWSC, storeID, level) level := step + 1
// globals.SugarLogger.Debug(utils.Format4Output(catList, false)) catList, err := dao.GetStoreCategories(db, model.VendorIDWSC, storeID, level)
if len(catList) > 0 { // globals.SugarLogger.Debug(utils.Format4Output(catList, false))
num += len(catList) if len(catList) > 0 {
task := tasksch.NewParallelTask(fmt.Sprintf("微盟微商城SyncStoreCategory step2, level=%d", level), nil, userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { num += len(catList)
updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDWSC])} task := tasksch.NewParallelTask(fmt.Sprintf("微盟微商城SyncStoreCategory step2, level=%d", level), nil, ctx,
catInfo := batchItemList[0].(*dao.StoreCatSyncInfo) func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
if globals.EnableStoreWrite && globals.EnableWscStoreWrite { updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDWSC])}
if catInfo.WscSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 catInfo := batchItemList[0].(*dao.StoreCatSyncInfo)
globals.SugarLogger.Debugf("UpdateClassify strStoreID:%s, WscID:%d", strStoreID, catInfo.WscID) if globals.EnableStoreWrite && globals.EnableWscStoreWrite {
err = api.WeimobAPI.UpdateClassify(catInfo.WscID, composeFakeDelName(catInfo.CatName), "") if catInfo.WscSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除
} else if catInfo.WscSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增 globals.SugarLogger.Debugf("UpdateClassify strStoreID:%s, WscID:%d", strStoreID, catInfo.WscID)
catImg := "" err = api.WeimobAPI.UpdateClassify(catInfo.WscID, composeFakeDelName(catInfo.CatName), "")
if level == 2 { } else if catInfo.WscSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增
catImg = DefCatImg catImg := ""
if level == 2 {
catImg = DefCatImg
}
if catInfo.WscID, err = api.WeimobAPI.AddClassify(catInfo.CatName, utils.Str2Int64WithDefault(catInfo.ParentVendorCatID, 0), catImg); err == nil {
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDWSC]))
}
} else if catInfo.WscSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagModifiedMask) != 0 { // 修改
err = api.WeimobAPI.UpdateClassify(catInfo.WscID, catInfo.CatName, "")
}
} }
if catInfo.WscID, err = api.WeimobAPI.AddClassify(catInfo.CatName, utils.Str2Int64WithDefault(catInfo.ParentVendorCatID, 0), catImg); err == nil { if err == nil {
updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDWSC])) db2 := dao.GetDB()
catInfo.WscSyncStatus = 0
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
} }
} else if catInfo.WscSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagModifiedMask) != 0 { // 修改 return nil, err
err = api.WeimobAPI.UpdateClassify(catInfo.WscID, catInfo.CatName, "") }, catList)
} rootTask.AddChild(task).Run()
} _, err = task.GetResult(0)
if err == nil { }
db2 := dao.GetDB() return nil, err
catInfo.WscSyncStatus = 0 }, 2)
_, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...)
}
return nil, err
}, catList)
rootTask.AddChild(task).Run()
_, err = task.GetResult(0)
}
return nil, err
}, 2)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
hint = utils.Int2Str(num) hint = utils.Int2Str(num)
@@ -170,80 +171,81 @@ func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasks
return "", err return "", err
} }
globals.SugarLogger.Debug(utils.Format4Output(skus, false)) globals.SugarLogger.Debug(utils.Format4Output(skus, false))
rootTask := tasksch.NewParallelTask("微盟微商城SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx.GetUserName(), func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { rootTask := tasksch.NewParallelTask("微盟微商城SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
v := batchItemList[0] func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
skuItem := v.(*dao.StoreSkuSyncInfo) v := batchItemList[0]
updateFields := []string{model.FieldWscSyncStatus} skuItem := v.(*dao.StoreSkuSyncInfo)
storeSkuBind := &model.StoreSkuBind{} updateFields := []string{model.FieldWscSyncStatus}
storeSkuBind.ID = skuItem.BindID storeSkuBind := &model.StoreSkuBind{}
if skuItem.SkuSyncStatus&model.SyncFlagDeletedMask != 0 { storeSkuBind.ID = skuItem.BindID
goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0) if skuItem.SkuSyncStatus&model.SyncFlagDeletedMask != 0 {
if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil { goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0)
err = api.WeimobAPI.UpdateGoodsTitle(goodsID, composeFakeDelName(skuItem.Name)) if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil {
} err = api.WeimobAPI.UpdateGoodsTitle(goodsID, composeFakeDelName(skuItem.Name))
} else if skuItem.SkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask) != 0 {
outerGoodsCode := utils.Int2Str(skuItem.NameID)
title := jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30)
isPutAway := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) == model.SkuStatusNormal
categoryId := skuItem.VendorVendorCatID
if categoryId == 0 {
categoryId = DefVendorCategoryId
}
classifyIdList := []int64{utils.Str2Int64WithDefault(skuItem.VendorCatID, 0)}
if skuItem.SkuVendorCatID != "" {
if int64Value := utils.Str2Int64WithDefault(skuItem.SkuVendorCatID, 0); int64Value > 0 {
classifyIdList = append(classifyIdList, int64Value)
} }
} } else if skuItem.SkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask) != 0 {
b2cGoods := &weimobapi.PendingSaveB2CGoodsVo{ outerGoodsCode := utils.Int2Str(skuItem.NameID)
FreightTemplateId: DefFreightTemplateId, title := jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30)
DeliveryTypeIdList: []int64{DefDeliveryTypeId}, isPutAway := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) == model.SkuStatusNormal
B2cGoodsType: weimobapi.GoodsTypeNormal, categoryId := skuItem.VendorVendorCatID
} if categoryId == 0 {
salePrice := int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage))) categoryId = DefVendorCategoryId
skuList := []map[string]interface{}{ }
map[string]interface{}{ classifyIdList := []int64{utils.Str2Int64WithDefault(skuItem.VendorCatID, 0)}
weimobapi.KeyOuterSkuCode: utils.Int2Str(skuItem.ID), if skuItem.SkuVendorCatID != "" {
weimobapi.KeyImageURL: skuItem.Img, if int64Value := utils.Str2Int64WithDefault(skuItem.SkuVendorCatID, 0); int64Value > 0 {
weimobapi.KeySalePrice: jxutils.IntPrice2Standard(salePrice), classifyIdList = append(classifyIdList, int64Value)
weimobapi.KeyCostPrice: jxutils.IntPrice2Standard(salePrice * 8 / 10), }
weimobapi.KeyOriginalPrice: jxutils.IntPrice2Standard(salePrice * 10 / (6 + rand.Int63n(4))), }
weimobapi.KeyEditStockNum: model.MaxStoreSkuStockQty, b2cGoods := &weimobapi.PendingSaveB2CGoodsVo{
weimobapi.KeyB2cSku: &weimobapi.PendingSaveB2CSkuVo{ FreightTemplateId: DefFreightTemplateId,
Weight: jxutils.IntWeight2Float(skuItem.Weight), DeliveryTypeIdList: []int64{DefDeliveryTypeId},
B2cGoodsType: weimobapi.GoodsTypeNormal,
}
salePrice := int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage)))
skuList := []map[string]interface{}{
map[string]interface{}{
weimobapi.KeyOuterSkuCode: utils.Int2Str(skuItem.ID),
weimobapi.KeyImageURL: skuItem.Img,
weimobapi.KeySalePrice: jxutils.IntPrice2Standard(salePrice),
weimobapi.KeyCostPrice: jxutils.IntPrice2Standard(salePrice * 8 / 10),
weimobapi.KeyOriginalPrice: jxutils.IntPrice2Standard(salePrice * 10 / (6 + rand.Int63n(4))),
weimobapi.KeyEditStockNum: model.MaxStoreSkuStockQty,
weimobapi.KeyB2cSku: &weimobapi.PendingSaveB2CSkuVo{
Weight: jxutils.IntWeight2Float(skuItem.Weight),
},
}, },
}, }
} if globals.EnableStoreWrite && globals.EnableWscStoreWrite {
if globals.EnableStoreWrite && globals.EnableWscStoreWrite { if skuItem.SkuSyncStatus&model.SyncFlagNewMask != 0 {
if skuItem.SkuSyncStatus&model.SyncFlagNewMask != 0 { goodsID, skuMap, err2 := api.WeimobAPI.AddGoods(outerGoodsCode, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryId, classifyIdList, b2cGoods, skuList, nil)
goodsID, skuMap, err2 := api.WeimobAPI.AddGoods(outerGoodsCode, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryId, classifyIdList, b2cGoods, skuList, nil) if err = err2; err == nil {
if err = err2; err == nil { storeSkuBind.WscID = skuMap[utils.Int2Str(skuItem.ID)]
storeSkuBind.WscID = skuMap[utils.Int2Str(skuItem.ID)] storeSkuBind.WscID2 = goodsID
storeSkuBind.WscID2 = goodsID updateFields = append(updateFields, model.FieldWscID, model.FieldWscID2)
updateFields = append(updateFields, model.FieldWscID, model.FieldWscID2) }
} } else {
} else { goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0)
goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0)
goodsInfo, err2 := api.WeimobAPI.QueryGoodsDetail(goodsID)
goodsInfo, err2 := api.WeimobAPI.QueryGoodsDetail(goodsID) if err = err2; err == nil {
if err = err2; err == nil { // http://open.weimob.com/docapi/article?tag=Af
// http://open.weimob.com/docapi/article?tag=Af // sku id如果为空则新增sku 如果更新之前的skuId与入参skuId对应则更新sku 如果更新之前的skuId没有和入参的skuId对应删除更新之前的sku
// sku id如果为空则新增sku 如果更新之前的skuId与入参skuId对应则更新sku 如果更新之前的skuId没有和入参的skuId对应删除更新之前的sku skuList[0][weimobapi.KeySkuID] = utils.Str2Int64WithDefault(skuItem.VendorSkuID, 0)
skuList[0][weimobapi.KeySkuID] = utils.Str2Int64WithDefault(skuItem.VendorSkuID, 0) remoteSkuList := goodsInfo[weimobapi.KeySkuList].([]interface{})
remoteSkuList := goodsInfo[weimobapi.KeySkuList].([]interface{}) if len(remoteSkuList) > 0 {
if len(remoteSkuList) > 0 { skuList[0][weimobapi.KeyEditStockNum] = model.MaxStoreSkuStockQty - int(utils.MustInterface2Int64(remoteSkuList[0].(map[string]interface{})[weimobapi.KeyAvailableStockNum]))
skuList[0][weimobapi.KeyEditStockNum] = model.MaxStoreSkuStockQty - int(utils.MustInterface2Int64(remoteSkuList[0].(map[string]interface{})[weimobapi.KeyAvailableStockNum])) }
_, _, err = api.WeimobAPI.UpdateGoods(goodsID, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryId, classifyIdList, b2cGoods, skuList, nil)
} }
_, _, err = api.WeimobAPI.UpdateGoods(goodsID, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryId, classifyIdList, b2cGoods, skuList, nil)
} }
} }
} }
} if err == nil {
if err == nil { _, err = dao.UpdateEntity(nil, storeSkuBind, updateFields...)
_, err = dao.UpdateEntity(nil, storeSkuBind, updateFields...) }
} return nil, err
return nil, err }, skus)
}, skus)
if parentTask != nil { if parentTask != nil {
parentTask.AddChild(rootTask) parentTask.AddChild(rootTask)
} }
@@ -266,21 +268,22 @@ func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask t
globals.SugarLogger.Debugf("wsc FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) globals.SugarLogger.Debugf("wsc FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName)
db := dao.GetDB() db := dao.GetDB()
rootTask := tasksch.NewSeqTask("微盟微商城FullSyncStoreSkus", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { rootTask := tasksch.NewSeqTask("微盟微商城FullSyncStoreSkus", ctx,
switch step { func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
case 0: switch step {
_, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDWSC, storeID, nil, model.SyncFlagNewMask) case 0:
case 1: _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDWSC, storeID, nil, model.SyncFlagNewMask)
_, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDWSC, storeID, nil, model.SyncFlagNewMask) case 1:
case 2: _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDWSC, storeID, nil, model.SyncFlagNewMask)
_, err = p.SyncLocalStoreCategory(ctx, db, storeID, false) case 2:
case 3: _, err = p.SyncLocalStoreCategory(ctx, db, storeID, false)
_, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) case 3:
case 4: _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false)
_, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError) case 4:
} _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError)
return nil, err }
}, 5) return nil, err
}, 5)
tasksch.AddChild(parentTask, rootTask).Run() tasksch.AddChild(parentTask, rootTask).Run()
if !isAsync { if !isAsync {
_, err = rootTask.GetResult(0) _, err = rootTask.GetResult(0)

View File

@@ -54,6 +54,7 @@ weimobCallbackURL = "http://callback.test.jxc4.com/weimob"
weixinPageAppID = "wx018dbe7daa3d5627" weixinPageAppID = "wx018dbe7daa3d5627"
weixinPageSecret = "c7a84ed3ef3ae04ac78e02fb593ffbe5" weixinPageSecret = "c7a84ed3ef3ae04ac78e02fb593ffbe5"
dingdingAgentID = 241047291
dingdingAppKey = "dingpx4hcf55zb4ubewg" dingdingAppKey = "dingpx4hcf55zb4ubewg"
dingdingSecret = "1zooB4bmEXPesdwb1ElWASVQ1vinOSZM-1XCUFrrSjHsNAId1UuVCT5tmHSmg5_V" dingdingSecret = "1zooB4bmEXPesdwb1ElWASVQ1vinOSZM-1XCUFrrSjHsNAId1UuVCT5tmHSmg5_V"
@@ -123,6 +124,7 @@ enableWscStoreWrite = true
weimobCallbackURL = "http://callback.jxc4.com/weimob" weimobCallbackURL = "http://callback.jxc4.com/weimob"
dingdingAgentID = 239461075
dingdingAppKey = "ding7iu9cptairtcls0c" dingdingAppKey = "ding7iu9cptairtcls0c"
dingdingSecret = "LWrZAFeqUfuVv7n_tc8vPpCAx6PT4CwManx2XCVhJOqGsx2L5XCDuX1sAN_JtvsI" dingdingSecret = "LWrZAFeqUfuVv7n_tc8vPpCAx6PT4CwManx2XCVhJOqGsx2L5XCDuX1sAN_JtvsI"

View File

@@ -90,7 +90,7 @@ func Init() {
weimobAPIConfig.ClientTimeout = 120 * time.Second weimobAPIConfig.ClientTimeout = 120 * time.Second
WeimobAPI = weimobapi.New(nil, beego.AppConfig.DefaultString("weimobAppID", ""), beego.AppConfig.DefaultString("weimobAppSecret", ""), &weimobAPIConfig) WeimobAPI = weimobapi.New(nil, beego.AppConfig.DefaultString("weimobAppID", ""), beego.AppConfig.DefaultString("weimobAppSecret", ""), &weimobAPIConfig)
DingDingAPI = dingdingapi.New(beego.AppConfig.DefaultString("dingdingCorpID", ""), beego.AppConfig.DefaultString("dingdingAppKey", ""), beego.AppConfig.DefaultString("dingdingSecret", "")) DingDingAPI = dingdingapi.NewWithAgentID(beego.AppConfig.DefaultInt64("dingdingAgentID", 0), beego.AppConfig.DefaultString("dingdingCorpID", ""), beego.AppConfig.DefaultString("dingdingAppKey", ""), beego.AppConfig.DefaultString("dingdingSecret", ""))
DingDingQRCodeAPI = dingdingapi.New(beego.AppConfig.DefaultString("dingdingCorpID", ""), beego.AppConfig.DefaultString("dingdingQRCodeAppKey", ""), beego.AppConfig.DefaultString("dingdingQRCodeSecret", "")) DingDingQRCodeAPI = dingdingapi.New(beego.AppConfig.DefaultString("dingdingCorpID", ""), beego.AppConfig.DefaultString("dingdingQRCodeAppKey", ""), beego.AppConfig.DefaultString("dingdingQRCodeSecret", ""))
} }