From 1829156fbac6834b64ec4e45e18614e564b55672 Mon Sep 17 00:00:00 2001 From: gazebo Date: Tue, 13 Aug 2019 18:09:12 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=B0=86=E8=80=81=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=80=BB=E8=BE=91=E6=B3=A8=E9=87=8A=E6=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business/jxstore/cms/sync.go | 20 +- business/partner/partner.go | 6 +- business/partner/purchase/ebai/store_sku.go | 1067 ++++++++--------- business/partner/purchase/elm/store_sku.go | 12 +- business/partner/purchase/jd/store_sku.go | 387 +++--- business/partner/purchase/mtwm/store_sku.go | 879 +++++++------- .../partner/purchase/weimob/wsc/store_sku.go | 641 +++++----- .../partner/purchase/weimob/wsc/store_sku2.go | 11 + 8 files changed, 1479 insertions(+), 1544 deletions(-) diff --git a/business/jxstore/cms/sync.go b/business/jxstore/cms/sync.go index 8a036a363..d608aa56e 100644 --- a/business/jxstore/cms/sync.go +++ b/business/jxstore/cms/sync.go @@ -446,22 +446,22 @@ func (v *VendorSync) SyncStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, vendo return v.SyncStoresSkus2(ctx, db, vendorIDs, storeIDs, skuIDs, setSyncStatus, isAsync, isContinueWhenError) } -func isUseOldSyncLogic(storeMap *model.StoreMap) bool { - return false - return globals.IsProductEnv() && storeMap.StoreID != 102652 // 绿城四季鲜店 -} +// func isUseOldSyncLogic(storeMap *model.StoreMap) bool { +// return false +// return globals.IsProductEnv() && storeMap.StoreID != 102652 // 绿城四季鲜店 +// } func (v *VendorSync) proxySyncStoreSku(ctx *jxcontext.Context, parentTask tasksch.ITask, storeMap *model.StoreMap, nameIDs, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - if isUseOldSyncLogic(storeMap) { - return v.GetStoreHandler(storeMap.VendorID).SyncStoreSkus(ctx, parentTask, storeMap.StoreID, skuIDs, isAsync, isContinueWhenError) - } + // if isUseOldSyncLogic(storeMap) { + // return v.GetStoreHandler(storeMap.VendorID).SyncStoreSkus(ctx, parentTask, storeMap.StoreID, skuIDs, isAsync, isContinueWhenError) + // } return SyncStoreSkuNew(ctx, parentTask, storeMap.VendorID, storeMap.StoreID, storeMap.VendorStoreID, nil, skuIDs, isAsync, isContinueWhenError) } func (v *VendorSync) proxyFullSyncStoreSku(ctx *jxcontext.Context, parentTask tasksch.ITask, storeMap *model.StoreMap, isAsync, isContinueWhenError bool) (hint string, err error) { - if isUseOldSyncLogic(storeMap) { - return v.GetStoreHandler(storeMap.VendorID).FullSyncStoreSkus(ctx, parentTask, storeMap.StoreID, isAsync, isContinueWhenError) - } + // if isUseOldSyncLogic(storeMap) { + // return v.GetStoreHandler(storeMap.VendorID).FullSyncStoreSkus(ctx, parentTask, storeMap.StoreID, isAsync, isContinueWhenError) + // } return FullSyncStoreSkuNew(ctx, parentTask, storeMap.VendorID, storeMap.StoreID, storeMap.VendorStoreID, isAsync, isContinueWhenError) } diff --git a/business/partner/partner.go b/business/partner/partner.go index 7e3df1c82..ce68d376a 100644 --- a/business/partner/partner.go +++ b/business/partner/partner.go @@ -143,9 +143,9 @@ type IPurchasePlatformHandler interface { // OpenStore(vendorStoreID string, userName string) error // CloseStore(vendorStoreID, closeNotice, userName string) error - SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) - // !!!注意,此操作会先清除门店已有的商品,一般用于初始化,小心使用 - FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) + // SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) + // // !!!注意,此操作会先清除门店已有的商品,一般用于初始化,小心使用 + // FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) diff --git a/business/partner/purchase/ebai/store_sku.go b/business/partner/purchase/ebai/store_sku.go index 1001b300c..4a816bbae 100644 --- a/business/partner/purchase/ebai/store_sku.go +++ b/business/partner/purchase/ebai/store_sku.go @@ -1,572 +1,555 @@ package ebai -import ( - "errors" - "fmt" - "strings" - "time" +// type tStoreSkuFullInfo struct { +// model.StoreSkuBind - "git.rosy.net.cn/baseapi/platformapi/ebaiapi" - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils" - "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" -) +// NameID int `orm:"column(name_id)"` -type tStoreSkuFullInfo struct { - model.StoreSkuBind +// SpecQuality float32 `json:"specQuality"` +// SpecUnit string `orm:"size(8)" json:"specUnit"` // 质量或容量 +// Weight int `json:"weight"` // 重量/质量,单位为克,当相应的SkuName的SpecUnit为g或kg时,必须等于SpecQuality +// SkuStatus int - NameID int `orm:"column(name_id)"` +// Prefix string `orm:"size(255)" json:"prefix"` +// Name string `orm:"size(255);index" json:"name"` +// Comment string `orm:"size(255)" json:"comment"` +// IsGlobal int8 `orm:"default(1)" json:"isGlobal"` // 是否是全部(全国)可见,如果否的话,可见性由SkuPlace决定 +// Unit string `orm:"size(8)" json:"unit"` +// Img string `orm:"size(255)" json:"img"` +// PlaceStr string +// Upc string +// DescImgEbai string - SpecQuality float32 `json:"specQuality"` - SpecUnit string `orm:"size(8)" json:"specUnit"` // 质量或容量 - Weight int `json:"weight"` // 重量/质量,单位为克,当相应的SkuName的SpecUnit为g或kg时,必须等于SpecQuality - SkuStatus int +// CatName string `orm:"size(255)"` - Prefix string `orm:"size(255)" json:"prefix"` - Name string `orm:"size(255);index" json:"name"` - Comment string `orm:"size(255)" json:"comment"` - IsGlobal int8 `orm:"default(1)" json:"isGlobal"` // 是否是全部(全国)可见,如果否的话,可见性由SkuPlace决定 - Unit string `orm:"size(8)" json:"unit"` - Img string `orm:"size(255)" json:"img"` - PlaceStr string - Upc string - DescImgEbai string +// CatMapID int `orm:"column(cat_map_id)"` +// CatID int `orm:"column(cat_id)"` +// CatEbaiID int64 `orm:"column(cat_ebai_id)"` - CatName string `orm:"size(255)"` +// ParentCatMapID int `orm:"column(parent_cat_map_id)"` +// ParentCatID int `orm:"column(parent_cat_id)"` +// ParentCatEbaiID int64 `orm:"column(parent_cat_ebai_id)"` - CatMapID int `orm:"column(cat_map_id)"` - CatID int `orm:"column(cat_id)"` - CatEbaiID int64 `orm:"column(cat_ebai_id)"` +// EbaiCat1ID int64 `orm:"column(ebai_cat1_id)"` +// EbaiCat2ID int64 `orm:"column(ebai_cat2_id)"` +// EbaiCat3ID int64 `orm:"column(ebai_cat3_id)"` - ParentCatMapID int `orm:"column(parent_cat_map_id)"` - ParentCatID int `orm:"column(parent_cat_id)"` - ParentCatEbaiID int64 `orm:"column(parent_cat_ebai_id)"` +// CatPricePercentage int +// } - EbaiCat1ID int64 `orm:"column(ebai_cat1_id)"` - EbaiCat2ID int64 `orm:"column(ebai_cat2_id)"` - EbaiCat3ID int64 `orm:"column(ebai_cat3_id)"` +// type tStoreCatInfo struct { +// model.StoreSkuCategoryMap +// CatID int `orm:"column(cat_id)"` +// Name string +// ParentID int `orm:"column(parent_id)"` +// Level int +// Type int +// Seq int - CatPricePercentage int -} +// ParentEbaiID int64 `orm:"column(parent_ebai_id)"` +// Children map[string]*tStoreCatInfo `orm:"-"` +// } -type tStoreCatInfo struct { - model.StoreSkuCategoryMap - CatID int `orm:"column(cat_id)"` - Name string - ParentID int `orm:"column(parent_id)"` - Level int - Type int - Seq int +// func (p *PurchaseHandler) getDirtyStoreSkus(db *dao.DaoDB, storeID int, skuIDs []int) (storeSkuInfoList []*tStoreSkuFullInfo, err error) { +// sql := ` +// SELECT +// t1.*, t2.spec_quality, t2.spec_unit, t2.weight, t2.status sku_status, +// t3.id name_id, t3.prefix, t3.name, t2.comment, t3.is_global, t3.unit, IF(t3.img_ebai <> '', t3.img_ebai, t3.img) img, t3.upc, t3.desc_img_ebai, +// t4.name cat_name, t4.ebai_price_percentage cat_price_percentage, +// t4.id cat_id, +// t5.id cat_map_id, t5.ebai_id cat_ebai_id, +// t4p.id parent_cat_id, +// t5p.id parent_cat_map_id, t5p.ebai_id parent_cat_ebai_id, +// cat1.vendor_category_id ebai_cat3_id, cat2.vendor_category_id ebai_cat2_id, cat2.parent_id ebai_cat1_id +// FROM store_sku_bind t1 +// LEFT JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? AND t2.status = ? +// LEFT JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ? +// LEFT JOIN sku_category t4 ON t3.category_id = t4.id +// LEFT JOIN sku_category t4p ON t4p.id = t4.parent_id +// LEFT JOIN store_sku_category_map t5 ON t5.store_id = t1.store_id AND t5.category_id = t4.id AND t5.deleted_at = ? +// LEFT JOIN store_sku_category_map t5p ON t5p.store_id = t1.store_id AND t5p.category_id = t4p.id AND t5p.deleted_at = ? +// LEFT JOIN sku_vendor_category cat1 ON t4.ebai_category_id = cat1.vendor_category_id AND cat1.vendor_id = ? +// LEFT JOIN sku_vendor_category cat2 ON cat1.parent_id = cat2.vendor_category_id AND cat1.vendor_id = ? +// WHERE t1.store_id = ? AND (t1.ebai_sync_status <> 0 OR (t1.ebai_id <> 0 AND t3.id IS NULL)) +// ` +// sqlParams := []interface{}{ +// utils.DefaultTimeValue, +// model.SkuStatusNormal, +// utils.DefaultTimeValue, +// model.SkuStatusNormal, +// utils.DefaultTimeValue, +// utils.DefaultTimeValue, +// model.VendorIDEBAI, +// model.VendorIDEBAI, +// storeID, +// } +// if len(skuIDs) > 0 { +// sql += " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")" +// sqlParams = append(sqlParams, skuIDs) +// } +// sql += " ORDER BY t1.price DESC" +// err = dao.GetRows(db, &storeSkuInfoList, sql, sqlParams...) +// return storeSkuInfoList, err +// } - ParentEbaiID int64 `orm:"column(parent_ebai_id)"` - Children map[string]*tStoreCatInfo `orm:"-"` -} +// func (p *PurchaseHandler) createCatByStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, storeSkuInfoList []*tStoreSkuFullInfo) (num int64, err error) { +// catList2Add := make(map[int]int) +// for _, storeSku := range storeSkuInfoList { +// if storeSku.CatID != 0 && storeSku.EbaiSyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreSkuModifiedMask) != 0 && storeSku.Status == model.SkuStatusNormal { +// if storeSku.ParentCatMapID == 0 && storeSku.ParentCatID != 0 { +// catList2Add[storeSku.ParentCatID] = 1 +// } +// if storeSku.CatMapID == 0 { +// catList2Add[storeSku.CatID] = 1 +// } +// } +// } +// num = int64(len(catList2Add)) +// if num > 0 { +// for k := range catList2Add { +// if err = dao.AddStoreCategoryMap(db, storeID, k, model.VendorIDEBAI, "", model.SyncFlagNewMask, ctx.GetUserName()); err != nil { +// return 0, err +// } +// } +// if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { +// return 0, err +// } +// } +// return num, nil +// } -func (p *PurchaseHandler) getDirtyStoreSkus(db *dao.DaoDB, storeID int, skuIDs []int) (storeSkuInfoList []*tStoreSkuFullInfo, err error) { - sql := ` - SELECT - t1.*, t2.spec_quality, t2.spec_unit, t2.weight, t2.status sku_status, - t3.id name_id, t3.prefix, t3.name, t2.comment, t3.is_global, t3.unit, IF(t3.img_ebai <> '', t3.img_ebai, t3.img) img, t3.upc, t3.desc_img_ebai, - t4.name cat_name, t4.ebai_price_percentage cat_price_percentage, - t4.id cat_id, - t5.id cat_map_id, t5.ebai_id cat_ebai_id, - t4p.id parent_cat_id, - t5p.id parent_cat_map_id, t5p.ebai_id parent_cat_ebai_id, - cat1.vendor_category_id ebai_cat3_id, cat2.vendor_category_id ebai_cat2_id, cat2.parent_id ebai_cat1_id - FROM store_sku_bind t1 - LEFT JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? AND t2.status = ? - LEFT JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ? - LEFT JOIN sku_category t4 ON t3.category_id = t4.id - LEFT JOIN sku_category t4p ON t4p.id = t4.parent_id - LEFT JOIN store_sku_category_map t5 ON t5.store_id = t1.store_id AND t5.category_id = t4.id AND t5.deleted_at = ? - LEFT JOIN store_sku_category_map t5p ON t5p.store_id = t1.store_id AND t5p.category_id = t4p.id AND t5p.deleted_at = ? - LEFT JOIN sku_vendor_category cat1 ON t4.ebai_category_id = cat1.vendor_category_id AND cat1.vendor_id = ? - LEFT JOIN sku_vendor_category cat2 ON cat1.parent_id = cat2.vendor_category_id AND cat1.vendor_id = ? - WHERE t1.store_id = ? AND (t1.ebai_sync_status <> 0 OR (t1.ebai_id <> 0 AND t3.id IS NULL)) - ` - sqlParams := []interface{}{ - utils.DefaultTimeValue, - model.SkuStatusNormal, - utils.DefaultTimeValue, - model.SkuStatusNormal, - utils.DefaultTimeValue, - utils.DefaultTimeValue, - model.VendorIDEBAI, - model.VendorIDEBAI, - storeID, - } - if len(skuIDs) > 0 { - sql += " AND t1.sku_id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")" - sqlParams = append(sqlParams, skuIDs) - } - sql += " ORDER BY t1.price DESC" - err = dao.GetRows(db, &storeSkuInfoList, sql, sqlParams...) - return storeSkuInfoList, err -} +// func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// userName := ctx.GetUserName() +// globals.SugarLogger.Debugf("ebai FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) -func (p *PurchaseHandler) createCatByStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, storeSkuInfoList []*tStoreSkuFullInfo) (num int64, err error) { - catList2Add := make(map[int]int) - for _, storeSku := range storeSkuInfoList { - if storeSku.CatID != 0 && storeSku.EbaiSyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreSkuModifiedMask) != 0 && storeSku.Status == model.SkuStatusNormal { - if storeSku.ParentCatMapID == 0 && storeSku.ParentCatID != 0 { - catList2Add[storeSku.ParentCatID] = 1 - } - if storeSku.CatMapID == 0 { - catList2Add[storeSku.CatID] = 1 - } - } - } - num = int64(len(catList2Add)) - if num > 0 { - for k := range catList2Add { - if err = dao.AddStoreCategoryMap(db, storeID, k, model.VendorIDEBAI, "", model.SyncFlagNewMask, ctx.GetUserName()); err != nil { - return 0, err - } - } - if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { - return 0, err - } - } - return num, nil -} +// db := dao.GetDB() +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDEBAI) +// if err != nil { +// return "", err +// } +// rootTask := tasksch.NewSeqTask("FullSyncStoreSkus", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// switch step { +// case 0: +// err = p.DeleteStoreAllSkus(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError) +// // 强制忽略删除SKU错误 +// if isContinueWhenError { +// err = nil +// } +// if err == nil { +// _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDEBAI, []int{storeID}, nil, model.SyncFlagNewMask) +// } +// case 1: +// if err = p.DeleteStoreAllCategories(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError); err == nil { +// _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, []int{storeID}, nil, model.SyncFlagNewMask) +// } +// case 2: +// err = p.SyncLocalStoreCategory(db, storeID, userName) +// case 3: +// _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) +// case 4: +// _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError) +// } +// return nil, err +// }, 5) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// } +// return rootTask.ID, err +// } -func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - userName := ctx.GetUserName() - globals.SugarLogger.Debugf("ebai FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) +// func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// db := dao.GetDB() +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDEBAI) +// if err != nil { +// return "", err +// } +// return p.syncStoreSkus(ctx, parentTask, storeDetail, skuIDs, isAsync, isContinueWhenError) +// } - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDEBAI) - if err != nil { - return "", err - } - rootTask := tasksch.NewSeqTask("FullSyncStoreSkus", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - switch step { - case 0: - err = p.DeleteStoreAllSkus(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError) - // 强制忽略删除SKU错误 - if isContinueWhenError { - err = nil - } - if err == nil { - _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDEBAI, []int{storeID}, nil, model.SyncFlagNewMask) - } - case 1: - if err = p.DeleteStoreAllCategories(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError); err == nil { - _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDEBAI, []int{storeID}, nil, model.SyncFlagNewMask) - } - case 2: - err = p.SyncLocalStoreCategory(db, storeID, userName) - case 3: - _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) - case 4: - _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError) - } - return nil, err - }, 5) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - _, err = rootTask.GetResult(0) - } - return rootTask.ID, err -} +// func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeDetail *dao.StoreDetail, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// storeID := storeDetail.Store.ID +// userName := ctx.GetUserName() +// globals.SugarLogger.Debugf("ebai SyncStoreSkus storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName) -func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDEBAI) - if err != nil { - return "", err - } - return p.syncStoreSkus(ctx, parentTask, storeDetail, skuIDs, isAsync, isContinueWhenError) -} +// var storeSkuInfoList []*tStoreSkuFullInfo +// var num int64 +// strStoreID := utils.Int2Str(storeID) -func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeDetail *dao.StoreDetail, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - storeID := storeDetail.Store.ID - userName := ctx.GetUserName() - globals.SugarLogger.Debugf("ebai SyncStoreSkus storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName) +// rootTask := tasksch.NewSeqTask("SyncStoreSkus饿百1", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// if step == 0 { +// db := dao.GetDB() +// if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { +// return nil, err +// } +// for i := 0; i < 3; i++ { +// if storeSkuInfoList, err = p.getDirtyStoreSkus(db, storeID, skuIDs); err != nil { +// return nil, err +// } +// if num, err = p.createCatByStoreSkus(ctx, rootTask, db, storeID, storeSkuInfoList); err != nil { +// return nil, err +// } +// if num == 0 { +// break +// } +// if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { +// return nil, err +// } +// } +// if num != 0 { +// globals.SugarLogger.Infof("SyncStoreSkus 不能创建商品所需的类别, storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName) +// return nil, errors.New("不能创建商品所需的类别") +// } +// } else if step == 1 { +// task := tasksch.NewParallelTask("SyncStoreSkus饿百2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, +// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// storeSku := batchItemList[0].(*tStoreSkuFullInfo) +// pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, storeSku.Price, int(storeDetail.PricePercentage)) +// // globals.SugarLogger.Debugf("skuID:%d, price:%d, pricePercentage:%d", storeSku.SkuID, storeSku.Price, pricePercentage) +// // globals.SugarLogger.Debugf(utils.Format4Output(storeDetail.PricePercentagePackObj, false)) +// updateFields := []string{model.FieldEbaiSyncStatus} +// syncStatus := int8(0) +// if storeSku.NameID == 0 || storeSku.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { +// if storeSku.EbaiSyncStatus&model.SyncFlagNewMask == 0 && !jxutils.IsEmptyID(storeSku.EbaiID) { +// if globals.EnableEbaiStoreWrite { +// opResult, err2 := api.EbaiAPI.SkuDelete(ctx.GetTrackInfo(), strStoreID, []int64{storeSku.EbaiID}, nil) +// if err = err2; err != nil { +// if ebaiapi.IsErrSkuNotExist(err) || (opResult != nil && len(opResult.FailedList) == 1) { +// err = nil +// } +// } +// } +// } +// if err == nil { +// if utils.IsTimeZero(storeSku.DeletedAt) { +// storeSku.DeletedAt = time.Now() +// updateFields = append(updateFields, model.FieldDeletedAt) +// } +// storeSku.EbaiID = 0 +// updateFields = append(updateFields, model.FieldEbaiID) +// } +// } else { +// if storeSku.EbaiSyncStatus&model.SyncFlagNewMask != 0 { +// // globals.SugarLogger.Debug(utils.Format4Output(genSkuParamsFromStoreSkuInfo(storeSku), false)) +// // todo 适当处理重复(即已经创建)的情况 +// mergedStoreSkuStatus := jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status) +// if mergedStoreSkuStatus == model.SkuStatusNormal { // 待创建且不可售的,暂不新建 +// if storeSku.Img != "" { +// if globals.EnableEbaiStoreWrite { +// if storeSku.EbaiID, err = api.EbaiAPI.SkuCreate(ctx.GetTrackInfo(), strStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err == nil { +// utils.AfterFuncWithRecover(5*time.Second, func() { +// api.EbaiAPI.SkuShopCategoryMap(strStoreID, storeSku.EbaiID, "", storeSku.CatEbaiID, ebaiapi.MaxSkuCatRank-storeSku.Price) +// }) +// } +// } else { +// storeSku.EbaiID = jxutils.GenFakeID() +// } +// if err == nil { +// updateFields = append(updateFields, model.FieldEbaiID) +// } else if ebaiapi.IsErrSkuExist(err) { +// if storeSku.EbaiID = api.EbaiAPI.GetEbaiSkuIDFromCustomID(strStoreID, utils.Int2Str(storeSku.SkuID)); storeSku.EbaiID > 0 { +// err = nil +// updateFields = append(updateFields, model.FieldEbaiID) +// if err2 := skuUpdate(ctx, strStoreID, pricePercentage, storeSku); err2 != nil { +// syncStatus = model.SyncFlagStoreSkuModifiedMask +// } +// } +// } +// } else { +// err = fmt.Errorf("SKUANME%d:%s没有图片,同步失败", storeSku.NameID, storeSku.Name) +// } +// } else { +// updateFields = nil +// } +// } else if storeSku.EbaiSyncStatus&model.SyncFlagStoreSkuModifiedMask != 0 { +// if jxutils.IsEmptyID(storeSku.EbaiID) { +// err = fmt.Errorf("京西数据异常,修改一个没有创建的饿百商品:%d, store:%s", storeSku.SkuID, strStoreID) +// } else { +// if storeSku.Img != "" { +// err = skuUpdate(ctx, strStoreID, pricePercentage, storeSku) +// } else { +// err = fmt.Errorf("SKUANME%d:%s没有图片,同步失败", storeSku.NameID, storeSku.Name) +// } +// } +// } +// } +// if err == nil { +// if len(updateFields) > 0 { +// storeSku.EbaiSyncStatus = syncStatus +// _, err = dao.UpdateEntity(nil, &storeSku.StoreSkuBind, updateFields...) +// } +// } else if isErrModifyPrice(err) { +// // err = partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDEBAI) +// } +// return nil, err +// }, storeSkuInfoList) +// tasksch.AddChild(rootTask, task).Run() +// _, err = task.GetResult(0) +// } +// return nil, err +// }, 2) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// } +// return rootTask.ID, err +// } - var storeSkuInfoList []*tStoreSkuFullInfo - var num int64 - strStoreID := utils.Int2Str(storeID) +// func skuUpdate(ctx *jxcontext.Context, strStoreID string, pricePercentage int, storeSku *tStoreSkuFullInfo) (err error) { +// if globals.EnableEbaiStoreWrite { +// if _, err = api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err != nil { +// // 如果是改价错误,尝试把价格标志去掉再同步 +// if isErrModifyPrice(err) { +// storeSku.EbaiSyncStatus = storeSku.EbaiSyncStatus & ^model.SyncFlagPriceMask +// if storeSku.EbaiSyncStatus != 0 { +// if _, err2 := api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err2 != nil { +// err = err2 +// } +// } +// } +// } +// } +// return err +// } - rootTask := tasksch.NewSeqTask("SyncStoreSkus饿百1", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - if step == 0 { - db := dao.GetDB() - if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { - return nil, err - } - for i := 0; i < 3; i++ { - if storeSkuInfoList, err = p.getDirtyStoreSkus(db, storeID, skuIDs); err != nil { - return nil, err - } - if num, err = p.createCatByStoreSkus(ctx, rootTask, db, storeID, storeSkuInfoList); err != nil { - return nil, err - } - if num == 0 { - break - } - if _, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { - return nil, err - } - } - if num != 0 { - globals.SugarLogger.Infof("SyncStoreSkus 不能创建商品所需的类别, storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, userName) - return nil, errors.New("不能创建商品所需的类别") - } - } else if step == 1 { - task := tasksch.NewParallelTask("SyncStoreSkus饿百2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, - func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - storeSku := batchItemList[0].(*tStoreSkuFullInfo) - pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, storeSku.Price, int(storeDetail.PricePercentage)) - // globals.SugarLogger.Debugf("skuID:%d, price:%d, pricePercentage:%d", storeSku.SkuID, storeSku.Price, pricePercentage) - // globals.SugarLogger.Debugf(utils.Format4Output(storeDetail.PricePercentagePackObj, false)) - updateFields := []string{model.FieldEbaiSyncStatus} - syncStatus := int8(0) - if storeSku.NameID == 0 || storeSku.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { - if storeSku.EbaiSyncStatus&model.SyncFlagNewMask == 0 && !jxutils.IsEmptyID(storeSku.EbaiID) { - if globals.EnableEbaiStoreWrite { - opResult, err2 := api.EbaiAPI.SkuDelete(ctx.GetTrackInfo(), strStoreID, []int64{storeSku.EbaiID}, nil) - if err = err2; err != nil { - if ebaiapi.IsErrSkuNotExist(err) || (opResult != nil && len(opResult.FailedList) == 1) { - err = nil - } - } - } - } - if err == nil { - if utils.IsTimeZero(storeSku.DeletedAt) { - storeSku.DeletedAt = time.Now() - updateFields = append(updateFields, model.FieldDeletedAt) - } - storeSku.EbaiID = 0 - updateFields = append(updateFields, model.FieldEbaiID) - } - } else { - if storeSku.EbaiSyncStatus&model.SyncFlagNewMask != 0 { - // globals.SugarLogger.Debug(utils.Format4Output(genSkuParamsFromStoreSkuInfo(storeSku), false)) - // todo 适当处理重复(即已经创建)的情况 - mergedStoreSkuStatus := jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status) - if mergedStoreSkuStatus == model.SkuStatusNormal { // 待创建且不可售的,暂不新建 - if storeSku.Img != "" { - if globals.EnableEbaiStoreWrite { - if storeSku.EbaiID, err = api.EbaiAPI.SkuCreate(ctx.GetTrackInfo(), strStoreID, storeSku.SkuID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err == nil { - utils.AfterFuncWithRecover(5*time.Second, func() { - api.EbaiAPI.SkuShopCategoryMap(strStoreID, storeSku.EbaiID, "", storeSku.CatEbaiID, ebaiapi.MaxSkuCatRank-storeSku.Price) - }) - } - } else { - storeSku.EbaiID = jxutils.GenFakeID() - } - if err == nil { - updateFields = append(updateFields, model.FieldEbaiID) - } else if ebaiapi.IsErrSkuExist(err) { - if storeSku.EbaiID = api.EbaiAPI.GetEbaiSkuIDFromCustomID(strStoreID, utils.Int2Str(storeSku.SkuID)); storeSku.EbaiID > 0 { - err = nil - updateFields = append(updateFields, model.FieldEbaiID) - if err2 := skuUpdate(ctx, strStoreID, pricePercentage, storeSku); err2 != nil { - syncStatus = model.SyncFlagStoreSkuModifiedMask - } - } - } - } else { - err = fmt.Errorf("SKUANME%d:%s没有图片,同步失败", storeSku.NameID, storeSku.Name) - } - } else { - updateFields = nil - } - } else if storeSku.EbaiSyncStatus&model.SyncFlagStoreSkuModifiedMask != 0 { - if jxutils.IsEmptyID(storeSku.EbaiID) { - err = fmt.Errorf("京西数据异常,修改一个没有创建的饿百商品:%d, store:%s", storeSku.SkuID, strStoreID) - } else { - if storeSku.Img != "" { - err = skuUpdate(ctx, strStoreID, pricePercentage, storeSku) - } else { - err = fmt.Errorf("SKUANME%d:%s没有图片,同步失败", storeSku.NameID, storeSku.Name) - } - } - } - } - if err == nil { - if len(updateFields) > 0 { - storeSku.EbaiSyncStatus = syncStatus - _, err = dao.UpdateEntity(nil, &storeSku.StoreSkuBind, updateFields...) - } - } else if isErrModifyPrice(err) { - // err = partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDEBAI) - } - return nil, err - }, storeSkuInfoList) - tasksch.AddChild(rootTask, task).Run() - _, err = task.GetResult(0) - } - return nil, err - }, 2) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - _, err = rootTask.GetResult(0) - } - return rootTask.ID, err -} +// func isErrModifyPrice(err error) bool { +// if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 1 { +// for _, v := range []string{ +// "无法修改价格", +// "sku_参加营销活动", +// } { +// if strings.Index(errExt.ErrMsg(), v) >= 0 { +// return true +// } +// } +// } +// return false +// } -func skuUpdate(ctx *jxcontext.Context, strStoreID string, pricePercentage int, storeSku *tStoreSkuFullInfo) (err error) { - if globals.EnableEbaiStoreWrite { - if _, err = api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err != nil { - // 如果是改价错误,尝试把价格标志去掉再同步 - if isErrModifyPrice(err) { - storeSku.EbaiSyncStatus = storeSku.EbaiSyncStatus & ^model.SyncFlagPriceMask - if storeSku.EbaiSyncStatus != 0 { - if _, err2 := api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, storeSku.EbaiID, genSkuParamsFromStoreSkuInfo(pricePercentage, storeSku)); err2 != nil { - err = err2 - } - } - } - } - } - return err -} +// func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { +// return hint, err +// } -func isErrModifyPrice(err error) bool { - if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 1 { - for _, v := range []string{ - "无法修改价格", - "sku_参加营销活动", - } { - if strings.Index(errExt.ErrMsg(), v) >= 0 { - return true - } - } - } - return false -} +// /////////// +// func genSkuParamsFromStoreSkuInfo(pricePercentage int, storeSku *tStoreSkuFullInfo) (params map[string]interface{}) { +// price := jxutils.CaculateSkuVendorPrice(storeSku.Price, pricePercentage, storeSku.CatPricePercentage) +// params = map[string]interface{}{ +// "name": utils.LimitMixedStringLen(jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0), ebaiapi.MaxSkuNameByteCount), +// "left_num": model.MaxStoreSkuStockQty, +// "category_id": storeSku.CatEbaiID, +// "predict_cat": 0, // 不使用推荐类目 +// "cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1), +// "cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2), +// "cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3), +// "weight": storeSku.Weight, +// "photos": []map[string]interface{}{ +// map[string]interface{}{ +// "is_master": true, +// "url": storeSku.Img, +// }, +// }, +// } +// if storeSku.DescImgEbai != "" { +// params["rtf"] = storeSku.DescImgEbai +// } +// if storeSku.EbaiSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 { +// params["sale_price"] = price +// } +// if storeSku.EbaiSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 { +// params["status"] = jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status)) +// } +// // todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄? +// // if storeSku.Upc != "" { +// // params["upc"] = storeSku.Upc +// // } +// return params +// } -func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { - return hint, err -} +// // 从饿百同步分类信息到本地 +// // 些函数执行后: +// // 远程有与本地有的条目会关联(并置标记,下次同步会刷新远程) +// // 远程没有本地有的条目会标记新增 +// // 远程有本地没有的条目不做处理 +// func (p *PurchaseHandler) SyncLocalStoreCategory(db *dao.DaoDB, storeID int, userName string) (err error) { +// globals.SugarLogger.Debugf("ebai SyncLocalStoreCategory storeID:%d, userName:%s", storeID, userName) -/////////// -func genSkuParamsFromStoreSkuInfo(pricePercentage int, storeSku *tStoreSkuFullInfo) (params map[string]interface{}) { - price := jxutils.CaculateSkuVendorPrice(storeSku.Price, pricePercentage, storeSku.CatPricePercentage) - params = map[string]interface{}{ - "name": utils.LimitMixedStringLen(jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0), ebaiapi.MaxSkuNameByteCount), - "left_num": model.MaxStoreSkuStockQty, - "category_id": storeSku.CatEbaiID, - "predict_cat": 0, // 不使用推荐类目 - "cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1), - "cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2), - "cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3), - "weight": storeSku.Weight, - "photos": []map[string]interface{}{ - map[string]interface{}{ - "is_master": true, - "url": storeSku.Img, - }, - }, - } - if storeSku.DescImgEbai != "" { - params["rtf"] = storeSku.DescImgEbai - } - if storeSku.EbaiSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 { - params["sale_price"] = price - } - if storeSku.EbaiSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 { - params["status"] = jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status)) - } - // todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄? - // if storeSku.Upc != "" { - // params["upc"] = storeSku.Upc - // } - return params -} +// sql := ` +// SELECT t2.*, t1.id cat_id, t1.name, t1.parent_id, t1.level, t1.type, t1.seq +// FROM sku_category t1 +// LEFT JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND (t2.deleted_at = ?) +// WHERE t1.deleted_at = ? +// ORDER BY t1.level +// ` +// var catList []*tStoreCatInfo +// if err = dao.GetRows(db, &catList, sql, storeID, utils.DefaultTimeValue, utils.DefaultTimeValue); err == nil { +// cat1Map := map[string]*tStoreCatInfo{} +// for _, v := range catList { +// v.Name = formatCatName(v.Name) +// if v.Level == 1 { +// cat1 := cat1Map[v.Name] +// if cat1 == nil { +// cat1Map[v.Name] = v +// cat1Map[utils.Int2Str(v.CatID)] = v +// v.Children = make(map[string]*tStoreCatInfo) +// } +// } else { +// cat1 := cat1Map[utils.Int2Str(v.ParentID)] +// if cat1 == nil { +// panic(fmt.Sprintf("can not find category, id:%d", v.ParentID)) +// } +// cat1.Children[v.Name] = v +// } +// v.EbaiSyncStatus |= model.SyncFlagNewMask +// } +// result, err2 := api.EbaiAPI.ShopCategoryGet(utils.Int2Str(storeID)) +// if err = err2; err == nil { +// dao.Begin(db) +// defer func() { +// dao.Rollback(db) +// }() +// // globals.SugarLogger.Debug(utils.Format4Output(cat1Map, false)) +// if err = p.processLocalCatByRemote(db, storeID, cat1Map, result, userName); err == nil { +// err = p.updateLocalCatAsNew(db, cat1Map, userName) +// } +// if err == nil { +// dao.Commit(db) +// } +// } +// } +// return err +// } -// 从饿百同步分类信息到本地 -// 些函数执行后: -// 远程有与本地有的条目会关联(并置标记,下次同步会刷新远程) -// 远程没有本地有的条目会标记新增 -// 远程有本地没有的条目不做处理 -func (p *PurchaseHandler) SyncLocalStoreCategory(db *dao.DaoDB, storeID int, userName string) (err error) { - globals.SugarLogger.Debugf("ebai SyncLocalStoreCategory storeID:%d, userName:%s", storeID, userName) +// // 从本地同步分类信息到饿百 +// // 测试过程中出现过,父分类创建成功后马上创建子分类会报没有父分类错 +// func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { +// userName := ctx.GetUserName() +// globals.SugarLogger.Debugf("ebai SyncStoreCategory storeID:%d, userName:%s", storeID, userName) - sql := ` - SELECT t2.*, t1.id cat_id, t1.name, t1.parent_id, t1.level, t1.type, t1.seq - FROM sku_category t1 - LEFT JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND (t2.deleted_at = ?) - WHERE t1.deleted_at = ? - ORDER BY t1.level - ` - var catList []*tStoreCatInfo - if err = dao.GetRows(db, &catList, sql, storeID, utils.DefaultTimeValue, utils.DefaultTimeValue); err == nil { - cat1Map := map[string]*tStoreCatInfo{} - for _, v := range catList { - v.Name = formatCatName(v.Name) - if v.Level == 1 { - cat1 := cat1Map[v.Name] - if cat1 == nil { - cat1Map[v.Name] = v - cat1Map[utils.Int2Str(v.CatID)] = v - v.Children = make(map[string]*tStoreCatInfo) - } - } else { - cat1 := cat1Map[utils.Int2Str(v.ParentID)] - if cat1 == nil { - panic(fmt.Sprintf("can not find category, id:%d", v.ParentID)) - } - cat1.Children[v.Name] = v - } - v.EbaiSyncStatus |= model.SyncFlagNewMask - } - result, err2 := api.EbaiAPI.ShopCategoryGet(utils.Int2Str(storeID)) - if err = err2; err == nil { - dao.Begin(db) - defer func() { - dao.Rollback(db) - }() - // globals.SugarLogger.Debug(utils.Format4Output(cat1Map, false)) - if err = p.processLocalCatByRemote(db, storeID, cat1Map, result, userName); err == nil { - err = p.updateLocalCatAsNew(db, cat1Map, userName) - } - if err == nil { - dao.Commit(db) - } - } - } - return err -} +// db := dao.GetDB() +// rootTask := tasksch.NewSeqTask("ebai SyncStoreCategory", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// level := step + 1 +// sql := ` +// SELECT t2.*, t1.name, t1.parent_id, t1.level, t1.type, t1.seq, t2p.ebai_id parent_ebai_id +// FROM sku_category t1 +// LEFT JOIN sku_category t1p ON t1.parent_id = t1p.id +// JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND t2.ebai_sync_status <> 0 +// LEFT JOIN store_sku_category_map t2p ON t1p.id = t2p.category_id AND t2p.store_id = ? AND t2p.deleted_at = ? +// WHERE t1.level = ? AND t1.deleted_at = ? +// ` +// var catList []*tStoreCatInfo +// sqlParams := []interface{}{ +// storeID, +// storeID, +// utils.DefaultTimeValue, +// level, +// utils.DefaultTimeValue, +// } +// if err = dao.GetRows(db, &catList, sql, sqlParams...); err == nil { +// if len(catList) > 0 { +// strStoreID := utils.Int2Str(storeID) +// task := tasksch.NewParallelTask("SyncStoreCategory", nil, ctx, +// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// updateFields := []string{model.FieldEbaiSyncStatus} +// catInfo := batchItemList[0].(*tStoreCatInfo) +// // globals.SugarLogger.Debug(utils.Format4Output(catInfo, false)) +// if catInfo.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 +// if catInfo.EbaiSyncStatus&model.SyncFlagNewMask == 0 && catInfo.EbaiID != 0 { +// if globals.EnableEbaiStoreWrite { +// if err = api.EbaiAPI.ShopCategoryDelete(strStoreID, catInfo.EbaiID); ebaiapi.IsErrCategoryNotExist(err) { +// err = nil +// } +// } +// } +// } else if catInfo.EbaiSyncStatus&model.SyncFlagNewMask != 0 { // 新增 +// if globals.EnableEbaiStoreWrite { +// catName := formatCatName(catInfo.Name) +// catInfo.EbaiID, err = api.EbaiAPI.ShopCategoryCreate(strStoreID, catInfo.ParentEbaiID, catName, jxCatSeq2Ebai(catInfo.Seq)) +// if ebaiapi.IsErrCategoryExist(err) { +// if catInfo.EbaiID = api.EbaiAPI.GetEbaiCatIDFromName(strStoreID, catName); catInfo.EbaiID > 0 { +// err = nil +// } +// } +// } else { +// catInfo.EbaiID = jxutils.GenFakeID() +// } +// if err == nil { +// updateFields = append(updateFields, model.FieldEbaiID) +// } +// } else if catInfo.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改 +// if globals.EnableEbaiStoreWrite { +// err = api.EbaiAPI.ShopCategoryUpdate(strStoreID, catInfo.EbaiID, formatCatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq)) +// } +// } +// if err == nil { +// db2 := dao.GetDB() +// catInfo.EbaiSyncStatus = 0 +// _, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...) +// } +// return nil, err +// }, catList) +// rootTask.AddChild(task).Run() +// _, err = task.GetResult(0) +// } +// } +// return nil, err +// }, 2) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// } +// return rootTask.ID, err +// } -// 从本地同步分类信息到饿百 -// 测试过程中出现过,父分类创建成功后马上创建子分类会报没有父分类错 -func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { - userName := ctx.GetUserName() - globals.SugarLogger.Debugf("ebai SyncStoreCategory storeID:%d, userName:%s", storeID, userName) +// func (p *PurchaseHandler) processLocalCatByRemote(db *dao.DaoDB, storeID int, localCatMap map[string]*tStoreCatInfo, remoteCatList []*ebaiapi.CategoryInfo, userName string) (err error) { +// if localCatMap == nil || remoteCatList == nil { +// return nil +// } +// for _, v := range remoteCatList { +// jxCat := localCatMap[v.Name] +// if jxCat == nil { // 远程有,本地没有,非法类别 +// // globals.SugarLogger.Debug(v.Name) +// // globals.SugarLogger.Debug(utils.Format4Output(localCatMap, false)) +// } else { +// if jxCat.EbaiID != v.CategoryID { +// if jxCat.ID == 0 { // 远程有,本门店没有 +// globals.SugarLogger.Debug(jxCat.CatID) +// err = dao.AddStoreCategoryMap(db, storeID, jxCat.CatID, model.VendorIDEBAI, utils.Int64ToStr(v.CategoryID), model.SyncFlagModifiedMask, userName) +// } else { // 远程有,本门店有,但ID信息不一致 +// _, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &jxCat.StoreSkuCategoryMap, map[string]interface{}{ +// model.FieldEbaiID: v.CategoryID, +// }, userName, nil, model.FieldEbaiSyncStatus, model.SyncFlagModifiedMask) +// } +// } else { // 两边都有,且信息一致 +// } +// jxCat.EbaiSyncStatus = 0 +// if err = p.processLocalCatByRemote(db, storeID, jxCat.Children, v.Children, userName); err != nil { +// return err +// } +// } +// if err != nil { +// return err +// } +// } +// return nil +// } - db := dao.GetDB() - rootTask := tasksch.NewSeqTask("ebai SyncStoreCategory", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - level := step + 1 - sql := ` - SELECT t2.*, t1.name, t1.parent_id, t1.level, t1.type, t1.seq, t2p.ebai_id parent_ebai_id - FROM sku_category t1 - LEFT JOIN sku_category t1p ON t1.parent_id = t1p.id - JOIN store_sku_category_map t2 ON t1.id = t2.category_id AND t2.store_id = ? AND t2.ebai_sync_status <> 0 - LEFT JOIN store_sku_category_map t2p ON t1p.id = t2p.category_id AND t2p.store_id = ? AND t2p.deleted_at = ? - WHERE t1.level = ? AND t1.deleted_at = ? - ` - var catList []*tStoreCatInfo - sqlParams := []interface{}{ - storeID, - storeID, - utils.DefaultTimeValue, - level, - utils.DefaultTimeValue, - } - if err = dao.GetRows(db, &catList, sql, sqlParams...); err == nil { - if len(catList) > 0 { - strStoreID := utils.Int2Str(storeID) - task := tasksch.NewParallelTask("SyncStoreCategory", nil, ctx, - func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - updateFields := []string{model.FieldEbaiSyncStatus} - catInfo := batchItemList[0].(*tStoreCatInfo) - // globals.SugarLogger.Debug(utils.Format4Output(catInfo, false)) - if catInfo.EbaiSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 - if catInfo.EbaiSyncStatus&model.SyncFlagNewMask == 0 && catInfo.EbaiID != 0 { - if globals.EnableEbaiStoreWrite { - if err = api.EbaiAPI.ShopCategoryDelete(strStoreID, catInfo.EbaiID); ebaiapi.IsErrCategoryNotExist(err) { - err = nil - } - } - } - } else if catInfo.EbaiSyncStatus&model.SyncFlagNewMask != 0 { // 新增 - if globals.EnableEbaiStoreWrite { - catName := formatCatName(catInfo.Name) - catInfo.EbaiID, err = api.EbaiAPI.ShopCategoryCreate(strStoreID, catInfo.ParentEbaiID, catName, jxCatSeq2Ebai(catInfo.Seq)) - if ebaiapi.IsErrCategoryExist(err) { - if catInfo.EbaiID = api.EbaiAPI.GetEbaiCatIDFromName(strStoreID, catName); catInfo.EbaiID > 0 { - err = nil - } - } - } else { - catInfo.EbaiID = jxutils.GenFakeID() - } - if err == nil { - updateFields = append(updateFields, model.FieldEbaiID) - } - } else if catInfo.EbaiSyncStatus&model.SyncFlagModifiedMask != 0 { // 修改 - if globals.EnableEbaiStoreWrite { - err = api.EbaiAPI.ShopCategoryUpdate(strStoreID, catInfo.EbaiID, formatCatName(catInfo.Name), jxCatSeq2Ebai(catInfo.Seq)) - } - } - if err == nil { - db2 := dao.GetDB() - catInfo.EbaiSyncStatus = 0 - _, err = dao.UpdateEntity(db2, &catInfo.StoreSkuCategoryMap, updateFields...) - } - return nil, err - }, catList) - rootTask.AddChild(task).Run() - _, err = task.GetResult(0) - } - } - return nil, err - }, 2) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - _, err = rootTask.GetResult(0) - } - return rootTask.ID, err -} - -func (p *PurchaseHandler) processLocalCatByRemote(db *dao.DaoDB, storeID int, localCatMap map[string]*tStoreCatInfo, remoteCatList []*ebaiapi.CategoryInfo, userName string) (err error) { - if localCatMap == nil || remoteCatList == nil { - return nil - } - for _, v := range remoteCatList { - jxCat := localCatMap[v.Name] - if jxCat == nil { // 远程有,本地没有,非法类别 - // globals.SugarLogger.Debug(v.Name) - // globals.SugarLogger.Debug(utils.Format4Output(localCatMap, false)) - } else { - if jxCat.EbaiID != v.CategoryID { - if jxCat.ID == 0 { // 远程有,本门店没有 - globals.SugarLogger.Debug(jxCat.CatID) - err = dao.AddStoreCategoryMap(db, storeID, jxCat.CatID, model.VendorIDEBAI, utils.Int64ToStr(v.CategoryID), model.SyncFlagModifiedMask, userName) - } else { // 远程有,本门店有,但ID信息不一致 - _, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &jxCat.StoreSkuCategoryMap, map[string]interface{}{ - model.FieldEbaiID: v.CategoryID, - }, userName, nil, model.FieldEbaiSyncStatus, model.SyncFlagModifiedMask) - } - } else { // 两边都有,且信息一致 - } - jxCat.EbaiSyncStatus = 0 - if err = p.processLocalCatByRemote(db, storeID, jxCat.Children, v.Children, userName); err != nil { - return err - } - } - if err != nil { - return err - } - } - return nil -} - -func (p *PurchaseHandler) updateLocalCatAsNew(db *dao.DaoDB, localCatMap map[string]*tStoreCatInfo, userName string) (err error) { - if localCatMap == nil { - return nil - } - for _, v := range localCatMap { - if v.EbaiSyncStatus&model.SyncFlagNewMask != 0 { - dao.WrapUpdateULEntity(&v.StoreSkuCategoryMap, userName) - if _, err = dao.UpdateEntity(db, &v.StoreSkuCategoryMap); err != nil { - return err - } - } - if err = p.updateLocalCatAsNew(db, v.Children, userName); err != nil { - return err - } - } - return nil -} +// func (p *PurchaseHandler) updateLocalCatAsNew(db *dao.DaoDB, localCatMap map[string]*tStoreCatInfo, userName string) (err error) { +// if localCatMap == nil { +// return nil +// } +// for _, v := range localCatMap { +// if v.EbaiSyncStatus&model.SyncFlagNewMask != 0 { +// dao.WrapUpdateULEntity(&v.StoreSkuCategoryMap, userName) +// if _, err = dao.UpdateEntity(db, &v.StoreSkuCategoryMap); err != nil { +// return err +// } +// } +// if err = p.updateLocalCatAsNew(db, v.Children, userName); err != nil { +// return err +// } +// } +// return nil +// } diff --git a/business/partner/purchase/elm/store_sku.go b/business/partner/purchase/elm/store_sku.go index 4657b4a48..b38fcae09 100644 --- a/business/partner/purchase/elm/store_sku.go +++ b/business/partner/purchase/elm/store_sku.go @@ -9,14 +9,14 @@ func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask t return "", nil } -func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - return hint, err -} +// func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// return hint, err +// } func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { return hint, err } -func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - return hint, err -} +// func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// return hint, err +// } diff --git a/business/partner/purchase/jd/store_sku.go b/business/partner/purchase/jd/store_sku.go index e7ab65ccf..fe416f748 100644 --- a/business/partner/purchase/jd/store_sku.go +++ b/business/partner/purchase/jd/store_sku.go @@ -1,206 +1,191 @@ package jd -import ( - "fmt" +// // 京东到家,以有库存表示关注(认领) +// func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, storeSkus []*dao.StoreSkuSyncInfo, isAsync, isContinueWhenError bool) (hint string, err error) { +// globals.SugarLogger.Debugf("jd syncStoreSkus, storeID:%d", storeID) +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD) +// if err != nil { +// return "", err +// } +// batchSize := jdapi.MaxStoreSkuBatchSize +// // storeSkusLen := len(storeSkus) +// // if storeSkusLen < jdapi.MaxStoreSkuBatchSize/2 { +// // batchSize = 1 +// // } else if storeSkusLen < jdapi.MaxStoreSkuBatchSize { +// // batchSize = (storeSkusLen + 1) / 2 +// // } else if storeSkusLen < jdapi.MaxStoreSkuBatchSize*2 { +// // batchSize = (storeSkusLen + 2) / 3 +// // } +// task := tasksch.NewParallelTask("syncStoreSkus京东", tasksch.NewParallelConfig().SetBatchSize(batchSize).SetIsContinueWhenError(isContinueWhenError), ctx, +// func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// doWork := func(batchItemList []interface{}) (isPartialFailed bool, err error) { +// var skuPriceInfoList []*jdapi.SkuPriceInfo +// var skuVendibilityList []*jdapi.StockVendibility +// var skuStockList []*jdapi.SkuStock +// vendorSkuID4Price := "" +// vendorSkuID4Qty := "" +// stationNo := storeDetail.VendorStoreID +// var batchBindIDs []int +// for _, v := range batchItemList { +// storeSku := v.(*dao.StoreSkuSyncInfo) +// alreadyAddStock := false +// if storeSku.StoreSkuSyncStatus&model.SyncFlagChangedMask != 0 || storeSku.BindID == 0 || storeSku.NameID == 0 { +// if storeSku.BindID > 0 { +// batchBindIDs = append(batchBindIDs, storeSku.BindID) +// } +// if storeSku.StoreSkuSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 || storeSku.BindID == 0 || storeSku.NameID == 0 { // 关注或取消关注 +// stock := &jdapi.SkuStock{ +// OutSkuId: utils.Int2Str(storeSku.SkuID), +// StockQty: model.MaxStoreSkuStockQty, +// } +// if storeSku.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 || storeSku.DeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 || storeSku.NameID == 0 { +// stock.StockQty = 0 +// } else { +// alreadyAddStock = true +// } +// if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { +// vendorSkuID4Qty = storeSku.VendorSkuID +// skuStockList = append(skuStockList, stock) +// } +// } +// if storeSku.StoreSkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 { +// vendorSkuID4Price = storeSku.VendorSkuID +// pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(storeSku.Price), int(storeDetail.PricePercentage)) +// skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{ +// OutSkuId: utils.Int2Str(storeSku.SkuID), +// Price: constrainPrice(jxutils.CaculateSkuVendorPrice(int(storeSku.Price), pricePercentage, storeSku.CatPricePercentage)), +// }) +// } +// if storeSku.StoreSkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 { +// vendibility := &jdapi.StockVendibility{ +// OutSkuId: utils.Int2Str(storeSku.SkuID), +// DoSale: true, +// } +// if storeSku.StoreSkuStatus != model.StoreSkuBindStatusNormal { +// vendibility.DoSale = false +// } else if !alreadyAddStock { // 如果是设置可售则自动将库存加满 +// stock := &jdapi.SkuStock{ +// OutSkuId: utils.Int2Str(storeSku.SkuID), +// StockQty: model.MaxStoreSkuStockQty, +// } +// vendorSkuID4Qty = storeSku.VendorSkuID +// skuStockList = append(skuStockList, stock) +// } +// if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { +// skuVendibilityList = append(skuVendibilityList, vendibility) +// } +// } +// } +// } +// syncMask := 0 +// errList := []error{} +// if globals.EnableJdStoreWrite { +// // todo 以下可以优化为并行操作 +// // globals.SugarLogger.Debug(utils.Format4Output(skuVendibilityList, false), utils.Format4Output(skuPriceInfoList, false), utils.Format4Output(skuStockList, false)) +// if len(skuVendibilityList) > 0 { +// if _, err = api.JdAPI.BatchUpdateVendibility(ctx.GetTrackInfo(), "", stationNo, skuVendibilityList, ctx.GetUserName()); err == nil { +// syncMask |= model.SyncFlagSaleMask +// } else { +// if !isPartialFailed { +// isPartialFailed = isErrPartialFailed(err) +// } +// errList = append(errList, err) +// } +// } +// if (err == nil || isContinueWhenError) && len(skuStockList) > 0 { +// if len(skuStockList) == 1 { +// err = api.JdAPI.UpdateCurrentQty(ctx.GetTrackInfo(), stationNo, utils.Str2Int64WithDefault(vendorSkuID4Qty, 0), skuStockList[0].StockQty) +// } else { +// _, err = api.JdAPI.BatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", stationNo, skuStockList, ctx.GetUserName()) +// } +// if err == nil { +// syncMask |= model.SyncFlagNewMask | model.SyncFlagDeletedMask +// } else { +// if !isPartialFailed { +// isPartialFailed = isErrPartialFailed(err) +// } +// errList = append(errList, err) +// } +// } +// if (err == nil || isContinueWhenError) && len(skuPriceInfoList) > 0 { +// if len(skuPriceInfoList) == 1 { +// _, err = api.JdAPI.UpdateStationPrice(ctx.GetTrackInfo(), utils.Str2Int64WithDefault(vendorSkuID4Price, 0), stationNo, skuPriceInfoList[0].Price) +// } else { +// _, err = api.JdAPI.UpdateVendorStationPrice(ctx.GetTrackInfo(), "", stationNo, skuPriceInfoList) +// } +// if err == nil { +// syncMask |= model.SyncFlagPriceMask +// } else { +// if !isPartialFailed { +// isPartialFailed = isErrPartialFailed(err) +// } +// // errList = append(errList, partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDJD)) +// errList = append(errList, err) +// } +// } +// } +// if len(errList) == 0 { +// syncMask = -1 +// } +// if syncMask != 0 && len(batchBindIDs) > 0 { +// // db := dao.GetDB() // 多线程问题 +// sql := ` +// UPDATE store_sku_bind t1 +// SET t1.jd_sync_status = t1.jd_sync_status & ? +// WHERE t1.id IN (` + dao.GenQuestionMarks(len(batchBindIDs)) + ")" +// if _, err = dao.ExecuteSQL(db, sql, ^syncMask, batchBindIDs); err != nil { +// errList = append(errList, err) +// } +// } +// if len(errList) == 1 { +// err = errList[0] +// } else if len(errList) > 1 { +// err = fmt.Errorf("%v", errList) +// } +// return isPartialFailed, err +// } +// isErrPartialFailed, err := doWork(batchItemList) +// if isErrPartialFailed && len(batchItemList) > 1 { +// for _, v := range batchItemList { +// doWork([]interface{}{v}) +// } +// } +// return nil, err +// }, storeSkus) +// tasksch.HandleTask(task, parentTask, false).Run() +// if !isAsync { +// _, err = task.GetResult(0) +// } +// return task.ID, err +// } - "git.rosy.net.cn/baseapi/platformapi/jdapi" - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils" - "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" - "git.rosy.net.cn/jx-callback/business/jxutils/storeskulock" - "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" -) +// func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// globals.SugarLogger.Debugf("jd SyncStoresSkus, storeID:%d, skuIDs:%v", storeID, skuIDs) +// db := dao.GetDB() +// storeSkus, err := dao.GetStoreSkus(db, model.VendorIDJD, storeID, skuIDs) +// if err != nil { +// return "", err +// } +// return p.syncStoreSkus(ctx, parentTask, db, storeID, storeSkus, isAsync, isContinueWhenError) +// } -// 京东到家,以有库存表示关注(认领) -func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, storeID int, storeSkus []*dao.StoreSkuSyncInfo, isAsync, isContinueWhenError bool) (hint string, err error) { - globals.SugarLogger.Debugf("jd syncStoreSkus, storeID:%d", storeID) - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD) - if err != nil { - return "", err - } - batchSize := jdapi.MaxStoreSkuBatchSize - // storeSkusLen := len(storeSkus) - // if storeSkusLen < jdapi.MaxStoreSkuBatchSize/2 { - // batchSize = 1 - // } else if storeSkusLen < jdapi.MaxStoreSkuBatchSize { - // batchSize = (storeSkusLen + 1) / 2 - // } else if storeSkusLen < jdapi.MaxStoreSkuBatchSize*2 { - // batchSize = (storeSkusLen + 2) / 3 - // } - task := tasksch.NewParallelTask("syncStoreSkus京东", tasksch.NewParallelConfig().SetBatchSize(batchSize).SetIsContinueWhenError(isContinueWhenError), ctx, - func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - doWork := func(batchItemList []interface{}) (isPartialFailed bool, err error) { - var skuPriceInfoList []*jdapi.SkuPriceInfo - var skuVendibilityList []*jdapi.StockVendibility - var skuStockList []*jdapi.SkuStock - vendorSkuID4Price := "" - vendorSkuID4Qty := "" - stationNo := storeDetail.VendorStoreID - var batchBindIDs []int - for _, v := range batchItemList { - storeSku := v.(*dao.StoreSkuSyncInfo) - alreadyAddStock := false - if storeSku.StoreSkuSyncStatus&model.SyncFlagChangedMask != 0 || storeSku.BindID == 0 || storeSku.NameID == 0 { - if storeSku.BindID > 0 { - batchBindIDs = append(batchBindIDs, storeSku.BindID) - } - if storeSku.StoreSkuSyncStatus&(model.SyncFlagDeletedMask|model.SyncFlagNewMask) != 0 || storeSku.BindID == 0 || storeSku.NameID == 0 { // 关注或取消关注 - stock := &jdapi.SkuStock{ - OutSkuId: utils.Int2Str(storeSku.SkuID), - StockQty: model.MaxStoreSkuStockQty, - } - if storeSku.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 || storeSku.DeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 || storeSku.NameID == 0 { - stock.StockQty = 0 - } else { - alreadyAddStock = true - } - if stock.StockQty != 0 || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { - vendorSkuID4Qty = storeSku.VendorSkuID - skuStockList = append(skuStockList, stock) - } - } - if storeSku.StoreSkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 { - vendorSkuID4Price = storeSku.VendorSkuID - pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(storeSku.Price), int(storeDetail.PricePercentage)) - skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{ - OutSkuId: utils.Int2Str(storeSku.SkuID), - Price: constrainPrice(jxutils.CaculateSkuVendorPrice(int(storeSku.Price), pricePercentage, storeSku.CatPricePercentage)), - }) - } - if storeSku.StoreSkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 { - vendibility := &jdapi.StockVendibility{ - OutSkuId: utils.Int2Str(storeSku.SkuID), - DoSale: true, - } - if storeSku.StoreSkuStatus != model.StoreSkuBindStatusNormal { - vendibility.DoSale = false - } else if !alreadyAddStock { // 如果是设置可售则自动将库存加满 - stock := &jdapi.SkuStock{ - OutSkuId: utils.Int2Str(storeSku.SkuID), - StockQty: model.MaxStoreSkuStockQty, - } - vendorSkuID4Qty = storeSku.VendorSkuID - skuStockList = append(skuStockList, stock) - } - if vendibility.DoSale || !storeskulock.IsJdStoreSkuLocked(stationNo, storeSku.JdID) { - skuVendibilityList = append(skuVendibilityList, vendibility) - } - } - } - } - syncMask := 0 - errList := []error{} - if globals.EnableJdStoreWrite { - // todo 以下可以优化为并行操作 - // globals.SugarLogger.Debug(utils.Format4Output(skuVendibilityList, false), utils.Format4Output(skuPriceInfoList, false), utils.Format4Output(skuStockList, false)) - if len(skuVendibilityList) > 0 { - if _, err = api.JdAPI.BatchUpdateVendibility(ctx.GetTrackInfo(), "", stationNo, skuVendibilityList, ctx.GetUserName()); err == nil { - syncMask |= model.SyncFlagSaleMask - } else { - if !isPartialFailed { - isPartialFailed = isErrPartialFailed(err) - } - errList = append(errList, err) - } - } - if (err == nil || isContinueWhenError) && len(skuStockList) > 0 { - if len(skuStockList) == 1 { - err = api.JdAPI.UpdateCurrentQty(ctx.GetTrackInfo(), stationNo, utils.Str2Int64WithDefault(vendorSkuID4Qty, 0), skuStockList[0].StockQty) - } else { - _, err = api.JdAPI.BatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", stationNo, skuStockList, ctx.GetUserName()) - } - if err == nil { - syncMask |= model.SyncFlagNewMask | model.SyncFlagDeletedMask - } else { - if !isPartialFailed { - isPartialFailed = isErrPartialFailed(err) - } - errList = append(errList, err) - } - } - if (err == nil || isContinueWhenError) && len(skuPriceInfoList) > 0 { - if len(skuPriceInfoList) == 1 { - _, err = api.JdAPI.UpdateStationPrice(ctx.GetTrackInfo(), utils.Str2Int64WithDefault(vendorSkuID4Price, 0), stationNo, skuPriceInfoList[0].Price) - } else { - _, err = api.JdAPI.UpdateVendorStationPrice(ctx.GetTrackInfo(), "", stationNo, skuPriceInfoList) - } - if err == nil { - syncMask |= model.SyncFlagPriceMask - } else { - if !isPartialFailed { - isPartialFailed = isErrPartialFailed(err) - } - // errList = append(errList, partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDJD)) - errList = append(errList, err) - } - } - } - if len(errList) == 0 { - syncMask = -1 - } - if syncMask != 0 && len(batchBindIDs) > 0 { - // db := dao.GetDB() // 多线程问题 - sql := ` - UPDATE store_sku_bind t1 - SET t1.jd_sync_status = t1.jd_sync_status & ? - WHERE t1.id IN (` + dao.GenQuestionMarks(len(batchBindIDs)) + ")" - if _, err = dao.ExecuteSQL(db, sql, ^syncMask, batchBindIDs); err != nil { - errList = append(errList, err) - } - } - if len(errList) == 1 { - err = errList[0] - } else if len(errList) > 1 { - err = fmt.Errorf("%v", errList) - } - return isPartialFailed, err - } - isErrPartialFailed, err := doWork(batchItemList) - if isErrPartialFailed && len(batchItemList) > 1 { - for _, v := range batchItemList { - doWork([]interface{}{v}) - } - } - return nil, err - }, storeSkus) - tasksch.HandleTask(task, parentTask, false).Run() - if !isAsync { - _, err = task.GetResult(0) - } - return task.ID, err -} +// func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// globals.SugarLogger.Debugf("jd FullSyncStoreSkus, storeID:%d", storeID) +// db := dao.GetDB() +// _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, []int{storeID}, nil, model.SyncFlagStoreSkuOnlyMask) +// if err != nil { +// return "", err +// } +// storeSkus, err := dao.GetFullStoreSkus(db, model.VendorIDJD, storeID) +// if err != nil { +// return "", err +// } +// return p.syncStoreSkus(ctx, parentTask, db, storeID, storeSkus, isAsync, isContinueWhenError) +// } -func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - globals.SugarLogger.Debugf("jd SyncStoresSkus, storeID:%d, skuIDs:%v", storeID, skuIDs) - db := dao.GetDB() - storeSkus, err := dao.GetStoreSkus(db, model.VendorIDJD, storeID, skuIDs) - if err != nil { - return "", err - } - return p.syncStoreSkus(ctx, parentTask, db, storeID, storeSkus, isAsync, isContinueWhenError) -} - -func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - globals.SugarLogger.Debugf("jd FullSyncStoreSkus, storeID:%d", storeID) - db := dao.GetDB() - _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, []int{storeID}, nil, model.SyncFlagStoreSkuOnlyMask) - if err != nil { - return "", err - } - storeSkus, err := dao.GetFullStoreSkus(db, model.VendorIDJD, storeID) - if err != nil { - return "", err - } - return p.syncStoreSkus(ctx, parentTask, db, storeID, storeSkus, isAsync, isContinueWhenError) -} - -func constrainPrice(price int) int { - if price <= 0 { - price = 1 - } - return price -} +// func constrainPrice(price int) int { +// if price <= 0 { +// price = 1 +// } +// return price +// } diff --git a/business/partner/purchase/mtwm/store_sku.go b/business/partner/purchase/mtwm/store_sku.go index 1288dbd57..149e7559e 100644 --- a/business/partner/purchase/mtwm/store_sku.go +++ b/business/partner/purchase/mtwm/store_sku.go @@ -1,459 +1,442 @@ package mtwm -import ( - "errors" - "fmt" - "strings" - "time" +// // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 +// func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { +// globals.SugarLogger.Debugf("mtwm SyncStoreCategory storeID:%d, userName:%s", storeID, ctx.GetUserName()) +// num := 0 +// db := dao.GetDB() +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) +// if err != nil { +// return hint, err +// } +// vendorStoreID := storeDetail.VendorStoreID +// rootTask := tasksch.NewSeqTask("美团外卖SyncStoreCategory step1", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// level := step + 1 +// catList, err := dao.GetStoreCategories(db, model.VendorIDMTWM, storeID, level) +// if len(catList) > 0 { +// num += len(catList) +// task := tasksch.NewParallelTask(fmt.Sprintf("美团外卖SyncStoreCategory step2, level=%d", level), nil, ctx, +// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDMTWM])} +// catInfo := batchItemList[0].(*dao.SkuStoreCatInfo) +// storeCatMap := &model.StoreSkuCategoryMap{} +// storeCatMap.ID = catInfo.MapID +// if catInfo.StoreCatSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 +// if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { +// globals.SugarLogger.Debugf("RetailCatDelete vendorStoreID:%s, MtwmID:%s", vendorStoreID, catInfo.VendorCatID) +// if globals.EnableMtwmStoreWrite { +// if err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catInfo.VendorCatID); mtwmapi.IsErrCategoryNotExist(err) { +// err = nil +// } +// } +// } +// } else if catInfo.StoreCatSyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreSkuModifiedMask) != 0 { // 新增或修改 +// catName := catInfo.Name +// subCatName := "" +// originName := "" +// if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { +// originName = catInfo.VendorCatID +// } +// if level == 2 { +// originName = catInfo.ParentCatName +// catName = catInfo.ParentCatName +// subCatName = catInfo.Name +// if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { +// originName = catInfo.VendorCatID +// catName = catInfo.Name +// subCatName = "" +// } +// } +// if catName == "" { +// panic("catName is empty") +// } +// globals.SugarLogger.Debugf("RetailCatUpdate vendorStoreID:%s, originName:%s, catName:%s, subCatName:%s, seq:%d", vendorStoreID, originName, catName, subCatName, catInfo.Seq) +// if globals.EnableMtwmStoreWrite { +// if err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, originName, catName, subCatName, catInfo.Seq); catInfo.StoreCatSyncStatus&model.SyncFlagNewMask != 0 && mtwmapi.IsErrCategoryExist(err) { +// err = nil +// } +// } +// if err == nil { +// storeCatMap.MtwmID = catInfo.Name +// updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDMTWM])) +// } +// } +// if err == nil { +// db2 := dao.GetDB() +// storeCatMap.MtwmSyncStatus = 0 +// _, err = dao.UpdateEntity(db2, storeCatMap, updateFields...) +// } +// return nil, err +// }, catList) +// rootTask.AddChild(task).Run() +// _, err = task.GetResult(0) +// } +// return nil, err +// }, 2) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// hint = utils.Int2Str(num) +// _, err = rootTask.GetResult(0) +// } else { +// hint = rootTask.ID +// } +// return hint, err +// } - "git.rosy.net.cn/baseapi/platformapi/mtwmapi" - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils" - "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" -) +// // 此函数根据门店商品信息重建分类信息 +// // 远程有,本地无, --> 删除远程 +// // 远程有,本地有,映射无, --> 添加关联 +// // 远程有,本地有,映射有, --> 不处理 +// // 远程无,本地有,映射无, --> 添加本地 +// // 远程无,本地有,映射有, --> 同步标记改为新增 +// // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 +// func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, isCheckRemote bool, skuIDs []int) (hint string, err error) { +// globals.SugarLogger.Debugf("mtwm SyncLocalStoreCategory storeID:%d, userName:%s", storeID, ctx.GetUserName()) +// if db == nil { +// db = dao.GetDB() +// } +// catMap := make([]map[string]*dao.SkuStoreCatInfo, 2) +// for i := 0; i < 2; i++ { +// catMap[i] = make(map[string]*dao.SkuStoreCatInfo) +// localCats, err := dao.GetSkusCategories(db, model.VendorIDMTWM, storeID, skuIDs, i+1) +// // globals.SugarLogger.Debug(utils.Format4Output(localCats, false)) +// if err != nil { +// return "", err +// } +// for _, cat := range localCats { +// catMap[i][cat.ParentCatName+"/"+cat.Name] = cat +// } +// } +// identityCatMap := make(map[int]int) // 这里面表示远程有,本地有,且完全相同,可擦掉本地的修改标记 +// if isCheckRemote { +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) +// if err != nil { +// return hint, err +// } +// vendorStoreID := storeDetail.VendorStoreID +// remoteCats, err := api.MtwmAPI.RetailCatList(vendorStoreID) +// if err != nil { +// return "", err +// } +// if err = TranverseRemoteCatList("", remoteCats, func(level int, parentCatName, catName string) (err error) { +// localCat := catMap[level-1][parentCatName+"/"+catName] +// // globals.SugarLogger.Debug(parentCatName, " ", catName, " ", localCat) +// if localCat == nil { // 本地分类就没有这个名字,直接删除 +// if globals.EnableMtwmStoreWrite { +// globals.SugarLogger.Debugf("RetailCatDelete2 vendorStoreID:%s, catName:%s", vendorStoreID, catName) +// if err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catName); err != nil { +// return err +// } +// } +// } else { // 本地分类有这个名字 +// if localCat.MapID == 0 { // 本地映射没有 +// localCat.MapID = -1 // 表示远程有同名的 +// } else { // 本地映射有 +// identityCatMap[localCat.MapID] = 1 +// } +// } +// return nil +// }); err != nil { +// return "", err +// } +// } +// dao.Begin(db) +// defer func() { +// dao.Rollback(db) +// }() +// num := 0 +// for i := 0; i < 2; i++ { +// for _, v := range catMap[i] { +// if v.MapID == -1 || v.MapID == 0 { // 本地缺失 +// mtwmSyncStatus := int8(model.SyncFlagNewMask) +// if v.MapID == -1 { // 远程有同名的,只是简单增加一条本地记录关联 +// mtwmSyncStatus = 0 +// } +// catMap := &model.StoreSkuCategoryMap{ +// StoreID: storeID, +// CategoryID: v.ID, +// MtwmID: v.Name, +// MtwmSyncStatus: mtwmSyncStatus, +// EbaiSyncStatus: model.SyncFlagNewMask, +// ElmSyncStatus: model.SyncFlagNewMask, +// WscSyncStatus: model.SyncFlagNewMask, +// } +// num++ +// dao.WrapAddIDCULDEntity(catMap, ctx.GetUserName()) +// if err = dao.CreateEntity(db, catMap); err != nil { +// return "", err +// } +// } else { +// if dao.IsVendorThingIDEmpty(v.VendorCatID) { +// num++ +// } +// if isCheckRemote { +// catMap := &model.StoreSkuCategoryMap{ +// MtwmSyncStatus: model.SyncFlagNewMask, +// } +// updateFields := []string{ +// model.FieldUpdatedAt, +// model.FieldLastOperator, +// model.FieldMtwmSyncStatus, +// } +// if identityCatMap[v.MapID] == 1 { // 如果一样,则要刷新ID(对于MTWM其实就是名字) +// catMap.MtwmID = v.Name +// catMap.MtwmSyncStatus = 0 +// updateFields = append(updateFields, model.FieldMtwmID) +// } +// catMap.ID = v.MapID +// num++ +// dao.WrapUpdateULEntity(catMap, ctx.GetUserName()) +// if _, err = dao.UpdateEntity(db, catMap, updateFields...); err != nil { +// return "", err +// } +// } +// } +// } +// } +// dao.Commit(db) +// return utils.Int2Str(num), err +// } -// hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 -func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { - globals.SugarLogger.Debugf("mtwm SyncStoreCategory storeID:%d, userName:%s", storeID, ctx.GetUserName()) - num := 0 - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) - if err != nil { - return hint, err - } - vendorStoreID := storeDetail.VendorStoreID - rootTask := tasksch.NewSeqTask("美团外卖SyncStoreCategory step1", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - level := step + 1 - catList, err := dao.GetStoreCategories(db, model.VendorIDMTWM, storeID, level) - if len(catList) > 0 { - num += len(catList) - task := tasksch.NewParallelTask(fmt.Sprintf("美团外卖SyncStoreCategory step2, level=%d", level), nil, ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDMTWM])} - catInfo := batchItemList[0].(*dao.SkuStoreCatInfo) - storeCatMap := &model.StoreSkuCategoryMap{} - storeCatMap.ID = catInfo.MapID - if catInfo.StoreCatSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 - if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { - globals.SugarLogger.Debugf("RetailCatDelete vendorStoreID:%s, MtwmID:%s", vendorStoreID, catInfo.VendorCatID) - if globals.EnableMtwmStoreWrite { - if err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catInfo.VendorCatID); mtwmapi.IsErrCategoryNotExist(err) { - err = nil - } - } - } - } else if catInfo.StoreCatSyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreSkuModifiedMask) != 0 { // 新增或修改 - catName := catInfo.Name - subCatName := "" - originName := "" - if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { - originName = catInfo.VendorCatID - } - if level == 2 { - originName = catInfo.ParentCatName - catName = catInfo.ParentCatName - subCatName = catInfo.Name - if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 { - originName = catInfo.VendorCatID - catName = catInfo.Name - subCatName = "" - } - } - if catName == "" { - panic("catName is empty") - } - globals.SugarLogger.Debugf("RetailCatUpdate vendorStoreID:%s, originName:%s, catName:%s, subCatName:%s, seq:%d", vendorStoreID, originName, catName, subCatName, catInfo.Seq) - if globals.EnableMtwmStoreWrite { - if err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, originName, catName, subCatName, catInfo.Seq); catInfo.StoreCatSyncStatus&model.SyncFlagNewMask != 0 && mtwmapi.IsErrCategoryExist(err) { - err = nil - } - } - if err == nil { - storeCatMap.MtwmID = catInfo.Name - updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDMTWM])) - } - } - if err == nil { - db2 := dao.GetDB() - storeCatMap.MtwmSyncStatus = 0 - _, err = dao.UpdateEntity(db2, storeCatMap, updateFields...) - } - return nil, err - }, catList) - rootTask.AddChild(task).Run() - _, err = task.GetResult(0) - } - return nil, err - }, 2) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - hint = utils.Int2Str(num) - _, err = rootTask.GetResult(0) - } else { - hint = rootTask.ID - } - return hint, err -} +// func TranverseRemoteCatList(parentCatName string, remoteCats []*mtwmapi.RetailCategoryInfo, handler func(level int, parentCatName, catName string) error) (err error) { +// for _, remoteCat := range remoteCats { +// name := utils.Interface2String(remoteCat.Name) +// TranverseRemoteCatList(name, remoteCat.Children, handler) +// if err = handler(remoteCat.Level, parentCatName, name); err != nil { +// return err +// } +// } +// return nil +// } -// 此函数根据门店商品信息重建分类信息 -// 远程有,本地无, --> 删除远程 -// 远程有,本地有,映射无, --> 添加关联 -// 远程有,本地有,映射有, --> 不处理 -// 远程无,本地有,映射无, --> 添加本地 -// 远程无,本地有,映射有, --> 同步标记改为新增 -// hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 -func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, isCheckRemote bool, skuIDs []int) (hint string, err error) { - globals.SugarLogger.Debugf("mtwm SyncLocalStoreCategory storeID:%d, userName:%s", storeID, ctx.GetUserName()) - if db == nil { - db = dao.GetDB() - } - catMap := make([]map[string]*dao.SkuStoreCatInfo, 2) - for i := 0; i < 2; i++ { - catMap[i] = make(map[string]*dao.SkuStoreCatInfo) - localCats, err := dao.GetSkusCategories(db, model.VendorIDMTWM, storeID, skuIDs, i+1) - // globals.SugarLogger.Debug(utils.Format4Output(localCats, false)) - if err != nil { - return "", err - } - for _, cat := range localCats { - catMap[i][cat.ParentCatName+"/"+cat.Name] = cat - } - } - identityCatMap := make(map[int]int) // 这里面表示远程有,本地有,且完全相同,可擦掉本地的修改标记 - if isCheckRemote { - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) - if err != nil { - return hint, err - } - vendorStoreID := storeDetail.VendorStoreID - remoteCats, err := api.MtwmAPI.RetailCatList(vendorStoreID) - if err != nil { - return "", err - } - if err = TranverseRemoteCatList("", remoteCats, func(level int, parentCatName, catName string) (err error) { - localCat := catMap[level-1][parentCatName+"/"+catName] - // globals.SugarLogger.Debug(parentCatName, " ", catName, " ", localCat) - if localCat == nil { // 本地分类就没有这个名字,直接删除 - if globals.EnableMtwmStoreWrite { - globals.SugarLogger.Debugf("RetailCatDelete2 vendorStoreID:%s, catName:%s", vendorStoreID, catName) - if err = api.MtwmAPI.RetailCatDelete(vendorStoreID, catName); err != nil { - return err - } - } - } else { // 本地分类有这个名字 - if localCat.MapID == 0 { // 本地映射没有 - localCat.MapID = -1 // 表示远程有同名的 - } else { // 本地映射有 - identityCatMap[localCat.MapID] = 1 - } - } - return nil - }); err != nil { - return "", err - } - } - dao.Begin(db) - defer func() { - dao.Rollback(db) - }() - num := 0 - for i := 0; i < 2; i++ { - for _, v := range catMap[i] { - if v.MapID == -1 || v.MapID == 0 { // 本地缺失 - mtwmSyncStatus := int8(model.SyncFlagNewMask) - if v.MapID == -1 { // 远程有同名的,只是简单增加一条本地记录关联 - mtwmSyncStatus = 0 - } - catMap := &model.StoreSkuCategoryMap{ - StoreID: storeID, - CategoryID: v.ID, - MtwmID: v.Name, - MtwmSyncStatus: mtwmSyncStatus, - EbaiSyncStatus: model.SyncFlagNewMask, - ElmSyncStatus: model.SyncFlagNewMask, - WscSyncStatus: model.SyncFlagNewMask, - } - num++ - dao.WrapAddIDCULDEntity(catMap, ctx.GetUserName()) - if err = dao.CreateEntity(db, catMap); err != nil { - return "", err - } - } else { - if dao.IsVendorThingIDEmpty(v.VendorCatID) { - num++ - } - if isCheckRemote { - catMap := &model.StoreSkuCategoryMap{ - MtwmSyncStatus: model.SyncFlagNewMask, - } - updateFields := []string{ - model.FieldUpdatedAt, - model.FieldLastOperator, - model.FieldMtwmSyncStatus, - } - if identityCatMap[v.MapID] == 1 { // 如果一样,则要刷新ID(对于MTWM其实就是名字) - catMap.MtwmID = v.Name - catMap.MtwmSyncStatus = 0 - updateFields = append(updateFields, model.FieldMtwmID) - } - catMap.ID = v.MapID - num++ - dao.WrapUpdateULEntity(catMap, ctx.GetUserName()) - if _, err = dao.UpdateEntity(db, catMap, updateFields...); err != nil { - return "", err - } - } - } - } - } - dao.Commit(db) - return utils.Int2Str(num), err -} +// func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// db := dao.GetDB() +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) +// if err != nil { +// return "", err +// } +// return p.syncStoreSkus(ctx, parentTask, storeDetail, skuIDs, isAsync, isContinueWhenError) +// } -func TranverseRemoteCatList(parentCatName string, remoteCats []*mtwmapi.RetailCategoryInfo, handler func(level int, parentCatName, catName string) error) (err error) { - for _, remoteCat := range remoteCats { - name := utils.Interface2String(remoteCat.Name) - TranverseRemoteCatList(name, remoteCat.Children, handler) - if err = handler(remoteCat.Level, parentCatName, name); err != nil { - return err - } - } - return nil -} +// // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 +// func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeDetail *dao.StoreDetail, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// storeID := storeDetail.Store.ID +// globals.SugarLogger.Debugf("mtwm SyncStoreSkus storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, ctx.GetUserName()) +// db := dao.GetDB() +// for i := 0; i < 3; i++ { // 最多重试三次 +// if hint, err = p.SyncLocalStoreCategory(ctx, db, storeID, false, skuIDs); err != nil { +// return "", err +// } +// if hint != "0" { +// if hint, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { +// return "", err +// } +// } +// if hint == "0" { +// break +// } +// } +// if hint != "0" { +// return "", errors.New("同步门店商品所需目录失败") +// } +// skus, err := dao.GetStoreSkus(db, model.VendorIDMTWM, storeID, skuIDs) +// if err != nil { +// return "", err +// } +// // globals.SugarLogger.Debug(utils.Format4Output(skus, false)) +// vendorStoreID := storeDetail.VendorStoreID +// rootTask := tasksch.NewParallelTask("美团外卖SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, +// func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// foodDataList := make([]map[string]interface{}, len(batchItemList)) +// // for k, v := range batchItemList { +// v := batchItemList[0] +// skuItem := v.(*dao.StoreSkuSyncInfo) +// updateFields := []string{model.FieldMtwmSyncStatus} +// storeSkuBind := &model.StoreSkuBind{} +// storeSkuBind.ID = skuItem.BindID +// if skuItem.NameID == 0 || skuItem.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 { +// if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(skuItem.VendorSkuID) { +// if globals.EnableMtwmStoreWrite { +// if err = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, skuItem.VendorSkuID); mtwmapi.IsErrSkuNotExist(err) { +// err = nil +// } +// } +// } +// if err == nil { +// if utils.IsTimeZero(storeSkuBind.DeletedAt) { +// storeSkuBind.DeletedAt = time.Now() +// updateFields = append(updateFields, model.FieldDeletedAt) +// } +// if !dao.IsVendorThingIDEmpty(skuItem.VendorSkuID) { +// storeSkuBind.MtwmID = 0 +// updateFields = append(updateFields, model.FieldMtwmID) +// } +// } +// } else if skuItem.StoreSkuSyncStatus&(model.SyncFlagStoreSkuModifiedMask|model.SyncFlagNewMask) != 0 { +// foodData := make(map[string]interface{}) +// foodDataList[0] = foodData +// foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(skuItem.SkuID) +// skus := []map[string]interface{}{ +// map[string]interface{}{ +// "sku_id": foodData[mtwmapi.KeyAppFoodCode], +// }, +// } +// foodData["skus"] = skus +// shouldCallSellStatus := !(skuItem.StoreSkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask|model.SyncFlagPriceMask) != 0) +// if !shouldCallSellStatus { +// globals.SugarLogger.Debugf("mtwm SyncStoreSkus3 skuID:%d, SkuSyncStatus:%d", skuItem.SkuID, skuItem.StoreSkuSyncStatus) +// mergeStoreSkuStatus := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) +// if !(skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask != 0 && mergeStoreSkuStatus != model.SkuStatusNormal) { // 待创建且不可售的,暂不新建 +// if skuItem.Img == "" { +// err = fmt.Errorf("SKUNAME%d:%s没有图片,同步失败", skuItem.NameID, skuItem.Name) +// } else { +// pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(skuItem.Price), int(storeDetail.PricePercentage)) +// // globals.SugarLogger.Debugf("skuID:%d, price:%d, pricePercentage:%d", skuItem.SkuID, skuItem.Price, pricePercentage) +// // globals.SugarLogger.Debugf(utils.Format4Output(storeDetail.PricePercentagePackObj, false)) +// foodData["name"] = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, mtwmapi.MaxSkuNameCharCount) +// foodData["description"] = skuItem.Comment +// foodData["price"] = jxutils.IntPrice2Standard(int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), pricePercentage, skuItem.CatPricePercentage))) +// foodData["min_order_count"] = 1 +// foodData["unit"] = skuItem.Unit +// foodData["box_num"] = 0 +// foodData["box_price"] = 0.0 +// foodData["category_name"] = skuItem.VendorCatID +// foodData["is_sold_out"] = skuStatusJX2Mtwm(mergeStoreSkuStatus) +// foodData["picture"] = skuItem.Img +// if skuItem.DescImg != "" { +// foodData["picture_contents"] = skuItem.DescImg +// } +// foodData["sequence"] = skuItem.Price +// if skuItem.VendorVendorCatID != 0 { +// foodData["tag_id"] = utils.Int64ToStr(skuItem.VendorVendorCatID) +// } else { +// // foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) +// } +// skus[0]["spec"] = jxutils.ComposeSkuSpec(skuItem.SpecQuality, skuItem.SpecUnit) +// skus[0]["price"] = foodData["price"] +// skus[0]["stock"] = "*" +// skus[0]["upc"] = skuItem.Upc +// if foodData["tag_id"] != nil { +// skus[0]["weight"] = skuItem.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 +// } +// if globals.EnableMtwmStoreWrite { +// // err = api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) -func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) - if err != nil { - return "", err - } - return p.syncStoreSkus(ctx, parentTask, storeDetail, skuIDs, isAsync, isContinueWhenError) -} +// foodData["skus"] = string(utils.MustMarshal(skus)) +// err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(skuItem.SkuID), foodData) +// } +// if err == nil { +// storeSkuBind.MtwmID = int64(skuItem.SkuID) +// updateFields = append(updateFields, model.FieldMtwmID) +// } +// } +// } else { +// // 暂不创建 +// updateFields = nil +// } +// } +// if err != nil { +// if isErrModifyPrice(err) { +// shouldCallSellStatus = true +// } +// } +// if shouldCallSellStatus { +// if skuItem.StoreSkuSyncStatus&(model.SyncFlagSaleMask) != 0 { +// globals.SugarLogger.Debugf("mtwm SyncStoreSkus4 skuID:%d, SkuSyncStatus:%d", skuItem.SkuID, skuItem.StoreSkuSyncStatus) +// sellStatus := skuStatusJX2Mtwm(jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus)) +// if globals.EnableMtwmStoreWrite { +// if _, err2 := api.MtwmAPI.RetailSkuSellStatus(ctx.GetTrackInfo(), vendorStoreID, []*mtwmapi.BareStoreFoodInfo{ +// &mtwmapi.BareStoreFoodInfo{ +// AppFoodCode: utils.Int2Str(skuItem.SkuID), +// Skus: []*mtwmapi.BareStoreSkuInfo{ +// &mtwmapi.BareStoreSkuInfo{ +// SkuID: utils.Int2Str(skuItem.SkuID), +// }, +// }, +// }, +// }, sellStatus); err2 != nil { +// err = err2 +// } +// } +// } +// } +// } +// if err == nil { +// if len(updateFields) > 0 { +// _, err = dao.UpdateEntity(db, storeSkuBind, updateFields...) +// } +// } else if isErrModifyPrice(err) { +// // err = partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDMTWM) +// } +// return nil, err +// }, skus) +// if parentTask != nil { +// parentTask.AddChild(rootTask) +// } +// rootTask.Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// hint = utils.Int2Str(len(skus)) +// } else { +// hint = rootTask.ID +// } +// return hint, err +// } -// hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 -func (p *PurchaseHandler) syncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeDetail *dao.StoreDetail, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - storeID := storeDetail.Store.ID - globals.SugarLogger.Debugf("mtwm SyncStoreSkus storeID:%d, skuIDs:%v, isContinueWhenError:%t, userName:%s", storeID, skuIDs, isContinueWhenError, ctx.GetUserName()) - db := dao.GetDB() - for i := 0; i < 3; i++ { // 最多重试三次 - if hint, err = p.SyncLocalStoreCategory(ctx, db, storeID, false, skuIDs); err != nil { - return "", err - } - if hint != "0" { - if hint, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { - return "", err - } - } - if hint == "0" { - break - } - } - if hint != "0" { - return "", errors.New("同步门店商品所需目录失败") - } - skus, err := dao.GetStoreSkus(db, model.VendorIDMTWM, storeID, skuIDs) - if err != nil { - return "", err - } - // globals.SugarLogger.Debug(utils.Format4Output(skus, false)) - vendorStoreID := storeDetail.VendorStoreID - rootTask := tasksch.NewParallelTask("美团外卖SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, - func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - foodDataList := make([]map[string]interface{}, len(batchItemList)) - // for k, v := range batchItemList { - v := batchItemList[0] - skuItem := v.(*dao.StoreSkuSyncInfo) - updateFields := []string{model.FieldMtwmSyncStatus} - storeSkuBind := &model.StoreSkuBind{} - storeSkuBind.ID = skuItem.BindID - if skuItem.NameID == 0 || skuItem.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 { - if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(skuItem.VendorSkuID) { - if globals.EnableMtwmStoreWrite { - if err = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, skuItem.VendorSkuID); mtwmapi.IsErrSkuNotExist(err) { - err = nil - } - } - } - if err == nil { - if utils.IsTimeZero(storeSkuBind.DeletedAt) { - storeSkuBind.DeletedAt = time.Now() - updateFields = append(updateFields, model.FieldDeletedAt) - } - if !dao.IsVendorThingIDEmpty(skuItem.VendorSkuID) { - storeSkuBind.MtwmID = 0 - updateFields = append(updateFields, model.FieldMtwmID) - } - } - } else if skuItem.StoreSkuSyncStatus&(model.SyncFlagStoreSkuModifiedMask|model.SyncFlagNewMask) != 0 { - foodData := make(map[string]interface{}) - foodDataList[0] = foodData - foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(skuItem.SkuID) - skus := []map[string]interface{}{ - map[string]interface{}{ - "sku_id": foodData[mtwmapi.KeyAppFoodCode], - }, - } - foodData["skus"] = skus - shouldCallSellStatus := !(skuItem.StoreSkuSyncStatus&(model.SyncFlagModifiedMask|model.SyncFlagNewMask|model.SyncFlagPriceMask) != 0) - if !shouldCallSellStatus { - globals.SugarLogger.Debugf("mtwm SyncStoreSkus3 skuID:%d, SkuSyncStatus:%d", skuItem.SkuID, skuItem.StoreSkuSyncStatus) - mergeStoreSkuStatus := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) - if !(skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask != 0 && mergeStoreSkuStatus != model.SkuStatusNormal) { // 待创建且不可售的,暂不新建 - if skuItem.Img == "" { - err = fmt.Errorf("SKUNAME%d:%s没有图片,同步失败", skuItem.NameID, skuItem.Name) - } else { - pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(skuItem.Price), int(storeDetail.PricePercentage)) - // globals.SugarLogger.Debugf("skuID:%d, price:%d, pricePercentage:%d", skuItem.SkuID, skuItem.Price, pricePercentage) - // globals.SugarLogger.Debugf(utils.Format4Output(storeDetail.PricePercentagePackObj, false)) - foodData["name"] = jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, mtwmapi.MaxSkuNameCharCount) - foodData["description"] = skuItem.Comment - foodData["price"] = jxutils.IntPrice2Standard(int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), pricePercentage, skuItem.CatPricePercentage))) - foodData["min_order_count"] = 1 - foodData["unit"] = skuItem.Unit - foodData["box_num"] = 0 - foodData["box_price"] = 0.0 - foodData["category_name"] = skuItem.VendorCatID - foodData["is_sold_out"] = skuStatusJX2Mtwm(mergeStoreSkuStatus) - foodData["picture"] = skuItem.Img - if skuItem.DescImg != "" { - foodData["picture_contents"] = skuItem.DescImg - } - foodData["sequence"] = skuItem.Price - if skuItem.VendorVendorCatID != 0 { - foodData["tag_id"] = utils.Int64ToStr(skuItem.VendorVendorCatID) - } else { - // foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) - } - skus[0]["spec"] = jxutils.ComposeSkuSpec(skuItem.SpecQuality, skuItem.SpecUnit) - skus[0]["price"] = foodData["price"] - skus[0]["stock"] = "*" - skus[0]["upc"] = skuItem.Upc - if foodData["tag_id"] != nil { - skus[0]["weight"] = skuItem.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 - } - if globals.EnableMtwmStoreWrite { - // err = api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) +// func isErrModifyPrice(err error) bool { +// if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 1 { +// for _, v := range []string{ +// "折扣商品原价不允许修改", +// } { +// if strings.Index(errExt.ErrMsg(), v) >= 0 { +// return true +// } +// } +// } +// return false +// } +// func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { +// return hint, err +// } - foodData["skus"] = string(utils.MustMarshal(skus)) - err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(skuItem.SkuID), foodData) - } - if err == nil { - storeSkuBind.MtwmID = int64(skuItem.SkuID) - updateFields = append(updateFields, model.FieldMtwmID) - } - } - } else { - // 暂不创建 - updateFields = nil - } - } - if err != nil { - if isErrModifyPrice(err) { - shouldCallSellStatus = true - } - } - if shouldCallSellStatus { - if skuItem.StoreSkuSyncStatus&(model.SyncFlagSaleMask) != 0 { - globals.SugarLogger.Debugf("mtwm SyncStoreSkus4 skuID:%d, SkuSyncStatus:%d", skuItem.SkuID, skuItem.StoreSkuSyncStatus) - sellStatus := skuStatusJX2Mtwm(jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus)) - if globals.EnableMtwmStoreWrite { - if _, err2 := api.MtwmAPI.RetailSkuSellStatus(ctx.GetTrackInfo(), vendorStoreID, []*mtwmapi.BareStoreFoodInfo{ - &mtwmapi.BareStoreFoodInfo{ - AppFoodCode: utils.Int2Str(skuItem.SkuID), - Skus: []*mtwmapi.BareStoreSkuInfo{ - &mtwmapi.BareStoreSkuInfo{ - SkuID: utils.Int2Str(skuItem.SkuID), - }, - }, - }, - }, sellStatus); err2 != nil { - err = err2 - } - } - } - } - } - if err == nil { - if len(updateFields) > 0 { - _, err = dao.UpdateEntity(db, storeSkuBind, updateFields...) - } - } else if isErrModifyPrice(err) { - // err = partner.NewErrorCode(err.Error(), partner.ErrCodeChangePriceFailed, model.VendorIDMTWM) - } - return nil, err - }, skus) - if parentTask != nil { - parentTask.AddChild(rootTask) - } - rootTask.Run() - if !isAsync { - _, err = rootTask.GetResult(0) - hint = utils.Int2Str(len(skus)) - } else { - hint = rootTask.ID - } - return hint, err -} +// func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// userName := ctx.GetUserName() +// globals.SugarLogger.Debugf("mtwm FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) -func isErrModifyPrice(err error) bool { - if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 1 { - for _, v := range []string{ - "折扣商品原价不允许修改", - } { - if strings.Index(errExt.ErrMsg(), v) >= 0 { - return true - } - } - } - return false -} -func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { - return hint, err -} +// db := dao.GetDB() +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) +// if err != nil { +// return "", err +// } -func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - userName := ctx.GetUserName() - globals.SugarLogger.Debugf("mtwm FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) - - db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) - if err != nil { - return "", err - } - - rootTask := tasksch.NewSeqTask("美团外卖FullSyncStoreSkus", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - switch step { - case 0: - err = p.DeleteStoreAllSkus(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError) - if isContinueWhenError { - err = nil - } - if err == nil { - _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, []int{storeID}, nil, model.SyncFlagNewMask) - } - case 1: - if err = p.DeleteStoreAllCategories(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError); err == nil { - _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, []int{storeID}, nil, model.SyncFlagNewMask) - } - case 2: - _, err = p.SyncLocalStoreCategory(ctx, db, storeID, true, nil) - case 3: - _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) - case 4: - _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError) - } - return nil, err - }, 5) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - _, err = rootTask.GetResult(0) - } - return rootTask.ID, err -} +// rootTask := tasksch.NewSeqTask("美团外卖FullSyncStoreSkus", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// switch step { +// case 0: +// err = p.DeleteStoreAllSkus(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError) +// if isContinueWhenError { +// err = nil +// } +// if err == nil { +// _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDMTWM, []int{storeID}, nil, model.SyncFlagNewMask) +// } +// case 1: +// if err = p.DeleteStoreAllCategories(ctx, rootTask, storeID, storeDetail.VendorStoreID, isContinueWhenError); err == nil { +// _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDMTWM, []int{storeID}, nil, model.SyncFlagNewMask) +// } +// case 2: +// _, err = p.SyncLocalStoreCategory(ctx, db, storeID, true, nil) +// case 3: +// _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) +// case 4: +// _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, false, isContinueWhenError) +// } +// return nil, err +// }, 5) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// } +// return rootTask.ID, err +// } diff --git a/business/partner/purchase/weimob/wsc/store_sku.go b/business/partner/purchase/weimob/wsc/store_sku.go index 9814c1038..c3e3e95d7 100644 --- a/business/partner/purchase/weimob/wsc/store_sku.go +++ b/business/partner/purchase/weimob/wsc/store_sku.go @@ -1,340 +1,313 @@ package wsc -import ( - "errors" - "fmt" - "math/rand" - - "git.rosy.net.cn/baseapi/platformapi/weimobapi" - "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxutils" - "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" -) - -const ( - DefFreightTemplateId = 6537248 - DefDeliveryTypeId = 177445 - DefVendorCategoryId = 35 - DefCatImg = "https://image-c.weimobwmc.com/openruntime/249b77ced5da4736a56641ebcf4875ec.png" -) - -func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { - strStoreID := utils.Int2Str(storeID) - num := 0 - db := dao.GetDB() - rootTask := tasksch.NewSeqTask("微盟微商城SyncStoreCategory step1", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - level := step + 1 - catList, err := dao.GetStoreCategories(db, model.VendorIDWSC, storeID, level) - // globals.SugarLogger.Debug(utils.Format4Output(catList, false)) - if len(catList) > 0 { - num += len(catList) - task := tasksch.NewParallelTask(fmt.Sprintf("微盟微商城SyncStoreCategory step2, level=%d", level), nil, ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDWSC])} - catInfo := batchItemList[0].(*dao.SkuStoreCatInfo) - storeCatMap := &model.StoreSkuCategoryMap{} - storeCatMap.ID = catInfo.MapID - if catInfo.StoreCatSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 - if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { - globals.SugarLogger.Debugf("UpdateClassify strStoreID:%s, WscID:%s", strStoreID, catInfo.VendorCatID) - if globals.EnableWscStoreWrite { - err = api.WeimobAPI.UpdateClassify(utils.Str2Int64(catInfo.VendorCatID), composeFakeDelName(catInfo.Name), "") - } - } - } else if catInfo.StoreCatSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增 - catImg := "" - if level == 2 { - catImg = DefCatImg - } - if globals.EnableWscStoreWrite { - storeCatMap.WscID, err = api.WeimobAPI.AddClassify(catInfo.Name, utils.Str2Int64WithDefault(catInfo.ParentVendorCatID, 0), catImg) - } - if err == nil { - updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDWSC])) - } - } else if catInfo.StoreCatSyncStatus&(model.SyncFlagModifiedMask) != 0 { // 修改 - if globals.EnableWscStoreWrite { - err = api.WeimobAPI.UpdateClassify(utils.Str2Int64(catInfo.VendorCatID), catInfo.Name, "") - } - } - if err == nil { - db2 := dao.GetDB() - storeCatMap.WscSyncStatus = 0 - _, err = dao.UpdateEntity(db2, storeCatMap, updateFields...) - } - return nil, err - }, catList) - rootTask.AddChild(task).Run() - _, err = task.GetResult(0) - } - return nil, err - }, 2) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - hint = utils.Int2Str(num) - _, err = rootTask.GetResult(0) - } else { - hint = rootTask.ID - } - return "", nil -} - -// 此函数根据门店商品信息重建分类信息 -// 远程有,本地无, --> 删除远程 -// 远程有,本地有,映射无, --> 添加关联 -// 远程有,本地有,映射有, --> 不处理 -// 远程无,本地有,映射无, --> 添加本地 -// 远程无,本地有,映射有, --> 同步标记改为新增 -// hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 -func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, isAsync bool) (hint string, err error) { - if db == nil { - db = dao.GetDB() - } - catMap := make([]map[string]*dao.SkuStoreCatInfo, 2) - for i := 0; i < 2; i++ { - catMap[i] = make(map[string]*dao.SkuStoreCatInfo) - localCats, err := dao.GetSkusCategories(db, model.VendorIDWSC, storeID, nil, i+1) - // globals.SugarLogger.Debug(utils.Format4Output(localCats, false)) - if err != nil { - return "", err - } - for _, cat := range localCats { - catMap[i][cat.ParentCatName+"/"+cat.Name] = cat - } - } - - dao.Begin(db) - defer func() { - dao.Rollback(db) - }() - num := 0 - for i := 0; i < 2; i++ { - for _, v := range catMap[i] { - if v.MapID == -1 || v.MapID == 0 { // 本地缺失 - wscSyncStatus := int8(model.SyncFlagNewMask) - if v.MapID == -1 { // 远程有同名的,只是简单增加一条本地记录关联 - wscSyncStatus = 0 - } - catMap := &model.StoreSkuCategoryMap{ - StoreID: storeID, - CategoryID: v.ID, - WscID: utils.Str2Int64WithDefault(v.VendorCatID, 0), - WscSyncStatus: wscSyncStatus, - MtwmSyncStatus: model.SyncFlagNewMask, - EbaiSyncStatus: model.SyncFlagNewMask, - ElmSyncStatus: model.SyncFlagNewMask, - } - num++ - dao.WrapAddIDCULDEntity(catMap, ctx.GetUserName()) - if err = dao.CreateEntity(db, catMap); err != nil { - return "", err - } - } else { - if dao.IsVendorThingIDEmpty(v.VendorCatID) && ((v.StoreCatSyncStatus & model.SyncFlagNewMask) == 0) { - catMap := &model.StoreSkuCategoryMap{} - catMap.ID = v.MapID - if _, err = dao.UpdateEntityLogically(db, catMap, map[string]interface{}{ - model.FieldWscSyncStatus: model.SyncFlagNewMask, - }, ctx.GetUserName(), nil); err != nil { - return "", err - } - } - } - } - } - dao.Commit(db) - return utils.Int2Str(num), err -} - -// hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 -func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - db := dao.GetDB() - for i := 0; i < 3; i++ { // 最多重试三次 - if hint, err = p.SyncLocalStoreCategory(ctx, db, storeID, false); err != nil { - return "", err - } - if hint != "0" { - if hint, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { - return "", err - } - } - if hint == "0" { - break - } - } - if hint != "0" { - return "", errors.New("同步门店商品所需目录失败") - } - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDWSC) - if err != nil { - return "", err - } - skus, err := dao.GetStoreSkus(db, model.VendorIDWSC, storeID, skuIDs) - if err != nil { - return "", err - } - globals.SugarLogger.Debug(utils.Format4Output(skus, false)) - rootTask := tasksch.NewParallelTask("微盟微商城SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, - func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - v := batchItemList[0] - skuItem := v.(*dao.StoreSkuSyncInfo) - pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(skuItem.Price), int(storeDetail.PricePercentage)) - updateFields := []string{model.FieldWscSyncStatus} - storeSkuBind := &model.StoreSkuBind{} - storeSkuBind.ID = skuItem.BindID - if skuItem.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 { - if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask == 0 { - goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0) - if globals.EnableWscStoreWrite { - if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil { - err = api.WeimobAPI.UpdateGoodsTitle(goodsID, composeFakeDelName(skuItem.Name)) - } else if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.Code() == "1001930300001" { // 商品不存在错 - err = nil // 强制忽略 - } - } - } - } else if skuItem.StoreSkuSyncStatus&(model.SyncFlagStoreSkuModifiedMask|model.SyncFlagNewMask) != 0 { - outerGoodsCode := utils.Int2Str(skuItem.NameID) - title := jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30) - isPutAway := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) == model.SkuStatusNormal - categoryID := skuItem.VendorVendorCatID - if categoryID == 0 { - categoryID = DefVendorCategoryId - } - classifyIDList := []int64{utils.Str2Int64WithDefault(skuItem.VendorCatID, 0)} - if skuItem.SkuVendorCatID != "" { - if int64Value := utils.Str2Int64WithDefault(skuItem.SkuVendorCatID, 0); int64Value > 0 { - classifyIDList = append(classifyIDList, int64Value) - } - } - b2cGoods := &weimobapi.PendingSaveB2CGoodsVo{ - FreightTemplateId: DefFreightTemplateId, - DeliveryTypeIdList: []int64{DefDeliveryTypeId}, - B2cGoodsType: weimobapi.GoodsTypeNormal, - } - salePrice := int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), pricePercentage, skuItem.CatPricePercentage)) - skuList := []map[string]interface{}{ - map[string]interface{}{ - weimobapi.KeyOuterSkuCode: utils.Int2Str(skuItem.ID), - weimobapi.KeyImageURL: skuItem.Img, - weimobapi.KeySalePrice: jxutils.IntPrice2Standard(salePrice), - weimobapi.KeyCostPrice: jxutils.IntPrice2Standard(salePrice * 8 / 10), - weimobapi.KeyOriginalPrice: jxutils.IntPrice2Standard(salePrice * 10 / (6 + rand.Int63n(4))), - weimobapi.KeyEditStockNum: 0, //model.MaxStoreSkuStockQty, - weimobapi.KeyB2cSku: &weimobapi.PendingSaveB2CSkuVo{ - Weight: jxutils.IntWeight2Float(skuItem.Weight), - }, - }, - } - if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask != 0 { - var ( - goodsID int64 - skuMap map[string]int64 - ) - if globals.EnableWscStoreWrite { - goodsID, skuMap, err = api.WeimobAPI.AddGoods(outerGoodsCode, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryID, classifyIDList, b2cGoods, skuList, nil) - } else { - goodsID = jxutils.GenFakeID() - skuMap = map[string]int64{ - utils.Int2Str(skuItem.ID): jxutils.GenFakeID(), - } - } - if err == nil { - storeSkuBind.WscID = skuMap[utils.Int2Str(skuItem.ID)] - storeSkuBind.WscID2 = goodsID - updateFields = append(updateFields, model.FieldWscID, model.FieldWscID2) - } - } else { - goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0) - goodsInfo, err2 := api.WeimobAPI.QueryGoodsDetail(goodsID) - if err = err2; err == nil { - // http://open.weimob.com/docapi/article?tag=Af - // sku id,如果为空,则新增sku; 如果更新之前的skuId与入参skuId对应,则更新sku; 如果更新之前的skuId没有和入参的skuId对应,删除更新之前的sku - skuList[0][weimobapi.KeySkuID] = utils.Str2Int64WithDefault(skuItem.VendorSkuID, 0) - remoteSkuList := goodsInfo[weimobapi.KeySkuList].([]interface{}) - if len(remoteSkuList) > 0 { - // skuList[0][weimobapi.KeyEditStockNum] = model.MaxStoreSkuStockQty - int(utils.MustInterface2Int64(remoteSkuList[0].(map[string]interface{})[weimobapi.KeyAvailableStockNum])) - } - if globals.EnableWscStoreWrite { - _, _, err = api.WeimobAPI.UpdateGoods(goodsID, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryID, classifyIDList, b2cGoods, skuList, nil) - } - } - } - } - if err == nil { - _, err = dao.UpdateEntity(nil, storeSkuBind, updateFields...) - } - return nil, err - }, skus) - if parentTask != nil { - parentTask.AddChild(rootTask) - } - rootTask.Run() - if !isAsync { - _, err = rootTask.GetResult(0) - hint = utils.Int2Str(len(skus)) - } else { - hint = rootTask.ID - } - return hint, err -} - -func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { - return hint, err -} - -func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - userName := ctx.GetUserName() - globals.SugarLogger.Debugf("wsc FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) - - db := dao.GetDB() - rootTask := tasksch.NewSeqTask("微盟微商城FullSyncStoreSkus", ctx, - func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - switch step { - case 0: - _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDWSC, []int{storeID}, nil, model.SyncFlagNewMask) - case 1: - _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDWSC, []int{storeID}, nil, model.SyncFlagNewMask) - case 2: - _, err = p.SyncLocalStoreCategory(ctx, db, storeID, false) - case 3: - _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) - case 4: - _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError) - } - return nil, err - }, 5) - tasksch.AddChild(parentTask, rootTask).Run() - if !isAsync { - _, err = rootTask.GetResult(0) - } - return rootTask.ID, err -} - -func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { - return hint, err -} - -func composeFakeDelName(name string) string { - return "del_" + name -} - -// func SplitGoodsAndSkuIDFromJXVendorSkuID(vendorSkuID string) (goodsID, skuID int64) { -// list := strings.Split(vendorSkuID, ",") -// if len(list) == 2 { -// skuID = utils.Str2Int64WithDefault(list[0], 0) -// goodsID = utils.Str2Int64WithDefault(list[1], 0) +// func (p *PurchaseHandler) SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error) { +// strStoreID := utils.Int2Str(storeID) +// num := 0 +// db := dao.GetDB() +// rootTask := tasksch.NewSeqTask("微盟微商城SyncStoreCategory step1", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// level := step + 1 +// catList, err := dao.GetStoreCategories(db, model.VendorIDWSC, storeID, level) +// // globals.SugarLogger.Debug(utils.Format4Output(catList, false)) +// if len(catList) > 0 { +// num += len(catList) +// task := tasksch.NewParallelTask(fmt.Sprintf("微盟微商城SyncStoreCategory step2, level=%d", level), nil, ctx, +// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[model.VendorIDWSC])} +// catInfo := batchItemList[0].(*dao.SkuStoreCatInfo) +// storeCatMap := &model.StoreSkuCategoryMap{} +// storeCatMap.ID = catInfo.MapID +// if catInfo.StoreCatSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除 +// if catInfo.StoreCatSyncStatus&model.SyncFlagNewMask == 0 && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { +// globals.SugarLogger.Debugf("UpdateClassify strStoreID:%s, WscID:%s", strStoreID, catInfo.VendorCatID) +// if globals.EnableWscStoreWrite { +// err = api.WeimobAPI.UpdateClassify(utils.Str2Int64(catInfo.VendorCatID), composeFakeDelName(catInfo.Name), "") +// } +// } +// } else if catInfo.StoreCatSyncStatus&(model.SyncFlagNewMask|model.SyncFlagModifiedMask) != 0 { // 新增 +// catImg := "" +// if level == 2 { +// catImg = DefCatImg +// } +// if globals.EnableWscStoreWrite { +// storeCatMap.WscID, err = api.WeimobAPI.AddClassify(catInfo.Name, utils.Str2Int64WithDefault(catInfo.ParentVendorCatID, 0), catImg) +// } +// if err == nil { +// updateFields = append(updateFields, dao.GetVendorThingIDStructField(model.VendorNames[model.VendorIDWSC])) +// } +// } else if catInfo.StoreCatSyncStatus&(model.SyncFlagModifiedMask) != 0 { // 修改 +// if globals.EnableWscStoreWrite { +// err = api.WeimobAPI.UpdateClassify(utils.Str2Int64(catInfo.VendorCatID), catInfo.Name, "") +// } +// } +// if err == nil { +// db2 := dao.GetDB() +// storeCatMap.WscSyncStatus = 0 +// _, err = dao.UpdateEntity(db2, storeCatMap, updateFields...) +// } +// return nil, err +// }, catList) +// rootTask.AddChild(task).Run() +// _, err = task.GetResult(0) +// } +// return nil, err +// }, 2) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// hint = utils.Int2Str(num) +// _, err = rootTask.GetResult(0) +// } else { +// hint = rootTask.ID // } -// return goodsID, skuID +// return "", nil // } -// // skuID放在前面的原因是存入数据库后,便于以skuID的查找 -// func ComposeJXVendorSkuIDFromGoodsAndSkuID(goodsID, skuID int64) (vendorSkuID string) { -// return utils.Int64ToStr(skuID) + "," + utils.Int64ToStr(goodsID) +// // 此函数根据门店商品信息重建分类信息 +// // 远程有,本地无, --> 删除远程 +// // 远程有,本地有,映射无, --> 添加关联 +// // 远程有,本地有,映射有, --> 不处理 +// // 远程无,本地有,映射无, --> 添加本地 +// // 远程无,本地有,映射有, --> 同步标记改为新增 +// // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 +// func (p *PurchaseHandler) SyncLocalStoreCategory(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, isAsync bool) (hint string, err error) { +// if db == nil { +// db = dao.GetDB() +// } +// catMap := make([]map[string]*dao.SkuStoreCatInfo, 2) +// for i := 0; i < 2; i++ { +// catMap[i] = make(map[string]*dao.SkuStoreCatInfo) +// localCats, err := dao.GetSkusCategories(db, model.VendorIDWSC, storeID, nil, i+1) +// // globals.SugarLogger.Debug(utils.Format4Output(localCats, false)) +// if err != nil { +// return "", err +// } +// for _, cat := range localCats { +// catMap[i][cat.ParentCatName+"/"+cat.Name] = cat +// } +// } + +// dao.Begin(db) +// defer func() { +// dao.Rollback(db) +// }() +// num := 0 +// for i := 0; i < 2; i++ { +// for _, v := range catMap[i] { +// if v.MapID == -1 || v.MapID == 0 { // 本地缺失 +// wscSyncStatus := int8(model.SyncFlagNewMask) +// if v.MapID == -1 { // 远程有同名的,只是简单增加一条本地记录关联 +// wscSyncStatus = 0 +// } +// catMap := &model.StoreSkuCategoryMap{ +// StoreID: storeID, +// CategoryID: v.ID, +// WscID: utils.Str2Int64WithDefault(v.VendorCatID, 0), +// WscSyncStatus: wscSyncStatus, +// MtwmSyncStatus: model.SyncFlagNewMask, +// EbaiSyncStatus: model.SyncFlagNewMask, +// ElmSyncStatus: model.SyncFlagNewMask, +// } +// num++ +// dao.WrapAddIDCULDEntity(catMap, ctx.GetUserName()) +// if err = dao.CreateEntity(db, catMap); err != nil { +// return "", err +// } +// } else { +// if dao.IsVendorThingIDEmpty(v.VendorCatID) && ((v.StoreCatSyncStatus & model.SyncFlagNewMask) == 0) { +// catMap := &model.StoreSkuCategoryMap{} +// catMap.ID = v.MapID +// if _, err = dao.UpdateEntityLogically(db, catMap, map[string]interface{}{ +// model.FieldWscSyncStatus: model.SyncFlagNewMask, +// }, ctx.GetUserName(), nil); err != nil { +// return "", err +// } +// } +// } +// } +// } +// dao.Commit(db) +// return utils.Int2Str(num), err // } + +// // hint,如果是异步,返回的是任务ID,如果是同步,返回是本次需要同步的目录数 +// func (p *PurchaseHandler) SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +// db := dao.GetDB() +// for i := 0; i < 3; i++ { // 最多重试三次 +// if hint, err = p.SyncLocalStoreCategory(ctx, db, storeID, false); err != nil { +// return "", err +// } +// if hint != "0" { +// if hint, err = p.SyncStoreCategory(ctx, parentTask, storeID, false); err != nil { +// return "", err +// } +// } +// if hint == "0" { +// break +// } +// } +// if hint != "0" { +// return "", errors.New("同步门店商品所需目录失败") +// } +// storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDWSC) +// if err != nil { +// return "", err +// } +// skus, err := dao.GetStoreSkus(db, model.VendorIDWSC, storeID, skuIDs) +// if err != nil { +// return "", err +// } +// globals.SugarLogger.Debug(utils.Format4Output(skus, false)) +// rootTask := tasksch.NewParallelTask("微盟微商城SyncStoreSkus", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, +// func(rootTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { +// v := batchItemList[0] +// skuItem := v.(*dao.StoreSkuSyncInfo) +// pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, int(skuItem.Price), int(storeDetail.PricePercentage)) +// updateFields := []string{model.FieldWscSyncStatus} +// storeSkuBind := &model.StoreSkuBind{} +// storeSkuBind.ID = skuItem.BindID +// if skuItem.StoreSkuSyncStatus&model.SyncFlagDeletedMask != 0 { +// if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask == 0 { +// goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0) +// if globals.EnableWscStoreWrite { +// if err = api.WeimobAPI.UpdateGoodsShelfStatus([]int64{goodsID}, false); err == nil { +// err = api.WeimobAPI.UpdateGoodsTitle(goodsID, composeFakeDelName(skuItem.Name)) +// } else if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.Code() == "1001930300001" { // 商品不存在错 +// err = nil // 强制忽略 +// } +// } +// } +// } else if skuItem.StoreSkuSyncStatus&(model.SyncFlagStoreSkuModifiedMask|model.SyncFlagNewMask) != 0 { +// outerGoodsCode := utils.Int2Str(skuItem.NameID) +// title := jxutils.ComposeSkuName(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 30) +// isPutAway := jxutils.MergeSkuStatus(skuItem.Status, skuItem.StoreSkuStatus) == model.SkuStatusNormal +// categoryID := skuItem.VendorVendorCatID +// if categoryID == 0 { +// categoryID = DefVendorCategoryId +// } +// classifyIDList := []int64{utils.Str2Int64WithDefault(skuItem.VendorCatID, 0)} +// if skuItem.SkuVendorCatID != "" { +// if int64Value := utils.Str2Int64WithDefault(skuItem.SkuVendorCatID, 0); int64Value > 0 { +// classifyIDList = append(classifyIDList, int64Value) +// } +// } +// b2cGoods := &weimobapi.PendingSaveB2CGoodsVo{ +// FreightTemplateId: DefFreightTemplateId, +// DeliveryTypeIdList: []int64{DefDeliveryTypeId}, +// B2cGoodsType: weimobapi.GoodsTypeNormal, +// } +// salePrice := int64(jxutils.CaculateSkuVendorPrice(int(skuItem.Price), pricePercentage, skuItem.CatPricePercentage)) +// skuList := []map[string]interface{}{ +// map[string]interface{}{ +// weimobapi.KeyOuterSkuCode: utils.Int2Str(skuItem.ID), +// weimobapi.KeyImageURL: skuItem.Img, +// weimobapi.KeySalePrice: jxutils.IntPrice2Standard(salePrice), +// weimobapi.KeyCostPrice: jxutils.IntPrice2Standard(salePrice * 8 / 10), +// weimobapi.KeyOriginalPrice: jxutils.IntPrice2Standard(salePrice * 10 / (6 + rand.Int63n(4))), +// weimobapi.KeyEditStockNum: 0, //model.MaxStoreSkuStockQty, +// weimobapi.KeyB2cSku: &weimobapi.PendingSaveB2CSkuVo{ +// Weight: jxutils.IntWeight2Float(skuItem.Weight), +// }, +// }, +// } +// if skuItem.StoreSkuSyncStatus&model.SyncFlagNewMask != 0 { +// var ( +// goodsID int64 +// skuMap map[string]int64 +// ) +// if globals.EnableWscStoreWrite { +// goodsID, skuMap, err = api.WeimobAPI.AddGoods(outerGoodsCode, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryID, classifyIDList, b2cGoods, skuList, nil) +// } else { +// goodsID = jxutils.GenFakeID() +// skuMap = map[string]int64{ +// utils.Int2Str(skuItem.ID): jxutils.GenFakeID(), +// } +// } +// if err == nil { +// storeSkuBind.WscID = skuMap[utils.Int2Str(skuItem.ID)] +// storeSkuBind.WscID2 = goodsID +// updateFields = append(updateFields, model.FieldWscID, model.FieldWscID2) +// } +// } else { +// goodsID := utils.Str2Int64WithDefault(skuItem.VendorNameID, 0) +// goodsInfo, err2 := api.WeimobAPI.QueryGoodsDetail(goodsID) +// if err = err2; err == nil { +// // http://open.weimob.com/docapi/article?tag=Af +// // sku id,如果为空,则新增sku; 如果更新之前的skuId与入参skuId对应,则更新sku; 如果更新之前的skuId没有和入参的skuId对应,删除更新之前的sku +// skuList[0][weimobapi.KeySkuID] = utils.Str2Int64WithDefault(skuItem.VendorSkuID, 0) +// remoteSkuList := goodsInfo[weimobapi.KeySkuList].([]interface{}) +// if len(remoteSkuList) > 0 { +// // skuList[0][weimobapi.KeyEditStockNum] = model.MaxStoreSkuStockQty - int(utils.MustInterface2Int64(remoteSkuList[0].(map[string]interface{})[weimobapi.KeyAvailableStockNum])) +// } +// if globals.EnableWscStoreWrite { +// _, _, err = api.WeimobAPI.UpdateGoods(goodsID, title, false, []string{skuItem.Img}, skuItem.Comment, isPutAway, 0, categoryID, classifyIDList, b2cGoods, skuList, nil) +// } +// } +// } +// } +// if err == nil { +// _, err = dao.UpdateEntity(nil, storeSkuBind, updateFields...) +// } +// return nil, err +// }, skus) +// if parentTask != nil { +// parentTask.AddChild(rootTask) +// } +// rootTask.Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// hint = utils.Int2Str(len(skus)) +// } else { +// hint = rootTask.ID +// } +// return hint, err +// } + +// func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error) { +// return hint, err +// } + +// func (p *PurchaseHandler) FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// userName := ctx.GetUserName() +// globals.SugarLogger.Debugf("wsc FullSyncStoreSkus storeID:%d, isContinueWhenError:%t, userName:%s", storeID, isContinueWhenError, userName) + +// db := dao.GetDB() +// rootTask := tasksch.NewSeqTask("微盟微商城FullSyncStoreSkus", ctx, +// func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { +// switch step { +// case 0: +// _, err = dao.SetStoreCategorySyncStatus(db, model.VendorIDWSC, []int{storeID}, nil, model.SyncFlagNewMask) +// case 1: +// _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDWSC, []int{storeID}, nil, model.SyncFlagNewMask) +// case 2: +// _, err = p.SyncLocalStoreCategory(ctx, db, storeID, false) +// case 3: +// _, err = p.SyncStoreCategory(ctx, rootTask, storeID, false) +// case 4: +// _, err = p.SyncStoreSkus(ctx, rootTask, storeID, nil, true, isContinueWhenError) +// } +// return nil, err +// }, 5) +// tasksch.AddChild(parentTask, rootTask).Run() +// if !isAsync { +// _, err = rootTask.GetResult(0) +// } +// return rootTask.ID, err +// } + +// func (p *PurchaseHandler) DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error) { +// return hint, err +// } + +// // func SplitGoodsAndSkuIDFromJXVendorSkuID(vendorSkuID string) (goodsID, skuID int64) { +// // list := strings.Split(vendorSkuID, ",") +// // if len(list) == 2 { +// // skuID = utils.Str2Int64WithDefault(list[0], 0) +// // goodsID = utils.Str2Int64WithDefault(list[1], 0) +// // } +// // return goodsID, skuID +// // } + +// // // skuID放在前面的原因是存入数据库后,便于以skuID的查找 +// // func ComposeJXVendorSkuIDFromGoodsAndSkuID(goodsID, skuID int64) (vendorSkuID string) { +// // return utils.Int64ToStr(skuID) + "," + utils.Int64ToStr(goodsID) +// // } diff --git a/business/partner/purchase/weimob/wsc/store_sku2.go b/business/partner/purchase/weimob/wsc/store_sku2.go index a606527b7..64804c785 100644 --- a/business/partner/purchase/weimob/wsc/store_sku2.go +++ b/business/partner/purchase/weimob/wsc/store_sku2.go @@ -16,6 +16,13 @@ import ( "git.rosy.net.cn/jx-callback/globals/api" ) +const ( + DefFreightTemplateId = 6537248 + DefDeliveryTypeId = 177445 + DefVendorCategoryId = 35 + DefCatImg = "https://image-c.weimobwmc.com/openruntime/249b77ced5da4736a56641ebcf4875ec.png" +) + // 门店分类 func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { remoteCats, err := api.WeimobAPI.QueryClassifyInfoList() @@ -190,3 +197,7 @@ func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, storeID i func (p *PurchaseHandler) GetStoreSkusInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) { return outStoreSkuList, err } + +func composeFakeDelName(name string) string { + return "del_" + name +}