package cms import ( "errors" "fmt" "io" "mime/multipart" "net/http" "regexp" "strconv" "strings" "time" "git.rosy.net.cn/baseapi/platformapi/aliupcapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/platformapi/ebaiapi" "github.com/360EntSecGroup-Skylar/excelize" "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/excel" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/refutil" "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/datares" "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" ) type SkuNamesInfo struct { TotalCount int `json:"totalCount"` SkuNames []*model.SkuNameExt `json:"skuNames"` } type CreateUpcSkuByExcelErr struct { Upc string `json:"商品条码"` Name string `json:"商品名称"` Unit string `json:"单位"` SpecQuality string `json:"重量(g)"` Price int `json:"售价"` Err string `json:"错误原因"` } var ( ErrInputCatsDoesntMatch = errors.New("输入的类别列表不合法,需要输入一个父ID下的所有子类别") ) var ( ebaiUploadRTFShopID string // 饿百找一个店用于调用SkuUploadRTF ) var ( sendNoCatSkusMobile = []string{ "18048531223", "18982250714", } ) // func getAndSetEbaiUploadRTFShopID() (shopID string) { // if ebaiUploadRTFShopID == "" { // if storeDetail, err := dao.GetStoreDetail(dao.GetDB(), 0, model.VendorIDEBAI); err == nil { // ebaiUploadRTFShopID = utils.Int2Str(storeDetail.Store.ID) // } // } // return ebaiUploadRTFShopID // } // parentID 为-1表示所有 func GetVendorCategories(ctx *jxcontext.Context, vendorID int, parentID string) (vendorCats []*model.SkuVendorCategory, err error) { cond := map[string]interface{}{ model.FieldVendorID: vendorID, } if parentID != "-1" { cond[model.FieldParentID] = parentID } return vendorCats, dao.GetEntitiesByKV(nil, &vendorCats, cond, false) } // parentID 为-1表示所有 func GetCategories(ctx *jxcontext.Context, parentID int, isExd bool) (catList []*dao.SkuCategoryWithVendor, err error) { db := dao.GetDB() cats, err := dao.GetCategories(db, parentID, 0, nil, isExd) if err == nil { var ids []int for _, v := range cats { ids = append(ids, v.ID) } thingMapMap, err2 := dao.GetThingMapMap(db, model.ThingTypeCategory, nil, ids) // globals.SugarLogger.Debug(utils.Format4Output(thingMapMap, false)) if err = err2; err == nil { for _, v := range cats { catList = append(catList, &dao.SkuCategoryWithVendor{ SkuCategory: v, MapList: thingMapMap[int64(v.ID)], }) } } } return catList, err } func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string) (outCat *model.SkuCategory, err error) { db := dao.GetDB() if cat.Level < 0 || cat.Level > 3 { return nil, errors.New("Level必须为1或2,3") } else if cat.Level == 1 && cat.ParentID != 0 { return nil, errors.New("Level1的分类其父分类必须为0") } else if cat.Level == 2 { if cat.ParentID == 0 { return nil, errors.New("Level2的分类其父分类必须不为0") } parentCat := &model.SkuCategory{} parentCat.ID = cat.ParentID if err = dao.GetEntity(db, parentCat); err != nil { return nil, err } if parentCat.Level != 1 { return nil, errors.New("Level2的分类其父分类必须为Level1分类") } } else if cat.Level == 3 { if cat.ParentID == 0 { return nil, errors.New("Level3的分类其父分类必须不为0") } parentCat := &model.SkuCategory{} parentCat.ID = cat.ParentID if err = dao.GetEntity(db, parentCat); err != nil { return nil, err } if parentCat.Level != 2 { return nil, errors.New("Level3的分类其父分类必须为Level2分类") } } dao.WrapAddIDCULDEntity(cat, userName) // cat.JdSyncStatus = model.SyncFlagNewMask // cat.JdID = 0 cat.Status = model.CategoryStatusEnable cat.Name = strings.Trim(cat.Name, " ") if cat.Img != "" { _, err2 := datares.TryRegisterDataResource(ctx, cat.Name, cat.Img, model.ImgTypeLocal, false) if err = err2; err != nil { return nil, err } } if cat.Seq <= 0 { var maxSeq struct { MaxSeq int } if err = dao.GetRow(db, &maxSeq, "SELECT MAX(seq) max_seq FROM sku_category t1 WHERE level = ?", cat.Level); err != nil { return nil, err } cat.Seq = maxSeq.MaxSeq + 1 } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if err = dao.CreateEntity(db, cat); err != nil { dao.Rollback(db) return nil, err } if cat.IsExdSpec == model.NO { if err = OnCreateThing(ctx, db, nil, int64(cat.ID), model.ThingTypeCategory); err != nil { dao.Rollback(db) return nil, err } } dao.Commit(db) outCat = cat _, err = CurVendorSync.SyncCategory(ctx, nil, cat.ID, false, userName) return outCat, err } func UpdateCategory(ctx *jxcontext.Context, categoryID int, payload map[string]interface{}, userName string) (num int64, err error) { cat := &model.SkuCategory{} cat.ID = categoryID db := dao.GetDB() if err = dao.GetEntity(db, cat); err != nil { return 0, err } for k, v := range payload { if v == nil { delete(payload, k) } } valid := dao.StrictMakeMapByStructObject(payload, cat, userName) if len(valid) > 0 { // syncStatus := 0 // if valid["name"] != nil { // valid["name"] = strings.Trim(valid["name"].(string), " ") // syncStatus = model.SyncFlagModifiedMask // valid[model.FieldJdSyncStatus] = int8(syncStatus) | cat.JdSyncStatus // } if valid["status"] != nil { if utils.Interface2Int64WithDefault(valid["status"], -1) == model.CategoryStatusDisabled { if skuList, err2 := dao.GetSkuByCats(db, []int{categoryID}); err2 == nil && len(skuList) > 0 { return 0, fmt.Errorf("暂不允许禁用分类下有商品的分类!") } } } if valid["img"] != nil { if imgStr := utils.Interface2String(valid["img"]); imgStr != "" { _, err2 := datares.TryRegisterDataResource(ctx, cat.Name, utils.Interface2String(valid["img"]), model.ImgTypeLocal, false) if err = err2; err != nil { return 0, err } } } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if num, err = dao.UpdateEntityLogically(db, cat, valid, userName, nil); err != nil { dao.Rollback(db) return 0, err } if cat.IsExdSpec == model.NO { if err = OnUpdateThing(ctx, db, nil, int64(categoryID), model.ThingTypeCategory); err != nil { dao.Rollback(db) return 0, err } } dao.Commit(db) SetStoreCategorySyncStatus2(db, nil, []int{categoryID}, model.SyncFlagModifiedMask) var skuIDs []int if valid["jdCategoryID"] != nil || valid["ebaiCategoryID"] != nil || valid["mtwmCategoryID"] != nil || valid["jdPricePercentage"] != nil || valid["ebaiPricePercentage"] != nil || valid["mtwmPricePercentage"] != nil { if skuList, err2 := dao.GetSkuByCats(db, []int{categoryID}); err2 == nil && len(skuList) > 0 { for _, sku := range skuList { skuIDs = append(skuIDs, sku.ID) } if valid["jdCategoryID"] != nil { dao.SetSkuSyncStatus(db, model.VendorIDJD, skuIDs, model.SyncFlagModifiedMask) } // todo 如下逻辑,在不同平台同时改pricePercentage与平台分类映射时,会不必要的打上多余的标记 var vendorIDs []int syncStatus := model.SyncFlagModifiedMask if valid["jdPricePercentage"] != nil { vendorIDs = append(vendorIDs, model.VendorIDJD) syncStatus |= model.SyncFlagPriceMask } if valid["ebaiPricePercentage"] != nil { vendorIDs = append(vendorIDs, model.VendorIDEBAI) syncStatus |= model.SyncFlagPriceMask } else if valid["ebaiCategoryID"] != nil { vendorIDs = append(vendorIDs, model.VendorIDEBAI) } if valid["mtwmPricePercentage"] != nil { vendorIDs = append(vendorIDs, model.VendorIDMTWM) syncStatus |= model.SyncFlagPriceMask } else if valid["mtwmCategoryID"] != nil { vendorIDs = append(vendorIDs, model.VendorIDMTWM) } if len(vendorIDs) > 0 { SetStoreSkuSyncStatus2(db, nil, vendorIDs, skuIDs, syncStatus) } } } _, err = CurVendorSync.SyncCategory(ctx, db, categoryID, false, userName) if len(skuIDs) > 0 { CurVendorSync.SyncSkus(ctx, db, nil, skuIDs, true, true, userName) } } return num, err } func SetStoreCategorySyncStatus2(db *dao.DaoDB, storeIDs []int, catIDs []int, syncStatus int) (num int64, err error) { for _, vendorID := range partner.GetSingleStoreVendorIDs() { num2, err2 := dao.SetStoreCategorySyncStatus(db, vendorID, storeIDs, catIDs, syncStatus) if err = err2; err != nil { return 0, err } num += num2 } return num, nil } func ReorderCategories(ctx *jxcontext.Context, parentID int, categoryIDs []int, userName string, isExd bool) (err error) { var cats []*model.SkuCategory db := dao.GetDB() if err = dao.GetEntitiesByKV(db, &cats, utils.Params2Map(model.FieldParentID, parentID), false); err == nil { catsLen := len(cats) if !isExd { for _, v := range cats { if v.IsExdSpec == 1 { catsLen-- } } } if catsLen != len(categoryIDs) { return ErrInputCatsDoesntMatch } catsMap := make(map[int]*model.SkuCategory, catsLen) for _, cat := range cats { catsMap[cat.ID] = cat } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() for k, v := range categoryIDs { if catsMap[v] == nil { dao.Rollback(db) return fmt.Errorf("分类:%d不在%d分类下", v, parentID) } if isExd { catsMap[v].ExdSeq = k } else { catsMap[v].Seq = k } catsMap[v].LastOperator = ctx.GetUserName() if _, err = dao.UpdateEntity(db, catsMap[v]); err != nil { dao.Rollback(db) return err } if catsMap[v].IsExdSpec == model.NO { if err = OnUpdateThing(ctx, db, nil, int64(catsMap[v].ID), model.ThingTypeCategory); err != nil { dao.Rollback(db) return err } } } dao.Commit(db) SetStoreCategorySyncStatus2(db, nil, categoryIDs, model.SyncFlagModifiedMask) if err == nil { _, err = CurVendorSync.SyncReorderCategories(ctx, db, parentID, false, userName) CurVendorSync.SyncStoresCategory(ctx, db, nil, nil, false, true, true) } } return err } func DeleteCategory(ctx *jxcontext.Context, categoryID int, userName string) (num int64, err error) { cat := &model.SkuCategory{} cat.ID = categoryID var countInfos []*struct{ Ct int } db := dao.GetDB() if err = dao.GetRows(db, &countInfos, ` SELECT COUNT(*) ct FROM sku t1 WHERE t1.category_id = ? AND t1.deleted_at = ? UNION ALL SELECT COUNT(*) ct FROM sku_name t1 WHERE t1.category_id = ? AND t1.deleted_at = ? UNION ALL SELECT COUNT(*) ct FROM sku_category t1 WHERE t1.parent_id = ? AND t1.deleted_at = ? `, categoryID, utils.DefaultTimeValue, categoryID, utils.DefaultTimeValue, categoryID, utils.DefaultTimeValue, &countInfos); err == nil { if countInfos[0].Ct != 0 { return 0, errors.New("还有商品使用此类别,不能删除") } else if countInfos[1].Ct != 0 { return 0, errors.New("还有商品名使用此类别,不能删除") } else if countInfos[2].Ct != 0 { return 0, errors.New("还有商品类别使用此类别,不能删除") } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if _, err = DeleteCategoryMap(ctx, db, categoryID); err != nil { dao.Rollback(db) return 0, err } if err = OnDeleteThing(ctx, db, nil, int64(categoryID), model.ThingTypeCategory); err != nil { dao.Rollback(db) return 0, err } if num, err = dao.DeleteEntityLogically(db, cat, map[string]interface{}{ // model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldStatus: 0, }, userName, nil); err != nil { dao.Rollback(db) return 0, err } dao.Commit(db) _, err = CurVendorSync.SyncCategory(ctx, db, cat.ID, false, userName) } return num, err } func DeleteCategoryMap(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int) (num int64, err error) { if db == nil { db = dao.GetDB() } catMap := &model.StoreSkuCategoryMap{} return dao.DeleteEntityLogically(db, catMap, map[string]interface{}{ model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask, }, ctx.GetUserName(), map[string]interface{}{ model.FieldCategoryID: categoryID, model.FieldDeletedAt: utils.DefaultTimeValue, }) } func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPrice bool, params map[string]interface{}, offset, pageSize int) (skuNamesInfo *SkuNamesInfo, err error) { db := dao.GetDB() sql := ` FROM sku_name t1 LEFT JOIN sku t2 ON t1.id = t2.name_id AND t2.deleted_at = ? LEFT JOIN sku_name_place_bind t3 ON t1.id = t3.name_id ` sqlParams := []interface{}{ utils.DefaultTimeValue, } if isQueryMidPrice { sql += ` LEFT JOIN price_refer_snapshot t4 ON t4.city_code = ? AND t4.snapshot_at = ? AND t4.name_id = t1.id` sqlParams = append(sqlParams, 0, utils.Time2Date(time.Now().AddDate(0, 0, -1))) } sql += " WHERE t1.deleted_at = ?" sqlParams = append(sqlParams, utils.DefaultTimeValue) if keyword != "" { keywordLike := "%" + keyword + "%" sql += ` AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t2.comment LIKE ? OR t1.upc LIKE ? OR t1.img LIKE ? OR (SELECT COUNT(*) FROM thing_map tm WHERE tm.vendor_thing_id LIKE ? AND tm.thing_type = ? AND tm.thing_id = t2.id AND tm.deleted_at = ?) > 0` sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, model.ThingTypeSku, utils.DefaultTimeValue) if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil { sql += " OR t1.id = ? OR t2.id = ? OR t1.category_id = ?" sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64) } sql += ")" } if params["isSpu"] != nil { sql += " AND t1.is_spu = ?" sqlParams = append(sqlParams, utils.Bool2Int(params["isSpu"].(bool))) } if params["nameID"] != nil { sql += " AND t1.id = ?" sqlParams = append(sqlParams, params["nameID"].(int)) } if params["nameIDs"] != nil { var nameIDs []int if ids, ok := params["nameIDs"].([]int); ok { nameIDs = ids } else { if err = utils.UnmarshalUseNumber([]byte(params["nameIDs"].(string)), &nameIDs); err != nil { return nil, err } } if len(nameIDs) > 0 { sql += " AND t1.id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")" sqlParams = append(sqlParams, nameIDs) } } if params["isExd"] != nil { var idExd = params["isExd"].(bool) if idExd { sql += " AND t2.exd_sku_id <> ''" } else { sql += " AND t2.exd_sku_id = ''" } } else { sql += " AND t2.exd_sku_id = ''" } if params["categoryID"] != nil { cat := &model.SkuCategory{} cat.ID = params["categoryID"].(int) if err = dao.GetEntity(db, cat); err != nil { return nil, err } sql += " AND (t1.category_id = ?" sqlParams = append(sqlParams, cat.ID) if cat.Level == 1 { sql += " OR t1.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)" sqlParams = append(sqlParams, cat.ID) } sql += ")" } if params["skuCategoryID"] != nil { cat := &model.SkuCategory{} cat.ID = params["skuCategoryID"].(int) if err = dao.GetEntity(db, cat); err != nil { return nil, err } sql += " AND (t2.category_id = ?" sqlParams = append(sqlParams, cat.ID) if cat.Level == 1 { sql += " OR t2.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)" sqlParams = append(sqlParams, cat.ID) } sql += ")" } if params["vendorSkuIDs"] != nil { var vendorSkuIDs []int if err = utils.UnmarshalUseNumber([]byte(params["vendorSkuIDs"].(string)), &vendorSkuIDs); err != nil { return nil, err } if len(vendorSkuIDs) > 0 { sql += " AND (SELECT COUNT(*) FROM thing_map tm WHERE tm.thing_type = ? AND tm.thing_id = t2.id AND tm.deleted_at = ? AND tm.vendor_thing_id IN (" + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")) > 0" sqlParams = append(sqlParams, utils.DefaultTimeValue, vendorSkuIDs) } } if params["name"] != nil { sql += " AND t1.name LIKE ?" sqlParams = append(sqlParams, "%"+params["name"].(string)+"%") } if params["prefix"] != nil { sql += " AND t1.prefix LIKE ?" sqlParams = append(sqlParams, "%"+params["prefix"].(string)+"%") } if params["unit"] != nil { sql += " AND t1.unit = ?" sqlParams = append(sqlParams, params["unit"].(string)) } if placeCond := strings.ToUpper(utils.Interface2String(params["placeCond"])); placeCond == "AND" || placeCond == "OR" { sqlPlaceCond := "" if placeCond == "AND" { sqlPlaceCond += " AND ( 1 = 1" } else { sqlPlaceCond += " AND ( 1 = 0" } if params["placeCode"] != nil { sqlPlaceCond += " " + placeCond + " t3.place_code = ?" sqlParams = append(sqlParams, params["placeCode"].(int)) } if params["isGlobal"] != nil { if params["isGlobal"].(bool) { sqlPlaceCond += " " + placeCond + " t1.is_global = 1" } else { sqlPlaceCond += " " + placeCond + " t1.is_global = 0" } } if sqlPlaceCond != " AND ( 1 = 0" { sql += sqlPlaceCond + ")" } } if params["skuID"] != nil { sql += " AND t2.id = ?" sqlParams = append(sqlParams, params["skuID"].(int)) } if params["skuIDs"] != nil { var skuIDs []int if err = utils.UnmarshalUseNumber([]byte(params["skuIDs"].(string)), &skuIDs); err != nil { return nil, err } if len(skuIDs) > 0 { sql += " AND t2.id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } } if params["fromStatus"] != nil { fromStatus := params["fromStatus"].(int) toStatus := fromStatus if params["toStatus"] != nil { toStatus = params["toStatus"].(int) } sql += " AND t2.status >= ? AND t2.status <= ?" sqlParams = append(sqlParams, fromStatus, toStatus) } sql += ` GROUP BY t1.id, t1.created_at, t1.updated_at, t1.last_operator, t1.deleted_at, t1.prefix, t1.name, t1.brand_id, t1.category_id, t1.jd_category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.img2, t1.img3, t1.img_watermark, t1.img_mix, t1.status, t1.is_spu, t1.desc_img, t1.upc, t1.ex_prefix, t1.ex_prefix_begin, t1.ex_prefix_end, t1.yb_name_suffix, t1.jds_stock_switch, t1.preparation_time, t1.best_seller ` if isQueryMidPrice { sql += `, t4.mid_unit_price` } if isBySku { sql += `, t2.id` } sqlData := ` SELECT SQL_CALC_FOUND_ROWS t1.id, t1.created_at, t1.updated_at, t1.last_operator, t1.deleted_at, t1.prefix, t1.name, t1.brand_id, t1.category_id, t1.jd_category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.img2, t1.img3, t1.img_watermark, t1.img_mix, t1.status, t1.is_spu, t1.desc_img, t1.upc, /* t1.jd_id, t1.jd_sync_status, */ t1.ex_prefix, t1.ex_prefix_begin, t1.ex_prefix_end, t1.yb_name_suffix, t1.jds_stock_switch, t1.preparation_time, t1.best_seller, ` if isQueryMidPrice { sqlData += " t4.mid_unit_price," } sqlData += ` CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t2.id, ',"comment":"', t2.comment, '","status":', t2.status, ',"createdAt":"', CONCAT(REPLACE(t2.created_at," ","T"),"+08:00"), '","updatedAt":"', CONCAT(REPLACE(t2.updated_at," ","T"),"+08:00"), '","lastOperator":"', t2.last_operator, '","specQuality":', t2.spec_quality, ',"specUnit":"', t2.spec_unit, '","exdSkuID":"', t2.exd_sku_id, '","eclpID":"', t2.eclp_id, '","weight":', t2.weight, ',"categoryID":', t2.category_id, ',"nameID":', t2.name_id, ', "seq":', t2.seq, ', "minOrderCount":', t2.min_order_count, "}")), "]") skus_str, CONCAT("[", GROUP_CONCAT(DISTINCT t3.place_code), "]") places_str ` + sql + ` ORDER BY MIN(t2.seq), t1.id DESC LIMIT ? OFFSET ?` pageSize = jxutils.FormalizePageSize(pageSize) offset = jxutils.FormalizePageOffset(offset) sqlParams = append(sqlParams, pageSize, offset) skuNamesInfo = &SkuNamesInfo{} dao.Begin(db) // todo 这里用事务的原因是,SQL_CALC_FOUND_ROWS会出错 defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() // globals.SugarLogger.Debug(sqlData) // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) if err = dao.GetRows(db, &skuNamesInfo.SkuNames, sqlData, sqlParams...); err == nil { skuNamesInfo.TotalCount = dao.GetLastTotalRowCount(db) dao.Commit(db) var skuIDs []int for _, skuName := range skuNamesInfo.SkuNames { skuName.FullName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, "", "", 0, "", 0, skuName.ExPrefix, skuName.ExPrefixBegin, skuName.ExPrefixEnd) if skuName.SkusStr != "" { if err = utils.UnmarshalUseNumber([]byte(skuName.SkusStr), &skuName.Skus); err != nil { dao.Rollback(db) return nil, err } for _, v := range skuName.Skus { skuIDs = append(skuIDs, v.ID) } } if skuName.PlacesStr != "" { if err = utils.UnmarshalUseNumber([]byte(skuName.PlacesStr), &skuName.Places); err != nil { dao.Rollback(db) return nil, err } } skuVendorCats, _ := dao.GetSkuVendorCategoryMaps(db, []int{skuName.ID}, []int{model.VendorIDMTWM, model.VendorIDEBAI, model.VendorIDJDShop, model.VendorIDJD}, nil) if len(skuVendorCats) > 0 { for _, v := range skuVendorCats { if v.VendorID == model.VendorIDJD { skuName.JdCategoryID = v.VendorCategoryID } if v.VendorID == model.VendorIDEBAI { skuName.EbaiCategoryID = v.VendorCategoryID } if v.VendorID == model.VendorIDMTWM { skuName.MtwmCategoryID = v.VendorCategoryID } if v.VendorID == model.VendorIDJDShop { skuName.JdsCategoryID = v.VendorCategoryID } } } } if len(skuIDs) > 0 { thingMapMap, err2 := dao.GetThingMapMap(db, model.ThingTypeSku, nil, skuIDs) if err = err2; err == nil { for _, skuName := range skuNamesInfo.SkuNames { for _, v := range skuName.Skus { v.MapList = thingMapMap[int64(v.ID)] } } } } } else { dao.Rollback(db) } return skuNamesInfo, err } func CheckHasSensitiveWord(word string) (bool, error) { if hasSensitiveWord, sensitiveWord := IsSensitiveWordInList(word); hasSensitiveWord { return true, errors.New(fmt.Sprintf("不能包含敏感词:[%s]", sensitiveWord)) } return false, nil } func IsSensitiveWordInList(str string) (bool, string) { wordList, err := dao.GetSensitiveWordList(-1) if err == nil { for _, value := range wordList { keyWord := value.Word if value.VendorID != -2 { checkHas := strings.Contains(str, keyWord) if checkHas { return true, keyWord } } else { var index int for index > 0 { index = strings.Index(keyWord, ",") keyWord = keyWord[:index-1] globals.SugarLogger.Debug("keyWord", keyWord) checkHas := strings.Contains(str, keyWord) if checkHas { return true, keyWord } } } } } return false, "" } func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName string) (outSkuNameExt *model.SkuNameExt, err error) { if skuNameExt.CategoryID == 0 { return nil, errors.New("CategoryID不能为空") } if len(skuNameExt.Skus) == 0 { return nil, errors.New("创建SKU NAME时必须至少创建一个SKU") } else if skuNameExt.Unit != model.SpecialUnit { if len(skuNameExt.Skus) != 1 { return nil, errors.New("不为份的SKU NAME只能有一个SKU") } } skuNameExt.Name = utils.TrimBlankChar(skuNameExt.Name) if hasSensitiveWord, err := CheckHasSensitiveWord(skuNameExt.Name); hasSensitiveWord { return nil, err } upc := utils.Pointer2String(skuNameExt.Upc) if upc == "" { skuNameExt.Upc = nil } else if !jxutils.IsUpcValid(upc) { return nil, fmt.Errorf("upc:%s不合法,请仔细检查", upc) } db := dao.GetDB() skuNameExt.SkuName.Status = model.SkuStatusNormal if skuNameExt.IsSpu == 1 { return nil, fmt.Errorf("不允许创建多规格商品") // skuNameExt.SkuName.JdSyncStatus = model.SyncFlagNewMask } if skuNameExt.Unit == model.SpecialUnit { skuNameExt.SpecQuality = float32(model.SpecialSpecQuality) skuNameExt.SpecUnit = model.SpecialSpecUnit } else { skuNameExt.SpecQuality = skuNameExt.Skus[0].SpecQuality skuNameExt.SpecUnit = skuNameExt.Skus[0].SpecUnit } if skuNameExt.YbNameSuffix == "" { var name *model.SkuName sql := "SELECT * FROM sku_name WHERE yb_name_suffix <> '' ORDER BY yb_name_suffix DESC LIMIT 1" dao.GetRow(db, &name, sql, nil) if name != nil { if skuNameExt.Unit == model.UnitNames[0] { prefix := utils.Int64ToStr(utils.Str2Int64(name.YbNameSuffix) + 1) realPrefix := prefix for i := 0; i < 4-len(prefix); i++ { realPrefix = "0" + realPrefix } skuNameExt.YbNameSuffix = realPrefix if utils.Str2Int64(prefix) > 9999 { return nil, fmt.Errorf("银豹的商品后缀已超过9999!") } } } } picType := true for _, imgName := range []string{skuNameExt.Img, skuNameExt.Img2} { if imgName != "" { dataRes, err2 := datares.TryRegisterDataResource(ctx, skuNameExt.Name, imgName, model.ImgTypeMain, false) if err = err2; err != nil { return nil, err } if dataRes.ResourceType == model.MimeTypeJpeg || dataRes.ResourceType == model.MimeTypePng { picType = false } } } if picType { return nil, fmt.Errorf("商品图片应至少包含一张非gif格式的图片!") } if skuNameExt.DescImg != "" { dataRes, err2 := datares.TryRegisterDataResource(ctx, skuNameExt.Name+"desc", skuNameExt.DescImg, model.ImgTypeDesc, false) if err = err2; err != nil { return nil, err } if dataRes.ResourceType == model.MimeTypeGif { return nil, fmt.Errorf("商品详情图片不能上传gif格式的图片!") } } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() dao.WrapAddIDCULDEntity(&skuNameExt.SkuName, userName) if err = dao.CreateEntity(db, &skuNameExt.SkuName); err != nil { dao.Rollback(db) return nil, err } if err = OnCreateThing(ctx, db, nil, int64(skuNameExt.SkuName.ID), model.ThingTypeSkuName); err != nil { dao.Rollback(db) return nil, err } for _, v := range skuNameExt.Skus { sku := v.Sku dao.WrapAddIDCULDEntity(sku, userName) sku.NameID = skuNameExt.ID // sku.JdSyncStatus = model.SyncFlagNewMask // sku.JdID = 0 if err = dao.CreateEntity(db, sku); err != nil { dao.Rollback(db) return nil, err } if sku.EclpID == "" { if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil { dao.Rollback(db) return nil, err } } } for _, placeCode := range skuNameExt.Places { placeBind := &model.SkuNamePlaceBind{} dao.WrapAddIDCULEntity(placeBind, userName) placeBind.NameID = skuNameExt.ID placeBind.PlaceCode = placeCode if err = dao.CreateEntity(db, placeBind); err != nil { dao.Rollback(db) return nil, err } } dao.Commit(db) tmpInfo, err := GetSkuNames(ctx, "", false, false, utils.Params2Map("nameID", skuNameExt.SkuName.ID), 0, 1) if err != nil { return nil, err } if tmpInfo.TotalCount != 1 { return nil, ErrEntityNotExist } outSkuNameExt = tmpInfo.SkuNames[0] _, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, -1, false, false, userName) updateOrCreateSkuVendorCategoryMap(db, ctx, outSkuNameExt.SkuName.ID, nil, skuNameExt, false) return outSkuNameExt, err } func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interface{}, isExd bool) (num int64, err error) { userName := ctx.GetUserName() skuName := &model.SkuName{} skuName.ID = nameID db := dao.GetDB() if err = dao.GetEntity(db, skuName); err != nil { return 0, err } var beforSkuName = *skuName if payload["name"] != nil { newSkuName := utils.TrimBlankChar(utils.Interface2String(payload["name"])) if hasSensitiveWord, err := CheckHasSensitiveWord(newSkuName); hasSensitiveWord { return 0, err } payload["name"] = newSkuName } delete(payload, "isSpu") delete(payload, "seq") valid := dao.StrictMakeMapByStructObject(payload, skuName, userName) valid = utils.RemoveGeneralMapKeys(valid, model.FieldSpecQuality, model.FieldSpecUnit) _, hasPlaces := payload["places"] flag := updateOrCreateSkuVendorCategoryMap(db, ctx, nameID, payload, nil, false) if len(valid) > 0 || hasPlaces || flag { if valid["Upc"] != nil { if upc, _ := valid["Upc"].(string); upc == "" { valid["Upc"] = nil } else if !jxutils.IsUpcValid(upc) { return 0, fmt.Errorf("upc:%s不合法,请仔细检查", upc) } } globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false)) for _, imgName := range []string{"img", "img2", "img3"} { if valid[imgName] != nil { if imgStr := utils.Interface2String(valid[imgName]); imgStr != "" { _, err2 := datares.TryRegisterDataResource(ctx, skuName.Name, valid[imgName].(string), model.ImgTypeMain, true) if err = err2; err != nil { return 0, err } } } } if valid["descImg"] != nil { descImg := valid["descImg"].(string) if descImg != "" { _, err2 := datares.TryRegisterDataResource(ctx, skuName.Name+"_desc", descImg, model.ImgTypeDesc, false) if err = err2; err != nil { return 0, err } } } var eclpID string if payload["eclpID"] != nil { eclpID = payload["eclpID"].(string) } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() // valid[model.FieldJdSyncStatus] = model.SyncFlagModifiedMask | skuName.JdSyncStatus if num, err = dao.UpdateEntityLogically(db, skuName, valid, userName, nil); err != nil { dao.Rollback(db) return 0, err } if !isExd && eclpID == "" { if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil { dao.Rollback(db) return 0, err } } if utils.Interface2Int64WithDefault(payload["isGlobal"], 0) == 0 && payload["places"] != nil { if places, ok := payload["places"].([]interface{}); ok { if _, err = dao.DeleteSkuNamePlace(db, nameID, nil); err != nil { dao.Rollback(db) return 0, err } for _, placeCode := range places { placeBind := &model.SkuNamePlaceBind{} placeBind.PlaceCode = int(utils.Interface2Int64WithDefault(placeCode, 0)) if placeBind.PlaceCode > 0 { dao.WrapAddIDCULEntity(placeBind, userName) placeBind.NameID = nameID err = dao.CreateEntity(db, placeBind) } else { dao.Rollback(db) return 0, errors.New("地点代码非法") } } } } skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) if err = err2; err == nil { for _, v := range skuList { sku := &v.Sku // sku.JdSyncStatus |= model.SyncFlagModifiedMask sku.LastOperator = userName sku.UpdatedAt = time.Now() if _, err = dao.UpdateEntity(db, sku); err != nil { dao.Rollback(db) return 0, err } if sku.ExdSkuID == "" && sku.EclpID == "" { if err = OnUpdateThing(ctx, db, nil, int64(v.ID), model.ThingTypeSku); err != nil { dao.Rollback(db) return 0, err } } } } skuIDs, err2 := dao.GetSkuIDByNames(db, []int{nameID}) if err = err2; err != nil { dao.Rollback(db) return 0, err } if len(skuIDs) > 0 { if _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), skuIDs, model.SyncFlagModifiedMask); err != nil { dao.Rollback(db) return 0, err } if valid["jdsStockSwitch"] != nil { if _, err = SetStoreSkuSyncStatus2(db, []int{model.JdShopMainStoreID}, []int{model.VendorIDJDShop}, skuIDs, model.SyncFlagSaleMask); err != nil { dao.Rollback(db) return 0, err } } } dao.Commit(db) errList := errlist.New() errList.AddErr(err) _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) errList.AddErr(err) err = errList.GetErrListAsOne() if globals.IsAddEvent { mapBefore := refutil.FindMapAndStructMixed(valid, beforSkuName) err = AddEventDetail(db, ctx, model.OperateUpdate, nameID, model.ThingTypeSkuName, 0, BuildDiffData(mapBefore), BuildDiffData(valid)) } } return num, err } func updateOrCreateSkuVendorCategoryMap(db *dao.DaoDB, ctx *jxcontext.Context, nameID int, payload map[string]interface{}, skuNameExt *model.SkuNameExt, isDelete bool) (flag bool) { if isDelete { skuVendorCatMaps, _ := dao.GetSkuVendorCategoryMaps(db, []int{nameID}, nil, nil) for _, v := range skuVendorCatMaps { v.DeletedAt = time.Now() v.LastOperator = ctx.GetUserName() dao.UpdateEntity(db, v, "DeletedAt", "LastOperator") } flag = true } else { updateOrCreate := func(vendorID, nameID int, vendorCatID string) { skuVendorCatMaps, _ := dao.GetSkuVendorCategoryMaps(db, []int{nameID}, []int{vendorID}, nil) if len(skuVendorCatMaps) > 0 { skuVendorCatMaps[0].VendorCategoryID = vendorCatID dao.UpdateEntity(db, skuVendorCatMaps[0], "VendorCategoryID") } else { skuVendorCatMap := &model.SkuVendorCategoryMap{ NameID: nameID, VendorID: vendorID, VendorCategoryID: vendorCatID, } dao.WrapAddIDCULDEntity(skuVendorCatMap, ctx.GetUserName()) dao.CreateEntity(db, skuVendorCatMap) } } if skuNameExt != nil { if skuNameExt.JdCategoryID != "" { updateOrCreate(model.VendorIDJD, nameID, skuNameExt.JdCategoryID) flag = true } if skuNameExt.JdsCategoryID != "" { updateOrCreate(model.VendorIDJDShop, nameID, skuNameExt.JdsCategoryID) flag = true } if skuNameExt.EbaiCategoryID != "" { updateOrCreate(model.VendorIDEBAI, nameID, skuNameExt.EbaiCategoryID) flag = true } if skuNameExt.MtwmCategoryID != "" { updateOrCreate(model.VendorIDMTWM, nameID, skuNameExt.MtwmCategoryID) flag = true } } else { if payload["jdCategoryID"] != nil { updateOrCreate(model.VendorIDJD, nameID, payload["jdCategoryID"].(string)) flag = true } if payload["jdsCategoryID"] != nil { updateOrCreate(model.VendorIDJDShop, nameID, payload["jdsCategoryID"].(string)) flag = true } if payload["ebaiCategoryID"] != nil { updateOrCreate(model.VendorIDEBAI, nameID, payload["ebaiCategoryID"].(string)) flag = true } if payload["mtwmCategoryID"] != nil { updateOrCreate(model.VendorIDMTWM, nameID, payload["mtwmCategoryID"].(string)) flag = true } } } return flag } func SetStoreSkuSyncStatus2(db *dao.DaoDB, storeIDs []int, vendorIDs, skuIDs []int, syncStatus int) (num int64, err error) { for _, vendorID := range vendorIDs { num2, err2 := dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, skuIDs, syncStatus) if err = err2; err != nil { return 0, err } num += num2 } return num, nil } func DeleteSkuName(ctx *jxcontext.Context, nameID int, userName string) (num int64, err error) { db := dao.GetDB() dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if _, err := dao.DeleteSkuNamePlace(db, nameID, nil); err != nil { dao.Rollback(db) return 0, err } if _, err = DeleteStoreSku(ctx, db, nameID, 0); err != nil { dao.Rollback(db) return 0, err } skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) if err = err2; err == nil { for _, v := range skuList { sku := &v.Sku if err = OnDeleteThing(ctx, db, nil, int64(v.ID), model.ThingTypeSku); err != nil { dao.Rollback(db) return 0, err } if _, err = dao.DeleteEntityLogically(db, sku, map[string]interface{}{ // model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldStatus: model.SkuStatusDeleted, }, userName, nil); err != nil { dao.Rollback(db) return 0, err } } } if err = OnDeleteThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil { dao.Rollback(db) return 0, err } skuName := &model.SkuName{} skuName.ID = nameID if num, err = dao.DeleteEntityLogically(db, skuName, map[string]interface{}{ // model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldStatus: model.SkuStatusDeleted, }, userName, nil); err != nil { dao.Rollback(db) return 0, err } dao.Commit(db) if len(skuList) > 0 { _, err = CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, false, userName) } updateOrCreateSkuVendorCategoryMap(db, ctx, nameID, nil, nil, true) return num, err } func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) (outSkuNameExt *model.SkuNameExt, err error) { db := dao.GetDB() skuName := &model.SkuName{} skuName.ID = nameID if err = dao.GetEntity(db, skuName); err != nil { return nil, err } if skuName.Unit != model.SpecialUnit { return nil, errors.New("不为份的SKU NAME只能有一个SKU") } dao.WrapAddIDCULDEntity(sku, userName) // sku.JdSyncStatus = model.SyncFlagNewMask // sku.JdID = 0 sku.NameID = nameID dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if err = dao.CreateEntity(db, sku); err != nil { dao.Rollback(db) return nil, err } if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil { dao.Rollback(db) return nil, err } dao.Commit(db) result, err2 := GetSkuNames(ctx, "", false, false, utils.Params2Map("skuID", sku.ID), 0, 0) if err = err2; err == nil { if result.TotalCount == 1 { outSkuNameExt = result.SkuNames[0] _, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, sku.ID, false, false, userName) } else { err = ErrEntityNotExist } } //增加规格则同步到门店,目前只做了京东商城的。 storeSkus, err := dao.GetStoreSkusByNameIDs(db, []int{model.JdShopMainStoreID}, nameID) if len(storeSkus) > 0 { storeIDs := make(map[int]int) storeMaps, err2 := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "") err = err2 for _, v := range storeMaps { storeSkus2, err2 := dao.GetStoreSkusByNameIDs(db, []int{v.StoreID}, nameID) err = err2 if len(storeSkus2) > 0 { storeIDs[v.StoreID] = v.StoreID } } skuBindInfos := []*StoreSkuBindInfo{} for _, v := range storeIDs { skus2 := []*StoreSkuBindSkuInfo{} skuBindInfo := &StoreSkuBindInfo{ StoreID: v, } sku2 := &StoreSkuBindSkuInfo{ SkuID: sku.ID, } skus2 = append(skus2, sku2) skuBindInfo.Skus = skus2 skuBindInfos = append(skuBindInfos, skuBindInfo) } FocusStoreSkusBySku(ctx, skuBindInfos, true, true) } return outSkuNameExt, err } func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{}) (num int64, err error) { userName := ctx.GetUserName() sku := &model.Sku{} sku.ID = skuID db := dao.GetDB() if err = dao.GetEntity(db, sku); err != nil { return 0, err } var beforSku = *sku valid := dao.StrictMakeMapByStructObject(payload, sku, userName) if len(valid) > 0 { // globals.SugarLogger.Debug(utils.Format4Output(valid, false)) dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() maskValue := int8(model.SyncFlagModifiedMask) if valid["specQuality"] != nil || valid["specUnit"] != nil { maskValue |= model.SyncFlagSpecMask } // valid[model.FieldJdSyncStatus] = maskValue | sku.JdSyncStatus if num, err = dao.UpdateEntityLogically(db, sku, valid, userName, nil); err != nil || num == 0 { dao.Rollback(db) if err == nil { err = ErrEntityNotExist } return 0, err } if _, err = dao.ExecuteSQL(db, ` UPDATE sku_name t1 JOIN sku t2 ON t1.id = t2.name_id SET t1.spec_quality = t2.spec_quality, t1.spec_unit = t2.spec_unit WHERE t1.deleted_at = ? AND t2.id = ? AND t1.unit <> ? `, utils.DefaultTimeValue, skuID, model.SpecialUnit); err != nil { dao.Rollback(db) if err == nil { err = ErrEntityNotExist } return 0, err } if sku.ExdSkuID == "" && sku.EclpID == "" { if err = OnUpdateThing(ctx, db, nil, int64(skuID), model.ThingTypeSku); err != nil { dao.Rollback(db) return 0, err } } dao.Commit(db) if _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), []int{skuID}, model.SyncFlagModifiedMask); err == nil { if maskValue&model.SyncFlagSpecMask != 0 { err = refreshStoreSkuPrice(ctx, db, skuID) } if valid["status"] != nil { SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), []int{skuID}, model.SyncFlagSaleMask) } } errList := errlist.New() errList.AddErr(err) _, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName) errList.AddErr(err) err = errList.GetErrListAsOne() if globals.IsAddEvent { mapBefore := refutil.FindMapAndStructMixed(valid, beforSku) err = AddEventDetail(db, ctx, model.OperateUpdate, skuID, model.ThingTypeSku, 0, BuildDiffData(mapBefore), BuildDiffData(valid)) } } return num, err } func refreshStoreSkuPrice(ctx *jxcontext.Context, db *dao.DaoDB, skuID int) (err error) { list, err := dao.GetStoreSkusAndSkuName(db, nil, []int{skuID}, nil) task := tasksch.NewParallelTask("refreshStoreSkuPrice", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*dao.StoreSkuAndName) storeID := v.StoreID storeDetail, _ := dao.GetStoreDetail(db, storeID, model.VendorIDJX) if storeDetail == nil { return retVal, err } storeSku := &model.StoreSkuBind{} storeSku.ID = v.BindID storeSku.JdSyncStatus = v.JdSyncStatus | model.SyncFlagPriceMask storeSku.MtwmSyncStatus = v.MtwmSyncStatus | model.SyncFlagPriceMask storeSku.EbaiSyncStatus = v.EbaiSyncStatus | model.SyncFlagPriceMask storeSku.Price = jxutils.CaculateSkuPrice(int(v.UnitPrice), v.SpecQuality, v.SpecUnit, v.Unit) storeSku.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), int(storeSku.Price)) storeSku.LastOperator = ctx.GetUserName() storeSku.UpdatedAt = time.Now() dao.Begin(db) defer func() { if r := recover(); r != nil || err != nil { dao.Rollback(db) if r != nil { panic(r) } } }() dao.UpdateEntity(db, storeSku, "Price", "JdSyncStatus", "MtwmSyncStatus", "EbaiSyncStatus", "JxPrice", "LastOperator") dao.Commit(db) return retVal, err }, list) tasksch.HandleTask(task, nil, true).Run() _, err = task.GetResult(0) return err } func DeleteSku(ctx *jxcontext.Context, skuID int, userName string) (num int64, err error) { db := dao.GetDB() dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if _, err = DeleteStoreSku(ctx, db, 0, skuID); err != nil { dao.Rollback(db) return 0, err } if err = OnDeleteThing(ctx, db, nil, int64(skuID), model.ThingTypeSku); err != nil { dao.Rollback(db) return 0, err } sku := &model.Sku{} sku.ID = skuID if num, err = dao.DeleteEntityLogically(db, sku, map[string]interface{}{ model.FieldStatus: model.SkuStatusDeleted, // model.FieldJdSyncStatus: model.SyncFlagDeletedMask, }, userName, nil); err != nil { dao.Rollback(db) return 0, err } dao.Commit(db) if num == 1 { _, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName) } err = deleteJdsSku(db, skuID) return num, err } func DeleteStoreSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int) (num int64, err error) { if db == nil { db = dao.GetDB() } sql := ` SELECT * FROM sku t1 WHERE 1 = 1 ` sqlParams := []interface{}{} if nameID > 0 { sql += " AND t1.name_id = ?" sqlParams = append(sqlParams, nameID) } else { sql += " AND t1.id = ?" sqlParams = append(sqlParams, skuID) } var skuList []*model.Sku if err = dao.GetRows(db, &skuList, sql, sqlParams); err == nil { num = int64(len(skuList)) for _, v := range skuList { storeSkuBind := &model.StoreSkuBind{} _, err = dao.DeleteEntityLogically(db, storeSkuBind, map[string]interface{}{ model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask, model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, model.FieldJdsSyncStatus: model.SyncFlagDeletedMask, }, ctx.GetUserName(), map[string]interface{}{ model.FieldSkuID: v.ID, model.FieldDeletedAt: utils.DefaultTimeValue, }) if err != nil { break } } } return num, err } func AddSkuNamePlace(ctx *jxcontext.Context, nameID, placeCode int, userName string) (outPlaceBind *model.SkuNamePlaceBind, err error) { db := dao.GetDB() placeBind := &model.SkuNamePlaceBind{ NameID: nameID, PlaceCode: placeCode, } dao.WrapAddIDCULEntity(placeBind, userName) dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if err = dao.CreateEntity(db, placeBind); err != nil { dao.Rollback(db) return nil, err } if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil { dao.Rollback(db) return nil, err } dao.Commit(db) _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) return placeBind, err } func DeleteSkuNamePlace(ctx *jxcontext.Context, nameID, placeCode int, userName string) (num int64, err error) { db := dao.GetDB() placeBind := &model.SkuNamePlaceBind{} placeBind.NameID = nameID placeBind.PlaceCode = placeCode dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if num, err = dao.DeleteEntity(db, placeBind, model.FieldNameID, model.FieldPlaceCode); err != nil || num == 0 { dao.Rollback(db) if err == nil { err = ErrEntityNotExist } return 0, err } if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil { dao.Rollback(db) return 0, err } dao.Commit(db) _, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName) return num, err } // func GetVendorSku(ctx *jxcontext.Context, vendorID int, vendorOrgCode, vendorSkuID string) (skuNameInfo *model.SkuNameExt, err error) { // if handler := CurVendorSync.GetMultiStoreHandler(vendorID); handler != nil { // return handler.ReadSku(ctx, vendorOrgCode, vendorSkuID) // } // return nil, ErrCanNotFindVendor // } func SortCategorySkus(ctx *jxcontext.Context, catID int, skuIDList []int) (err error) { db := dao.GetDB() userName := ctx.GetUserName() var skuList []*model.Sku if skuList, err = dao.GetSkuByCats(db, []int{catID}); err == nil && len(skuList) > 0 { if len(skuList) != len(skuIDList) { return errors.New("商品数量不匹配!") } skuIDMap := make(map[int]int) for index, id := range skuIDList { skuIDMap[id] = index + 1 } for _, value := range skuList { if _, ok := skuIDMap[value.ID]; !ok { return errors.New("商品数据不匹配!") } } dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() nameIDList := []int{} for _, value := range skuList { seq := skuIDMap[value.ID] if value.Seq != seq { kvs := map[string]interface{}{ model.FieldSkuSeq: seq, //model.FieldJdSyncStatus: (value.JdSyncStatus | model.SyncFlagModifiedMask), } dao.UpdateEntityLogically(db, value, kvs, userName, nil) nameIDList = append(nameIDList, value.NameID) } } //_, err = CurVendorSync.SyncSkus(ctx, db, nameIDList, []int{}, false, false, userName) if err == nil && len(nameIDList) > 0 { dao.Commit(db) skuIDs, err2 := dao.GetSkuIDByNames(db, nameIDList) if err = err2; err == nil && len(skuIDs) > 0 { _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), skuIDs, model.SyncFlagModifiedMask) } } else { dao.Rollback(db) } } return err } func GetJdUpcCodeByCode(ctx *jxcontext.Context, upcCode string) (productInfos []*jdapi.ProductInfo, err error) { productInfo, err := api.JdAPI.GetJdUpcCodeByName("", upcCode, 1, 30) if err != nil { return nil, err } for _, v := range productInfo { _, name, _, specUnit, unit, specQuality := jxutils.SplitSkuName(v.OriginalName) v.Name = name v.SpecQuality = specQuality v.SpecUnit = specUnit v.Unit = unit } return productInfo, err } func GetJdUpcCodeByName(ctx *jxcontext.Context, name, upcCode string) (productInfos []*jdapi.ProductInfo, err error) { if name != "" { var ( pageNo = 5 pageSize = 30 pageNoList []int ) if name == "" && upcCode == "" { return nil, fmt.Errorf("至少输入一个条件查询,商品名或者upc码!") } for i := 1; i < pageNo+1; i++ { pageNoList = append(pageNoList, i) } task := tasksch.NewParallelTask("获取京东商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { pageNum := batchItemList[0].(int) productInfo, err := api.JdAPI.GetJdUpcCodeByName(name, upcCode, pageNum, pageSize) if err != nil { return retVal, err } for _, v := range productInfo { _, name, _, specUnit, unit, specQuality := jxutils.SplitSkuName(v.OriginalName) v.Name = name v.SpecQuality = specQuality v.SpecUnit = specUnit v.Unit = unit } retVal = productInfo return retVal, err }, pageNoList) tasksch.HandleTask(task, nil, true).Run() productInfoInterface, err2 := task.GetResult(0) err = err2 for _, v := range productInfoInterface { productInfos = append(productInfos, v.(*jdapi.ProductInfo)) } } else { productInfos, err = GetJdUpcCodeByCode(ctx, upcCode) } return productInfos, err } func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, imgWaterMark string, vendorID int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) { var ( fromTimeP time.Time toTimeP time.Time db = dao.GetDB() ) if fromTime != "" { fromTimeP = utils.Time2Date(utils.Str2Time(fromTime)) } if toTime != "" { toTimeP = utils.Time2Date(utils.Str2Time(toTime)) } if toTimeP.Before(fromTimeP) { return "", fmt.Errorf("结束时间不可以小于开始时间!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP) } task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { step := batchItemList[0].(int) now := utils.Time2Date(time.Now()) switch step { case 0: task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { nameID := batchItemList[0].(int) payload := map[string]interface{}{ "exPrefix": exPrefix, "exPrefixBegin": fromTimeP, "exPrefixEnd": toTimeP, "imgWaterMark": imgWaterMark, "exVendorID": vendorID, } if now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) <= 0 { _, err = UpdateSkuName(ctx, nameID, payload, false) } else if now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0 { payload["exPrefixBegin"] = nil payload["exPrefixEnd"] = nil payload["imgWaterMark"] = nil payload["exVendorID"] = nil _, err = UpdateSkuName(ctx, nameID, payload, false) } else { skuList, err := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) if err == nil && len(skuList) > 0 { if skuList[0].ExPrefixBegin != nil { _, err = UpdateSkuName(ctx, nameID, payload, false) CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, []int{vendorID}, nil, false, []int{skuList[0].ID}, nil, model.SyncFlagModifiedMask, true, true) } else { skuName := &model.SkuName{ ExPrefix: exPrefix, ExPrefixBegin: &fromTimeP, ExPrefixEnd: &toTimeP, ImgWatermark: imgWaterMark, ExVendorID: vendorID, } skuName.ID = nameID skuName.LastOperator = ctx.GetLoginID() skuName.UpdatedAt = time.Now() dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() _, err = dao.UpdateEntity(db, skuName, "ImgWatermark", "ExVendorID", "ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "LastOperator", "UpdatedAt") dao.Commit(db) } } } return retVal, err }, nameIDs) tasksch.HandleTask(task, nil, true).Run() _, err = task.GetResult(0) case 1: if (now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0) || (now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0) { var skuIDs []int skuList, err2 := dao.GetSkus(db, nil, nameIDs, nil, nil, nil) if err = err2; err == nil { if len(skuList) > 0 { for _, v := range skuList { skuIDs = append(skuIDs, v.ID) } CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, []int{vendorID}, nil, false, skuIDs, nil, model.SyncFlagModifiedMask, true, true) } } } } return retVal, err }, []int{0, 1}) tasksch.HandleTask(task, nil, true).Run() if !isAsync { _, err = task.GetResult(0) hint = "1" } else { hint = task.GetID() } return hint, err } func SetSingleStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) { _, err = dao.UpdateStoreSkuBindSyncStatusForExPrefix(db, vendorIDs) return err } func SetMultiStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) { _, err = dao.UpdateSkuSyncStatusForExPrefix(db, vendorIDs) return err } func DeleteSkuNameExPrefixOverdue(db *dao.DaoDB) (err error) { _, err = dao.DeleteSkuNameExPrefixOverdue(db) return err } func SumExianDaDepot(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() results, err := api.EbaiAPI.GetExianDaSkuDepot("") taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*ebaiapi.ExianDaSkus) skus, err := api.EbaiAPI.GetExianDaSku(utils.Str2Int64(v.ElemeGoodsID)) if err != nil || skus == nil { globals.SugarLogger.Debugf("GetExianDaSku,[%v]", v.ElemeGoodsID) return result, err } // sku := &model.Sku{} // sku.ExdSkuID = v.ElemeGoodsID // sku.DeletedAt = utils.DefaultTimeValue // dao.GetEntity(db, sku, "ExdSkuID","DeletedAt") skuNameExt := &model.SkuName{} sql2 := ` SELECT a.* FROM sku_name a JOIN sku b ON b.name_id = a.id WHERE a.upc = ? AND a.deleted_at = ? AND b.deleted_at = ? ` sqlParams2 := []interface{}{ skus.UpcIds[0], utils.DefaultTimeValue, utils.DefaultTimeValue, } dao.GetRow(db, skuNameExt, sql2, sqlParams2) prefix, _, _, specUnit, unit, specQuality := jxutils.SplitSkuName(v.GoodsName) //京西库中存在此商品 if skuNameExt.ID != 0 { var flag = false if skuNameExt.Name != v.GoodsName { skuNameExt.Name = v.GoodsName skuNameExt.Prefix = prefix skuNameExt.SpecUnit = specUnit skuNameExt.Unit = unit skuNameExt.SpecQuality = specQuality flag = true } if skuNameExt.Img != v.ImageURL { skuNameExt.Img = v.ImageURL flag = true } if flag { _, err = dao.UpdateEntity(db, skuNameExt, "Name", "Prefix", "SpecUnit", "Unit", "SpecQuality", "Img") if err != nil { return result, err } } } else { skuName := &model.SkuName{ Prefix: prefix, Name: v.GoodsName, IsGlobal: model.YES, Unit: unit, SpecQuality: specQuality, SpecUnit: specUnit, Price: 100, Img: v.ImageURL, Upc: &v.UpcID, Status: model.SkuStatusNormal, } skuName.CategoryID = model.NoCatCatgoryID //默认给了个分类 dao.WrapAddIDCULDEntity(skuName, ctx.GetUserName()) err = dao.CreateEntity(db, skuName) if err != nil { return result, err } sku := &model.Sku{ NameID: skuName.ID, SpecQuality: specQuality, SpecUnit: specUnit, Weight: int(utils.Str2Int64(skus.Weight)), Status: model.SkuStatusNormal, ExdSkuID: v.ElemeGoodsID, ExdCategoryThirdID: skus.CategoryIDThird, } dao.WrapAddIDCULDEntity(sku, ctx.GetUserName()) err = dao.CreateEntity(db, sku) if err != nil { return result, err } } return retVal, err } taskParallel := tasksch.NewParallelTask("更新京西上饿鲜达商品库", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, taskFunc, results) tasksch.HandleTask(taskParallel, task, true).Run() _, err = taskParallel.GetResult(0) case 1: } return result, err } taskSeq := tasksch.NewSeqTask2("合并饿鲜达商品库", ctx, isContinueWhenError, taskSeqFunc, 2) tasksch.HandleTask(taskSeq, nil, true).Run() if !isAsync { _, err = taskSeq.GetResult(0) hint = "1" } else { hint = taskSeq.GetID() } return hint, err } func UpdateExianDaSkuCategory(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { var ( db = dao.GetDB() skus []*model.SkuName ) sql := ` SELECT a.* FROM sku_name a JOIN sku b ON b.name_id = a.id WHERE b.exd_sku_id <> '' AND a.deleted_at = ? AND b.deleted_at = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, utils.DefaultTimeValue, } err = dao.GetRows(db, &skus, sql, sqlParams...) task := tasksch.NewParallelTask("更新京西上饿鲜达商品分类", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*model.SkuName) skuList, err := api.Ebai2API.GetEbaiDepotSku(ebaiapi.EbaiWholeCountryStore, *v.Upc) if err != nil || len(skuList) == 0 || skuList[0] == nil { return retVal, err } sku, err := api.Ebai2API.GetEbaiSku(skuList[0].UpcID, ebaiapi.EbaiWholeCountryStore) if err != nil || sku == nil || sku.CustomCatName == "" { return retVal, err } skuCat := &model.SkuCategory{} sql := ` SELECT * FROM sku_category WHERE exd_name like ? ` sqlParams := []interface{}{ "%" + sku.CustomCatName + "%", } err = dao.GetRow(db, skuCat, sql, sqlParams) v.CategoryID = skuCat.ID _, err = dao.UpdateEntity(db, v, "CategoryID") if err != nil { return retVal, err } return retVal, err }, skus) tasksch.HandleTask(task, nil, true).Run() if !isAsync { _, err = task.GetResult(0) hint = "1" } else { hint = task.GetID() } return hint, err } func SendNoCatSkusToOperater(ctx *jxcontext.Context) (err error) { var ( db = dao.GetDB() skuNames []*model.SkuName ) globals.SugarLogger.Debugf("SendNoCatSkusToOperater") sql := ` SELECT * FROM sku_name WHERE deleted_at = ? AND (category_id = ? OR img = ?) AND unit <> ? ` sqlParams := []interface{}{utils.DefaultTimeValue, model.NoCatCatgoryID, model.NOSkuNameImg, model.UnitNames[0]} err = dao.GetRows(db, &skuNames, sql, sqlParams) if err != nil { return err } if len(skuNames) > 10 { noticeMsg := "有超过10个标品未进行分类和未设置图片!" for _, v := range skuNames { noticeMsg += "NameID:" + utils.Int2Str(v.ID) + ",商品名:" + v.Name + "," } for _, mobile := range sendNoCatSkusMobile { if user, err := dao.GetUserByID(db, "mobile", mobile); err != nil { ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "标品未分类和未设置图片", noticeMsg) } } } return err } func buildCreateUpcSkuByExcelErr(v *model.SkuName, errMsg string) (createUpcSkuByExcelErr *CreateUpcSkuByExcelErr) { createUpcSkuByExcelErr = &CreateUpcSkuByExcelErr{ Upc: *v.Upc, Name: v.Name, Unit: v.Unit, SpecQuality: utils.Float64ToStr(float64(v.SpecQuality)), Price: v.Price / 100, Err: errMsg, } return createUpcSkuByExcelErr } func CreateUpcSkuByExcel(ctx *jxcontext.Context, files []*multipart.FileHeader, categoryID int) (hint string, err error) { if len(files) == 0 { return "", errors.New("没有文件上传!") } fileHeader := files[0] file, err := fileHeader.Open() hint, err = CreateUpcSkuByExcelBin(ctx, file, categoryID) file.Close() return hint, err } func CreateUpcSkuByExcelBin(ctx *jxcontext.Context, reader io.Reader, categoryID int) (hint string, err error) { var ( db = dao.GetDB() skuParams []*model.SkuName createUpcSkuByExcelErrList []*CreateUpcSkuByExcelErr createUpcSkuByExcelErrListInterface []interface{} excelTitle = []string{ "商品条码", "商品名称", "单位", "重量(g)", "售价", "错误原因", } upcRegexp = regexp.MustCompile(`(^\d{12,13}$)`) ) taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result2 interface{}, err error) { switch step { case 0: xlsx, err := excelize.OpenReader(reader) if err != nil { return result2, err } rows, _ := xlsx.GetRows(xlsx.GetSheetName(1)) for rowNum, row := range rows { if rowNum < 1 { continue } var ( skuParam = &model.SkuName{} upc string unit string specQuality float32 price int name string ) for k, cell := range row { if cell != "" { if k == 0 { upc = cell } if k == 1 { name = cell } if k == 2 { unit = cell } if k == 3 { specQuality = float32(utils.Str2Float64WithDefault(cell, 0)) } if k == 4 { price = int(utils.Str2Float64WithDefault(cell, 0) * 100) } } } skuParam.Upc = &upc skuParam.Unit = unit skuParam.SpecQuality = specQuality skuParam.Price = price skuParam.Name = name skuParams = append(skuParams, skuParam) } case 1: taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { var ( v = batchItemList[0].(*model.SkuName) skuNames []model.SkuName skuName = &model.SkuNameExt{ SkuName: model.SkuName{}, Skus: []*model.SkuWithVendor{ &model.SkuWithVendor{ Sku: &model.Sku{}, }, }, } ) if v.Upc != nil { upc := upcRegexp.FindString(*v.Upc) if upc == "" { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "请输入正确的商品条码!")} return retVal, err } skuName.Upc = v.Upc } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "商品的条码不能为空!")} return retVal, err } sql := ` SELECT * FROM sku_name WHERE upc = ? AND deleted_at = ? ` sqlParams := []interface{}{*v.Upc, utils.DefaultTimeValue} err = dao.GetRows(db, &skuNames, sql, sqlParams) if len(skuNames) > 0 { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "商品在京西库中已存在!")} return retVal, err } productInfos, err := GetJdUpcCodeByCode(ctx, *v.Upc) if err != nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} return retVal, err } if len(productInfos) == 0 { var result *aliupcapi.GetAliUpcInfoResult upcDepot, err := dao.GetUpcDepot(db, *v.Upc) if upcDepot == nil { result, err = api.AliUpcAPI.GetAliUpcInfo(*v.Upc) if err == nil { err = dao.InsertUpcDepot(db, result) } } else { result = upcDepot } if result == nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未在标品库查到此商品,请手动创建!")} return retVal, err } if result.Img != "" { downloadURL, err := uploadImgStandard(skuName.Img) if err != nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} return retVal, err } skuName.Img = downloadURL // if resBinary, _, err := jxutils.DownloadFileByURL(result.Img); err == nil { // if downloadURL, err := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+"origin"+result.Img[strings.LastIndex(result.Img, "/")+1:len(result.Img)]); err == nil { // resBinary2, _, err := jxutils.DownloadFileByURL(downloadURL + model.SkuNameImgStandard) // downloadURL2, err := jxutils.UploadExportContent(resBinary2, utils.Int64ToStr(time.Now().Unix())+downloadURL[strings.LastIndex(downloadURL, "/")+1:len(downloadURL)]) // if err == nil { // skuName.Img = downloadURL2 // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } } else { skuName.Img = model.NOSkuNameImg } if v.Name != "" { skuName.Name = v.Name } else { skuName.Name = result.GoodsName } if v.Price == 0 { if result.Price == "" { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品售价,请补充商品的售价!")} return retVal, err } else { skuName.Price = int(utils.Str2Int64(result.Price) * 100) } } else { skuName.Price = v.Price } getNetUpcInfo, err := api.AliUpcAPI.GetNetUpcInfo(*v.Upc) if v.Unit != "" { if v.Unit == model.UnitNames[0] { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "标品的单位不能为份!")} return retVal, err } skuName.Unit = v.Unit } else { if getNetUpcInfo.Unit != "" { skuName.Unit = getNetUpcInfo.Unit } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品单位,请补充商品单位!")} return retVal, err } } if v.SpecQuality != 0 { skuName.Skus[0].SpecQuality = v.SpecQuality skuName.Skus[0].Weight = utils.Float32ToInt(v.SpecQuality) skuName.Skus[0].SpecUnit = model.SpecUnitNames[0] } else { _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.Name) if specQuality != 0 { skuName.Skus[0].SpecQuality = specQuality if specUnit == model.SpecUnitNames[1] || specUnit == model.SpecUnitNames[2] { skuName.Skus[0].Weight = int(utils.Str2Int64(utils.Float64ToStr(float64(specQuality) * 1000))) } else { skuName.Skus[0].Weight = utils.Float32ToInt(specQuality) } } else { if getNetUpcInfo.SpecQuality != 0 { if getNetUpcInfo.SpecUnit == model.SpecUnitNames[1] || getNetUpcInfo.SpecUnit == model.SpecUnitNames[2] || getNetUpcInfo.SpecUnit == "KG" || getNetUpcInfo.SpecUnit == "l" { skuName.Skus[0].Weight = int(utils.Str2Int64(utils.Float64ToStr(float64(getNetUpcInfo.SpecQuality) * 1000))) } else { skuName.Skus[0].Weight = utils.Float32ToInt(getNetUpcInfo.SpecQuality) } skuName.Skus[0].SpecQuality = getNetUpcInfo.SpecQuality } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品重量,请补充商品重量!")} return retVal, err } } if getNetUpcInfo.SpecUnit != "" { skuName.Skus[0].SpecUnit = getNetUpcInfo.SpecUnit } else { skuName.Skus[0].SpecUnit = model.SpecUnitNames[0] } } } else { productInfo := productInfos[0] if productInfo.Name == "" { if v.Name != "" { productInfo.Name = v.Name } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "需要填上一个合适的商品名!")} return retVal, err } } skuNames2, _ := dao.GetSkuNames(db, nil, nil, productInfo.Name, false) if len(skuNames2) > 1 { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "此商品名在京西库中查询出了大于1个商品!")} return retVal, err } //表示查到了,需要把upc更新上去,没查到就要新建 if len(skuNames2) == 1 && (productInfo.SpecQuality == skuNames2[0].SpecQuality && productInfo.SpecUnit == skuNames2[0].SpecUnit) { skuNames2[0].Upc = v.Upc dao.UpdateEntity(db, skuNames2[0], "Upc") return retVal, err } else { if v.Price == 0 { result, err := api.AliUpcAPI.GetAliUpcInfo(*v.Upc) if err != nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} return retVal, err } if result.Price == "" { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品售价,请补充商品售价!")} return retVal, err } else { skuName.Price = int(utils.Str2Int64(result.Price) * 100) } } else { skuName.Price = v.Price } skuName.Name = productInfo.Name getNetUpcInfo, err := api.AliUpcAPI.GetNetUpcInfo(*v.Upc) if v.Unit != "" { skuName.Unit = v.Unit } else { if productInfo.Unit == "" { if getNetUpcInfo.Unit != "" { skuName.Unit = getNetUpcInfo.Unit } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品单位,请补充商品单位!")} return retVal, err } } else { skuName.Unit = productInfo.Unit } } if v.SpecQuality != 0 { skuName.Skus[0].SpecQuality = v.SpecQuality skuName.Skus[0].Weight = utils.Float32ToInt(v.SpecQuality) skuName.Skus[0].SpecUnit = model.SpecUnitNames[0] } else { _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.Name) if specQuality != 0 { skuName.Skus[0].SpecQuality = specQuality if specUnit == model.SpecUnitNames[1] || specUnit == model.SpecUnitNames[2] { skuName.Skus[0].Weight = int(utils.Str2Int64(utils.Float64ToStr(float64(specQuality) * 1000))) } else { skuName.Skus[0].Weight = utils.Float32ToInt(specQuality) } } else { if productInfo.SpecQuality == 0 { if getNetUpcInfo.SpecQuality != 0 { if getNetUpcInfo.SpecUnit == model.SpecUnitNames[1] || getNetUpcInfo.SpecUnit == model.SpecUnitNames[2] || getNetUpcInfo.SpecUnit == "KG" || getNetUpcInfo.SpecUnit == "l" { skuName.Skus[0].Weight = int(utils.Str2Int64(utils.Float64ToStr(float64(getNetUpcInfo.SpecQuality) * 1000))) } else { skuName.Skus[0].Weight = utils.Float32ToInt(getNetUpcInfo.SpecQuality) } skuName.Skus[0].SpecQuality = getNetUpcInfo.SpecQuality } else { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品重量,请补充商品重量!")} return retVal, err } } else { if productInfo.Weight != 0 { skuName.Skus[0].Weight = int(utils.Str2Int64(utils.Float64ToStr(float64(productInfo.Weight)))) } else { skuName.Skus[0].Weight = utils.Float32ToInt(v.SpecQuality) } skuName.Skus[0].SpecQuality = productInfo.SpecQuality } } if productInfo.SpecUnit == "" { if getNetUpcInfo.SpecUnit != "" { skuName.Skus[0].SpecUnit = getNetUpcInfo.SpecUnit } else { skuName.Skus[0].SpecUnit = model.SpecUnitNames[0] } } else { skuName.Skus[0].SpecUnit = productInfo.SpecUnit } } if len(productInfo.ImgList) > 0 { skuName.Img = productInfo.ImgList[0] } else { skuName.Img = model.NOSkuNameImg } } } if skuName.Img == "" { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, "未查询到商品图片,请联系开发!")} return retVal, err } suffix := skuName.Img[strings.LastIndex(skuName.Img, "."):] if suffix != ".jpg" && suffix != ".png" && suffix != ".jpeg" && suffix != ".gif" { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, fmt.Sprintf("暂不支持的图片格式:[%v]", skuName.Img))} return retVal, err } //需要把图片传到七牛云上 if !strings.Contains(skuName.Img, "image.jxc4.com") { downloadURL, err := uploadImgStandard(skuName.Img) if err != nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} return retVal, err } skuName.Img = downloadURL // if resBinary, _, err := jxutils.DownloadFileByURL(skuName.Img); err == nil { // if downloadURL, err := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+"origin"+skuName.Img[strings.LastIndex(skuName.Img, "/")+1:len(skuName.Img)]); err == nil { // if img, _, err := datares.Binary2Image(resBinary, http.DetectContentType(resBinary)); err == nil { // if img.Bounds().Dx() != datares.MainImgWidth || img.Bounds().Dy() != datares.MainImgHeight { // if resBinary2, _, err := jxutils.DownloadFileByURL(downloadURL + model.SkuNameImgStandard); err == nil { // if downloadURL2, err := jxutils.UploadExportContent(resBinary2, utils.Int64ToStr(time.Now().Unix())+skuName.Img[strings.LastIndex(skuName.Img, "/")+1:len(skuName.Img)]); err == nil { // skuName.Img = downloadURL2 // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // skuName.Img = downloadURL // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } // } else { // retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} // return retVal, err // } } skuName.Status = model.SkuStatusNormal skuName.IsGlobal = model.YES if categoryID == 0 { skuName.CategoryID = model.NoCatCatgoryID } else { skuName.CategoryID = categoryID } skuName.Skus[0].Status = model.SkuStatusNormal _, err = AddSkuName(ctx, skuName, ctx.GetUserName()) if err != nil { retVal = []*CreateUpcSkuByExcelErr{buildCreateUpcSkuByExcelErr(v, err.Error())} return retVal, err } return retVal, err } taskParallel := tasksch.NewParallelTask("创建标品中", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, skuParams) tasksch.HandleTask(taskParallel, task, true).Run() createUpcSkuByExcelErrListInterface, err = taskParallel.GetResult(0) case 2: if len(createUpcSkuByExcelErrListInterface) > 0 { for _, v := range createUpcSkuByExcelErrListInterface { createUpcSkuByExcelErrList = append(createUpcSkuByExcelErrList, v.(*CreateUpcSkuByExcelErr)) } if len(createUpcSkuByExcelErrList) > 0 { err = writeToExcel(excelTitle, createUpcSkuByExcelErrList, ctx) } } } return result2, err } taskSeq := tasksch.NewSeqTask2("根据excel创建标品-序列任务", ctx, true, taskSeqFunc, 3) tasksch.HandleTask(taskSeq, nil, true).Run() hint = taskSeq.GetID() return hint, err } func writeToExcel(excelTitle []string, dataList interface{}, ctx *jxcontext.Context) (err error) { var sheetList []*excel.Obj2ExcelSheetConfig var downloadURL, fileName string excelConf := &excel.Obj2ExcelSheetConfig{ Title: "sheet1", Data: dataList, CaptionList: excelTitle, } sheetList = append(sheetList, excelConf) if excelConf != nil { downloadURL, fileName, err = jxutils.UploadExeclAndPushMsg(sheetList, "创建标品错误") } else { baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!") } if err != nil { baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName, err) } else { noticeMsg := fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) ddmsg.SendUserMessage(dingdingapi.MsgTyeText, ctx.GetUserID(), "异步任务完成", noticeMsg) baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess downloadURL: [%v]", downloadURL) } return err } //恢复京东回收站,修改京西的京东id func RefreshJdDepot(ctx *jxcontext.Context) (err error) { var ( pageSize = 20 searchResults []*jdapi.SearchDeleteWareResult db = dao.GetDB() // pageList []int // skuIDs []int ) for page := 1; page < 2; page++ { searchDeleteWareResults, err := api.JdAPI.SearchDeleteWare("2020-04-22", "2020-04-22", page, pageSize) if err == nil && len(searchDeleteWareResults) > 0 { searchResults = append(searchResults, searchDeleteWareResults...) } } for _, v := range searchResults { param := &jdapi.OpSkuParam{ TraceID: ctx.GetTrackInfo(), OutSkuID: utils.Int2Str(v.SkuID), FixedStatus: jdapi.SkuFixedStatusDeleted, } time.Sleep(time.Second * 1) _, err = api.JdAPI.UpdateSku2(param) if err != nil { globals.SugarLogger.Debugf("RefreshJdDepot UpdateSku2", err.Error()) continue } api.JdAPI.RefreshJdDepot(v.JdID) sql := ` UPDATE thing_map SET vendor_thing_id = ?, sync_status = ?, updated_at = NOW() WHERE thing_type = ? AND vendor_id = ? AND vendor_org_code = ? AND deleted_at = ? AND thing_id = ? ` sqlParams := []interface{}{v.JdID, model.SyncFlagModifiedMask, model.ThingTypeSku, model.VendorIDJD, "320406", utils.DefaultTimeValue, v.SkuID} dao.ExecuteSQL(db, sql, sqlParams) _, err = SyncSkus(ctx, nil, []int{0}, []string{"320406"}, nil, []int{v.SkuID}, false) time.Sleep(time.Second * 1) // skuIDs = append(skuIDs, v.SkuID) } return err } //标准化上传图片。 //图片是非京西图片上传到七牛云转换为京西图片 func uploadImgStandard(imgUrl string) (downloadResult string, err error) { if resBinary, _, err := jxutils.DownloadFileByURL(imgUrl); err == nil { if downloadURL, err := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+"origin"+imgUrl[strings.LastIndex(imgUrl, "/")+1:len(imgUrl)]); err == nil { if img, _, err := datares.Binary2Image(resBinary, http.DetectContentType(resBinary)); err == nil { if img.Bounds().Dx() != datares.MainImgWidth || img.Bounds().Dy() != datares.MainImgHeight { //如果不是标准的800x800就再把图片格式化上传 if resBinary2, _, err := jxutils.DownloadFileByURL(downloadURL + model.SkuNameImgStandard); err == nil { if downloadURL2, err := jxutils.UploadExportContent(resBinary2, utils.Int64ToStr(time.Now().Unix())+imgUrl[strings.LastIndex(imgUrl, "/")+1:len(imgUrl)]); err == nil { downloadResult = downloadURL2 } else { return downloadResult, err } } else { return downloadResult, err } } else { downloadResult = downloadURL } } else { return downloadResult, err } } else { return downloadResult, err } } else { return downloadResult, err } return downloadResult, err } func AddSkuNameByUpc(ctx *jxcontext.Context, upc string, store *dao.StoreDetail, v *partner.SkuNameInfo) (err error) { var ( db = dao.GetDB() // skuBindInfos []*StoreSkuBindInfo ) skuNames, err := dao.GetSkuNames(db, nil, []string{upc}, "", false) if err != nil { return err } //表示我们商品库中没有这个upc商品,如果有就直接关注上 if len(skuNames) == 0 { skuNameExt := &model.SkuNameExt{ SkuName: model.SkuName{ Upc: &upc, Status: model.SkuStatusNormal, CategoryID: model.NoCatCatgoryID, IsGlobal: model.YES, Price: int(v.SkuList[0].VendorPrice), }, Skus: []*model.SkuWithVendor{ &model.SkuWithVendor{ Sku: &model.Sku{ Status: model.SkuStatusNormal, }, }, }, } //我们商品库中有这个商品,但是upc没有填,则尝试用upc去查一下 productInfos, err2 := GetJdUpcCodeByName(ctx, "", upc) getNetUpcInfo, err2 := api.AliUpcAPI.GetNetUpcInfo(upc) err = err2 //表示用upc也没有找到这个商品 if len(productInfos) == 0 { if getNetUpcInfo == nil || getNetUpcInfo.SpecQuality == 0 || getNetUpcInfo.Unit == "" { return fmt.Errorf("此商品无规格无法创建,upc :[%s] , unit: [%s], specQuality : [%v]", upc, getNetUpcInfo.Unit, getNetUpcInfo.SpecQuality) } if len(v.PictureList) > 0 { skuNameExt.Img = v.PictureList[0] } else { img := getImgFromNet(db, upc) if img != "" { skuNameExt.Img = img } else { skuNameExt.Img = model.NOSkuNameImg } } if skuNameExt.Name == "" { skuNameExt.Name = v.SkuList[0].SkuName } else { skuNameExt.Name = v.Name } skuNameExt.Name = v.Name skuNameExt.Unit = getNetUpcInfo.Unit skuNameExt.Skus[0].SpecQuality = getNetUpcInfo.SpecQuality skuNameExt.Skus[0].SpecUnit = getNetUpcInfo.SpecUnit skuNameExt.Skus[0].Weight = utils.Float32ToInt(getNetUpcInfo.SpecQuality) } else { productInfo := productInfos[0] if (productInfo.SpecQuality == 0 || productInfo.Unit == "") && (getNetUpcInfo == nil || getNetUpcInfo.SpecQuality == 0 || getNetUpcInfo.Unit == "") { return fmt.Errorf("此商品无规格无法创建,upc :[%s] , unit: [%s], specQuality : [%v]", upc, getNetUpcInfo.Unit, getNetUpcInfo.SpecQuality) } if productInfo.SpecQuality == 0 { skuNameExt.Skus[0].SpecQuality = getNetUpcInfo.SpecQuality skuNameExt.Skus[0].Weight = utils.Float32ToInt(getNetUpcInfo.SpecQuality) } else { skuNameExt.Skus[0].SpecQuality = productInfo.SpecQuality skuNameExt.Skus[0].Weight = utils.Float32ToInt(productInfo.SpecQuality) } if productInfo.SpecUnit == "" { skuNameExt.Skus[0].SpecUnit = getNetUpcInfo.SpecUnit } else { skuNameExt.Skus[0].SpecUnit = productInfo.SpecUnit } if len(productInfo.ImgList) > 0 { skuNameExt.Img = productInfo.ImgList[0] } else { img := getImgFromNet(db, upc) if img != "" { skuNameExt.Img = img } else { skuNameExt.Img = model.NOSkuNameImg } } if productInfo.Name == "" { if v.Name == "" { skuNameExt.Name = v.SkuList[0].SkuName } else { skuNameExt.Name = v.Name } } else { skuNameExt.Name = productInfo.Name } if productInfo.Unit == "" { skuNameExt.Unit = getNetUpcInfo.Unit } else { skuNameExt.Unit = productInfo.Unit } } if flag := checkAndUpdateUpc(ctx, db, skuNameExt, v, store); !flag { if !strings.Contains(skuNameExt.Img, "image.jxc4.com") { downloadURL, err := uploadImgStandard(skuNameExt.Img) if err != nil { skuNameExt.Img = model.NOSkuNameImg } else { skuNameExt.Img = downloadURL } } if resBinary, _, err := jxutils.DownloadFileByURL(skuNameExt.Img); err == nil { if model.ValidMimeTypes[http.DetectContentType(resBinary)] == 0 { skuNameExt.Img = model.NOSkuNameImg } } if skuNameExt.Skus[0].SpecUnit == model.SpecUnitNames[1] || skuNameExt.Skus[0].SpecUnit == model.SpecUnitNames[2] || skuNameExt.Skus[0].SpecUnit == "KG" || skuNameExt.Skus[0].SpecUnit == "l" { skuNameExt.Skus[0].Weight = skuNameExt.Skus[0].Weight * 1000 } outSkuNameExt, err := AddSkuName(ctx, skuNameExt, ctx.GetUserName()) if err != nil { return err } // skuBindInfo := &StoreSkuBindInfo{ // NameID: outSkuNameExt.SkuName.ID, // IsFocus: 1, // UnitPrice: outSkuNameExt.SkuName.Price, // } // skuBindInfos = append(skuBindInfos, skuBindInfo) // updateStoresSkusWithoutSync(ctx, db, []int{store.ID}, skuBindInfos, false) buildStoreSkuBindInfosAndFocus(ctx, db, store, v, outSkuNameExt.ID) } } else { // skuBindInfo := &StoreSkuBindInfo{ // NameID: skuNames[0].ID, // IsFocus: 1, // UnitPrice: skuNames[0].Price, // } // skuBindInfos = append(skuBindInfos, skuBindInfo) // updateStoresSkusWithoutSync(ctx, db, []int{store.ID}, skuBindInfos, false) buildStoreSkuBindInfosAndFocus(ctx, db, store, v, skuNames[0].ID) } return err } //该商品名,规格在库中能查询出则更新upc不插入 func checkAndUpdateUpc(ctx *jxcontext.Context, db *dao.DaoDB, skuNameExt *model.SkuNameExt, v *partner.SkuNameInfo, store *dao.StoreDetail) (flag bool) { skuNames2, err := dao.GetSkuNames(db, nil, nil, skuNameExt.Name, false) if err != nil { return false } if len(skuNames2) == 0 { return false } //表示查到了,需要把upc更新上去,没查到就要新建 if skuNameExt.SpecQuality == skuNames2[0].SpecQuality { skuNames2[0].Upc = skuNameExt.Upc dao.UpdateEntity(db, skuNames2[0], "Upc") // var skuBindInfos []*StoreSkuBindInfo // skuBindInfo := &StoreSkuBindInfo{ // NameID: skuNames2[0].ID, // IsFocus: 1, // UnitPrice: skuNames2[0].Price, // } // skuBindInfos = append(skuBindInfos, skuBindInfo) // updateStoresSkusWithoutSync(ctx, db, []int{store.ID}, skuBindInfos, false) buildStoreSkuBindInfosAndFocus(ctx, db, store, v, skuNames2[0].ID) return true } return false } func getImgFromNet(db *dao.DaoDB, upc string) (img string) { var result *aliupcapi.GetAliUpcInfoResult upcDepot, err := dao.GetUpcDepot(db, upc) if upcDepot == nil { result, err = api.AliUpcAPI.GetAliUpcInfo(upc) if err == nil { err = dao.InsertUpcDepot(db, result) } } else { result = upcDepot } img = result.Img return img } func deleteJdsSku(db *dao.DaoDB, skuID int) (err error) { storeBinds, err := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, []int{skuID}) if err == nil && len(storeBinds) > 0 { err = api.JdShopAPI.DeleteSku(storeBinds[0].JdsID) } return err } func UpdateSkuExinfoMap(ctx *jxcontext.Context, nameIDs []int, imgWaterMark string, vendorID int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) { var ( fromTimeP time.Time toTimeP time.Time db = dao.GetDB() // skuIDs []int ) if fromTime != "" { fromTimeP = utils.Time2Date(utils.Str2Time(fromTime)) } if toTime != "" { toTimeP = utils.Time2Date(utils.Str2Time(toTime)) } if toTimeP.Before(fromTimeP) { return "", fmt.Errorf("结束时间不可以小于开始时间!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP) } task := tasksch.NewParallelTask("刷新商品前缀水印图", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { nameID := batchItemList[0].(int) skuEx := &model.SkuExinfoMap{ NameID: nameID, ImgWatermark: imgWaterMark, ExPrefix: exPrefix, VendorID: vendorID, BeginAt: fromTimeP, EndAt: toTimeP, } dao.WrapAddIDCULDEntity(skuEx, ctx.GetUserName()) skuExs, _ := dao.GetSkuExinfos(db, []int{nameID}, []int{vendorID}, "", utils.ZeroTimeValue, utils.ZeroTimeValue) if len(skuExs) > 0 { skuEx2 := skuExs[0] skuEx2.DeletedAt = time.Now() skuEx2.LastOperator = ctx.GetUserName() dao.UpdateEntity(db, skuEx2, "DeletedAt", "LastOperator") dao.CreateEntity(db, skuEx) } else { dao.CreateEntity(db, skuEx) } now := utils.Time2Date(time.Now()) if now.Sub(fromTimeP) >= 0 && now.Sub(toTimeP) <= 0 { var skuIDs []int skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) if err = err2; err == nil { if len(skuList) > 0 { for _, v := range skuList { skuIDs = append(skuIDs, v.ID) } if partner.IsMultiStore(vendorID) { for _, v := range skuIDs { OnUpdateThing(ctx, db, nil, int64(v), model.ThingTypeSku) } } else { SetStoreSkuSyncStatus2(db, nil, []int{vendorID}, skuIDs, model.SyncFlagModifiedMask) } } } } return retVal, err }, nameIDs) tasksch.HandleTask(task, nil, true).Run() if isAsync { hint = task.GetID() } else { _, err = task.GetResult(0) hint = "1" } return hint, err }