package wsc import ( "errors" "fmt" "strings" "git.rosy.net.cn/baseapi/platformapi/weimobapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) const ( DefFreightTemplateId = 6537248 DefDeliveryTypeId = 177445 DefVendorCategoryId = 35 DefCatImg = "https://image-c.weimobwmc.com/openruntime/249b77ced5da4736a56641ebcf4875ec.png" ) 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) num := 0 db := dao.GetDB() rootTask := tasksch.NewSeqTask("微盟微商城SyncStoreCategory step1", userName, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { level := step + 1 catList, err := dao.GetStoreCategories(db, model.VendorIDWSC, storeID, level) // globals.SugarLogger.Debug(utils.Format4Output(catList, false)) if len(catList) > 0 { num += len(catList) task := tasksch.NewParallelTask(fmt.Sprintf("微盟微商城SyncStoreCategory step2, level=%d", level), nil, userName, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDWSC])} catInfo := batchItemList[0].(*dao.StoreCatSyncInfo) if globals.EnableStoreWrite && globals.EnableWscStoreWrite { if catInfo.WscSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 globals.SugarLogger.Debugf("UpdateClassify strStoreID:%s, WscID:%d", strStoreID, catInfo.WscID) err = api.WeimobAPI.UpdateClassify(catInfo.WscID, catInfo.CatName+"del", "") } else if catInfo.WscSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增 catImg := "" if level == 2 { catImg = DefCatImg } if catInfo.WscID, err = api.WeimobAPI.AddClassify(catInfo.CatName, utils.Str2Int64(catInfo.ParentVendorCatID), 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 err == nil { db2 := dao.GetDB() catInfo.WscSyncStatus = 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() if !isAsync { hint = utils.Int2Str(num) _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return "", nil } // 此函数根据门店商品信息重建分类信息 // 远程有,本地无, --> 删除远程 // 远程有,本地有,映射无, --> 添加关联 // 远程有,本地有,映射有, --> 不处理 // 远程无,本地有,映射无, --> 添加本地 // 远程无,本地有,映射有, --> 同步标记改为新增 // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, isAsync bool) (hint string, err error) { if db == nil { db = dao.GetDB() } catMap := make([]map[string]*dao.SkuStoreCatInfo, 2) for i := 0; i < 2; i++ { catMap[i] = make(map[string]*dao.SkuStoreCatInfo) localCats, err := dao.GetSkusCategories(db, model.VendorIDWSC, storeID, nil, i+1) // globals.SugarLogger.Debug(utils.Format4Output(localCats, false)) if err != nil { return "", err } for _, cat := range localCats { catMap[i][cat.ParentCatName+"/"+cat.Name] = cat } } dao.Begin(db) defer func() { dao.Rollback(db) }() num := 0 for i := 0; i < 2; i++ { for _, v := range catMap[i] { if v.MapID == -1 || v.MapID == 0 { // 本地缺失 wscSyncStatus := int8(model.SyncFlagNewMask) if v.MapID == -1 { // 远程有同名的,只是简单增加一条本地记录关联 wscSyncStatus = 0 } catMap := &model.StoreSkuCategoryMap{ StoreID: storeID, CategoryID: v.ID, WscID: utils.Str2Int64(v.VendorCatID), WscSyncStatus: wscSyncStatus, MtwmSyncStatus: model.SyncFlagNewMask, EbaiSyncStatus: model.SyncFlagNewMask, ElmSyncStatus: model.SyncFlagNewMask, } num++ dao.WrapAddIDCULDEntity(catMap, ctx.GetUserName()) if err = dao.CreateEntity(db, catMap); err != nil { return "", err } } else { if (v.VendorCatID == "0" || v.VendorCatID == "") && ((v.CatSyncStatus & model.SyncFlagNewMask) == 0) { catMap := &model.StoreSkuCategoryMap{} catMap.ID = v.MapID if _, err = dao.UpdateEntityLogically(db, catMap, map[string]interface{}{ model.FieldWscSyncStatus: model.SyncFlagNewMask, }, ctx.GetUserName(), nil); err != nil { return "", err } } } } } dao.Commit(db) return utils.Int2Str(num), err } // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() for i := 0; i < 3; i++ { // 最多重试三次 if hint, err = p.SyncLocalStoreCategory(ctx, db, storeID, false); err != nil { return "", err } if hint != "0" { if hint, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { return "", err } } if hint == "0" { break } } if hint != "0" { return "", errors.New("同步门店商品所需目录失败") } storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDWSC) if err != nil { return "", err } skus, err := dao.GetStoreSkus(db, model.VendorIDWSC, storeID, skuIDs) if err != nil { return "", err } 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) { v := batchItemList[0] skuItem := v.(*dao.StoreSkuSyncInfo) updateFields := []string{model.FieldWscSyncStatus} storeSkuBind := &model.StoreSkuBind{} storeSkuBind.ID = skuItem.BindID if skuItem.SkuSyncStatus&model.SyncFlagDeletedMask != 0 { goodsID, _ := SplitGoodsAndSkuIDFromJXVendorSkuID(skuItem.VendorSkuID) if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil { err = api.WeimobAPI.UpdateGoodsTitle(goodsID, skuItem.Name+"del") } } 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.Str2Int64(skuItem.VendorCatID)} if skuItem.SkuVendorCatID != "" { if int64Value := utils.Str2Int64(skuItem.SkuVendorCatID); int64Value > 0 { classifyIdList = append(classifyIdList, int64Value) } } b2cGoods := &weimobapi.PendingSaveB2CGoodsVo{ FreightTemplateId: DefFreightTemplateId, DeliveryTypeIdList: []int64{DefDeliveryTypeId}, B2cGoodsType: weimobapi.GoodsTypeNormal, } skuList := []map[string]interface{}{ map[string]interface{}{ weimobapi.KeyOuterSkuCode: utils.Int2Str(skuItem.ID), weimobapi.KeyImageURL: skuItem.Img, weimobapi.KeySalePrice: jxutils.IntPrice2Standard(int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), int(storeDetail.PricePercentage)))), weimobapi.KeyEditStockNum: model.MaxStoreSkuStockQty, weimobapi.KeyB2cSku: &weimobapi.PendingSaveB2CSkuVo{ Weight: jxutils.IntWeight2Float(skuItem.Weight), }, }, } if globals.EnableStoreWrite && globals.EnableWscStoreWrite { 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) if err = err2; err == nil { storeSkuBind.WscID = ComposeJXVendorSkuIDFromGoodsAndSkuID(goodsID, skuMap[utils.Int2Str(skuItem.ID)]) updateFields = append(updateFields, model.FieldWscID) } } else { goodsID, _ := SplitGoodsAndSkuIDFromJXVendorSkuID(skuItem.VendorSkuID) _, _, err = api.WeimobAPI.UpdateGoods(goodsID, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryId, classifyIdList, b2cGoods, skuList, nil) } } } if err == nil { _, err = dao.UpdateEntity(nil, storeSkuBind, updateFields...) } return nil, err }, skus) if parentTask != nil { parentTask.AddChild(rootTask) } rootTask.Run() if !isAsync { _, err = rootTask.GetResult(0) hint = utils.Int2Str(len(skus)) } else { hint = rootTask.ID } return hint, err } func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { return hint, err } func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { return hint, err } func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { return hint, err } func SplitGoodsAndSkuIDFromJXVendorSkuID(vendorSkuID string) (goodsID, skuID int64) { list := strings.Split(vendorSkuID, ",") if len(list) == 2 { goodsID = utils.Str2Int64(list[0]) skuID = utils.Str2Int64(list[1]) } return goodsID, skuID } func ComposeJXVendorSkuIDFromGoodsAndSkuID(goodsID, skuID int64) (vendorSkuID string) { return utils.Int64ToStr(goodsID) + "," + utils.Int64ToStr(skuID) }