Files
jx-callback/business/jxstore/yonghui/yonghui.go
2020-06-05 10:29:07 +08:00

1105 lines
35 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"
"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 DataStoreSkusSuccessLock struct {
dataStoreSkusSuccessList []DataStoreSkusSuccess
locker sync.RWMutex
}
type DataSuccessLock struct {
dataSuccessList []DataSuccess
locker sync.RWMutex
}
type DataFailedLock struct {
dataFailedList []DataFailed
locker sync.RWMutex
}
type DataStoreSkusSuccess struct {
StoreID int `json:"门店ID"`
NameID int `json:"商品编码"`
Name string `json:"商品名称"`
Unit string `json:"单位"`
OrgPrice float64 `json:"原价"`
NowPrice float64 `json:"现价"`
MixPrice float64 `json:"涨跌"`
}
type DataSuccess struct {
NameID string `json:"商品编码"`
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"`
}
type WeimobOrderSkusExcelResult struct {
DownloadUrlFine string `json:"downloadUrlFine,omitempty"`
DownloadUrlHairy string `json:"downloadUrlHairy,omitempty"`
}
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: 14,
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,
},
}
titleListStoreSkusSuccess = []string{
"门店ID",
"商品编码",
"商品名称",
"单位",
"原价",
"现价",
"涨跌",
}
titleListSuccess = []string{
"商品编码",
"商品名称",
"单位",
"原价",
"现价",
"涨跌",
}
titleListFailed = []string{
"商品ID",
"商品名称",
"备注",
}
titleList = []string{
"商品编码",
"商品名称",
"订货数量",
}
dataSuccess DataSuccessLock
dataFailed DataFailedLock
dataStoreSkusSuccess DataStoreSkusSuccessLock
)
const (
parallelCount = 5
UpdateGoodsShelfStatusCount = 50 //微盟下架商品api限制一次50个
)
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 (d *DataStoreSkusSuccessLock) AppendData3(dataStoreSkusSuccess DataStoreSkusSuccess) {
d.locker.Lock()
defer d.locker.Unlock()
d.dataStoreSkusSuccessList = append(d.dataStoreSkusSuccessList, dataStoreSkusSuccess)
}
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)
costPrice float64 //成本价
goodsList []*weimobapi.GoodsInfo
goodsIDListForPutAway []interface{}
isCompare bool
isExecute = false
)
db := dao.GetDB()
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
var errMsg string
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 {
errMsg += GetCellIntoMap(sheetParam, skuMap, row, k, rowNum)
}
}
//修改分组名
// 分类名格式为可定XX日
// XX为上传永辉 提供的 价格表时间 +2天
if errMsg == "" {
isExecute = true
} else {
return "", fmt.Errorf(errMsg)
}
if isExecute {
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)
}
}
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, nil)
if len(skuList) == 0 {
outPutData := DataFailed{
GoodsID: spuCode,
GoodsName: skuMap[spuCode].Name,
Comment: "在京西库中未找到该商品",
}
dataFailed.AppendData2(outPutData)
} 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
}
if isExecute {
_, _, _ = 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))
}
if isExecute {
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)
}
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 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.OuterGoodsCode,
Name: newSkuTitle,
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 GetCellIntoMap(sheetParam *SheetParam, skuMap map[string]*ExcelParam, row []string, sheetName string, rowNum int) (errMsg string) {
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 k == skuIDCol && skuIDCol >= 0 {
skuID = cell
}
if k == skuPriceCol && skuPriceCol >= 0 {
if rowNum == sheetParam.SkuRow-1 {
if !strings.Contains(cell, "今日供价") && !strings.Contains(cell, "单价") {
errMsg += fmt.Sprintf("sheet页[%v],Excel排版发生变化第[%v]列今日供价附近可能增加或减少了一列,请确认!", sheetName, k+1)
}
}
skuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
if k == orgSkuIDCol && orgSkuIDCol >= 0 {
orgSkuID = "0" + cell
}
if k == orgSkuPriceCol && orgSkuPriceCol >= 0 {
if rowNum == sheetParam.SkuRow-1 {
if !strings.Contains(cell, "进价") {
errMsg += fmt.Sprintf("sheet页[%v],Excel排版发生变化第[%v]列进价附近可能增加或减少了一列,请确认!", sheetName, k+1)
}
}
orgSkuPrice = Float64Round(utils.Str2Float64WithDefault(cell, 0))
}
if k == skuNameCol && skuNameCol >= 0 {
skuName = cell
}
if k == orgSkuNameCol && orgSkuNameCol >= 0 {
orgSkuName = cell
}
}
}
if rowNum >= sheetParam.SkuRow {
if rowNum == sheetParam.SkuRow {
if cms.IsChineseChar(skuID) {
errMsg += fmt.Sprintf("sheet页[%v],Excel排版发生变化第[%v]行附近可能增加了一行,请确认!", sheetName, rowNum)
}
}
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, "")
} else {
for i := rowNum; i < sheetParam.SkuRow; i++ {
if !cms.IsChineseChar(skuID) {
errMsg += fmt.Sprintf("sheet页[%v],Excel排版发生变化第[%v]行附近可能减少了一行,请确认!", sheetName, rowNum)
}
}
}
return errMsg
}
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 = jxutils.UploadExeclAndPushMsg(sheetList1, "微盟已更新商品")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!")
}
if excelConf2 != nil {
downloadURL2, fileName2, err = jxutils.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", downloadURL1, downloadURL2)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
return err
}
func UpdateJxPriceByWeimob(ctx *jxcontext.Context, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
storeSkuBindInfoList []interface{}
skuBindInfos []*cms.StoreSkuBindInfo
nameID int
)
db := dao.GetDB()
dataFailed.dataFailedList = dataFailed.dataFailedList[0:0]
dataStoreSkusSuccess.dataStoreSkusSuccessList = dataStoreSkusSuccess.dataStoreSkusSuccessList[0:0]
//获取微盟所有商品
param := &weimobapi.QueryGoodsListParam{
PageNum: 1,
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds,
}
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)
}
goodsID := goodsDetail.OuterGoodsCode
unitPrice := int(utils.Float64TwoInt64(goodsDetail.SkuMap.SingleSku.CostPrice * 100))
if goodsDetail.SkuMap.SingleSku.OuterSkuCode != "" {
nameID = int(utils.Str2Int64(goodsDetail.SkuMap.SingleSku.OuterSkuCode))
} else {
outPutData := DataFailed{
GoodsID: goodsID,
GoodsName: goodsDetail.Title,
Comment: "微盟上没有该商品的商品编码",
}
dataFailed.AppendData2(outPutData)
nameID = -1
}
skuList, err := dao.GetStoreSkusByNameIDs(db, storeIDs, nameID)
if len(skuList) > 0 {
if goodsDetail.OuterGoodsCode != "" {
if goodsDetail.IsPutAway == weimobapi.GoodsTypeNormal {
storeSkuBindInfo := &cms.StoreSkuBindInfo{
NameID: nameID,
UnitPrice: unitPrice,
}
retVal = []*cms.StoreSkuBindInfo{storeSkuBindInfo}
for _, v := range skuList {
outPutData := DataStoreSkusSuccess{
StoreID: v.StoreID,
NameID: nameID,
Name: v.Name,
Unit: v.Unit,
OrgPrice: utils.Str2Float64(utils.Int64ToStr(v.UnitPrice)) / 100,
NowPrice: goodsDetail.SkuMap.SingleSku.CostPrice,
MixPrice: Float64Round((utils.Str2Float64(utils.Int64ToStr(v.UnitPrice)) / 100) - goodsDetail.SkuMap.SingleSku.CostPrice),
}
dataStoreSkusSuccess.AppendData3(outPutData)
}
} else { //如果微盟为下架
outPutData := DataFailed{
GoodsID: goodsID,
GoodsName: goodsDetail.Title,
Comment: "微盟已下架",
}
dataFailed.AppendData2(outPutData)
}
} else {
outPutData := DataFailed{
GoodsID: goodsID,
GoodsName: goodsDetail.Title,
Comment: "微盟上没有该商品的spu编码",
}
dataFailed.AppendData2(outPutData)
}
} else {
outPutData := DataFailed{
GoodsID: goodsID,
GoodsName: goodsDetail.Title,
Comment: "京西未关注该商品",
}
dataFailed.AppendData2(outPutData)
}
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, 0, storeIDs, skuBindInfos, false, false, isAsync, isContinueWhenError)
case 2:
WriteToExcel3(task, dataStoreSkusSuccess.dataStoreSkusSuccessList, dataFailed.dataFailedList)
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("根据微盟商品更新京西价", ctx, isContinueWhenError, taskSeqFunc, 3)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}
func WriteToExcel3(task *tasksch.SeqTask, dataSuccess []DataStoreSkusSuccess, 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: titleListStoreSkusSuccess,
}
sheetList1 = append(sheetList1, excelConf1)
excelConf2 := &excel.Obj2ExcelSheetConfig{
Title: "sheet1",
Data: dataFailed,
CaptionList: titleListFailed,
}
sheetList2 = append(sheetList2, excelConf2)
if excelConf1 != nil {
downloadURL1, fileName1, err = jxutils.UploadExeclAndPushMsg(sheetList1, "京西已更新商品")
} else {
baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!")
}
if excelConf2 != nil {
downloadURL2, fileName2, err = jxutils.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", downloadURL1, downloadURL2)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s ,%s success, downloadURL1:%s ,downloadURL2:%s", fileName1, fileName2, downloadURL1, downloadURL2)
}
return 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 *WeimobOrderSkusExcelResult, 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 != "" {
var goodsTile string
if v.GoodsTitle[0:1] == "(" {
goodsTile = v.GoodsTitle[strings.Index(v.GoodsTitle, ")")+1 : len(v.GoodsTitle)]
} else {
goodsTile = v.GoodsTitle
}
if v.GoodsCode[0:1] == "0" {
DataHairy := &Data{
GoodsID: v.GoodsCode[1:len(v.GoodsCode)],
GoodsName: goodsTile,
GoodsNum: v.SkuNum,
}
DataHairyList = append(DataHairyList, DataHairy)
} else {
DataFine := &Data{
GoodsID: v.GoodsCode,
GoodsName: goodsTile,
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)
result = &WeimobOrderSkusExcelResult{
DownloadUrlFine: downloadURL1,
DownloadUrlHairy: 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 = jxutils.UploadExeclAndPushMsg(sheetList1, "京西采购_精品")
noticeMsg += "path1=" + downloadURL1 + " "
} else {
baseapi.SugarLogger.Debug("WriteToExcel: DataFineList is nil!")
}
if len(DataHairyList) > 0 {
downloadURL2, fileName2, err = jxutils.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
}