package enterprise import ( "fmt" "git.rosy.net.cn/baseapi/platformapi/ebaiapi" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" tao "git.rosy.net.cn/baseapi/platformapi/tao_vegetable" domain585 "git.rosy.net.cn/baseapi/platformapi/tao_vegetable/sdk/ability585/domain" request585 "git.rosy.net.cn/baseapi/platformapi/tao_vegetable/sdk/ability585/request" product_listV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_listV2/request" product_listV2_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_listV2/response" sku_syncStock_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/sku_syncStock/request" "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api/apimanager" beego "github.com/astaxie/beego/server/web" "strings" ) // 该函数主要用于对比京西平台商品和各个平台门店商品的差异 // 对比上下架状态以及商品价格差异,相同的不做修改,不同的以京西系统商品为主 func CompareJxVendorSku(jxStoreId int, vendorIds []int) (string, error) { var ( db = dao.GetDB() errListToStr = new(strings.Builder) ) skuList, err := dao.GetStoresSkusInfo(db, []int{jxStoreId}, nil) if err != nil { return "", err } // 门店商品列表平 skuMap := make(map[string]*model.StoreSkuBind, 0) skuIdList := make([]string, 0, len(skuList)) for _, v := range skuList { localSkuId := utils.Int2Str(v.SkuID) skuMap[localSkuId] = v skuIdList = append(skuIdList, localSkuId) } // 有效的三方平台 storeMap, err := dao.GetStoresMapList(db, vendorIds, []int{jxStoreId}, []int{model.StoreStatusOpened, model.StoreStatusClosed, model.StoreStatusHaveRest}, model.StoreStatusDisabled, 1, "", "", "") if err != nil { return "", err } for _, sm := range storeMap { switch sm.VendorID { case model.VendorIDJD: if errs := JdSyncSkuPriceAndStatus(db, sm, skuMap); err != nil { errListToStr.WriteString(errs.Error()) globals.SugarLogger.Debugf("京东同步商品异常信息: %v", errs) } continue case model.VendorIDMTWM: if errs := MtWmSyncSkuPriceAndStatus(db, sm, skuMap); errs != nil { errListToStr.WriteString(errs.Error()) globals.SugarLogger.Debugf("美团同步商品异常信息: %v", errs) } continue case model.VendorIDEBAI: if errs := EBaiSyncSkuPriceAndStatus(db, sm, skuMap); errs != nil { errListToStr.WriteString(errs.Error()) globals.SugarLogger.Debugf("饿百同步商品异常信息: %v", errs) } continue case model.VendorIDDD: if errs := TiktokSyncSkuPriceAndStatus(db, sm, skuMap); errs != nil { errListToStr.WriteString(errs.Error()) globals.SugarLogger.Debugf("抖音同步商品异常信息: %v", errs) } continue case model.VendorIDTaoVegetable: if errs := TaoSyncSkuPriceAndStatus(db, sm, skuMap, skuIdList); errs != nil { errListToStr.WriteString(errs.Error()) globals.SugarLogger.Debugf("淘宝同步商品异常信息: %v", errs) } continue default: return errListToStr.String(), fmt.Errorf("无法识别的平台id") } } return "", err } // MtWmSyncSkuPriceAndStatus 校验美团平台和京西系统商品差异 func MtWmSyncSkuPriceAndStatus(db *dao.DaoDB, sm *model.StoreMap, skuMap map[string]*model.StoreSkuBind) (err error) { var ( mtApi = apimanager.CurAPIManager.GetAPI(sm.VendorID, sm.VendorOrgCode).(*mtwmapi.API) i = model.NO foodListData = make([]*mtwmapi.AppFood, 0, 0) errs = make([]string, 0, 0) vendorStatus = 0 ) if len(skuMap) == 0 || sm.IsSync != model.YES { return fmt.Errorf("门店未打开同步或者未关注商品") } if sm.VendorOrgCode == globals.Mtwm2Code { mtApi = mtwmapi.New(beego.AppConfig.DefaultString("mtwmAppID2", ""), beego.AppConfig.DefaultString("mtwmSecret2", ""), beego.AppConfig.DefaultString("mtwmCallbackURL2", ""), "") mtApi.SetToken(sm.MtwmToken) } else { mtApi = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, sm.VendorOrgCode).(*mtwmapi.API) } for { foodList, err := mtApi.RetailListAll(sm.VendorStoreID, i) if err != nil { globals.SugarLogger.Debugf("美团商品价格和上下架状态获取平台商品异常 :%v", err) break } foodListData = append(foodListData, foodList...) if len(foodList) < 100 { break } i++ } for _, vsl := range foodListData { if sku, ok := skuMap[vsl.AppFoodCode]; ok { // 同步商品价格 if utils.Float64TwoInt(vsl.Price*float64(100)) != sku.MtwmPrice { _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{sm.VendorID}, []int{sku.StoreID}, false, []int{sku.SkuID}, []int{27379}, model.SyncFlagPriceMask, true, true) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改美团价格错误:%v", sku.SkuID, err)) } } // 同步商品上下架状态 // SPU(可能包含多个SKU)上下架状态,字段取值范围:0-全部sku上架,1-全部sku下架。以下功能灰度中:若同时传递sku_is_sold_out,则优先根据sku_is_sold_out传参判断单个sku的上下架状态。 // 本地sku.Status 0-不可售, 1-可售 if vsl.IsSoldOut == sku.Status { if sku.Status == model.SkuStatusNormal { vendorStatus = mtwmapi.SellStatusOnline } else { vendorStatus = mtwmapi.SellStatusOffline } param := []*mtwmapi.BareStoreFoodInfo{ &mtwmapi.BareStoreFoodInfo{ AppFoodCode: utils.Int64ToStr(sku.MtwmID), Skus: nil, }, } foodErrList, err := mtApi.RetailSellStatus(jxcontext.AdminCtx.GetTrackInfo(), sm.VendorStoreID, param, vendorStatus) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改美团可售状态错误%v", sku.SkuID, err)) } for _, fel := range foodErrList { errs = append(errs, fmt.Sprintf("skuCode:%s,修改美团可售状态错误:%s", fel.AppFoodCode, fel.ErrorMsg)) } } } else { param := []*mtwmapi.BareStoreFoodInfo{ &mtwmapi.BareStoreFoodInfo{ AppFoodCode: vsl.AppFoodCode, Skus: nil, }, } foodErrList, err := mtApi.RetailSellStatus(jxcontext.AdminCtx.GetTrackInfo(), sm.VendorStoreID, param, mtwmapi.SellStatusOffline) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改美团可售状态错误%v", vsl.AppFoodCode, err)) } for _, fel := range foodErrList { errs = append(errs, fmt.Sprintf("skuCode:%s,修改美团可售状态错误:%s", fel.AppFoodCode, fel.ErrorMsg)) } } } if len(errs) == model.NO { return nil } return fmt.Errorf("%s", strings.Join(errs, ",")) } // EBaiSyncSkuPriceAndStatus 校验饿了么平台和京西系统商品差异 func EBaiSyncSkuPriceAndStatus(db *dao.DaoDB, sm *model.StoreMap, skuMap map[string]*model.StoreSkuBind) (err error) { var ( ebaiApi = apimanager.CurAPIManager.GetAPI(sm.VendorID, sm.VendorOrgCode).(*ebaiapi.API) //skuIdOffset = 0 foodListData = make([]*ebaiapi.SkuInfo, 0, 0) errs = make([]string, 0, 0) ) if len(skuMap) == 0 || sm.IsSync != model.YES { return fmt.Errorf("门店未打开同步或者未关注商品") } for { page := 1 param := &ebaiapi.SkuListParams{ Page: page, PageSize: 100, //SkuIdOffset: skuIdOffset, } foodList, err := ebaiApi.SkuList(utils.Int2Str(sm.StoreID), param) if err != nil { globals.SugarLogger.Debugf("饿了么商品价格和上下架状态获取平台商品异常 :%v", err) break } foodListData = append(foodListData, foodList.List...) if len(foodList.List) < 100 { break } //skuIdOffset = foodList.SkuIdOffset page += 1 } globals.SugarLogger.Debugf("======len foodListData:= %d", len(foodListData)) globals.SugarLogger.Debugf("======len skuMap:= %d", len(skuMap)) for _, vsl := range foodListData { if sku, ok := skuMap[vsl.CustomSkuId]; ok { // 同步商品价格 if vsl.SalePrice != sku.EbaiPrice { _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{sm.VendorID}, []int{sku.StoreID}, false, []int{sku.SkuID}, []int{27379}, model.SyncFlagPriceMask, true, true) } // 同步商品上下架状态 // 1为上架,0为下架 // 本地sku.Status 0-不可售, 1-可售 if vsl.Status != utils.Int2Str(sku.Status) { // 平台上架本地下架,将平台商品下架 if sku.Status == model.StoreSkuBindStatusNormal { ebailResult, err := ebaiApi.SkuOnline(jxcontext.AdminCtx.GetTrackInfo(), utils.Int2Str(sm.StoreID), []int64{sku.EbaiID}, nil, nil) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百可售状态错误%v", sku.SkuID, err)) } for _, fel := range ebailResult.FailedList { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百可售状态错误:%s", fel.SkuID, fel.ErrorMsg)) } } else { err = ebaiApi.SkuOfflineOne(jxcontext.AdminCtx.GetTrackInfo(), utils.Int2Str(sm.StoreID), sku.EbaiID, "", "") if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百不可售状态错误%v", sku.SkuID, err)) } } } } else { _, err = ebaiApi.SkuDelete(jxcontext.AdminCtx.GetTrackInfo(), utils.Int2Str(sm.StoreID), nil, []string{vsl.CustomSkuId}) //err = ebaiApi.SkuOfflineOne(jxcontext.AdminCtx.GetTrackInfo(), utils.Int2Str(sm.StoreID), utils.Str2Int64(vsl.CustomSkuId), "", "") if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百不可售状态错误%v", sku.SkuID, err)) } } } if len(errs) == model.NO { return nil } return fmt.Errorf("%s", strings.Join(errs, ",")) } // TaoSyncSkuPriceAndStatus 校验淘宝平台和京西系统商品差异 func TaoSyncSkuPriceAndStatus(db *dao.DaoDB, sm *model.StoreMap, skuMap map[string]*model.StoreSkuBind, skuIdList []string) (err error) { var ( taoApi = apimanager.CurAPIManager.GetAPI(sm.VendorID, sm.VendorOrgCode).(*tao.API) length = len(skuIdList) / 100 foodListData = make([]domain585.AlibabaWdkSkuQuerySkuDo, 0, 0) onlineStatus int64 = 0 ) if len(skuMap) == 0 || sm.IsSync != model.YES { return fmt.Errorf("门店未打开同步或者未关注商品") } if len(skuIdList)%100 != 0 { length += 1 } // 获取平台商品列表 for i := 0; i < length; i++ { skuCods := skuIdList[i*100 : (i+1)*100] foodList, _ := taoApi.QueryStoreSKu(&request585.AlibabaWdkSkuQueryRequest{Param: &domain585.AlibabaWdkSkuQuerySkuQueryDo{ OuCode: utils.String2Pointer(sm.VendorStoreID), SkuCodes: &skuCods, }}) for _, fl := range *foodList { if *fl.Success { foodListData = append(foodListData, *fl.Model) } } } // 比较商品差异 errs := make([]string, 0, 0) for _, vsl := range foodListData { if sku, ok := skuMap[*vsl.SkuCode]; ok { // 同步商品价格 if utils.Float64TwoInt(utils.Str2Float64(*vsl.SalePrice)*float64(100)) != sku.TaoPrice { _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{sm.VendorID}, []int{sku.StoreID}, false, []int{sku.SkuID}, []int{27379}, model.SyncFlagPriceMask, true, true) if err != nil { errs = append(errs, fmt.Sprintf("淘宝对比商品价格异常skuid:%d,错误%v", sku.SkuID, err)) } } // 同步商品上下架状态 // 是否线上可售 是 0:否 1:是。 // 本地sku.Status 0-不可售, 1-可售 if int(*vsl.OnlineSaleFlag) != sku.Status { // 平台上架本地下架,将平台商品下架 param := &request585.AlibabaWdkSkuUpdateRequest{} updateSkuList := make([]domain585.AlibabaWdkSkuUpdateSkuDo, 0, 0) if sku.Status == model.SkuStatusNormal { onlineStatus = tao.CreateOnlineSaleFlag } else { onlineStatus = tao.CreateOfflineSaleFlag } updateSkuList = append(updateSkuList, domain585.AlibabaWdkSkuUpdateSkuDo{ OuCode: utils.String2Pointer(utils.Int64ToStr(sku.TaoID)), SkuCode: utils.String2Pointer(utils.Int2Str(sku.SkuID)), OnlineSaleFlag: utils.Int64ToPointer(onlineStatus), SubTitle: utils.String2Pointer("小时达"), AllowAppSale: utils.Int64ToPointer(onlineStatus), //CleanSkuMemberPrice: utils.Int64ToPointer(model.YES), }) param.ParamList = &updateSkuList result, err := taoApi.UpdateStoreSku(param) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百可售状态错误%v", sku.SkuID, err)) } for _, fel := range *result { if fel.ErrMsg != "" { errs = append(errs, fmt.Sprintf("skuCode:%s,修改饿百可售状态错误:%s", fel.SkuID, fel.ErrMsg)) } } //_, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{sm.VendorID}, []int{sku.StoreID}, false, []int{sku.SkuID}, []int{27379}, 56, true, true) //if err != nil { // errs = append(errs, fmt.Sprintf("%v", err)) //} } } else { // 平台上架本地下架,将平台商品下架 param := &request585.AlibabaWdkSkuUpdateRequest{} updateSkuList := make([]domain585.AlibabaWdkSkuUpdateSkuDo, 0, 0) onlineStatus = tao.CreateOfflineSaleFlag updateSkuList = append(updateSkuList, domain585.AlibabaWdkSkuUpdateSkuDo{ OuCode: vsl.OuCode, SkuCode: vsl.SkuCode, OnlineSaleFlag: utils.Int64ToPointer(onlineStatus), SubTitle: utils.String2Pointer("小时达"), AllowAppSale: utils.Int64ToPointer(onlineStatus), //CleanSkuMemberPrice: utils.Int64ToPointer(model.YES), }) param.ParamList = &updateSkuList result, err := taoApi.UpdateStoreSku(param) if err != nil { errs = append(errs, fmt.Sprintf("skuCode:%d,修改饿百可售状态错误%v", sku.SkuID, err)) } for _, fel := range *result { if fel.ErrMsg != "" { errs = append(errs, fmt.Sprintf("skuCode:%s,修改饿百可售状态错误:%s", fel.SkuID, fel.ErrMsg)) } } } } if len(errs) == model.NO { return nil } return fmt.Errorf("%s", strings.Join(errs, ",")) } // TiktokSyncSkuPriceAndStatus 校验抖音平台和京西系统商品差异 func TiktokSyncSkuPriceAndStatus(db *dao.DaoDB, sm *model.StoreMap, skuMap map[string]*model.StoreSkuBind) (err error) { var ( tiktokApi = apimanager.CurAPIManager.GetAPI(sm.VendorID, sm.VendorOrgCode).(*tiktok_api.API) page = 0 foodListData = make([]product_listV2_response.DataItem, 0, 0) errs = make([]string, 0, 0) ) if len(skuMap) == 0 || sm.IsSync != model.YES { return fmt.Errorf("门店未打开同步或者未关注商品") } for { param := &product_listV2_request.ProductListV2Param{ Page: int64(page), Size: 100, StoreId: utils.Str2Int64(sm.VendorStoreID), } foodList, err := tiktokApi.GetSkuDetailList(param) if err != nil { globals.SugarLogger.Debugf("抖音商品价格和上下架状态获取平台商品异常 :%v", err) break } foodListData = append(foodListData, foodList.Data...) if len(foodList.Data) < 100 { break } page += 1 } for _, vsl := range foodListData { if sku, ok := skuMap[vsl.OuterProductId]; ok { // 同步商品价格 if vsl.DiscountPrice != int64(sku.DdPrice) { _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{sm.VendorID}, []int{sku.StoreID}, false, []int{sku.SkuID}, []int{27379}, model.SyncFlagPriceMask, true, true) if err != nil { errs = append(errs, fmt.Sprintf("抖音对比商品价格异常skuid:%d,错误%v", sku.SkuID, err)) } } // 同步商品上下架状态 // 0-在线 1-下线 // 本地sku.Status 0-不可售,1-可售 if vsl.Status == int64(sku.Status) { if sku.Status == model.SkuStatusNormal { param := &sku_syncStock_request.SkuSyncStockParam{ ProductId: sku.DdID, Incremental: false, StockNum: 99999, OutSkuId: int64(sku.SkuID), } if err = tiktokApi.UpdateSkuStock(param); err != nil { errs = append(errs, fmt.Sprintf("抖音对比商品上架异常skuid:%d,错误%v", sku.SkuID, err)) } } else { param := &sku_syncStock_request.SkuSyncStockParam{ ProductId: sku.DdID, Incremental: false, StockNum: 0, OutSkuId: int64(sku.SkuID), } if err = tiktokApi.UpdateSkuStock(param); err != nil { errs = append(errs, fmt.Sprintf("抖音对比商品下架异常skuid:%d,错误%v", sku.SkuID, err)) } } } } else { param := &sku_syncStock_request.SkuSyncStockParam{ ProductId: sku.DdID, Incremental: false, StockNum: 0, OutSkuId: int64(sku.SkuID), } if err = tiktokApi.UpdateSkuStock(param); err != nil { errs = append(errs, fmt.Sprintf("抖音对比商品下架异常skuid:%d,错误%v", sku.SkuID, err)) } } } if len(errs) == model.NO { return nil } return fmt.Errorf("%s", strings.Join(errs, ",")) } // JdSyncSkuPriceAndStatus 校验京东平台和京西系统商品差异 func JdSyncSkuPriceAndStatus(db *dao.DaoDB, sm *model.StoreMap, skuMap map[string]*model.StoreSkuBind) (err error) { var ( jdsApi = apimanager.CurAPIManager.GetAPI(sm.VendorID, sm.VendorOrgCode).(*jdapi.API) ) skuVendibilityList := make([]*jdapi.StockVendibility, 0, 0) for _, v := range skuMap { skuVendibilityList = append(skuVendibilityList, &jdapi.StockVendibility{ OutSkuId: utils.Int2Str(v.SkuID), DoSale: v.Status == model.SkuStatusNormal, }) } count := len(skuVendibilityList) / 50 if len(skuVendibilityList)%50 != 0 { count += 1 } for i := 1; i <= count; i++ { if i == count { jdsApi.BatchUpdateVendibility(jxcontext.AdminCtx.GetTrackInfo(), "", sm.VendorStoreID, skuVendibilityList[i*50:], jxcontext.AdminCtx.GetUserName()) } else { jdsApi.BatchUpdateVendibility(jxcontext.AdminCtx.GetTrackInfo(), "", sm.VendorStoreID, skuVendibilityList[(i-1)*50:i*50], jxcontext.AdminCtx.GetUserName()) } } return fmt.Errorf("京东运行结束") }