@@ -6,16 +6,25 @@ import (
"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"
@@ -26,64 +35,156 @@ import (
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 ( "没有文件上传!" )
@@ -99,11 +200,12 @@ func LoadExcelByYongHui(ctx *jxcontext.Context, files []*multipart.FileHeader, i
func LoadExcelBinByYongHui ( ctx * jxcontext . Context , reader io . Reader , isAsync , isContinueWhenError bool ) ( hint string , err error ) {
var (
skuMap = make ( map [ string ] float64 )
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 ) {
@@ -121,7 +223,7 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
if rowNum < sheetParam . SkuRow {
continue
}
GetCellIntoMap ( sheetParam . SkuIDCol , sheetParam . SkuPriceCol , sheetParam . OrgSkuIdCol , sheetParam . OrgSkuPriceCol , skuMap , row , k , rowNum )
GetCellIntoMap ( sheetParam , skuMap , row , k , rowNum )
if len ( skuMap ) < 1 {
errMsg += fmt . Sprintf ( "读取Excel数据失败, Excel格式排版可能发生了变化! sheetName: [%v]\n" , k )
}
@@ -133,10 +235,14 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
//修改分组名
// 分类名格式为: 可定XX日
// XX为上传永辉 提供的 价格表时间 +2天
isCompare , err = UpdateClassifyAndGetLastClassify ( )
case 1 :
//获取微盟所有商品
goodsList , err = GetW eiM obGoodsList( )
param : = & w eim obapi . Query GoodsListParam {
PageNum : 1 ,
PageSize : jdapi . MaxSkuIDsCount4QueryListBySkuIds ,
}
goodsList , err = GetWeiMobGoodsList ( param )
if err != nil {
baseapi . SugarLogger . Errorf ( "GetWeiMobGoodsList error:%v" , err )
}
@@ -157,12 +263,15 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
for k , _ := range skuMap {
//表示excel上有, 微盟上没有
if goodsInfoAndDetailMap [ k ] == nil {
errMsg + = fmt . Sprintf ( "在微盟上未找到该商品! excel商品ID : [%v]\n" , k )
outPutData : = DataFailed {
GoodsID : k ,
GoodsName : skuMap [ k ] . Name ,
Comment : "在微盟上未找到该商品" ,
}
dataFailed . AppendData2 ( outPutData )
// errMsg += fmt.Sprintf("在微盟上未找到该商品xxx", xxx)
}
}
// if errMsg != "" {
// return "", errors.New(errMsg)
// }
case 2 :
//找出微盟上有, excel上没有的, 有就更新, 没有就下架
taskFunc3 := func ( task * tasksch . ParallelTask , batchItemList [ ] interface { } , params ... interface { } ) ( retVal interface { } , err error ) {
@@ -171,24 +280,28 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
spuCode := goodsDetail . OuterGoodsCode
if spuCode != "" {
//如果微盟商品里找得到excel中的商品
if skuMap [ spuCode ] != 0 {
if skuMap [ spuCode ] != nil {
//获取京西库商品
skuList , _ := dao . GetSkus ( db , nil , [ ] int { int ( utils . Str2Int64 ( goodsDetail . SkuMap . SingleSku . OuterSkuCode ) ) } , nil , nil )
if len ( skuList ) == 0 {
return "" , errors . New ( fmt . Sprintf ( "在京西库中未找到该商品! name_id : [%v]\n" , goodsDetail . SkuMap . SingleSku . OuterSkuCode ) )
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 ]
costPrice = skuMap [ spuCode ] . Price
} else {
costPrice = Float64Round ( 0.5 / goodsDetail . SkuMap . SingleSku . B2CSku . Weight * skuMap [ spuCode ] )
costPrice = Float64Round ( 0.5 / goodsDetail . SkuMap . SingleSku . B2CSku . Weight * skuMap [ spuCode ] . Price )
}
} else {
costPrice = skuMap [ spuCode ]
costPrice = skuMap [ spuCode ] . Price
}
// if errMsg == "" {
_ , _ , err = updateWeiMobGoods ( costPrice , skuMap [ spuCode ] , goodsDetail )
// }
_ , _ , _ = updateWeiMobGoods ( costPrice , skuMap [ spuCode ] . Price , skuList [ 0 ] . Unit , isCompare , goodsDetail )
}
} else {
//下架微盟商品
@@ -197,7 +310,7 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
}
return retVal , err
}
taskParallel3 := tasksch . NewParallelTask ( "根据获取的微盟所有商品并更新" , tasksch . NewParallelConfig ( ) . SetParallelCount ( parallelCount ) . SetIsContinueWhenError ( isContinueWhenError ) , ctx , taskFunc3 , goodsList )
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 {
@@ -206,7 +319,6 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
goodsIDListForPutAway = goodsIDListForPutAwayInterface
case 3 :
// 批量下架微盟商品
// if errMsg == "" {
taskFunc4 := func ( task * tasksch . ParallelTask , batchItemList [ ] interface { } , params ... interface { } ) ( retVal interface { } , err error ) {
int64Slice := [ ] int64 { }
for _ , v := range batchItemList {
@@ -218,14 +330,15 @@ func LoadExcelBinByYongHui(ctx *jxcontext.Context, reader io.Reader, isAsync, is
taskParallel4 := tasksch . NewParallelTask ( "下架微盟商品" , tasksch . NewParallelConfig ( ) . SetParallelCount ( parallelCount ) . SetBatchSize ( UpdateGoodsShelfStatusCount ) , ctx , taskFunc4 , goodsIDListForPutAway )
tasksch . HandleTask ( taskParallel4 , task , true ) . Run ( )
_ , err = taskParallel4 . GetResult ( 0 )
// }
}
if errMsg != "" {
return result , errors . New ( errMsg )
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 , 4 )
taskSeq := tasksch . NewSeqTask2 ( "读取永辉Excel文件修改微盟商品价格可售状态-序列任务" , ctx , isContinueWhenError , taskSeqFunc , 5 )
tasksch . HandleTask ( taskSeq , nil , true ) . Run ( )
if ! isAsync {
_ , err = taskSeq . GetResult ( 0 )
@@ -265,13 +378,14 @@ func GetGoodsInfoAndDetailMap(goodsList []*weimobapi.GoodsInfo) (goodsMap map[st
// return list
// }
func updateWeiMobGoods ( costPrice , salePrice float64 , goodsDetail * weimobapi . GoodsDetailInfo ) ( goodsID int64 , skuMap map [ string ] int64 , err error ) {
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
)
//查询配送方式
@@ -298,16 +412,51 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
return 0 , nil , errors . New ( fmt . Sprintf ( "未查询到此商品的分类信息! goodsID : [%v] ," , goodsDetail . GoodsID ) )
}
//获取分组
//商品分组( 原有的分组IDs)
selectedClassifyList := goodsDetail . SelectedClassifyList
var selectedClassifyListID [ ] int64
selectedClassifyListIDMap := make ( map [ int64 ] int64 )
if len ( selectedClassifyList ) > 0 {
for _ , v := range selectedClassifyList {
for _ , vv := range v . ChildrenClassify {
selectedClassifyListID = append ( selectedClassifyListID , vv . ClassifyID )
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 ,
@@ -329,7 +478,7 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
goods := & weimobapi . Goods {
B2CGoods : b2CGoods ,
SkuList : skuListParam ,
Title : goodsDetail . Title,
Title : newSku Title,
IsMultiSku : goodsDetail . IsMultiSku ,
IsPutAway : weimobapi . GoodsTypeNormal ,
GoodsImageURL : goodsDetail . GoodsImageURL ,
@@ -337,22 +486,38 @@ func updateWeiMobGoods(costPrice, salePrice float64, goodsDetail *weimobapi.Good
CategoryID : categoryID ,
OuterGoodsCode : goodsDetail . OuterGoodsCode ,
PointDeductRatio : goodsDetail . PointDeductRatio ,
SelectedClassifyIDList : selectedClassifyListID ,
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 ( ) ( goodsList [ ] * weimobapi . GoodsInfo , err error ) {
param := & weimobapi . QueryGoodsListParam {
PageNum : 1 ,
PageSize : jdapi . MaxSkuIDsCount4QueryListBySkuIds ,
}
func GetWeiMobGoodsList ( param * weimobapi . QueryGoodsListParam ) ( goodsList [ ] * weimobapi . GoodsInfo , err error ) {
for {
goodsInfoList , _ , err := api . WeimobAPI . QueryGoodsList ( param )
if err != nil {
@@ -378,52 +543,427 @@ func IsChineseChar(str string) bool {
return false
}
func GetCellIntoMap ( skuIDCol , skuPriceCol , orgSkuIDCol , orgSkuPriceCol int , skuMap map [ string ] float64 , row [ ] string , sheetName string , rowNum int ) {
func GetCellIntoMap ( sheetParam * SheetParam , skuMap map [ string ] * ExcelParam , row [ ] string , sheetName string , rowNum int ) {
var (
skuID string
orgSkuID string
skuPrice float64
orgSkuPrice float64
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 ! IsChineseChar ( cell ) && cell != "" {
if k == skuIDCol && skuIDCol >= 0 {
skuID = cell
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 == skuPric eCol && skuPric eCol >= 0 {
skuPric e = Float64Round ( utils . Str2Float64WithDefault ( cell , 0 ) )
if k == skuNam eCol && skuNam eCol >= 0 {
skuNam e = cell
}
if k == orgSkuID Col && orgSkuID Col >= 0 {
orgSkuID = "0" + cell
}
if k == orgSkuPriceCol && orgSkuPriceCol >= 0 {
orgSkuPrice = Float64Round ( utils . Str2Float64WithDefault ( cell , 0 ) )
if k == orgSkuName Col && orgSkuName Col >= 0 {
orgSkuName = cell
}
}
}
if skuMap [ skuID ] != 0 && skuMap [ skuID ] != skuPrice {
if skuPrice > skuMap[ skuID ] {
skuMap [ skuID ] = skuPrice
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 )
}
// fmt.Sprintf("读取excel表格出错! 有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v] , 商品编码 : [%v] , 价格:[%v]\n", sheetName, rowNum, skuID, skuPrice)
} else {
s kuMap[ skuID ] = skuPrice
}
if skuMap [ orgSkuID ] != 0 && skuMap [ orgSkuID ] != orgSkuPrice {
if orgSkuPrice > skuMap [ orgSkuID ] {
skuMap [ orgSkuID ] = orgSkuPrice
}
// fmt.Sprintf("读取excel表格出错! 有商品ID重复且价格不同,sheetName : [%v] ,行数 : [%v], 商品编码 : [%v] , 价格:[%v]\n", sheetName, rowNum, orgSkuID, orgSkuPrice)
} else if orgSkuPriceCol >= 0 && orgSkuIDCol >= 0 {
skuMap [ orgSkuID ] = orgSkuPrice
BuildS kuMap( 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 UpdateClassifyName ( ) {
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 ) {
return api . WeimobAPI . QueryOrderDetail2 ( orderNo , false )
}
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 ) ( err error ) {
var (
DataFineList [ ] * Data //精品
DataHairyList [ ] * Data //毛菜
)
orderSingle , err := GetWeimobOrderDetail ( utils . Str2Int64 ( OrderNo ) )
itemList := orderSingle . ItemList
for _ , v := range itemList {
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 )
}
}
WriteToExcel2 ( ctx , DataFineList , DataHairyList )
return err
}
func WriteToExcel2 ( ctx * jxcontext . Context , DataFineList , DataHairyList [ ] * Data ) ( err error ) {
var (
sheetList1 [ ] * excel . Obj2ExcelSheetConfig
sheetList2 [ ] * excel . Obj2ExcelSheetConfig
downloadURL1 , downloadURL2 string
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 err
}