diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index 1364ad65b..d5acfc8aa 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -354,7 +354,11 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s vendorStoreMap[v.VendorID] = append(vendorStoreMap[v.VendorID], v.StoreID) } for vendorID, storeIDs := range vendorStoreMap { - dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, nil, model.SyncFlagPriceMask) + if vendorID != model.VendorIDJX { + dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, nil, model.SyncFlagPriceMask) + } else { + ReCalculateJxPrice(ctx, storeIDs) + } } // for _, v := range storeMapList { // if _, err = dao.UpdateEntityLogicallyAndUpdateSyncStatus(db, &model.StoreSkuBind{}, nil, ctx.GetUserName(), map[string]interface{}{ diff --git a/business/jxstore/cms/store_sku.go b/business/jxstore/cms/store_sku.go index f9e8bf733..3dc915670 100644 --- a/business/jxstore/cms/store_sku.go +++ b/business/jxstore/cms/store_sku.go @@ -66,7 +66,7 @@ type StoreSkuExt struct { JdPrice int `json:"jdPrice"` EbaiPrice int `json:"ebaiPrice"` MtwmPrice int `json:"mtwmPrice"` - // WscPrice int `json:"wscPrice"` + JxPrice int `json:"jxPrice"` AutoSaleAt time.Time `orm:"type(datetime);null" json:"autoSaleAt"` @@ -198,7 +198,8 @@ func getGetStoresSkusBaseSQL(db *dao.DaoDB, storeIDs, skuIDs []int, isFocus bool sql += ` JOIN ( SELECT t2.store_id, t2.sku_id, - MIN(IF(t3.actual_act_price = 0, NULL, t3.actual_act_price)) actual_act_price, MIN(IF(t2.earning_price = 0, NULL, t2.earning_price)) earning_price /*non-zero min value*/ + MIN(IF(t3.actual_act_price <= 0, NULL, t3.actual_act_price)) actual_act_price, /*non-zero min value*/ + MIN(IF(t2.earning_price <= 0, NULL, t2.earning_price)) earning_price /*non-zero min value*/ FROM act t1 JOIN act_store_sku t2 ON t2.act_id = t1.id AND t2.deleted_at = ? JOIN act_store_sku_map t3 ON t3.bind_id = t2.id AND t3.act_id = t1.id AND (t3.sync_status & ? = 0 OR t1.type = ?) @@ -443,7 +444,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo t4.sub_store_id, t4.price bind_price, IF(t4.unit_price IS NOT NULL, t4.unit_price, t1.price) unit_price, t4.status store_sku_status, t4.auto_sale_at, t4.ebai_id, t4.mtwm_id, t4.jd_sync_status, t4.ebai_sync_status, t4.mtwm_sync_status, - t4.jd_price, t4.ebai_price, t4.mtwm_price + t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price ` + sql var tmpList []*tGetStoresSkusInfo beginTime := time.Now() @@ -924,6 +925,12 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs } }() for _, storeID := range storeIDs { + // todo 可以考虑在需要更新价格再获取 + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDJX) + if err != nil { + dao.Rollback(db) + return nil, err + } for _, skuBindInfo := range skuBindInfos { // 关注且没有给价时,需要尝试从store_sku_bind中得到已有的单价 needGetExistingUnitPrice := skuBindInfo.UnitPrice == 0 && skuBindInfo.IsFocus == 1 @@ -1001,6 +1008,7 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs Price: jxutils.CaculateSkuPrice(unitPrice, v.SpecQuality, v.SpecUnit, v.SkuNameUnit), Status: model.StoreSkuBindStatusDontSale, // 缺省不可售? } + skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) if tmpStatus := getSkuSaleStatus(inSkuBind, skuBindInfo); tmpStatus != model.StoreSkuBindStatusNA { skuBind.Status = tmpStatus } @@ -1048,9 +1056,11 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs if skuBindInfo.UnitPrice != 0 && isCanChangePrice { // 这里是否需要加此条件限制 skuBind.UnitPrice = unitPrice skuBind.Price = jxutils.CaculateSkuPrice(unitPrice, v.SpecQuality, v.SpecUnit, v.SkuNameUnit) + skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) setStoreSkuBindStatus(skuBind, model.SyncFlagPriceMask) updateFieldMap["UnitPrice"] = 1 updateFieldMap["Price"] = 1 + updateFieldMap["JxPrice"] = 1 } // todo 这里应该是不需处理这个信息的吧? // if inSkuBind != nil && inSkuBind.EbaiID != 0 { @@ -1267,6 +1277,7 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode SET t1.last_operator = ?, t1.updated_at = ?, t1.price = t1.price * ? / 100, + t1.jx_price = t1.jx_price * ? / 100, t1.unit_price = t1.unit_price * ? / 100, t1.jd_sync_status = t1.jd_sync_status | ?, t1.mtwm_sync_status = t1.mtwm_sync_status | ?, @@ -1281,6 +1292,7 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode now, pricePercentage, pricePercentage, + pricePercentage, model.SyncFlagPriceMask, model.SyncFlagPriceMask, model.SyncFlagPriceMask, @@ -1307,13 +1319,14 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode JOIN sku t2 ON t1.sku_id = t2.id/* AND t2.deleted_at = ?*/ JOIN sku_name t3 ON t2.name_id = t3.id/* AND t2.deleted_at = ?*/ LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t2.deleted_at = ? - SET t1.deleted_at = ?, - t1.updated_at = ?, - t1.last_operator = ?, - t1.status = ?, - t1.jd_sync_status = IF((t1.jd_sync_status & ?) <> 0, 0, ?), - t1.mtwm_sync_status = IF((t1.mtwm_sync_status & ?) <> 0, 0, ?), - t1.ebai_sync_status = IF((t1.ebai_sync_status & ?) <> 0, 0, ?) + SET + t1.deleted_at = ?, + t1.updated_at = ?, + t1.last_operator = ?, + t1.status = ?, + t1.jd_sync_status = IF((t1.jd_sync_status & ?) <> 0, 0, ?), + t1.mtwm_sync_status = IF((t1.mtwm_sync_status & ?) <> 0, 0, ?), + t1.ebai_sync_status = IF((t1.ebai_sync_status & ?) <> 0, 0, ?) WHERE t1.store_id = ? AND t1.deleted_at = ? AND t0.id IS NULL ` sqlDeleteParams := []interface{}{ @@ -1356,10 +1369,12 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode JOIN sku t2 ON t1.sku_id = t2.id/* AND t2.deleted_at = ?*/ JOIN sku_name t3 ON t2.name_id = t3.id/* AND t3.deleted_at = ?*/ LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ? - SET t1.last_operator = ?, + SET + t1.last_operator = ?, t1.updated_at = ?, t1.sub_store_id = 0, t1.price = IF(t0.price * ? / 100 > 0, t0.price * ? / 100, 1), + t1.jx_price = IF(t0.jx_price * ? / 100 > 0, t0.jx_price * ? / 100, 1), t1.unit_price = IF(t0.unit_price * ? / 100 > 0, t0.unit_price * ? / 100, 1), t1.status = IF(? = 0, t1.status, t0.status), t1.jd_sync_status = t1.jd_sync_status | ?, @@ -1379,6 +1394,8 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode pricePercentage, pricePercentage, pricePercentage, + pricePercentage, + pricePercentage, isModifyStatus, syncStatus, syncStatus, @@ -1397,10 +1414,11 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode // 添加toStore中不存在,但fromStore存在的 sql = ` - INSERT INTO store_sku_bind(created_at, updated_at, last_operator, deleted_at, store_id, sku_id, sub_store_id, price, unit_price, status, + INSERT INTO store_sku_bind(created_at, updated_at, last_operator, deleted_at, store_id, sku_id, sub_store_id, price, jx_price, unit_price, status, jd_sync_status, ebai_sync_status, mtwm_sync_status) SELECT ?, ?, ?, ?, ?, - t1.sku_id, 0, IF(t1.price * ? / 100 > 0, t1.price * ? / 100, 1), IF(t1.unit_price * ? / 100 > 0, t1.unit_price * ? / 100, 1), + t1.sku_id, 0, + IF(t1.price * ? / 100 > 0, t1.price * ? / 100, 1), IF(t1.jx_price * ? / 100 > 0, t1.jx_price * ? / 100, 1), IF(t1.unit_price * ? / 100 > 0, t1.unit_price * ? / 100, 1), IF(? = 0, ?, t1.status), ?, ?, ? FROM store_sku_bind t1 JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? @@ -1415,6 +1433,8 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode pricePercentage, pricePercentage, pricePercentage, + pricePercentage, + pricePercentage, isModifyStatus, model.SkuStatusDontSale, model.SyncFlagNewMask, @@ -2045,3 +2065,22 @@ func AutoSaleStoreSku(ctx *jxcontext.Context, storeIDs []int, isNeedSync bool) ( } return err } + +func ReCalculateJxPrice(ctx *jxcontext.Context, storeIDs []int) (err error) { + db := dao.GetDB() + for _, storeID := range storeIDs { + if storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX); err == nil { + if storeSkuList, err := dao.GetStoresSkusInfo(db, []int{storeID}, nil); err == nil { + for _, skuBind := range storeSkuList { + skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) + dao.UpdateEntity(db, skuBind) + } + } else { + return err + } + } else { + return err + } + } + return err +} diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index cf92145b1..d63cf40d9 100644 --- a/business/jxstore/cms/sync_store_sku.go +++ b/business/jxstore/cms/sync_store_sku.go @@ -213,8 +213,7 @@ func storeSkuSyncInfo2Bare(inSku *dao.StoreSkuSyncInfo) (outSku *partner.StoreSk func calVendorPrice4StoreSku(inSku *dao.StoreSkuSyncInfo, pricePercentagePack model.PricePercentagePack, pricePercentage int) (outSku *dao.StoreSkuSyncInfo) { if inSku.VendorPrice <= 0 { // 避免重新计算 - pricePercentage2, priceAdd2 := jxutils.GetPricePercentage(pricePercentagePack, int(inSku.Price), pricePercentage) - inSku.VendorPrice = int64(jxutils.CaculateSkuVendorPrice(int(inSku.Price), pricePercentage2, priceAdd2)) + inSku.VendorPrice = int64(jxutils.CaculatePriceByPricePack(pricePercentagePack, pricePercentage, int(inSku.Price))) if inSku.VendorPrice <= 0 { inSku.VendorPrice = 1 // 最少1分钱 } @@ -348,7 +347,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo calVendorPrice4StoreSku(sku, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage)) if singleStoreHandler == nil { sku.StoreSkuSyncStatus |= model.SyncFlagSaleMask | model.SyncFlagPriceMask - bareSku = storeSkuSyncInfo2Bare(calVendorPrice4StoreSku(sku, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))) + bareSku = storeSkuSyncInfo2Bare(sku) stockList = append(stockList, bareSku) priceList = append(priceList, bareSku) if sku.MergedStatus == model.SkuStatusNormal { diff --git a/business/jxutils/jxutils_cms.go b/business/jxutils/jxutils_cms.go index 5c54e00e4..874682300 100644 --- a/business/jxutils/jxutils_cms.go +++ b/business/jxutils/jxutils_cms.go @@ -245,10 +245,15 @@ func CaculateUnitPrice(skuPrice int, specQuality float32, specUnit string, skuNa return unitPrice } -func CaculateSkuVendorPrice(price, percentage, priceAdd int) (vendorPrice int) { - if percentage <= 10 || percentage >= 400 { - percentage = 100 +func ConstrainPricePercentage(percentage int) int { + if percentage <= model.MinVendorPricePercentage || percentage >= model.MaxVendorPricePercentage { + percentage = model.DefVendorPricePercentage } + return percentage +} + +func CaculateSkuVendorPrice(price, percentage, priceAdd int) (vendorPrice int) { + percentage = ConstrainPricePercentage(percentage) vendorPrice = int(math.Round(float64(price*percentage)/100)) + priceAdd if vendorPrice < 1 { vendorPrice = 1 @@ -257,9 +262,7 @@ func CaculateSkuVendorPrice(price, percentage, priceAdd int) (vendorPrice int) { } func CaculateSkuPriceFromVendor(vendorPrice, percentage, priceAdd int) (price int) { - if percentage <= 10 || percentage >= 400 { - percentage = 100 - } + percentage = ConstrainPricePercentage(percentage) price = int(math.Round(float64(vendorPrice-priceAdd) * 100 / float64(percentage))) if price < 0 { price = 0 @@ -269,18 +272,28 @@ func CaculateSkuPriceFromVendor(vendorPrice, percentage, priceAdd int) (price in func GetPricePercentage(l model.PricePercentagePack, price int, defPricePercentage int) (pricePercentage, priceAdd int) { pricePercentage = defPricePercentage - if len(l) > 0 { - var lastItem *model.PricePercentageItem - for _, v := range l { - if v.BeginPrice > price { + itemLen := len(l) + if itemLen > 0 { + low := 0 + high := itemLen - 1 + mid := 0 + for low <= high { + mid = low + (high-low)/2 + if mid == 0 || mid == itemLen-1 { break } - lastItem = v - } - if lastItem != nil { - pricePercentage = lastItem.PricePercentage - priceAdd = lastItem.PriceAdd + if price >= l[mid].BeginPrice { + if price < l[mid+1].BeginPrice { + break + } else { + low = mid + 1 + } + } else { + high = mid - 1 + } } + pricePercentage = l[mid].PricePercentage + priceAdd = l[mid].PriceAdd } return pricePercentage, priceAdd } @@ -303,6 +316,11 @@ func GetPricePercentageByVendorPrice(l model.PricePercentagePack, vendorPrice in return pricePercentage, priceAdd } +func CaculatePriceByPricePack(l model.PricePercentagePack, defPricePercentage, price int) (outPrice int) { + pricePercentage, priceAdd := GetPricePercentage(l, price, defPricePercentage) + return CaculateSkuVendorPrice(price, pricePercentage, priceAdd) +} + func IsSkuSpecial(specQuality float32, specUnit string) bool { return int(specQuality) == model.SpecialSpecQuality && (specUnit == model.SpecialSpecUnit || specUnit == model.SpecialSpecUnit2) } diff --git a/business/jxutils/jxutils_cms_test.go b/business/jxutils/jxutils_cms_test.go index d447b160e..90bcd437e 100644 --- a/business/jxutils/jxutils_cms_test.go +++ b/business/jxutils/jxutils_cms_test.go @@ -164,3 +164,47 @@ func TestCaculateSkuPrice(t *testing.T) { } } } + +func TestGetPricePercentage(t *testing.T) { + type tTestInfo struct { + DesiredPrice int + UnitPrice int + SpecQuality float32 + SpecUnit string + Unit string + } + l := []*model.PricePercentageItem{ + &model.PricePercentageItem{ + BeginPrice: 0, + PricePercentage: 0, + PriceAdd: 0, + }, + &model.PricePercentageItem{ + BeginPrice: 10, + PricePercentage: 10, + PriceAdd: 1, + }, + &model.PricePercentageItem{ + BeginPrice: 20, + PricePercentage: 20, + PriceAdd: 2, + }, + &model.PricePercentageItem{ + BeginPrice: 30, + PricePercentage: 30, + PriceAdd: 3, + }, + } + for _, v := range [][]int{ + []int{0, 0, 0, 0}, + []int{30, 3, 40, 0}, + []int{20, 2, 25, 0}, + []int{10, 1, 10, 0}, + } { + pricePercentage, priceAdd := GetPricePercentage(l, v[2], v[3]) + if pricePercentage != v[0] || priceAdd != v[1] { + t.Errorf("price:%d, defPricePercentage:%d, expected pricePercentage:%d, priceAdd:%d, actual pricePercentage:%d, priceAdd:%d", + v[2], v[3], v[0], v[1], pricePercentage, priceAdd) + } + } +} diff --git a/business/model/const.go b/business/model/const.go index d055752f7..1a6030675 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -307,6 +307,14 @@ const ( AfsTypeFullRefund = 2 // 全额退款 ) +const ( + DefaultEarningPricePercentage = 70 // 门店缺省结算百分比 + + MinVendorPricePercentage = 10 + DefVendorPricePercentage = 100 // 平台缺省调价比例 + MaxVendorPricePercentage = 400 +) + func IsPurchaseVendorExist(vendorID int) bool { _, ok := VendorNames[vendorID] return ok && vendorID >= VendorIDPurchaseBegin && vendorID <= VendorIDPurchaseEnd @@ -358,7 +366,3 @@ func WaybillVendorID2Mask(vendorID int) (mask int8) { func IsAfsOrderFinalStatus(status int) bool { return status >= AfsOrderStatusFinished && status <= AfsOrderStatusFailed } - -const ( - DefaultEarningPricePercentage = 70 // 门店缺省结算百分比 -) diff --git a/business/model/dao/store.go b/business/model/dao/store.go index c9a63b540..75f0234a7 100644 --- a/business/model/dao/store.go +++ b/business/model/dao/store.go @@ -100,7 +100,7 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto storeDetail.FreightDeductionPackObj = FreightDeductionPack2Obj(storeDetail.FreightDeductionPackStr) if storeDetail.VendorStoreID == "" { storeDetail.VendorStatus = storeDetail.Status - storeDetail.PricePercentage = 100 + storeDetail.PricePercentage = model.DefVendorPricePercentage storeDetail.AutoPickup = 1 storeDetail.DeliveryType = model.StoreDeliveryTypeByStore storeDetail.DeliveryCompetition = 1 diff --git a/business/model/store_sku.go b/business/model/store_sku.go index 310697fcc..9147b3646 100644 --- a/business/model/store_sku.go +++ b/business/model/store_sku.go @@ -108,7 +108,7 @@ type StoreSkuBind struct { JdPrice int `json:"jdPrice"` EbaiPrice int `json:"ebaiPrice"` MtwmPrice int `json:"mtwmPrice"` - // JxPrice int `json:"jxPrice"` + JxPrice int `json:"jxPrice"` // WscPrice int `json:"wscPrice"` AutoSaleAt time.Time `orm:"type(datetime);null" json:"autoSaleAt"`