Files
jx-callback/business/jxstore/yonghui/yonghui.go
2019-11-26 11:42:20 +08:00

988 lines
31 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package yonghui
import (
"errors"
"fmt"
"io"
"math"
"mime/multipart"
"strings"
"sync"
"time"
"unicode"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils"
"github.com/360EntSecGroup-Skylar/excelize"
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
"git.rosy.net.cn/jx-callback/business/jxutils/excel"
"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/globals"
"git.rosy.net.cn/jx-callback/globals/api"
)
type SheetParam struct {
SkuIDCol int
SkuPriceCol int
SkuNameCol int
OrgSkuIdCol int
OrgSkuPriceCol int
OrgSkuNameCol int
SkuRow int
}
type DataSuccessLock struct {
dataSuccessList []DataSuccess
locker sync.RWMutex
}
type DataFailedLock struct {
dataFailedList []DataFailed
locker sync.RWMutex
}
type DataSuccess struct {
NameID string `json:"商品nameID"`
Name string `json:"商品名称"`
Unit string `json:"单位"`
OrgPrice float64 `json:"原价"`
NowPrice float64 `json:"现价"`
MixPrice float64 `json:"涨跌"`
}
type DataFailed struct {
GoodsID string `json:"商品ID"`
GoodsName string `json:"商品名称"`
Comment string `json:"备注"`
}
type Data struct {
GoodsID string `json:"商品编码"`
GoodsName string `json:"商品名称"`
GoodsNum int `json:"订货数量"`
}
type ExcelParam struct {
SpuCode string
Name string
Price float64
}
type OrderList struct {
Name string `json:"name"`
Phone string `json:"phone"`
OrderNo int64 `json:"orderNo"`
}
var (
sheetMap = map[string]*SheetParam{
"蔬菜": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 14,
SkuNameCol: 1,
OrgSkuIdCol: 5,
OrgSkuPriceCol: 8,
OrgSkuNameCol: 6,
SkuRow: 2,
}, "水果": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 14,
SkuNameCol: 1,
OrgSkuIdCol: 5,
OrgSkuPriceCol: 8,
OrgSkuNameCol: 6,
SkuRow: 2,
}, "肉禽": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 12,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 1,
}, "净配": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 12,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 1,
}, "水产": &SheetParam{
SkuIDCol: 1,
SkuPriceCol: 15,
SkuNameCol: 2,
OrgSkuIdCol: 6,
OrgSkuPriceCol: 9,
OrgSkuNameCol: 7,
SkuRow: 1,
}, "干货": &SheetParam{
SkuIDCol: 0,
SkuPriceCol: 13,
SkuNameCol: 1,
OrgSkuIdCol: 4,
OrgSkuPriceCol: 7,
OrgSkuNameCol: 5,
SkuRow: 2,
}, "MINI肉禽价格": &SheetParam{
SkuIDCol: 1,
SkuPriceCol: 5,
SkuNameCol: 2,
OrgSkuIdCol: -1,
OrgSkuPriceCol: -1,
OrgSkuNameCol: -1,
SkuRow: 1,
},
}
titleListSuccess = []string{
"商品nameID",
"商品名称",
"单位",
"原价",
"现价",
"涨跌",
}
titleListFailed = []string{
"商品ID",
"商品名称",
"备注",
}
titleList = []string{
"商品编码",
"商品名称",
"订货数量",
}
dataSuccess DataSuccessLock
dataFailed DataFailedLock
)
const (
parallelCount = 5
UpdateGoodsShelfStatusCount = 50 //微盟下架商品api限制一次50个
fileExt = ".xlsx"
)
func (d *DataSuccessLock) AppendData(dataSuccess DataSuccess) {
d.locker.Lock()
defer d.locker.Unlock()
d.dataSuccessList = append(d.dataSuccessList, dataSuccess)
}
func (d *DataFailedLock) AppendData2(dataFailed DataFailed) {
d.locker.Lock()
defer d.locker.Unlock()
d.dataFailedList = append(d.dataFailedList, dataFailed)
}
func LoadExcelByYongHui(ctx *jxcontext.Context, files []*multipart.FileHeader, isAsync, isContinueWhenError bool) (hint string, err error) {
if len(files) == 0 {
return "", errors.New("没有文件上传!")
}
fileHeader := files[0]
file, err := fileHeader.Open()
hint, err = LoadExcelBinByYongHui(ctx, file, true, true)
file.Close()
return hint, err
}
func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
skuMap = make(map[string]*ExcelParam)
errMsg string
costPrice float64 //成本价
goodsList []*weimobapi.GoodsInfo
goodsIDListForPutAway []interface{}
isCompare bool
)
db := dao.GetDB()
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
//读取excel文件
xlsx, err := excelize.OpenReader(reader)
if err != nil {
return "", err
}
for k := range sheetMap {
sheetParam := sheetMap[k]
rows, _ := xlsx.GetRows(k)
for rowNum, row := range rows {
if rowNum < sheetParam.SkuRow {
continue
}
GetCellIntoMap(sheetParam, skuMap, row, k, rowNum)
if len(skuMap) < 1 {
errMsg += fmt.Sprintf("读取Excel数据失败Excel格式排版可能发生了变化sheetName: [%v]\n", k)
}
}
if errMsg != "" {
return "", errors.New(errMsg)
}
}
//修改分组名
// 分类名格式为可定XX日
// XX为上传永辉 提供的 价格表时间 +2天
isCompare, err = UpdateClassifyAndGetLastClassify()
case 1:
//获取微盟所有商品
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
}
goodsList, err = GetWeiMobGoodsList(param)
if err != nil {
baseapi.SugarLogger.Errorf("GetWeiMobGoodsList error:%v", err)
}
taskFunc2 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*weimobapi.GoodsInfo)
goodsDetail, err := api.WeimobAPI.QueryGoodsDetail(v.GoodsID)
if err != nil {
baseapi.SugarLogger.Errorf("QueryGoodsDetail error:%v", err)
}
v.GoodsDetailInfo = goodsDetail
return retVal, err
}
taskParallel2 := tasksch.NewParallelTask("获取微盟商品", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc2, goodsList)
tasksch.HandleTask(taskParallel2, task, true).Run()
_, err = taskParallel2.GetResult(0)
//找出excel上有微盟没有的,有就列出报错,不进行更新
goodsInfoAndDetailMap := GetGoodsInfoAndDetailMap(goodsList)
for k, _ := range skuMap {
//表示excel上有微盟上没有
if goodsInfoAndDetailMap[k] == nil {
outPutData := DataFailed{
GoodsID: k,
GoodsName: skuMap[k].Name,
Comment: "在微盟上未找到该商品",
}
dataFailed.AppendData2(outPutData)
// errMsg += fmt.Sprintf("在微盟上未找到该商品xxx", xxx)
}
}
case 2:
//找出微盟上有excel上没有的有就更新没有就下架
taskFunc3 := 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] != nil {
//获取京西库商品
skuList, _ := dao.GetSkus(db, nil, []int{int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))}, nil, nil)
if len(skuList) == 0 {
outPutData := DataFailed{
GoodsID: spuCode,
GoodsName: skuMap[spuCode].Name,
Comment: "在京西库中未找到该商品",
}
dataFailed.AppendData2(outPutData)
// return "", errors.New(fmt.Sprintf("在京西库中未找到该商品name_id : [%v]\n", goodsDetail.SkuMap.SingleSku.OuterSkuCode))
} else {
if skuList[0].Unit == "份" {
if goodsDetail.SkuMap.SingleSku.B2CSku.Weight == 0 {
costPrice = skuMap[spuCode].Price
} else {
costPrice = Float64Round(0.5 / goodsDetail.SkuMap.SingleSku.B2CSku.Weight * skuMap[spuCode].Price)
}
} else {
costPrice = skuMap[spuCode].Price
}
_, _, _ = updateWeiMobGoods(costPrice, skuMap[spuCode].Price, skuList[0].Unit, isCompare, goodsDetail)
}
} else {
//下架微盟商品
retVal = []int64{goodsDetail.GoodsID}
}
}
return retVal, err
}
taskParallel3 := tasksch.NewParallelTask("根据获取的微盟所有商品并更新", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc3, goodsList)
tasksch.HandleTask(taskParallel3, task, true).Run()
goodsIDListForPutAwayInterface, err2 := taskParallel3.GetResult(0)
if err = err2; err != nil {
return "", err
}
goodsIDListForPutAway = goodsIDListForPutAwayInterface
case 3:
// 批量下架微盟商品
taskFunc4 := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
int64Slice := []int64{}
for _, v := range batchItemList {
int64Slice = append(int64Slice, v.(int64))
}
PutAwayWeiMobSku(int64Slice)
return retVal, err
}
taskParallel4 := tasksch.NewParallelTask("下架微盟商品", tasksch.NewParallelConfig().SetParallelCount(parallelCount).SetBatchSize(UpdateGoodsShelfStatusCount), ctx, taskFunc4, goodsIDListForPutAway)
tasksch.HandleTask(taskParallel4, task, true).Run()
_, err = taskParallel4.GetResult(0)
case 4:
WriteToExcel(task, dataSuccess.dataSuccessList, dataFailed.dataFailedList)
}
// if errMsg != "" {
// return result, errors.New(errMsg)
// }
return result, err
}
taskSeq := tasksch.NewSeqTask2("读取永辉Excel文件修改微盟商品价格可售状态-序列任务", ctx, isContinueWhenError, taskSeqFunc, 5)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}
func PutAwayWeiMobSku(goodsIDListForPutAway []int64) (err error) {
if globals.EnableStoreWrite {
err = api.WeimobAPI.UpdateGoodsShelfStatus(goodsIDListForPutAway, false)
}
if err != nil {
baseapi.SugarLogger.Errorf("UpdateGoodsShelfStatus error:%v", err)
}
return 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 getSelectedClassifyLeafList(l []weimobapi.SelectedClassifyList) (list []int64) {
// for _, v := range l {
// if v.ChildrenClassify == nil {
// list = append(list, v.ClassifyID)
// } else {
// subList := getSelectedClassifyLeafList(v.ChildrenClassify)
// }
// }
// return list
// }
func updateWeiMobGoods(costPrice, salePrice float64, unit string, isCompare bool, goodsDetail *weimobapi.GoodsDetailInfo) (goodsID int64, skuMap map[string]int64, err error) {
var (
categoryList []*weimobapi.CategoryList
skuListInfo = goodsDetail.SkuList[0]
skuListParam []*weimobapi.SkuList
categoryID int
deliveryTypeListSlice []int64
newSkuTitle string
)
//查询配送方式
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 {
categoryID = categoryList[len(categoryList)-1].CategoryID
} else {
return 0, nil, errors.New(fmt.Sprintf("未查询到此商品的分类信息goodsID : [%v] ,", goodsDetail.GoodsID))
}
//商品分组原有的分组IDs
selectedClassifyList := goodsDetail.SelectedClassifyList
selectedClassifyListIDMap := make(map[int64]int64)
if len(selectedClassifyList) > 0 {
for _, v := range selectedClassifyList {
for _, v := range v.ChildrenClassify {
selectedClassifyListIDMap[v.ClassifyID] = v.ClassifyID
}
}
}
//上次上传价格和这次上传价格对比
// 4、微盟商品。两个重要分组
// 降价超0.2元,与前一日数据对比,需要将此类商品增加分类到这里,不改变原分类
// 涨价超0.2元,与前一日数据对比,需要将此类商品增加分类到这里,不改变原分类
// 其他商品,取消 这两个分类
// 同一天第二次上传的处理,需要注意是与前一天价格的对比,不是当天的价格对比。
// 5. 涨价和跌价值保留2位小数
// 需要在每个商品中增加↑0.01或↓0.02。
// 显示在商品最前的括号里,如果没有括号,需要增加。都用小写的括号,大写括号需要删除。
// 包装菜需要增加“精”,其他不需要加字,比如:
// (精↓2.11)新土豆1kg/袋
// (↓2.11)新土豆1kg
//salePrice 这次上传的价格 goodsDetail.SkuMap.SingleSku.SalePrice 上次上传的价格 priceMix 两次上传价格差 priceMixRound 保留两位后的价格差
if !isCompare {
priceMix := salePrice - goodsDetail.SkuMap.SingleSku.SalePrice
if priceMix > 0.2 {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
selectedClassifyListIDMap[1064198248] = 1064198248
} else if priceMix < -0.2 {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
selectedClassifyListIDMap[1065246248] = 1065246248
} else {
delete(selectedClassifyListIDMap, 1064198248)
delete(selectedClassifyListIDMap, 1065246248)
}
priceMixRound := Float64Round(priceMix)
newSkuTitle = GetNewSkuTitle(priceMixRound, goodsDetail.Title, goodsDetail.OuterGoodsCode)
} else {
newSkuTitle = goodsDetail.Title
}
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: 9999 - skuListInfo.AvailableStockNum,
OuterSkuCode: skuListInfo.OuterSkuCode,
B2CSku: b2CSku,
}
skuListParam = append(skuListParam, skuList)
goods := &weimobapi.Goods{
B2CGoods: b2CGoods,
SkuList: skuListParam,
Title: newSkuTitle,
IsMultiSku: goodsDetail.IsMultiSku,
IsPutAway: weimobapi.GoodsTypeNormal,
GoodsImageURL: goodsDetail.GoodsImageURL,
GoodsID: goodsDetail.GoodsID,
CategoryID: categoryID,
OuterGoodsCode: goodsDetail.OuterGoodsCode,
PointDeductRatio: goodsDetail.PointDeductRatio,
SelectedClassifyIDList: Map2Int64Slice(selectedClassifyListIDMap),
}
updateGoodsParam := &weimobapi.UpdateGoodsParam{
Goods: goods,
}
if globals.EnableStoreWrite {
goodsID, skuMap, err = api.WeimobAPI.UpdateGoods3(updateGoodsParam)
if err != nil {
if errExt, ok := err.(*utils.ErrorWithCode); ok {
outPutData := DataFailed{
GoodsID: goodsDetail.OuterGoodsCode,
GoodsName: goodsDetail.Title,
Comment: errExt.ErrMsg(),
}
dataFailed.AppendData2(outPutData)
}
} else {
outPutData := DataSuccess{
NameID: goodsDetail.SkuMap.SingleSku.OuterSkuCode,
Name: goodsDetail.Title,
Unit: unit,
OrgPrice: goodsDetail.SkuMap.SingleSku.SalePrice,
NowPrice: salePrice,
MixPrice: Float64Round(salePrice - goodsDetail.SkuMap.SingleSku.SalePrice),
}
dataSuccess.AppendData(outPutData)
}
}
return goodsID, skuMap, err
}
func GetWeiMobGoodsList(param *weimobapi.QueryGoodsListParam) (goodsList []*weimobapi.GoodsInfo, err error) {
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(sheetParam *SheetParam, skuMap map[string]*ExcelParam, row []string, sheetName string, rowNum int) {
var (
skuID string
orgSkuID string
skuPrice float64
orgSkuPrice float64
skuName string
orgSkuName string
skuIDCol = sheetParam.SkuIDCol
skuPriceCol = sheetParam.SkuPriceCol
skuNameCol = sheetParam.SkuNameCol
orgSkuIDCol = sheetParam.OrgSkuIdCol
orgSkuPriceCol = sheetParam.OrgSkuPriceCol
orgSkuNameCol = sheetParam.OrgSkuNameCol
)
for k, cell := range row {
if cell != "" {
if !IsChineseChar(cell) {
if k == skuIDCol && skuIDCol >= 0 {
skuID = cell
}
if k == skuPriceCol && skuPriceCol >= 0 {
skuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
if k == orgSkuIDCol && orgSkuIDCol >= 0 {
orgSkuID = "0" + cell
}
if k == orgSkuPriceCol && orgSkuPriceCol >= 0 {
orgSkuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
}
if k == skuNameCol && skuNameCol >= 0 {
skuName = cell
}
if k == orgSkuNameCol && orgSkuNameCol >= 0 {
orgSkuName = cell
}
}
}
if len(skuMap) > 0 {
if skuMap[skuID] != nil {
if skuMap[skuID].Price != 0 && skuMap[skuID].Price != skuPrice && skuPrice != 0 {
if skuPrice > skuMap[skuID].Price {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
} else {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
} else if skuPrice != 0 {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
}
if skuMap[orgSkuID] != nil {
if skuMap[orgSkuID].Price != 0 && skuMap[orgSkuID].Price != orgSkuPrice && orgSkuPrice != 0 {
if orgSkuPrice > skuMap[orgSkuID].Price {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
} else if orgSkuPriceCol >= 0 && orgSkuIDCol >= 0 && orgSkuNameCol >= 0 {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
} else if orgSkuPrice != 0 {
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
} else {
BuildSkuMap(skuID, skuName, skuPrice, skuMap)
BuildSkuMap(orgSkuID, orgSkuName, orgSkuPrice, skuMap)
}
delete(skuMap, "")
}
func BuildSkuMap(id, name string, price float64, skuMap map[string]*ExcelParam) {
excelParam := &ExcelParam{
SpuCode: id,
Price: price,
Name: name,
}
skuMap[id] = excelParam
}
func Float64Round(f float64) (flt float64) {
return math.Round(f*100) / 100
}
func Map2Int64Slice(m map[int64]int64) (result []int64) {
for _, v := range m {
result = append(result, v)
}
return result
}
func UpdateClassifyAndGetLastClassify() (isCompare bool, err error) {
var lastTitle string
classfiyList, err := api.WeimobAPI.QueryClassifyInfoList()
if len(classfiyList) > 0 {
for _, v := range classfiyList {
if v.ClassifyID == 1065244148 {
lastTitle = v.Title
}
}
}
title := "可定"
now := time.Now()
afterDay := now.AddDate(0, 0, 2).Day()
title += utils.Int2Str(afterDay) + "日"
if lastTitle == title {
return true, err
} else {
err = api.WeimobAPI.UpdateClassify(1065244148, title, "")
return false, err
}
}
func GetNewSkuTitle(priceMixRound float64, orgTitle, outerGoodsCode string) (name string) {
var prefix = ""
title1 := strings.ReplaceAll(orgTitle, "", "(")
title := strings.ReplaceAll(title1, "", ")")
if outerGoodsCode[0:1] != "0" {
prefix += "(精"
if priceMixRound > 0 {
prefix += "↑"
} else if priceMixRound < 0 {
prefix += "↓"
} else {
prefix += ")"
return GetReplaceNewTitle(title, prefix)
}
} else {
if priceMixRound > 0 {
prefix += "(↑"
} else if priceMixRound < 0 {
prefix += "(↓"
} else {
return GetReplaceNewTitle(title, prefix)
}
}
prefix += utils.Float64ToStr(math.Abs(priceMixRound)) + ")"
return GetReplaceNewTitle(title, prefix)
}
func GetReplaceNewTitle(title, prefix string) (newTitle string) {
if title[0:1] == "(" {
return strings.Replace(title, title[0:strings.Index(title, ")")+1], prefix, 1)
} else {
return prefix + title
}
}
func WriteToExcel(task *tasksch.SeqTask, dataSuccess []DataSuccess, dataFailed []DataFailed) (err error) {
var sheetList1 []*excel.Obj2ExcelSheetConfig
var sheetList2 []*excel.Obj2ExcelSheetConfig
var downloadURL1, downloadURL2, fileName1, fileName2 string
excelConf1 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: dataSuccess,
CaptionList: titleListSuccess,
}
sheetList1 = append(sheetList1, excelConf1)
excelConf2 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: dataFailed,
CaptionList: titleListFailed,
}
sheetList2 = append(sheetList2, excelConf2)
if excelConf1 != nil {
downloadURL1, fileName1, err = UploadExeclAndPushMsg(sheetList1, "已更新商品")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!")
}
if excelConf2 != nil {
downloadURL2, fileName2, err = UploadExeclAndPushMsg(sheetList2, "缺少商品_微盟")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataFailed is nil!")
}
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName1, fileName2, err)
} else {
noticeMsg := fmt.Sprintf("[详情点我]path1=%s, path2=%s \n", globals.BackstageHost, downloadURL1, downloadURL2)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
return err
}
func UploadExeclAndPushMsg(sheetList []*excel.Obj2ExcelSheetConfig, name string) (downloadURL, fileName string, err error) {
excelBin := excel.Obj2Excel(sheetList)
timeStr := utils.Int64ToStr(time.Now().Unix())
fileName = name + timeStr + fileExt
baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", fileName)
downloadURL, err = jxutils.UploadExportContent(excelBin, fileName)
return downloadURL, fileName, err
}
func UpdateJxPriceByWeimob(ctx *jxcontext.Context, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
storeSkuBindInfoList []interface{}
skuBindInfos []*cms.StoreSkuBindInfo
)
//获取微盟所有上架商品
queryParameter := &weimobapi.QueryGoodsListRequestVo{
GoodsStatus: weimobapi.GoodsTypeNormal,
}
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
QueryParameter: queryParameter,
}
goodsList, err := GetWeiMobGoodsList(param)
if err != nil {
baseapi.SugarLogger.Errorf("GetWeiMobGoodsList error:%v", err)
}
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].(*weimobapi.GoodsInfo)
goodsDetail, err := api.WeimobAPI.QueryGoodsDetail(v.GoodsID)
if err != nil {
baseapi.SugarLogger.Errorf("QueryGoodsDetail error:%v", err)
}
if goodsDetail.OuterGoodsCode != "" && goodsDetail.IsPutAway == weimobapi.GoodsTypeNormal {
nameID := int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))
unitPrice := int(utils.Float64TwoInt64(goodsDetail.SkuMap.SingleSku.CostPrice * 100))
storeSkuBindInfo := &cms.StoreSkuBindInfo{
NameID: nameID,
UnitPrice: unitPrice,
}
retVal = []*cms.StoreSkuBindInfo{storeSkuBindInfo}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("获取微盟商品", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc, goodsList)
tasksch.HandleTask(taskParallel, task, true).Run()
storeSkuBindInfoList, err = taskParallel.GetResult(0)
case 1:
for _, v := range storeSkuBindInfoList {
skuBindInfos = append(skuBindInfos, v.(*cms.StoreSkuBindInfo))
}
cms.UpdateStoresSkus(ctx, storeIDs, skuBindInfos, isAsync, isContinueWhenError)
}
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 GetWeimobOrders(ctx *jxcontext.Context, fromTime, toTime string, params map[string]interface{}) (result []*OrderList, err error) {
if fromTime != "" && toTime != "" {
fromTimeParam := utils.Str2Time(fromTime).UnixNano() / 1e6
toTimeParam := utils.Str2Time(toTime).UnixNano() / 1e6
if params["keyword"] != nil {
if jxutils.GetPossibleVendorIDFromVendorOrderID(params["keyword"].(string)) > model.VendorIDUnknown {
resultList, err := GetSingleOrderResultList(params)
result = append(result, resultList...)
return result, err
} else {
orderList, err := GetWeimobOrdersList(fromTimeParam, toTimeParam, params["keyword"].(string))
return orderList, err
}
} else {
orderList, err := GetWeimobOrdersList(fromTimeParam, toTimeParam, "")
return orderList, err
}
}
if fromTime == "" && toTime == "" && params["keyword"] != nil {
if jxutils.GetPossibleVendorIDFromVendorOrderID(params["keyword"].(string)) > model.VendorIDUnknown {
resultList, err := GetSingleOrderResultList(params)
result = append(result, resultList...)
return result, err
} else {
orderList, err := GetWeimobOrdersList(0, 0, params["keyword"].(string))
return orderList, err
}
}
return result, err
}
func GetWeimobOrdersList(fromTimeParam, toTimeParam int64, keyword string) (aList []*OrderList, err error) {
var queryParameter *weimobapi.MerchantOrderListQueryParameter
if fromTimeParam == 0 && toTimeParam == 0 {
queryParameter = &weimobapi.MerchantOrderListQueryParameter{
CreateStartTime: time.Now().AddDate(0, -2, 0).UnixNano() / 1e6,
CreateEndTime: time.Now().UnixNano() / 1e6,
}
} else {
queryParameter = &weimobapi.MerchantOrderListQueryParameter{
CreateStartTime: fromTimeParam,
CreateEndTime: toTimeParam,
}
}
param := &weimobapi.QueryOrdersListParam{
PageNum: 1,
PageSize: weimobapi.QueryOrdersListPageSize,
QueryParameter: queryParameter,
}
for {
orderList, _, err2 := api.WeimobAPI.QueryOrdersList(param)
err = err2
if len(orderList) > 0 {
if keyword != "" {
for _, v := range orderList {
if ContainsKeyword(v, keyword) {
var aOrder = &OrderList{
Name: v.ReceiverName,
OrderNo: v.OrderNo,
Phone: v.ReceiverMobile,
}
aList = append(aList, aOrder)
}
}
} else {
for _, v := range orderList {
var aOrder = &OrderList{
Name: v.ReceiverName,
OrderNo: v.OrderNo,
Phone: v.ReceiverMobile,
}
aList = append(aList, aOrder)
}
}
}
if len(orderList) < param.PageSize {
break
}
param.PageNum++
}
return aList, err
}
func GetWeimobOrderDetail(orderNo int64) (order *weimobapi.OrderDetail, err error) {
order, err = api.WeimobAPI.QueryOrderDetail2(orderNo, false)
if err != nil {
return nil, err
}
return order, err
}
func GetSingleOrderResultList(params map[string]interface{}) (result []*OrderList, err error) {
weimobOrderID := params["keyword"].(string)
orderSingle, err := GetWeimobOrderDetail(utils.Str2Int64(weimobOrderID))
orderList := &OrderList{
Name: orderSingle.DeliveryDetail.LogisticsDeliveryDetail.ReceiverName,
Phone: orderSingle.DeliveryDetail.LogisticsDeliveryDetail.ReceiverMobile,
OrderNo: orderSingle.OrderNo,
}
result = append(result, orderList)
return result, err
}
func ContainsKeyword(v *weimobapi.OrderInfo, keyword string) bool {
return strings.Contains(v.ReceiverName, keyword) || strings.Contains(utils.Int64ToStr(v.OrderNo), keyword) || strings.Contains(v.ReceiverMobile, keyword)
}
func GetWeimobOrdersExcel(ctx *jxcontext.Context, OrderNo string) (result []string, err error) {
var (
DataFineList []*Data //精品
DataHairyList []*Data //毛菜
)
orderSingle, err := GetWeimobOrderDetail(utils.Str2Int64(OrderNo))
if err != nil {
return result, err
}
if len(orderSingle.ItemList) > 0 {
itemList := orderSingle.ItemList
for _, v := range itemList {
if v.GoodsCode != "" {
if v.GoodsCode[0:1] == "0" {
DataHairy := &Data{
GoodsID: v.GoodsCode,
GoodsName: v.GoodsTitle,
GoodsNum: v.SkuNum,
}
DataHairyList = append(DataHairyList, DataHairy)
} else {
DataFine := &Data{
GoodsID: v.GoodsCode,
GoodsName: v.GoodsTitle,
GoodsNum: v.SkuNum,
}
DataFineList = append(DataFineList, DataFine)
}
} else {
return result, errors.New(fmt.Sprintf("此订单中该商品无spu编码请检查订单号[%v] ,商品名: [%v]", OrderNo, v.GoodsTitle))
}
}
} else {
return result, errors.New(fmt.Sprintf("此订单中无商品信息,请检查!订单号:[%v]", OrderNo))
}
downloadURL1, downloadURL2, err := WriteToExcel2(ctx, DataFineList, DataHairyList)
if downloadURL1 != "" {
result = append(result, downloadURL1)
}
if downloadURL2 != "" {
result = append(result, downloadURL2)
}
return result, err
}
func WriteToExcel2(ctx *jxcontext.Context, DataFineList, DataHairyList []*Data) (downloadURL1, downloadURL2 string, err error) {
var (
sheetList1 []*excel.Obj2ExcelSheetConfig
sheetList2 []*excel.Obj2ExcelSheetConfig
fileName1, fileName2 string
noticeMsg string
)
excelConf1 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: DataFineList,
CaptionList: titleList,
}
sheetList1 = append(sheetList1, excelConf1)
excelConf2 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: DataHairyList,
CaptionList: titleList,
}
sheetList2 = append(sheetList2, excelConf2)
noticeMsg += "[详情点我]"
if len(DataFineList) > 0 {
downloadURL1, fileName1, err = UploadExeclAndPushMsg(sheetList1, "京西采购_精品")
noticeMsg += "path1=" + downloadURL1 + " "
} else {
baseapi.SugarLogger.Debug("WriteToExcel: DataFineList is nil!")
}
if len(DataHairyList) > 0 {
downloadURL2, fileName2, err = UploadExeclAndPushMsg(sheetList2, "京西采购_毛菜")
noticeMsg += "path2=" + downloadURL2
} else {
baseapi.SugarLogger.Debug("WriteToExcel: DataHairyList is nil!")
}
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName1, fileName2, err)
} else {
if authInfo, err := ctx.GetV2AuthInfo(); err == nil {
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, authInfo.UserID, "导出微盟订单商品成功", noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
}
return downloadURL1, downloadURL2, err
}