diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index cf12a8592..7005a68cb 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -1,8 +1,6 @@ package cms import ( - "crypto/md5" - "fmt" "strconv" "time" @@ -80,7 +78,7 @@ func GetQiniuUploadToken(ctx *jxcontext.Context, suffix, hashCode string) (upTok upTokenInfo = map[string]interface{}{ "token": putPolicy.UploadToken(api.QiniuAPI), "expires": putPolicy.Expires, - "fileName": genPicFileName(suffix), + "fileName": jxutils.GenPicFileName(suffix), "hit": imgURL != "", "img": imgURL, } @@ -145,8 +143,3 @@ func UpdatePlace(ctx *jxcontext.Context, placeCode int, payload map[string]inter func GetCoordinateDistrictCode(ctx *jxcontext.Context, lng, lat float64) (code int, err error) { return api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat), nil } - -///// -func genPicFileName(suffix string) string { - return fmt.Sprintf("%x%s", md5.Sum([]byte(utils.GetUUID()+suffix)), suffix) -} diff --git a/business/jxstore/cms/sku.go b/business/jxstore/cms/sku.go index e7355e91d..eff6470d5 100644 --- a/business/jxstore/cms/sku.go +++ b/business/jxstore/cms/sku.go @@ -6,12 +6,12 @@ import ( "strings" "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxstore/initdata" "git.rosy.net.cn/jx-callback/business/jxutils" "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/globals" + "git.rosy.net.cn/jx-callback/globals/api" ) type SkuNamesInfo struct { @@ -452,6 +452,23 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s skuNameExt.SpecQuality = skuNameExt.Skus[0].SpecQuality skuNameExt.SpecUnit = skuNameExt.Skus[0].SpecUnit } + imgContent, imgMD5, err := jxutils.DownloadFileByURL(skuNameExt.Img) + if err != nil { + dao.Rollback(db) + return nil, err + } + if globals.EnableWscStoreWrite { + if skuNameExt.ImgWeimob, err = api.WeimobAPI.UploadImg(imgContent, ""); err != nil { + dao.Rollback(db) + return nil, err + } + } + if skuNameExt.ImgHashCode == "" { + skuNameExt.ImgHashCode = imgMD5 + } else if skuNameExt.ImgHashCode != imgMD5 { + dao.Rollback(db) + return nil, errors.New("图片HASH值不同") + } if err = dao.CreateEntity(db, &skuNameExt.SkuName); err != nil { dao.Rollback(db) return nil, err @@ -488,7 +505,6 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s } outSkuNameExt = tmpInfo.SkuNames[0] _, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, -1, false, false, userName) - initdata.UploadWeimobImg4SkuName(ctx, []int{skuNameExt.SkuName.ID}, true, true) return outSkuNameExt, err } @@ -510,6 +526,16 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf dao.Begin(db) defer dao.Rollback(db) if valid["img"] != "" { + imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string)) + if err = err2; err != nil { + return 0, err + } + valid["ImgHashCode"] = imgMD5 + if globals.EnableWscStoreWrite { + if valid["ImgWeimob"], err = api.WeimobAPI.UploadImg(imgContent, ""); err != nil { + return 0, err + } + } valid["imgWeimob"] = "" } if num, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, skuName, valid, userName, nil, model.FieldJdSyncStatus, model.SyncFlagModifiedMask); err == nil && num == 1 { @@ -538,9 +564,6 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf if err == nil { dao.Commit(db) _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) - if valid["img"] != "" { - initdata.UploadWeimobImg4SkuName(ctx, []int{nameID}, true, true) - } } } } diff --git a/business/jxstore/cms/store.go b/business/jxstore/cms/store.go index e181b5553..398ad9680 100644 --- a/business/jxstore/cms/store.go +++ b/business/jxstore/cms/store.go @@ -419,7 +419,7 @@ func CreateStore(ctx *jxcontext.Context, storeExt *StoreExt, userName string) (i dao.WrapAddIDCULDEntity(store, userName) store.ID = existingID if err = dao.CreateEntity(nil, store); err == nil { - _, err = RefreshMissingDadaStores(ctx, store.ID, false, false) + RefreshMissingDadaStores(ctx, store.ID, false, false) return store.ID, err } return 0, err diff --git a/business/jxstore/initdata/initdata.go b/business/jxstore/initdata/initdata.go index fdfadb27d..059fa7f30 100644 --- a/business/jxstore/initdata/initdata.go +++ b/business/jxstore/initdata/initdata.go @@ -1,20 +1,28 @@ package initdata import ( + "bytes" + "context" "crypto/md5" "fmt" "io/ioutil" "net/http" + "strings" "git.rosy.net.cn/baseapi/platformapi/autonavi" + "git.rosy.net.cn/baseapi/platformapi/jdapi" "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/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" + "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" + "github.com/qiniu/api.v7/storage" ) func TruncateTable(db *dao.DaoDB, tableName string) (err error) { @@ -202,8 +210,10 @@ func UploadWeimobImg4SkuName(ctx *jxcontext.Context, nameIDs []int, isAsync, isC rootTask := tasksch.NewParallelTask("UploadWeimobImg4SkuName", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { skuName := batchItemList[0].(*model.SkuName) if skuName.Img != "" && skuName.ImgWeimob == "" { - if skuName.ImgWeimob, err = api.WeimobAPI.UploadImgByURL(skuName.Img, ""); err == nil { - _, err = dao.UpdateEntity(db, skuName, "ImgWeimob") + if globals.EnableWscStoreWrite { + if skuName.ImgWeimob, err = api.WeimobAPI.UploadImgByURL(skuName.Img, ""); err == nil { + _, err = dao.UpdateEntity(db, skuName, "ImgWeimob") + } } } return nil, err @@ -217,3 +227,216 @@ func UploadWeimobImg4SkuName(ctx *jxcontext.Context, nameIDs []int, isAsync, isC } return hint, err } + +func getSkuNameKey(prefix, name, comment, specUnit, unit string, specQuality float32) string { + return fmt.Sprintf("%s-%s-%f-%s-%s", prefix, name, specQuality, specUnit, unit) +} + +func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, isContinueWhenError bool) (hint string, err error) { + ebaiCatIDKey := "ebaiCatID" + catList, err := api.EbaiAPI.PageGetCustomCatList(baiduShopID) + if err != nil { + return hint, err + } + catMap := make(map[string]map[string]interface{}) + + allSkuInfo := make(map[string]map[string]map[string]map[string]interface{}) + for _, cat := range catList { + catName := utils.Interface2String(cat["cat_name"]) + if catName == "限时特惠" || catName == "应季热销" { + catName = "应季水果" + } + skuNameMap := allSkuInfo[catName] + if skuNameMap == nil { + skuNameMap = make(map[string]map[string]map[string]interface{}) + allSkuInfo[catName] = skuNameMap + } + if catMap[catName] == nil { + catMap[catName] = cat + } + skuList, err2 := api.EbaiAPI.PageGetCustomSkuList(baiduShopID, utils.Str2Int64(utils.Interface2String(cat["cat_id"]))) + if err = err2; err != nil { + return hint, err + } + for _, sku := range skuList { + _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(sku["upc_name"].(string)) + if specQuality > 0 { + if catMap[catName][ebaiCatIDKey] == nil { + catMap[catName][ebaiCatIDKey] = utils.Interface2String(sku["cat3_id"]) + } + skuNameKey := sku["photos"].([]interface{})[0].(map[string]interface{})["url"].(string) + if skuNameMap[skuNameKey] == nil { + skuNameMap[skuNameKey] = make(map[string]map[string]interface{}) + } + skuNameMap[skuNameKey][fmt.Sprintf("%f.%s", specQuality, specUnit)] = sku + } + } + } + allSkuInfo2 := make(map[*model.SkuCategory][]*model.SkuNameExt) + catSeq := 0 + for catName, catSkuNameMap := range allSkuInfo { + if len(catSkuNameMap) > 0 { + skuCat := &model.SkuCategory{ + Name: catName, + ParentID: 0, + Level: 1, + Type: model.SkuCategoryNormal, + Seq: catSeq, + EbaiCategoryID: utils.Str2Int64(utils.Interface2String(catMap[catName][ebaiCatIDKey])), + } + catSeq++ + for _, skuList := range catSkuNameMap { + var skuNameExt *model.SkuNameExt + for _, sku := range skuList { + prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku["upc_name"].(string)) + if skuNameExt == nil { + skuNameExt = &model.SkuNameExt{ + SkuName: model.SkuName{ + Prefix: prefix, + Name: name, + // CategoryID: + IsGlobal: 1, + Unit: unit, + SpecQuality: specQuality, + SpecUnit: specUnit, + Price: int(jxutils.StandardPrice2Int(utils.MustInterface2Float64(sku["sale_price"]))), + Img: sku["photos"].([]interface{})[0].(map[string]interface{})["url"].(string), + Status: model.SkuStatusNormal, + IsSpu: 0, + }, + } + if len(skuList) > 1 { + skuNameExt.Unit = "份" + skuNameExt.SpecQuality = 500 + skuNameExt.SpecUnit = "g" + } + if skuNameExt.Unit == "份" { + tmpSpecQuality := specQuality + if specUnit == "kg" || specUnit == "l" { + tmpSpecQuality *= 1000 + } + skuNameExt.Price = int(float32(skuNameExt.Price) * 500 / tmpSpecQuality) + } + } + mySku := &model.Sku{ + // CategoryID: + // NameID: + Comment: comment, + SpecQuality: specQuality, + SpecUnit: specUnit, + Weight: int(utils.Str2Int64(utils.Interface2String(sku["weight"]))), + Status: model.SkuStatusNormal, + + LinkID: int(jxutils.StandardPrice2Int(utils.MustInterface2Float64(sku["sale_price"]))), // 临时传递价格用 + } + if sku["enabled"].(string) == "0" { + mySku.Status = model.SkuStatusDontSale + } + skuNameExt.Skus = append(skuNameExt.Skus, mySku) + } + allSkuInfo2[skuCat] = append(allSkuInfo2[skuCat], skuNameExt) + } + } + } + + startOutSkuID := 1000 + var skuCatList []*model.SkuCategory + for cat := range allSkuInfo2 { + skuCatList = append(skuCatList, cat) + } + putPolicy := storage.PutPolicy{ + Scope: globals.QiniuBucket, + // Expires: 10 * 60, + } + cfg := &storage.Config{} + upToken := putPolicy.UploadToken(api.QiniuAPI) + rootTask := tasksch.NewSeqTask("BuildSkuFromEbaiStore", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { + var catID string + cat := skuCatList[step] + skuNameExtList := allSkuInfo2[cat] + catID, err = addShopCategory(0, cat.Name, int(cat.Level), cat.Seq, ctx.GetUserName()) + if err == nil { + shopCategories := []int64{utils.Str2Int64(catID)} + for _, skuNameExt := range skuNameExtList { + var imgContent []byte + skuNameExt.CategoryID = cat.ID + skuNameExt.Img = strings.Replace(skuNameExt.Img, "https://", "http://", 1) + if imgContent, _, err = jxutils.DownloadFileByURL(skuNameExt.Img); err != nil { + globals.SugarLogger.Infof("download pic %s failed with error:%v", skuNameExt.Img, err) + if !isContinueWhenError { + 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 := 20308 // 其他国产水果 + if cat.Name == "进口水果" { + jdCatID = 20327 // 其他进口水果 + } + 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 + } + } + } else { + return nil, err + } + return nil, err + }, len(skuCatList)) + tasksch.ManageTask(rootTask).Run() + if !isAsync { + _, err = rootTask.GetResult(0) + } else { + hint = rootTask.ID + } + return hint, err +} + +func addShopCategory(pid int64, shopCategoryName string, shopCategoryLevel, sort int, userName string) (catId string, err error) { + globals.SugarLogger.Debug(pid, shopCategoryName, shopCategoryLevel, sort, userName) + return "123", err + // return api.JdAPI.AddShopCategory(pid, shopCategoryName, shopCategoryLevel, sort, userName) +} + +func addSku(outSkuId string, cagtegoryId int, shopCategories []int64, brandId int, skuName string, skuPrice int, weight float32, images []string, fixedStatus int, isSale bool, addParams map[string]interface{}) (skuId string, err error) { + globals.SugarLogger.Debug(outSkuId, cagtegoryId, shopCategories, brandId, skuName, skuPrice, weight, images, fixedStatus, isSale, addParams) + return "456", err + // return api.JdAPI.AddSku(outSkuId, cagtegoryId, shopCategories, brandId, skuName, skuPrice, weight, images, fixedStatus, isSale, addParams) +} diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index d7304b0f3..c5737db75 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -8,7 +8,6 @@ import ( "strings" "sync" "time" - "unicode/utf8" "github.com/fatih/structs" @@ -322,12 +321,12 @@ func SplitSkuName(skuName string) (prefix, name, comment, specUnit, unit string, } comment = TrimDecorationChar(comment) name = TrimDecorationChar(searchResult[2]) - if comment != "" { - if utf8.RuneCountInString(comment) <= 5 { - name += "-" + comment - comment = "" - } - } + // if comment != "" { + // // if utf8.RuneCountInString(comment) <= 5 { + // // name += "-" + comment + // // comment = "" + // // } + // } specUnit = strings.ToLower(strings.Replace(searchResult[5], "克", "g", -1)) if specUnit == "l" { specUnit = "L" diff --git a/business/jxutils/jxutils_cms.go b/business/jxutils/jxutils_cms.go index 52815e9d7..0156071f2 100644 --- a/business/jxutils/jxutils_cms.go +++ b/business/jxutils/jxutils_cms.go @@ -1,13 +1,17 @@ package jxutils import ( + "crypto/md5" "fmt" + "io/ioutil" "math" + "net/http" "reflect" "regexp" "strings" "time" + "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" ) @@ -254,3 +258,25 @@ func (s SkuList) Swap(i, j int) { s[i] = s[j] s[j] = tmp } + +func DownloadFileByURL(fileURL string) (bodyData []byte, fileMD5 string, err error) { + response, err := http.Get(fileURL) + if err == nil { + defer func() { + response.Body.Close() + }() + if response.StatusCode == http.StatusOK { + if bodyData, err = ioutil.ReadAll(response.Body); err == nil { + fileMD5 = fmt.Sprintf("%X", md5.Sum(bodyData)) + } + } else { + err = platformapi.ErrHTTPCodeIsNot200 + } + } + return bodyData, fileMD5, err +} + +///// +func GenPicFileName(suffix string) string { + return fmt.Sprintf("%x%s", md5.Sum([]byte(utils.GetUUID()+suffix)), suffix) +} diff --git a/controllers/init_data.go b/controllers/init_data.go index cbafc3c11..a24d8a3f0 100644 --- a/controllers/init_data.go +++ b/controllers/init_data.go @@ -72,3 +72,19 @@ func (c *InitDataController) UploadWeimobImg4SkuName() { return retVal, "", err }) } + +// @Title 从饿百店建商品 +// @Description 从饿百店建商品 +// @Param token header string true "认证token" +// @Param baiduShopID formData int true "skuNameID" +// @Param isAsync formData bool false "是否异步操作" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /BuildSkuFromEbaiStore [post] +func (c *InitDataController) BuildSkuFromEbaiStore() { + c.callBuildSkuFromEbaiStore(func(params *tInitdataBuildSkuFromEbaiStoreParams) (retVal interface{}, errCode string, err error) { + retVal, err = initdata.BuildSkuFromEbaiStore(params.Ctx, int64(params.BaiduShopID), params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index f20e47745..14ef08d12 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -287,6 +287,14 @@ func init() { MethodParams: param.Make(), Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"], + beego.ControllerComments{ + Method: "BuildSkuFromEbaiStore", + Router: `/BuildSkuFromEbaiStore`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:InitDataController"], beego.ControllerComments{ Method: "Change2JDSPU4Store",