package yonghui import ( "errors" "fmt" "mime/multipart" "strconv" "unicode" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "github.com/360EntSecGroup-Skylar/excelize" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/platformapi/weimobapi" "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/dao" "git.rosy.net.cn/jx-callback/globals/api" ) var ( sheetNames = []string{"蔬菜", "水果", "肉禽", "净配", "水产", "干货", "MINI肉禽价格"} sheet1Name = "蔬菜" sheet2Name = "水果" sheet3Name = "肉禽" sheet4Name = "净配" sheet5Name = "水产" sheet6Name = "干货" sheet7Name = "MINI肉禽价格" ) //sheet1 蔬菜 var ( sheet1SkuIDCol = 0 //商品的spu编码 sheet1SkuPriceCol = 14 //对应商品的成本价 sheet1OrgSkuIdCol = 5 //原料的spu编码 sheet1OrgSkuPriceCol = 8 //对应原料的成本价 sheet1SkuRow = 2 ) //sheet2 水果 var ( sheet2SkuIDCol = 0 sheet2SkuPriceCol = 14 sheet2OrgSkuIdCol = 5 sheet2OrgSkuPriceCol = 8 sheet2SkuRow = 2 ) //sheet3 肉禽 var ( sheet3SkuIDCol = 0 sheet3SkuPriceCol = 12 sheet3OrgSkuIdCol = 4 sheet3OrgSkuPriceCol = 7 sheet3SkuRow = 1 ) //sheet4 净配 var ( sheet4SkuIDCol = 0 sheet4SkuPriceCol = 12 sheet4OrgSkuIdCol = 4 sheet4OrgSkuPriceCol = 7 sheet4SkuRow = 1 ) //sheet5 水产 var ( sheet5SkuIDCol = 1 sheet5SkuPriceCol = 15 sheet5OrgSkuIdCol = 6 sheet5OrgSkuPriceCol = 9 sheet5SkuRow = 1 ) //sheet6 干货 var ( sheet6SkuIDCol = 0 sheet6SkuPriceCol = 13 sheet6OrgSkuIdCol = 4 sheet6OrgSkuPriceCol = 7 sheet6SkuRow = 2 ) //sheet7 MINI肉禽价格 var ( sheet7SkuIDCol = 1 sheet7SkuPriceCol = 5 sheet7SkuRow = 1 ) const ( parallelCount = 5 ) func LoadExcelByYongHui(ctx *jxcontext.Context, files []*multipart.FileHeader, isAsync bool) (hint string, err error) { var ( skuMap = make(map[string]float64) errMsg string costPrice float64 //成本价 goodsIDListForPutAway []int64 goodsList []*weimobapi.GoodsInfo ) db := dao.GetDB() if len(files) == 0 { return "", errors.New("没有文件上传!") } //读取excel文件 xlsx, err := excelize.OpenFile(files[0].Filename) // xlsx, err := excelize.OpenFile("111.xlsx") if err != nil { return "", err } taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: taskFunc1 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(string) rows, _ := xlsx.GetRows(v) for rowNum, row := range rows { switch v { case sheet1Name: if rowNum < sheet1SkuRow { continue } GetCellIntoMap(sheet1SkuIDCol, sheet1SkuPriceCol, sheet1OrgSkuIdCol, sheet1OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet2Name: if rowNum < sheet2SkuRow { continue } GetCellIntoMap(sheet2SkuIDCol, sheet2SkuPriceCol, sheet2OrgSkuIdCol, sheet2OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet3Name: if rowNum < sheet3SkuRow { continue } GetCellIntoMap(sheet3SkuIDCol, sheet3SkuPriceCol, sheet3OrgSkuIdCol, sheet3OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet4Name: if rowNum < sheet4SkuRow { continue } GetCellIntoMap(sheet4SkuIDCol, sheet4SkuPriceCol, sheet4OrgSkuIdCol, sheet4OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet5Name: if rowNum < sheet5SkuRow { continue } GetCellIntoMap(sheet5SkuIDCol, sheet5SkuPriceCol, sheet5OrgSkuIdCol, sheet5OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet6Name: if rowNum < sheet6SkuRow { continue } GetCellIntoMap(sheet6SkuIDCol, sheet6SkuPriceCol, sheet6OrgSkuIdCol, sheet6OrgSkuPriceCol, skuMap, true, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } case sheet7Name: if rowNum < sheet7SkuRow { continue } GetCellIntoMap(sheet7SkuIDCol, sheet7SkuPriceCol, 0, 0, skuMap, false, row, v, rowNum) if len(skuMap) < 1 { errMsg += fmt.Sprintf("读取Excel数据失败,Excel格式排版可能发生了变化!sheetName: [%v]", v) } default: return retVal, errors.New("未找到配置的sheet页,请检查excel内容排版格式是否发生变化!\n") } } if errMsg != "" { return "", errors.New(errMsg) } return retVal, err } taskParallel1 := tasksch.NewParallelTask("读取Excel", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc1, sheetNames) tasksch.HandleTask(taskParallel1, task, true).Run() _, err = taskParallel1.GetResult(0) case 1: //获取微盟所有商品 goodsList = GetGoodsInfoAndDetail() //找出excel上有,微盟没有的,有就列出报错,不进行更新 goodsInfoAndDetailMap := GetGoodsInfoAndDetailMap(goodsList) delete(skuMap, "") for k, v := range skuMap { fmt.Printf("key %v, value %v\n", k, v) //表示excel上有,微盟上没有 if goodsInfoAndDetailMap[k] == nil { errMsg += fmt.Sprintf("在微盟上未找到该商品!excel商品ID : [%v]\n", k) } } fmt.Println(len(skuMap)) if errMsg != "" { return "", errors.New(errMsg) } case 2: //找出微盟上有,excel上没有的,有就更新,没有就下架 taskFunc2 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { goods := batchItemList[0].(*weimobapi.GoodsInfo) goodsDetail := goods.GoodsDetailInfo spuCode := goodsDetail.OuterGoodsCode if spuCode != "" { //如果微盟商品里找得到excel中的商品 if skuMap[spuCode] != 0 { //获取京西库商品 skuList, _ := dao.GetSkus(db, nil, []int{int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))}, nil, nil) if len(skuList) == 0 { errMsg += fmt.Sprintf("在京西库中未找到该商品!name_id : [%v] \n", goodsDetail.SkuMap.SingleSku.OuterSkuCode) } else { if skuList[0].Unit != "份" { costPrice = Float64Round(0.5 / goodsDetail.SkuMap.SingleSku.B2CSku.Weight * skuMap[spuCode]) } else { costPrice = skuMap[spuCode] } if errMsg == "" { _, _, err = updateWeiMobGoods(costPrice, skuMap[spuCode], goodsDetail) } } } else { //下架微盟商品 goodsIDListForPutAway = append(goodsIDListForPutAway, goodsDetail.GoodsID) } } return retVal, err } taskParallel2 := tasksch.NewParallelTask("获取微盟所有商品并更新", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc2, goodsList) tasksch.HandleTask(taskParallel2, task, true).Run() _, err = taskParallel2.GetResult(0) case 3: //批量下架微盟商品 if errMsg == "" { if len(goodsIDListForPutAway) <= 50 { //api要求最多传50个 PutAwayWeiMobSku(goodsIDListForPutAway) } else { for i := 0; i < len(goodsIDListForPutAway)/50+1; i++ { var int64Slice []int64 if len(goodsIDListForPutAway) > 50*(i+1) { int64Slice = goodsIDListForPutAway[i*50 : (i+1)*50+1] } else { int64Slice = goodsIDListForPutAway[i*50 : len(goodsIDListForPutAway)] } PutAwayWeiMobSku(int64Slice) } } } } return result, err } taskSeq := tasksch.NewSeqTask("读取永辉Excel文件修改微盟商品价格可售状态-序列任务", ctx, taskSeqFunc, 4) tasksch.HandleTask(taskSeq, nil, true).Run() if errMsg != "" { baseapi.SugarLogger.Debugf(errMsg) } return "", err } func PutAwayWeiMobSku(goodsIDListForPutAway []int64) { err := api.WeimobAPI.UpdateGoodsShelfStatus(goodsIDListForPutAway, false) if err != nil { baseapi.SugarLogger.Errorf("UpdateGoodsShelfStatus error:%v", err) } } func GetGoodsInfoAndDetailMap(goodsList []*weimobapi.GoodsInfo) (goodsMap map[string]*weimobapi.GoodsInfo) { goodsMap = make(map[string]*weimobapi.GoodsInfo) for _, v := range goodsList { goodsMap[v.GoodsDetailInfo.OuterGoodsCode] = v } return goodsMap } func GetGoodsInfoAndDetail() []*weimobapi.GoodsInfo { goodsList, err := GetWeiMobGoodsList() if err != nil { baseapi.SugarLogger.Errorf("GetWeiMobGoodsList error:%v", err) } for _, v := range goodsList { goodsDetail, err := api.WeimobAPI.QueryGoodsDetail(v.GoodsID) if err != nil { baseapi.SugarLogger.Errorf("QueryGoodsDetail error:%v", err) } v.GoodsDetailInfo = goodsDetail } return goodsList } func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.GoodsDetailInfo) (goodsID int64, skuMap map[string]int64, err error) { var ( skuListParam []*weimobapi.SkuList deliveryTypeListSlice []int64 skuListInfo = goodsDetail.SkuList[0] categoryList []*weimobapi.CategoryList categoryID int ) //查询配送方式 deliveryTypeList, err := api.WeimobAPI.FindDeliveryTypeList(goodsDetail.GoodsID) if err != nil { baseapi.SugarLogger.Errorf("FindDeliveryTypeList error:%v", err) } for _, deliveryType := range deliveryTypeList { if deliveryType.Selected { deliveryTypeListSlice = append(deliveryTypeListSlice, deliveryType.DeliveryID) } } //查询运费模板 freightTemplateListInfo, err := api.WeimobAPI.FindFreightTemplateList(goodsDetail.GoodsID) if err != nil { baseapi.SugarLogger.Errorf("FindFreightTemplateList error:%v", err) } //寻找分类子ID categoryList = goodsDetail.CategoryList if len(categoryList) > 0 { for k, v := range categoryList { if k < len(categoryList)-1 { continue } categoryID = v.CategoryID } } else { return 0, nil, errors.New(fmt.Sprintf("未查询到此商品的分类信息!goodsID : [%v] ,", goodsDetail.GoodsID)) } b2CSku := &weimobapi.B2CSku{ Weight: skuListInfo.B2CSku.Weight, Volume: skuListInfo.B2CSku.Volume, } b2CGoods := &weimobapi.B2CGoods{ B2CGoodsType: goodsDetail.B2CGoods.B2CGoodsType, DeliveryTypeIDList: deliveryTypeListSlice, FreightTemplateID: freightTemplateListInfo.DefaultFreightTemplate.TemplateID, } skuList := &weimobapi.SkuList{ SalePrice: salePrice, CostPrice: costPrice, SkuID: skuListInfo.SkuID, EditStockNum: skuListInfo.EditStockNum, OuterSkuCode: skuListInfo.OuterSkuCode, B2CSku: b2CSku, } skuListParam = append(skuListParam, skuList) goods := &weimobapi.Goods{ B2CGoods: b2CGoods, SkuList: skuListParam, Title: goodsDetail.Title, IsMultiSku: goodsDetail.IsMultiSku, IsPutAway: goodsDetail.IsPutAway, GoodsImageURL: goodsDetail.GoodsImageURL, GoodsID: goodsDetail.GoodsID, CategoryID: categoryID, OuterGoodsCode: goodsDetail.OuterGoodsCode, PointDeductRatio: goodsDetail.PointDeductRatio, } updateGoodsParam := &weimobapi.UpdateGoodsParam{ Goods: goods, } return api.WeimobAPI.UpdateGoods3(updateGoodsParam) } func GetWeiMobGoodsList() (goodsList []*weimobapi.GoodsInfo, err error) { param := &weimobapi.QueryGoodsListParam{ PageNum: 1, PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds, } for { goodsInfoList, _, err := api.WeimobAPI.QueryGoodsList(param) if err != nil { return nil, err } if len(goodsInfoList) > 0 { goodsList = append(goodsList, goodsInfoList...) } if len(goodsInfoList) < param.PageSize { break } param.PageNum++ } return goodsList, err } func IsChineseChar(str string) bool { for _, r := range str { if unicode.Is(unicode.Scripts["Han"], r) { return true } } return false } func GetCellIntoMap(skuIDCol, skuPriceCol, orgSkuIDCol, orgSkuPriceCol int, skuMap map[string]float64, isHaveOrg bool, row []string, sheetName string, rowNum int) { var ( skuID string orgSkuID string skuPrice float64 orgSkuPrice float64 ) for k, cell := range row { if !IsChineseChar(cell) && cell != "" { if k == skuIDCol { skuID = cell } if k == skuPriceCol { skuPrice = Float64Round(utils.Str2Float64(cell)) } if isHaveOrg { if k == orgSkuIDCol { orgSkuID = "0" + cell } if k == orgSkuPriceCol { orgSkuPrice = Float64Round(utils.Str2Float64(cell)) } } } } if skuMap[skuID] != 0 && skuMap[skuID] != skuPrice && skuID != "" { if skuPrice > skuMap[skuID] { skuMap[skuID] = skuPrice } // fmt.Sprintf("读取excel表格出错!有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v] , 商品编码 :[%v] , 价格:[%v]\n", sheetName, rowNum, skuID, skuPrice) } else { skuMap[skuID] = skuPrice } if isHaveOrg { if skuMap[orgSkuID] != 0 && skuMap[orgSkuID] != orgSkuPrice && orgSkuID != "" { if orgSkuPrice > skuMap[orgSkuID] { skuMap[orgSkuID] = orgSkuPrice } // fmt.Sprintf("读取excel表格出错!有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v], 商品编码 :[%v] , 价格:[%v]\n", sheetName, rowNum, orgSkuID, orgSkuPrice) } else { skuMap[orgSkuID] = orgSkuPrice } } } func Float64Round(f float64) (flt float64) { flt, err := strconv.ParseFloat(fmt.Sprintf("%.2f", f), 64) if err != nil { flt = 0 } return flt }