package yb import ( "fmt" "regexp" "strings" "git.rosy.net.cn/baseapi/platformapi/yinbaoapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "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/business/partner" "git.rosy.net.cn/jx-callback/business/partner/putils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) var ( sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`) ) const ( addErr1 = "商品已存在" ) func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { storeSku := storeSkuList[0] var result *yinbaoapi.AddProductInfoResult flag, err2 := checkYbSku(storeSku) //flag为true表示是标品,标品不用更新称编码 if err2 != nil { err = err2 } else { result, err = api.YinBaoAPI.AddProductInfo(buildProductInfoParam(storeSku)) } if err != nil { if errExt, ok := err.(*utils.ErrorWithCode); ok { if strings.Contains(errExt.ErrMsg(), addErr1) { queryProductByBarcodeResult, _ := api.YinBaoAPI.QueryProductByBarcodes([]string{storeSku.YbBarCode}) if len(queryProductByBarcodeResult) > 0 { api.YinBaoAPI.BatchUpdateProductEnable(vendorStoreID, utils.Int64ToStr(queryProductByBarcodeResult[0].UID), model.SkuStatusNormal) storeSku.VendorSkuID = utils.Int64ToStr(queryProductByBarcodeResult[0].UID) } } else { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") } } else { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") } } else { storeSku.VendorSkuID = utils.Int64ToStr(result.UID) err = uploadYbImage(vendorStoreID, storeSku.YbBarCode, storeSku.Img) if !flag { err = updateYbSku(vendorStoreID, storeSku.YbBarCode, nil) } if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") } } } return failedList, err } func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { for _, v := range storeSkuList { saveProductParam := &yinbaoapi.SaveProductParam{ CategoryUid: v.VendorCatID, } _, err = checkYbSku(v) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "修改商品") return failedList, err } err = updateYbImage(vendorStoreID, v) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "修改商品") return failedList, err } err = updateYbSku(vendorStoreID, v.YbBarCode, saveProductParam) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "修改商品") } } } return failedList, err } func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { for _, v := range storeSkuList { var productInfo = &yinbaoapi.ProductInfo{ UID: utils.Str2Int64(v.VendorSkuID), Enable: utils.Int2Pointer(yinbaoapi.SkuStatusDeleted), } err = api.YinBaoAPI.UpdateProductInfo(productInfo) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "删除商品") } } } return failedList, err } func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) { storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDYB, "") api.YinBaoAPI = yinbaoapi.New(storeDetail.YbAppKey, storeDetail.YbAppID) if configs, err := dao.QueryConfigs(dao.GetDB(), "yinbaoCookie", model.ConfigTypeCookie, ""); err == nil { yinbaoCookie := configs[0].Value api.YinBaoAPI.SetCookie(".POSPALAUTH30220", yinbaoCookie) } if storeSkuList != nil { if len(storeSkuList) == 1 { storeSku := storeSkuList[0] result, err := api.YinBaoAPI.QueryProductByBarcode(storeSku.VendorSkuID) if err != nil || result == nil { return nil, err } resultp, err := api.YinBaoAPI.QueryProductImagesByBarcode(result.Barcode) // resultp, err := getProductImages(vendorStoreID, storeSku.VendorSkuID) if err != nil { return nil, err } if skuName := vendorSku2Jx(result, resultp); skuName != nil { skuNameList = append(skuNameList, skuName) } } else { var barcodes []string for _, v := range storeSkuList { barcodes = append(barcodes, v.VendorSkuID) } results, err := api.YinBaoAPI.QueryProductByBarcodes(barcodes) if err != nil { return nil, err } for _, v := range results { resultp, err := api.YinBaoAPI.QueryProductImagesByBarcode(v.Barcode) // resultp, err := getProductImages(vendorStoreID, v.Barcode) if err != nil { return nil, err } if skuName := vendorSku2Jx(v, resultp); skuName != nil { skuNameList = append(skuNameList, skuName) } } } } else { result, err := api.YinBaoAPI.QueryProductPages(nil) if err != nil { return nil, err } if len(result.Result) < result.PageSize { for _, v := range result.Result { resultp, err := api.YinBaoAPI.QueryProductImagesByBarcode(v.Barcode) // resultp, err := getProductImages(vendorStoreID, v.Barcode) if err != nil { return nil, err } vv := &yinbaoapi.QueryProductByBarcodeResult{} err = utils.Map2StructByJson(utils.Struct2MapByJson(v), vv, false) if skuName := vendorSku2Jx(vv, resultp); skuName != nil { skuNameList = append(skuNameList, skuName) } } } else { for _, v := range result.Result { resultp, err := api.YinBaoAPI.QueryProductImagesByBarcode(v.Barcode) // resultp, err := getProductImages(vendorStoreID, v.Barcode) if err != nil { return nil, err } vv := &yinbaoapi.QueryProductByBarcodeResult{} err = utils.Map2StructByJson(utils.Struct2MapByJson(v), vv, false) if skuName := vendorSku2Jx(vv, resultp); skuName != nil { skuNameList = append(skuNameList, skuName) } } loopPages(result.PostBackParameter.ParameterType, result.PostBackParameter.ParameterValue, &skuNameList, vendorStoreID) } } return skuNameList, err } func getProductImages(vendorStoreID, barCode string) (findProductResult *yinbaoapi.FindProductResult, err error) { for { ybSkuID, err := api.YinBaoAPI.LoadProductsByPage(vendorStoreID, barCode) findProductResult, err = api.YinBaoAPI.FindProduct(ybSkuID) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } findProductResult, err = getProductImages(vendorStoreID, barCode) } else { break } } } return findProductResult, err } func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { for _, v := range storeSkuList { var productInfo = &yinbaoapi.ProductInfo{ UID: utils.Str2Int64(v.VendorSkuID), Enable: utils.Int2Pointer(ybSkuStatus2Jx(v.Status)), } err = api.YinBaoAPI.UpdateProductInfo(productInfo) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "更新商品状态") } } } return failedList, err } func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { for _, v := range storeSkuList { var productInfo = &yinbaoapi.ProductInfo{ UID: utils.Str2Int64(v.VendorSkuID), SellPrice: utils.Float64ToPointer(jxutils.IntPrice2Standard(v.VendorPrice)), BuyPrice: utils.Float64ToPointer(jxutils.IntPrice2Standard(v.JxPrice)), } err = api.YinBaoAPI.UpdateProductInfo(productInfo) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "更新商品价格") } } } return failedList, err } func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { for _, v := range storeSkuList { var productInfo = &yinbaoapi.ProductInfo{ UID: utils.Str2Int64(v.VendorSkuID), Stock: utils.Float64ToPointer(utils.Str2Float64(utils.Int2Str(v.Stock))), } err = api.YinBaoAPI.UpdateProductInfo(productInfo) if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "更新商品库存") } } } return failedList, err } func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { remoteCats, err := loadCategorysWithOption(vendorStoreID) cats = convertVendorCatList(remoteCats) return cats, err } func loadCategorysWithOption(vendorStoreID string) (remoteCats []*yinbaoapi.LoadCategorysWithOptionResult, err error) { for { remoteCats, err = api.YinBaoAPI.LoadCategorysWithOption(vendorStoreID) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } remoteCats, err = loadCategorysWithOption(vendorStoreID) } else { break } } } return remoteCats, err } func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { if globals.EnableYbStoreWrite { var ( catName = utils.FilterEmoji(storeCat.Name) parentCatName = utils.FilterEmoji(storeCat.ParentCatName) ) vendorCatID, err := addNewCategory(vendorStoreID, catName, parentCatName) if err == nil { storeCat.VendorCatID = vendorCatID } return err } return err } func addNewCategory(vendorStoreID, catName, parentCatName string) (vendorCatID string, err error) { for { vendorCatID, err = api.YinBaoAPI.AddNewCategory(vendorStoreID, catName, parentCatName) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } vendorCatID, err = addNewCategory(vendorStoreID, catName, parentCatName) } else { break } } } return vendorCatID, err } func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { if globals.EnableYbStoreWrite { var ( catName = utils.FilterEmoji(storeCat.Name) parentCatName = utils.FilterEmoji(storeCat.ParentCatName) ) err = updateCategory(vendorStoreID, storeCat.VendorCatID, catName, parentCatName) } return err } func updateCategory(vendorStoreID, vendorCatID, catName, parentCatName string) (err error) { for { err = api.YinBaoAPI.UpdateCategory(vendorStoreID, vendorCatID, catName, parentCatName) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } err = updateCategory(vendorStoreID, vendorCatID, catName, parentCatName) } else { break } } } return err } func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { if globals.EnableYbStoreWrite { err = deleteCategory(vendorStoreID, []string{vendorCatID}) } return err } func deleteCategory(vendorStoreID string, vendorCatIDs []string) (err error) { for { err = api.YinBaoAPI.DeleteCategory(vendorStoreID, vendorCatIDs) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } err = api.YinBaoAPI.DeleteCategory(vendorStoreID, vendorCatIDs) } else { break } } } return err } func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) { return yinbaoapi.IsErrSkuExist(err) } func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { return yinbaoapi.IsErrCategoryExist(err) } func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { return false } func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { return 1 } func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { return sensitiveWordRegexp } func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { return yinbaoapi.IsErrSkuNotExist(err) } func ybSkuStatus2Jx(ybStatus int) (jxSkuStatus int) { if ybStatus == yinbaoapi.SkuStatusEnable { jxSkuStatus = model.SkuStatusNormal } else if ybStatus == yinbaoapi.SkuStatusDisabled { jxSkuStatus = model.SkuStatusDontSale } else if ybStatus == yinbaoapi.SkuStatusDeleted { jxSkuStatus = model.SkuStatusDeleted } return jxSkuStatus } func vendorSku2Jx(result *yinbaoapi.QueryProductByBarcodeResult, resultp []*yinbaoapi.QueryProductImagesByBarcodeResult) (skuName *partner.SkuNameInfo) { var picList []string if result == nil { return nil } if len(resultp) > 0 { if resultp[0].ImageURL != "" { // for _, v := range resultp.Productimages { picList = append(picList, resultp[0].ImageURL) // } } } prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(result.Name) skuName = &partner.SkuNameInfo{ Prefix: prefix, Name: name, Unit: unit, YbBarCode: result.Barcode, SkuList: []*partner.SkuInfo{ &partner.SkuInfo{ StoreSkuInfo: partner.StoreSkuInfo{ VendorSkuID: utils.Int64ToStr(result.UID), Stock: int(utils.Float64TwoInt64(result.Stock)), VendorPrice: jxutils.StandardPrice2Int(result.SellPrice), Status: ybSkuStatus2Jx(result.Enable), }, SkuName: result.Name, Comment: comment, SpecQuality: float64(specQuality), SpecUnit: specUnit, Weight: int(utils.Float64TwoInt64(float64(specQuality))), }, }, PictureList: picList, } return skuName } func loopPages(parameterType, parameterValue string, skuNameList *[]*partner.SkuNameInfo, vendorStoreID string) (err error) { var postBackParameter = &yinbaoapi.PostBackParameter{ ParameterType: parameterType, ParameterValue: parameterValue, } resultPages, err := api.YinBaoAPI.QueryProductPages(postBackParameter) if err != nil { return err } for _, v := range resultPages.Result { // resultp, err := api.YinBaoAPI.QueryProductImagesByBarcode(v.Barcode) // resultp, err := getProductImages(vendorStoreID, v.Barcode) if err != nil { return err } var resultp []*yinbaoapi.QueryProductImagesByBarcodeResult vv := &yinbaoapi.QueryProductByBarcodeResult{} err = utils.Map2StructByJson(utils.Struct2MapByJson(v), vv, false) if skuName := vendorSku2Jx(vv, resultp); skuName != nil { *skuNameList = append(*skuNameList, skuName) } } if len(resultPages.Result) >= resultPages.PageSize { err = loopPages(resultPages.PostBackParameter.ParameterType, resultPages.PostBackParameter.ParameterValue, skuNameList, vendorStoreID) } return err } func buildProductInfoParam(storeSku *dao.StoreSkuSyncInfo) (productInfoParam *yinbaoapi.ProductInfoParam) { var ( buyPrice float64 = utils.Str2Float64(utils.Int64ToStr(storeSku.Price)) / 100 sellPrice float64 = utils.Str2Float64(utils.Int64ToStr(storeSku.VendorPrice)) / 100 // _, name, _, _, _, _ = jxutils.SplitSkuName() ) productInfoParam = &yinbaoapi.ProductInfoParam{} productInfo := &yinbaoapi.ProductInfo{ Stock: utils.Float64ToPointer(utils.Str2Float64(utils.Int2Str(model.MaxStoreSkuStockQty))), Name: storeSku.Name, Barcode: storeSku.YbBarCode, BuyPrice: &buyPrice, SellPrice: &sellPrice, CategoryUID: utils.Str2Int64(storeSku.VendorCatID), } productInfoParam.ProductInfo = productInfo return productInfoParam } func convertVendorCatList(remoteCats []*yinbaoapi.LoadCategorysWithOptionResult) (cats []*partner.BareCategoryInfo) { for _, rCat := range remoteCats { cat := &partner.BareCategoryInfo{ VendorCatID: rCat.TxtUID, Name: rCat.Name, } if rCat.TxtParentUID == "" { cat.Level = 1 } else { cat.Level = 2 } cats = append(cats, cat) } return cats } func updateYbSku(vendorStoreID, ybBarCode string, saveProductParam *yinbaoapi.SaveProductParam) (err error) { for { err = api.YinBaoAPI.SaveProduct(vendorStoreID, ybBarCode, saveProductParam) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } err = updateYbSku(vendorStoreID, ybBarCode, saveProductParam) } else { break } } } return err } func checkYbSku(storeSku *dao.StoreSkuSyncInfo) (flag bool, err error) { skuID := storeSku.SkuID skus, _ := dao.GetSkus(dao.GetDB(), []int{skuID}, nil, nil, nil, nil) if len(skus) > 0 { if skus[0].Unit != model.UnitNames[0] { flag = true if skus[0].Upc == "" { return flag, fmt.Errorf("标品必须指定upc码,skuID[%v]", skuID) } else { storeSku.YbBarCode = skus[0].Upc } } } return flag, err } func uploadYbImage(vendorStoreID, ybBarCode, img string) (err error) { ybSkuID, err := api.YinBaoAPI.LoadProductsByPage(vendorStoreID, ybBarCode) resBinary, _, err := jxutils.DownloadFileByURL(img) fileName := img[strings.LastIndex(img, "/")+1:] err = uploadYbImageLoop(vendorStoreID, ybSkuID, resBinary, fileName) return err } func uploadYbImageLoop(vendorStoreID, ybSkuID string, resBinary []byte, fileName string) (err error) { for { err = api.YinBaoAPI.UploadProductImage(vendorStoreID, ybSkuID, resBinary, fileName) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } err = uploadYbImageLoop(vendorStoreID, ybSkuID, resBinary, fileName) } else { break } } } return err } func updateYbImage(vendorStoreID string, v *dao.StoreSkuSyncInfo) (err error) { err = uploadYbImage(vendorStoreID, v.YbBarCode, v.Img) err = resetCoverImageLoop(vendorStoreID, v.YbBarCode) return err } func resetCoverImageLoop(vendorStoreID, ybBarCode string) (err error) { for { err = api.YinBaoAPI.ResetCoverImage(vendorStoreID, ybBarCode) if err == nil { break } else { if yinbaoapi.IsErrCookie(err) { err = cms.ChangeYbCookie() if err != nil { break } err = resetCoverImageLoop(vendorStoreID, ybBarCode) } else { break } } } return err }