From 0bdcdde11cb58e6ecbbf2d2e4e87e57679350d65 Mon Sep 17 00:00:00 2001 From: gazebo Date: Wed, 4 Sep 2019 11:42:58 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E6=B7=BB=E5=8A=A0IStoreSkuSorter=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E4=BD=86=E5=BD=93=E5=89=8D=E6=97=A0=E5=AE=9E?= =?UTF-8?q?=E9=99=85=E5=B9=B3=E5=8F=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business/jxstore/cms/sync_store_sku.go | 50 +++++++++++++++++++--- business/model/dao/store_sku.go | 11 ++++- business/model/model.go | 31 +++++++++----- business/partner/partner.go | 9 ++++ business/partner/partner_store_sku.go | 23 +++++++++- business/partner/purchase/jd/store_sku2.go | 14 ++++++ 6 files changed, 120 insertions(+), 18 deletions(-) diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index 0584ff5ca..8910894dd 100644 --- a/business/jxstore/cms/sync_store_sku.go +++ b/business/jxstore/cms/sync_store_sku.go @@ -3,6 +3,7 @@ package cms import ( "fmt" "regexp" + "sort" "strings" "time" @@ -189,6 +190,7 @@ func storeSkuSyncInfo2Bare(inSku *dao.StoreSkuSyncInfo) (outSku *partner.StoreSk Status: inSku.MergedStatus, VendorPrice: inSku.VendorPrice, + Seq: inSku.Seq, } if !isStoreSkuSyncNeedDelete(inSku) { outSku.Stock = model.MaxStoreSkuStockQty @@ -197,10 +199,12 @@ func storeSkuSyncInfo2Bare(inSku *dao.StoreSkuSyncInfo) (outSku *partner.StoreSk } func calVendorPrice4StoreSku(inSku *dao.StoreSkuSyncInfo, pricePercentagePack model.PricePercentagePack, pricePercentage int) (outSku *dao.StoreSkuSyncInfo) { - pricePercentage = jxutils.GetPricePercentage(pricePercentagePack, int(inSku.Price), pricePercentage) - inSku.VendorPrice = int64(jxutils.CaculateSkuVendorPrice(int(inSku.Price), pricePercentage, 0)) - if inSku.VendorPrice <= 0 { - inSku.VendorPrice = 1 // 最少1分钱 + if inSku.VendorPrice <= 0 { // 避免重新计算 + pricePercentage = jxutils.GetPricePercentage(pricePercentagePack, int(inSku.Price), pricePercentage) + inSku.VendorPrice = int64(jxutils.CaculateSkuVendorPrice(int(inSku.Price), pricePercentage, 0)) + if inSku.VendorPrice <= 0 { + inSku.VendorPrice = 1 // 最少1分钱 + } } return inSku } @@ -292,16 +296,22 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo singleStoreHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) storeSkuHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler) + reorderHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IStoreSkuSorter) var ( createList, updateList []*dao.StoreSkuSyncInfo deleteList, stockList, onlineList, offlineList, priceList []*partner.StoreSkuInfo updateItems []*dao.KVUpdateItem + reorderSkuMap map[string][]*dao.StoreSkuSyncInfo ) skuMap := make(map[*partner.StoreSkuInfo]*dao.StoreSkuSyncInfo) + if reorderHandler != nil { + reorderSkuMap = make(map[string][]*dao.StoreSkuSyncInfo) + } for _, sku := range skus { var bareSku *partner.StoreSkuInfo + isNeedReorder := false if isStoreSkuSyncNeedDelete(sku) { if !dao.IsVendorThingIDEmpty(sku.VendorSkuID) { bareSku = storeSkuSyncInfo2Bare(sku) @@ -330,6 +340,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo createList = append(createList, sku) } } + isNeedReorder = true } else { if dao.IsVendorThingIDEmpty(sku.VendorSkuID) { err = fmt.Errorf("门店:%d,修改没有创建的商品:%d", storeID, sku.SkuID) @@ -340,7 +351,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo } else { isAdded2Update := false // 修改商品信息时不改价(以免活动引起的失败),而用单独的改价来改 - if model.IsSyncStatusUpdate(sku.StoreSkuSyncStatus) && singleStoreHandler != nil { + if (model.IsSyncStatusUpdate(sku.StoreSkuSyncStatus) || (model.IsSyncStatusSec(sku.StoreSkuSyncStatus) && reorderHandler == nil)) && singleStoreHandler != nil { isAdded2Update = true updateList = append(updateList, calVendorPrice4StoreSku(sku, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))) } @@ -367,8 +378,12 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo } } } + isNeedReorder = model.IsSyncStatusSec(sku.StoreSkuSyncStatus) } } + if isNeedReorder && reorderHandler != nil && sku.VendorCatID != "" { + reorderSkuMap[sku.VendorCatID] = append(reorderSkuMap[sku.VendorCatID], sku) + } if bareSku != nil { skuMap[bareSku] = sku } @@ -500,9 +515,32 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo return nil, len(successList), err }, ctx, task, priceList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusPrice), isContinueWhenError) } + case 7: + if len(reorderSkuMap) > 0 { + var vendorCatIDs []string + for vendorCatID := range reorderSkuMap { + vendorCatIDs = append(vendorCatIDs, vendorCatID) + } + reorderTask := tasksch.NewParallelTask("门店商品排序", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + vendorCatID := batchItemList[0].(string) + skuList := reorderSkuMap[vendorCatID] + var bareList []*partner.StoreSkuInfo + for _, v := range skuList { + bareList = append(bareList, storeSkuSyncInfo2Bare(calVendorPrice4StoreSku(v, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage)))) + } + sort.Sort(partner.BareStoreSkuInfoList(bareList)) + if err = reorderHandler.ReorderStoreSkus(ctx, storeID, vendorStoreID, vendorCatID, bareList); err == nil { + updateStoreSku(dao.GetDB(), vendorID, skuList, model.SyncFlagSeqMask) + } + return retVal, err + }, vendorCatIDs) + tasksch.HandleTask(reorderTask, task, true).Run() + _, err = reorderTask.GetResult(0) + } } return retVal, err - }, []int{0, 1, 2, 3, 4, 5, 6}) + }, []int{0, 1, 2, 3, 4, 5, 6, 7}) tasksch.HandleTask(task, parentTask, true).Run() _, err = task.GetResult(0) return err diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index 83c4b58d7..1a31217ae 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -176,6 +176,7 @@ func GetStoreCategories(db *DaoDB, vendorID, storeID int, level int) (cats []*Sk } // 以store_sku_bind为基础来做同步,正常情况下使用 +// !!! 此函数不要将store_sku_bind中的vendor_price取出来放到StoreSkuSyncInfo.VendorPrice中,因为之后会依赖这个VendorPrice进行重算 // 单多门店模式厂商通用 func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, isDirty bool) (skus []*StoreSkuSyncInfo, err error) { if vendorID < 0 { @@ -211,6 +212,11 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, isDirty bool) t5.%s_sync_status store_cat_sync_status, t5.%s_id vendor_cat_id, t5sku.%s_sync_status sku_store_cat_sync_status, t5sku.%s_id sku_vendor_cat_id` fmtParams = append(fmtParams, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix) + } else { + sql += `, + t4.%s_id vendor_cat_id, + t5sku.%s_id sku_vendor_cat_id` + fmtParams = append(fmtParams, fieldPrefix, fieldPrefix) } sql += ` FROM store_sku_bind t1 @@ -236,6 +242,9 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, isDirty bool) LEFT JOIN store_sku_category_map t5 ON t4.id = t5.category_id AND t5.store_id = t1.store_id AND t5.deleted_at = ? LEFT JOIN store_sku_category_map t5sku ON t2.category_id = t5sku.category_id AND t5sku.store_id = t1.store_id AND t5sku.deleted_at = ?` sqlParams = append(sqlParams, utils.DefaultTimeValue, utils.DefaultTimeValue) + } else { + sql += ` + LEFT JOIN sku_category t5sku ON t5sku.id = t2.category_id` } sql += " WHERE 1 = 1" if storeID > 0 { @@ -532,4 +541,4 @@ func (s *StoreSkuSyncInfo) GetSeq() int { return s.Seq } return int(s.VendorPrice) - } \ No newline at end of file +} diff --git a/business/model/model.go b/business/model/model.go index dde6a51b9..d49ac05bc 100644 --- a/business/model/model.go +++ b/business/model/model.go @@ -67,24 +67,31 @@ type ModelIDCULD struct { DeletedAt time.Time `orm:"type(datetime);default('1970-01-01 00:00:00')" json:"deletedAt"` } -// flag按位表示,第一位表示修改,第二位表示新增,第三位表示删除 +// 同步标识掩码 const ( + // general SyncFlagModifiedMask = 1 SyncFlagNewMask = 2 SyncFlagDeletedMask = 4 - SyncFlagSaleMask = 8 // 改了门店商品可售状态必须设置此标志 - SyncFlagPriceMask = 16 // 改了门店商品价格必须设置此标志 - SyncFlagStockMask = 32 // 修改库存同步标识,当前只有多门店平台才会用到 - SyncFlagSpecMask = 64 // 原值32 - - SyncFlagStoreSkuOnlyMask = SyncFlagSaleMask | SyncFlagPriceMask - SyncFlagStoreSkuModifiedMask = SyncFlagStoreSkuOnlyMask | SyncFlagModifiedMask - SyncFlagChangedMask = SyncFlagSpecMask | SyncFlagNewMask | SyncFlagDeletedMask | SyncFlagStoreSkuModifiedMask - + // store only SyncFlagStoreName = 8 SyncFlagStoreAddress = 16 SyncFlagStoreStatus = 32 + + // sku only + SyncFlagSpecMask = 64 // 规格修改,原值32 + + // store sku only + SyncFlagSaleMask = 8 // 改了门店商品可售状态必须设置此标志 + SyncFlagPriceMask = 16 // 改了门店商品价格必须设置此标志 + SyncFlagStockMask = 32 // 修改库存同步标识,当前只有多门店平台才会用到 + SyncFlagSeqMask = 64 // 门店商家分类下的排序顺序 + + // combine + SyncFlagStoreSkuOnlyMask = SyncFlagSaleMask | SyncFlagPriceMask + SyncFlagStoreSkuModifiedMask = SyncFlagStoreSkuOnlyMask | SyncFlagModifiedMask + SyncFlagChangedMask = SyncFlagSpecMask | SyncFlagNewMask | SyncFlagDeletedMask | SyncFlagStoreSkuModifiedMask ) func IsSyncStatusNew(syncStatus int8) bool { @@ -107,6 +114,10 @@ func IsSyncStatusPrice(syncStatus int8) bool { return (syncStatus & SyncFlagPriceMask) != 0 } +func IsSyncStatusSec(syncStatus int8) bool { + return (syncStatus & SyncFlagSeqMask) != 0 +} + func IsSyncStatusNeedCreate(syncStatus int8) bool { return IsSyncStatusNew(syncStatus) && !IsSyncStatusDelete(syncStatus) } diff --git a/business/partner/partner.go b/business/partner/partner.go index 803ceb747..97c7c1b79 100644 --- a/business/partner/partner.go +++ b/business/partner/partner.go @@ -225,6 +225,15 @@ func GetPurchasePlatformFromVendorID(vendorID int) IPurchasePlatformHandler { return PurchasePlatformHandlers[vendorID] } +func GetExternalPurchasePlatformVendorIDs() (vendorIDs []int) { + for k := range PurchasePlatformHandlers { + if k != model.VendorIDJX { + vendorIDs = append(vendorIDs, k) + } + } + return vendorIDs +} + func GetMultiStoreVendorIDs() (vendorIDs []int) { for k, v := range PurchasePlatformHandlers { if _, ok := v.(IMultipleStoresHandler); ok { diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go index 0a9f33b02..ef9c654a0 100644 --- a/business/partner/partner_store_sku.go +++ b/business/partner/partner_store_sku.go @@ -2,8 +2,9 @@ package partner import ( "math" - "time" "regexp" + "time" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" @@ -39,6 +40,7 @@ type StoreSkuInfo struct { Stock int `json:"stock,omitempty"` VendorPrice int64 `json:"price,omitempty"` Status int `json:"status,omitempty"` + Seq int `json:"seq,omitempty"` } type SkuInfo struct { @@ -94,6 +96,21 @@ func (l BareStoreSkuInfoList) GetSkuIDList() (skuIDList []int) { return skuIDList } +func (l BareStoreSkuInfoList) Len() int { + return len(l) +} + +func (l BareStoreSkuInfoList) Less(i, j int) bool { + if l[i].Seq != l[j].Seq { + return l[i].Seq < l[j].Seq + } + return l[i].VendorPrice < l[j].VendorPrice +} + +func (l BareStoreSkuInfoList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + type BareCategoryInfo struct { VendorCatID string `json:"vendorCatID"` @@ -141,6 +158,10 @@ type ISingleStoreStoreSkuHandler interface { GetSensitiveWordRegexp() *regexp.Regexp } +type IStoreSkuSorter interface { + ReorderStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, vendorCatID string, storeSkuList []*StoreSkuInfo) (err error) +} + func BuildSkuName(skuID int, vendorSkuID string) (skuName *SkuNameInfo) { return &SkuNameInfo{ SkuList: []*SkuInfo{ diff --git a/business/partner/purchase/jd/store_sku2.go b/business/partner/purchase/jd/store_sku2.go index 6ef9a9c6d..fc3d5f7d2 100644 --- a/business/partner/purchase/jd/store_sku2.go +++ b/business/partner/purchase/jd/store_sku2.go @@ -209,3 +209,17 @@ func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, parentTask t } return hint, err } + +// func (p *PurchaseHandler) ReorderStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, vendorCatID string, storeSkuList []*partner.StoreSkuInfo) (err error) { +// storeSkuCount := len(storeSkuList) +// if storeSkuCount > 0 { +// if storeSkuCount > jdapi.MaxAddByStoreAndSkusCount { +// storeSkuList = storeSkuList[:jdapi.MaxAddByStoreAndSkusCount] +// } +// vendorSkuIDs := partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList() +// if globals.EnableJdStoreWrite { +// err = getAPI("").AddByStoreAndSkus(utils.Str2Int64(vendorStoreID), vendorSkuIDs) +// } +// } +// return err +// }