Files
jx-callback/business/jxstore/cms/store_sku_check.go
2020-03-10 13:53:11 +08:00

734 lines
27 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 cms
import (
"fmt"
"strings"
"sync"
"time"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"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/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api/apimanager"
)
const (
canWriteTolocal = false
needStatistic = true
isFilterToBeCreateAndNotSale = true
parallelCount = 5
fileExt = ".xlsx"
)
//错误类型
const (
DatAanalyse1 = "京西门店未关注,应删除对应的平台门店商品"
DatAanalyse2 = "平台商品库未创建成功(可能无经营许可等) "
DatAanalyse3 = "商品名不同 "
DatAanalyse4 = "商品可售状态不同 "
DatAanalyse5 = "京西商品库没有,平台商品库有 "
DatAanalyse6 = "京西商品库有,平台商品库没有"
DatAanalyse7 = "同步状态异常"
DatAanalyse8 = "平台门店未关注或平台门店商品库存为0应添加对应的平台门店商品"
)
var (
diffFileName = map[bool]string{
true: "export/JXCSAndVendorSkuDiff",
false: "export/JXGYAndVendorSkuDiff",
}
vendorNameList = map[int]string{
model.VendorIDMTWM: model.VendorChineseNames[model.VendorIDMTWM],
model.VendorIDEBAI: model.VendorChineseNames[model.VendorIDEBAI],
model.VendorIDJD: model.VendorChineseNames[model.VendorIDJD],
}
titleList = []string{
"京西门店ID",
"平台门店ID",
"门店名",
"SkuID",
"同步状态",
"待创建",
"待删除",
"京西商品名",
"平台商品名",
"京西可售状态",
"平台可售状态",
"数据分析",
}
deoptTitleList = []string{
"SkuID",
"京西商品名",
"平台商品名",
"京西可售状态",
"平台可售状态",
"数据分析",
}
statisticTitleList = []string{
"京西和平台商品状态",
"待创建",
"京西可售状态",
"数量",
"占比",
}
statisticDataList = [][]string{
{"京西有,平台无", "是", "下架"},
{"京西有,平台无", "是", "上架"},
{"京西有,平台无", "否", "下架"},
{"京西有,平台无", "否", "上架"},
{"京西无,平台有", "N/A", "N/A"},
{"京西有,平台有", "是", "下架"},
{"京西有,平台有", "是", "上架"},
{"京西有,平台有", "否", "下架"},
{"京西有,平台有", "否", "上架"},
}
diffData DiffDataLock
depotDiffData DeoptDiffDataLock
multiStoreAllSkuInfoMap map[int]map[string]map[int]*partner.SkuNameInfo
multiStoreAllSkuInfoList map[int]map[string][]*partner.StoreSkuInfo
skuNameInfoList []*partner.SkuNameInfo
filterVendorDepotUnSaleSkuIds []int
filterJxDepotUnSaleSkuIds []int
)
type DiffDataLock struct {
diffDataMap map[int][]DiffData
locker sync.RWMutex
}
type DeoptDiffDataLock struct {
diffDataMap map[int][]DepotDiffData
locker sync.RWMutex
}
type DepotDiffData struct {
SkuID string `json:"SkuID"`
JxSkuName string `json:"京西商品名"`
VendorSkuName string `json:"平台商品名"`
JxStatus string `json:"京西可售状态"`
VendorStatus string `json:"平台可售状态"`
DatAanalyse string `json:"数据分析"`
}
type DiffData struct {
JxStoreID string `json:"京西门店ID"`
VendorStoreID string `json:"平台门店ID"`
VendorStoreName string `json:"门店名"`
SkuID string `json:"SkuID"`
SyncStatus string `json:"同步状态"`
ToBeCreate string `json:"待创建"`
ToBeDel string `json:"待删除"`
JxSkuName string `json:"京西商品名"`
VendorSkuName string `json:"平台商品名"`
JxStatus string `json:"京西可售状态"`
VendorStatus string `json:"平台可售状态"`
DatAanalyse string `json:"数据分析"`
}
type StatisticData struct {
JxVendorStatus string `json:"京西和平台商品状态"`
ToBeCreate string `json:"待创建"`
JxSaleStatus string `json:"京西可售状态"`
Count string `json:"数量"`
Percent string `json:"占比"`
}
func (d *DeoptDiffDataLock) AppendData2(vendorID int, depotDiffData DepotDiffData) {
d.locker.Lock()
defer d.locker.Unlock()
d.diffDataMap[vendorID] = append(d.diffDataMap[vendorID], depotDiffData)
}
func (d *DeoptDiffDataLock) InitData2() {
d.diffDataMap = make(map[int][]DepotDiffData)
}
func (d *DiffDataLock) AppendData(vendorID int, diffData DiffData) {
d.locker.Lock()
defer d.locker.Unlock()
d.diffDataMap[vendorID] = append(d.diffDataMap[vendorID], diffData)
}
func (d *DiffDataLock) InitData() {
d.diffDataMap = make(map[int][]DiffData)
}
func InitMultiStoreData() {
multiStoreAllSkuInfoMap = make(map[int]map[string]map[int]*partner.SkuNameInfo)
multiStoreAllSkuInfoList = make(map[int]map[string][]*partner.StoreSkuInfo)
}
func GetMultiStoreAllSkuInfoMap(vendorID int, vendorOrgCode string) (retVal map[int]*partner.SkuNameInfo) {
if multiStoreAllSkuInfoMap[vendorID] != nil {
retVal = multiStoreAllSkuInfoMap[vendorID][vendorOrgCode]
}
return retVal
}
func GetMultiStoreAllSkuInfoList(vendorID int, vendorOrgCode string) (retVal []*partner.StoreSkuInfo) {
if multiStoreAllSkuInfoList[vendorID] != nil {
retVal = multiStoreAllSkuInfoList[vendorID][vendorOrgCode]
}
return retVal
}
//过滤掉平台下架的
func StoreSkuFullList2BareFilter(storeSkuFull []*partner.SkuNameInfo) (bareStoreSkuList []*partner.StoreSkuInfo) {
for _, v := range storeSkuFull {
for _, v2 := range v.SkuList {
if v2.Status > model.SkuStatusDontSale {
bareStoreSkuList = append(bareStoreSkuList, &v2.StoreSkuInfo)
}
}
}
return bareStoreSkuList
}
func GetMultiStoreAllSkuInfo(ctx *jxcontext.Context, vendorMap map[int]bool) {
InitMultiStoreData()
filterVendorDepotUnSaleSkuIds = filterVendorDepotUnSaleSkuIds[0:0]
for vendorID, _ := range vendorNameList {
//filter for vendorID
if len(vendorMap) > 0 {
if _, ok := vendorMap[vendorID]; !ok {
continue
}
}
if partner.IsMultiStore(vendorID) {
multiHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IMultipleStoresHandler)
for _, vendorOrgCode := range apimanager.CurAPIManager.GetAppOrgCodeList(vendorID) {
allSkuNameInfoList, err := multiHandler.GetSkus(ctx, vendorOrgCode, 0, "")
skuNameInfoList = allSkuNameInfoList
if err != nil {
baseapi.SugarLogger.Errorf("GetMultiStoreAllSkuInfo error:%v", err)
} else {
multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = StoreSkuFullList2BareFilter(allSkuNameInfoList) //map[平台ID[]StoreSkuInfo1,StoreSkuInfo2...]
tempMap := make(map[int]*partner.SkuNameInfo)
for _, value := range allSkuNameInfoList {
for _, skuInfo := range value.SkuList {
//表示平台商品库未下架的
if skuInfo.Status > model.SkuStatusDontSale {
filterVendorDepotUnSaleSkuIds = append(filterVendorDepotUnSaleSkuIds, skuInfo.SkuID)
tempMap[skuInfo.SkuID] = value
}
}
}
multiStoreAllSkuInfoMap[vendorID] = make(map[string]map[int]*partner.SkuNameInfo)
multiStoreAllSkuInfoMap[vendorID][vendorOrgCode] = tempMap //map[平台ID][map[skuID1SkuNameInfo1skuID2SkuNameInfo2]...]
}
}
}
}
}
func GetFilterJxSkuInfoMap(jxSkuInfoList []*dao.StoreSkuNameExt) map[int]*dao.StoreSkuNameExt {
filterJxSkuInfoMap := make(map[int]*dao.StoreSkuNameExt)
for _, value := range jxSkuInfoList {
for _, skuInfo := range value.Skus {
filterJxSkuInfoMap[skuInfo.SkuID] = value
}
}
return filterJxSkuInfoMap
}
func GetFilterVendorSkuInfoMap(vendorSkuInfoList []*partner.SkuNameInfo) map[int]*partner.SkuNameInfo {
filterVendorSkuInfoMap := make(map[int]*partner.SkuNameInfo)
for _, value := range vendorSkuInfoList {
for _, skuInfo := range value.SkuList {
filterVendorSkuInfoMap[skuInfo.SkuID] = value
}
}
return filterVendorSkuInfoMap
}
func GetFilterJxSkuInfoMap2(jxSkuInfoList []*model.SkuAndName) map[int]*model.SkuAndName {
filterVendorSkuInfoMap := make(map[int]*model.SkuAndName)
for _, value := range jxSkuInfoList {
filterVendorSkuInfoMap[value.ID] = value
}
return filterVendorSkuInfoMap
}
func GetFilterMultiStoreSkuInfoMap(vendorID int, vendorOrgCode string, skuInfoList []*partner.StoreSkuInfo) map[int]*partner.SkuNameInfo {
allSkuInfoMap := GetMultiStoreAllSkuInfoMap(vendorID, vendorOrgCode)
filterSkuInfoMap := make(map[int]*partner.SkuNameInfo)
for _, value := range skuInfoList {
if value.Stock > 0 {
filterSkuInfoMap[value.SkuID] = allSkuInfoMap[value.SkuID]
}
}
return filterSkuInfoMap
}
func GetFilterStoreList(storeList []*StoreExt, vendorMap, storeIDMap map[int]bool) (outStoreList []*StoreExt) {
for _, storeInfo := range storeList {
storeID := storeInfo.ID
//filter for storeID
if len(storeIDMap) > 0 {
if _, ok := storeIDMap[storeID]; !ok {
continue
}
}
if storeInfo.StoreMaps != nil {
var tempStoreMaps []*model.StoreMap
for _, vendorStoreInfo := range storeInfo.StoreMaps {
vendorID := vendorStoreInfo.VendorID
isSyncStoreSku := int(vendorStoreInfo.IsSync)
if isSyncStoreSku == 0 {
continue
}
//filter for vendorID
if len(vendorMap) > 0 {
if _, ok := vendorMap[vendorID]; !ok {
continue
}
}
if _, ok := vendorNameList[vendorID]; !ok {
continue
}
tempStoreMaps = append(tempStoreMaps, vendorStoreInfo)
}
if len(tempStoreMaps) > 0 {
storeInfo.StoreMaps = tempStoreMaps
outStoreList = append(outStoreList, storeInfo)
}
}
}
return outStoreList
}
func GetSkuSaleStatusName(status int) string {
return model.SkuStatusName[status]
}
func GetBoolName(flag bool) string {
if flag {
return "是"
} else {
return "否"
}
}
func IsSkuCanSale(saleStatus int) bool {
return saleStatus == model.SkuStatusNormal
}
//京西平台和其他平台商品的对比
//storeIDStr 京西商家id vendorStoreID 平台商家id
func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName string, filterJxSkuInfoMap map[int]*dao.StoreSkuNameExt, filterVendorSkuInfoMap map[int]*partner.SkuNameInfo) {
for skuID, jxSkuInfo := range filterJxSkuInfoMap {
skuIDStr := utils.Int2Str(skuID)
var jxSkuDetailName string
//多规格商品不用比较数量单位
if jxSkuInfo.IsSpu == 0 {
//jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, jxSkuInfo.SkuName.Unit, jxSkuInfo.Skus[0].SkuSpecQuality, jxSkuInfo.Skus[0].SkuSpecUnit, 0)
} else {
//jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..)
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, "", jxSkuInfo.Skus[0].SkuSpecQuality, "", 0)
}
//jxSkuSaleStatus : 商品状态 skustatus 优先级高于 StoreSkuStatus
jxSkuSaleStatus := jxutils.MergeSkuStatus(jxSkuInfo.Skus[0].SkuStatus, jxSkuInfo.Skus[0].StoreSkuStatus)
jxSkuSaleStatusName := GetSkuSaleStatusName(jxSkuSaleStatus)
vendorSkuInfo := filterVendorSkuInfoMap[skuID]
var status int8
if vendorID == model.VendorIDMTWM {
status = jxSkuInfo.Skus[0].MtwmSyncStatus
} else if vendorID == model.VendorIDEBAI {
status = jxSkuInfo.Skus[0].EbaiSyncStatus
} else if vendorID == model.VendorIDJD {
status = jxSkuInfo.Skus[0].JdSyncStatus
}
syncStatus := utils.Int2Str(int(status))
toBeCreate := GetBoolName(model.IsSyncStatusNeedCreate(status))
toBeDel := GetBoolName(model.IsSyncStatusNeedDelete(status))
if vendorSkuInfo != nil {
vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName
vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status)
isSaleStatusDiff := jxSkuSaleStatusName != vendorSkuSaleStatusName
isNameDiff := jxSkuDetailName != vendorSkuDetailName
if jxSkuDetailName != "" && vendorSkuDetailName != "" && strings.Contains(jxSkuDetailName, vendorSkuDetailName) {
isNameDiff = false
}
if isSaleStatusDiff || isNameDiff {
reason := ""
if isNameDiff {
reason += DatAanalyse3
}
if isSaleStatusDiff {
reason += DatAanalyse4
}
if status != model.SkuStatusDontSale {
reason += DatAanalyse7
}
outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, reason}
diffData.AppendData(vendorID, outPutData)
}
if !isSaleStatusDiff && !isNameDiff {
if status != model.SkuStatusDontSale {
outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, DatAanalyse7}
diffData.AppendData(vendorID, outPutData)
}
}
} else {
if isFilterToBeCreateAndNotSale && model.IsSyncStatusNeedCreate(status) && !IsSkuCanSale(jxSkuSaleStatus) {
continue
}
reason := ""
if status == model.SkuStatusDontSale {
reason = DatAanalyse8
} else {
reason = DatAanalyse2
}
if status != model.SkuStatusDontSale {
reason += DatAanalyse7
}
outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, "", jxSkuSaleStatusName, "", reason}
diffData.AppendData(vendorID, outPutData)
}
}
for skuID, vendorSkuInfo := range filterVendorSkuInfoMap {
if vendorSkuInfo != nil {
if len(vendorSkuInfo.SkuList) > 0 {
skuIDStr := utils.Int2Str(skuID)
vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName
vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status)
jxSkuInfo := filterJxSkuInfoMap[skuID]
if jxSkuInfo == nil {
outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, "", "", "", "", vendorSkuDetailName, "", vendorSkuSaleStatusName, DatAanalyse1}
diffData.AppendData(vendorID, outPutData)
}
} else {
globals.SugarLogger.Warnf("CompareJxAndVendor vendorSkuInfo.SkuList:%d is nil", skuID)
}
} else {
globals.SugarLogger.Warnf("CompareJxAndVendor skuID:%d is nil", skuID)
}
}
}
func FilterJxDepotUnSaleSkuID() {
db := dao.GetDB()
filterJxDepotUnSaleSkuIds = filterJxDepotUnSaleSkuIds[0:0]
skuList, _ := dao.GetSkus(db, filterVendorDepotUnSaleSkuIds, []int{}, []int{}, []int{}, nil)
filterJxSkuInfoMap2 := GetFilterJxSkuInfoMap2(skuList)
for skuid, jxSkuInfo := range filterJxSkuInfoMap2 {
//过滤掉平台库下架,且京西库下架的商品,为下面比较门店商品用
if jxSkuInfo.Status != model.SkuStatusDontSale {
filterJxDepotUnSaleSkuIds = append(filterJxDepotUnSaleSkuIds, skuid)
}
}
}
func CompareJxAndMultiVenderDepot(ctx *jxcontext.Context, vendorMap map[int]bool) {
db := dao.GetDB()
for vendorID, _ := range vendorNameList {
//filter for vendorID
if len(vendorMap) > 0 {
if _, ok := vendorMap[vendorID]; !ok {
continue
}
}
if partner.IsMultiStore(vendorID) {
FilterJxDepotUnSaleSkuID()
filterVendorSkuInfoMap := GetFilterVendorSkuInfoMap(skuNameInfoList)
skuNameInfoList = skuNameInfoList[0:0]
skuList, _ := dao.GetSkus(db, []int{}, []int{}, []int{}, []int{}, nil)
filterJxSkuInfoMap2 := GetFilterJxSkuInfoMap2(skuList)
for skuid, jxSkuInfo := range filterJxSkuInfoMap2 {
var jxSkuDetailName string
//多规格商品不用比较数量单位
if jxSkuInfo.IsSpu == 0 {
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, jxSkuInfo.Unit, jxSkuInfo.SpecQuality, jxSkuInfo.SpecUnit, 0)
} else {
jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.Prefix, jxSkuInfo.Name, jxSkuInfo.Comment, "", jxSkuInfo.SpecQuality, "", 0)
}
vendorSkuInfoMap := filterVendorSkuInfoMap[skuid]
jxSkuSaleStatus := jxSkuInfo.Status
jxSkuSaleStatusName := GetSkuSaleStatusName(jxSkuSaleStatus)
skuIDStr := utils.Int2Str(skuid)
if vendorSkuInfoMap != nil {
vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfoMap.SkuList[0].Status)
vendorSkuDetailName := vendorSkuInfoMap.SkuList[0].SkuName
isSaleStatusDiff := jxSkuSaleStatusName != vendorSkuSaleStatusName
isNameDiff := strings.Compare(jxSkuDetailName, vendorSkuDetailName) != 0
if isNameDiff || isSaleStatusDiff {
reason := ""
if isNameDiff {
reason += DatAanalyse3
}
if isSaleStatusDiff {
reason += DatAanalyse4
}
outPutData := DepotDiffData{skuIDStr, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, reason}
depotDiffData.AppendData2(vendorID, outPutData)
}
} else {
outPutData := DepotDiffData{skuIDStr, jxSkuDetailName, "", jxSkuSaleStatusName, "", DatAanalyse6}
depotDiffData.AppendData2(vendorID, outPutData)
}
}
for skuID, vendorSkuInfo := range filterVendorSkuInfoMap {
if vendorSkuInfo != nil {
if len(vendorSkuInfo.SkuList) > 0 {
skuIDStr := utils.Int2Str(skuID)
vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName
vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status)
jxSkuInfo := filterJxSkuInfoMap2[skuID]
if jxSkuInfo == nil {
outPutData := DepotDiffData{skuIDStr, "", vendorSkuDetailName, "", vendorSkuSaleStatusName, DatAanalyse5}
depotDiffData.AppendData2(vendorID, outPutData)
}
} else {
globals.SugarLogger.Warnf("CompareJxAndMultiVenderDepot vendorSkuInfo.SkuList:%d is nil", skuID)
}
} else {
globals.SugarLogger.Warnf("CompareJxAndMultiVenderDepot skuID:%d is nil", skuID)
}
}
}
}
}
//入口函数,校验本地商品京西和其他平台的差异
func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, storeIDList []int) {
startProcessTime := time.Now().Unix()
baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor start time: %v", time.Now())
vendorMap := make(map[int]bool)
for _, vendorID := range vendorIDList {
vendorMap[vendorID] = true //map[平台ID:true]
}
storeIDMap := make(map[int]bool)
for _, storeID := range storeIDList {
storeIDMap[storeID] = true //map[门店ID:true]
}
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
//获取所有多门店平台的商品信息
//1.循环传进来的平台id如果是多门店的平台查询该门店京东到家平台的所有商品
//2.为multiStoreAllSkuInfoList 和 multiStoreAllSkuInfoMap 赋值
GetMultiStoreAllSkuInfo(ctx, vendorMap)
case 1:
//对比京西库和多门店平台的库的信息
depotDiffData.InitData2()
CompareJxAndMultiVenderDepot(ctx, vendorMap)
case 2:
//1.获取京西本地所有门店信息 store、place、user表联查 jxStoreInfoList
//2.过滤所有门店信息只留下传进来的vendorMapstoreIDMap中对应的平台和门台信息 filterStoreList
//3.判断是否多平台门店,两种情况两种处理
jxStoreInfoList, err := GetStores(ctx, "", map[string]interface{}{}, 0, -1, utils.DefaultTimeValue, utils.DefaultTimeValue, 0, 0)
if err != nil {
baseapi.SugarLogger.Errorf("CheckSkuDiffBetweenJxAndVendor GetStores error:%v", err)
} else {
filterStoreList := GetFilterStoreList(jxStoreInfoList.Stores, vendorMap, storeIDMap)
diffData.InitData()
//循环门店store
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
jxStoreInfoListValue := batchItemList[0].(*StoreExt)
storeID := jxStoreInfoListValue.ID
storeIDStr := utils.Int2Str(storeID)
storeName := jxStoreInfoListValue.Name
jxSkuInfoDataSingle := &dao.StoreSkuNamesInfo{}
jxSkuInfoDataMulti := &dao.StoreSkuNamesInfo{}
if jxStoreInfoListValue.StoreMaps != nil {
var multiFlag = false
var singleFlag = false
var filterJxSkuInfoMapSingle map[int]*dao.StoreSkuNameExt
var filterJxSkuInfoMapMulti map[int]*dao.StoreSkuNameExt
for _, vendorListValue := range jxStoreInfoListValue.StoreMaps {
vendorID := vendorListValue.VendorID
if partner.IsMultiStore(vendorID) {
if multiFlag == false {
jxSkuInfoDataMulti, _ = GetStoreSkus(ctx, storeID, filterJxDepotUnSaleSkuIds, true, "", true, false, map[string]interface{}{}, 0, -1)
filterJxSkuInfoMapMulti = GetFilterJxSkuInfoMap(jxSkuInfoDataMulti.SkuNames) //map[京西商品ID:StoreSkuNameExt]
multiFlag = true
}
} else {
if singleFlag == false {
jxSkuInfoDataSingle, _ = GetStoreSkus(ctx, storeID, nil, true, "", true, false, map[string]interface{}{}, 0, -1)
filterJxSkuInfoMapSingle = GetFilterJxSkuInfoMap(jxSkuInfoDataSingle.SkuNames) //map[京西商品ID:StoreSkuNameExt]
singleFlag = true
}
}
vendorStoreID := vendorListValue.VendorStoreID
baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor storeID:%d vendorID:%d vendorStoreID:%s vendorListValue:%v", storeID, vendorID, vendorStoreID, vendorListValue)
if partner.IsMultiStore(vendorID) {
singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler)
allSkuInfoList := GetMultiStoreAllSkuInfoList(vendorID, vendorListValue.VendorOrgCode)
skuBareInfoList, err := singleStoreHandler.GetStoreSkusBareInfo(ctx, vendorListValue.VendorOrgCode, task, storeID, vendorStoreID, allSkuInfoList)
if err != nil {
baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusBareInfo error:%v", err)
} else if len(skuBareInfoList) > 0 {
filterSkuInfoMap := GetFilterMultiStoreSkuInfoMap(vendorID, vendorListValue.VendorOrgCode, skuBareInfoList) //map[京东商品ID:SkuNameInfo]
CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapMulti, filterSkuInfoMap)
}
} else {
singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler)
vendorSkuInfoList, err := singleStoreHandler.GetStoreSkusFullInfo(ctx, task, storeID, vendorStoreID, nil)
if err != nil {
baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusFullInfo error:%v", err)
} else if len(vendorSkuInfoList) > 0 {
filterVendorSkuInfoMap := GetFilterVendorSkuInfoMap(vendorSkuInfoList) //map[平台商品ID:SkuNameInfo]
CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapSingle, filterVendorSkuInfoMap)
}
}
}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("京西和平台商品差异对比-门店商品对比", tasksch.NewParallelConfig().SetParallelCount(parallelCount), ctx, taskFunc, filterStoreList)
tasksch.HandleTask(taskParallel, task, true).Run()
_, err = taskParallel.GetResult(0)
if err != nil {
baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor taskParallel error:%v", err)
}
}
case 3:
WriteToExcel(task, diffData.diffDataMap, depotDiffData.diffDataMap)
endProcessTime := time.Now().Unix()
diff := endProcessTime - startProcessTime
baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor end time: %v", time.Now())
baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor cost time: %d sec", diff)
}
return result, err
}
taskSeq := tasksch.NewSeqTask("京西和平台商品差异对比-序列任务", ctx, taskSeqFunc, 4)
tasksch.HandleTask(taskSeq, nil, true).Run()
}
func IsJXCS() bool {
return globals.IsMainProductEnv()
}
func AddStatisticSheet(sheetName string, data []DiffData) (sheet *excel.Obj2ExcelSheetConfig) {
statisticData := make([]StatisticData, 9)
var count [9]int
var percent [9]float32
totalCount := len(data)
for _, rowData := range data {
if rowData.JxSkuName != "" && rowData.VendorSkuName == "" {
if rowData.ToBeCreate == "是" {
if rowData.JxStatus == "下架" {
count[0]++
} else if rowData.JxStatus == "上架" {
count[1]++
}
} else if rowData.ToBeCreate == "否" {
if rowData.JxStatus == "下架" {
count[2]++
} else if rowData.JxStatus == "上架" {
count[3]++
}
}
} else if rowData.JxSkuName == "" && rowData.VendorSkuName != "" {
if rowData.ToBeCreate == "" && rowData.JxStatus == "" {
count[4]++
}
} else if rowData.JxSkuName != "" && rowData.VendorSkuName != "" {
if rowData.ToBeCreate == "是" {
if rowData.JxStatus == "下架" {
count[5]++
} else if rowData.JxStatus == "上架" {
count[6]++
}
} else if rowData.ToBeCreate == "否" {
if rowData.JxStatus == "下架" {
count[7]++
} else if rowData.JxStatus == "上架" {
count[8]++
}
}
}
}
for index, value := range count {
percent[index] = float32(value*100) / float32(totalCount)
countStr := utils.Int2Str(value)
percentStr := fmt.Sprintf("%.2f%%", percent[index])
subStatisticData := statisticDataList[index]
statisticData[index] = StatisticData{subStatisticData[0], subStatisticData[1], subStatisticData[2], countStr, percentStr}
}
sheetName = sheetName + "统计"
sheet = &excel.Obj2ExcelSheetConfig{
Title: sheetName,
Data: statisticData,
CaptionList: statisticTitleList,
}
return sheet
}
func WriteToExcel(task *tasksch.SeqTask, data map[int][]DiffData, depotData map[int][]DepotDiffData) {
var sheetList []*excel.Obj2ExcelSheetConfig
for key, value := range data {
sheetName := vendorNameList[key]
if partner.IsMultiStore(key) {
excelConfDepot := &excel.Obj2ExcelSheetConfig{
Title: sheetName + "商品库与京西商品库对比",
Data: depotData[key],
CaptionList: deoptTitleList,
}
sheetList = append(sheetList, excelConfDepot)
}
excelConf := &excel.Obj2ExcelSheetConfig{
Title: sheetName,
Data: value,
CaptionList: titleList,
}
sheetList = append(sheetList, excelConf)
if needStatistic {
statisticSheet := AddStatisticSheet(sheetName, value)
sheetList = append(sheetList, statisticSheet)
}
baseapi.SugarLogger.Debugf("WriteToExcel:append:%s count:%d", sheetName, len(value))
}
if len(sheetList) > 0 {
excelBin := excel.Obj2Excel(sheetList)
sheetList = nil
timeStr := utils.Int64ToStr(time.Now().Unix())
diffFullFileName := diffFileName[IsJXCS()] + timeStr + fileExt
if canWriteTolocal {
jxutils.WriteFile(diffFullFileName, excelBin)
}
baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", diffFullFileName)
downloadURL, err := jxutils.UploadExportContent(excelBin, diffFullFileName)
if err != nil {
baseapi.SugarLogger.Errorf("WriteToExcel:upload %s failed error:%v", diffFullFileName, err)
} else {
noticeMsg := fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL)
task.SetNoticeMsg(noticeMsg)
baseapi.SugarLogger.Debugf("WriteToExcel:upload %s success, downloadURL:%s", diffFullFileName, downloadURL)
}
} else {
baseapi.SugarLogger.Debug("WriteToExcel:No diff data!!!")
}
}