diff --git a/business/jxcallback/orderman/order.go b/business/jxcallback/orderman/order.go index 0dc2eda1e..38d34e093 100644 --- a/business/jxcallback/orderman/order.go +++ b/business/jxcallback/orderman/order.go @@ -21,13 +21,6 @@ import ( "github.com/astaxie/beego/orm" ) -type tStoreSkuBindAndVendorSkuID struct { - VendorSkuID int64 `orm:"column(vendor_sku_id)"` - SkuID int `orm:"column(sku_id)"` - Weight int - Price int -} - func init() { } @@ -323,49 +316,25 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. } orderSkus := order.Skus - vendorSkuIDs := make([]int64, 0) + var vendorSkuIDs []string for _, v := range orderSkus { - intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0) - if intVendorSkuID != 0 { - vendorSkuIDs = append(vendorSkuIDs, intVendorSkuID) + if v.VendorSkuID != "" { + vendorSkuIDs = append(vendorSkuIDs, v.VendorSkuID) } } if len(vendorSkuIDs) > 0 { - tableName := "t2" - if model.MultiStoresVendorMap[order.VendorID] == 1 { - tableName = "t1" - } - fieldPrefix := dao.ConvertDBFieldPrefix(model.VendorNames[order.VendorID]) - sql := ` - SELECT %s.%s_id vendor_sku_id, t1.id sku_id, t2.price, t1.weight - FROM sku t1 - LEFT JOIN store_sku_bind t2 ON t1.id = t2.sku_id AND t2.deleted_at = ? AND t2.store_id = ? - WHERE t1.deleted_at = ? AND %s.%s_id IN (-1, ` + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")" - sql = fmt.Sprintf(sql, tableName, fieldPrefix, tableName, fieldPrefix) - if order.VendorID == model.VendorIDJX { - sql = ` - SELECT t1.id vendor_sku_id, t1.id sku_id, t2.price, t1.weight - FROM sku t1 - LEFT JOIN store_sku_bind t2 ON t1.id = t2.sku_id AND t2.deleted_at = ? AND t2.store_id = ? - WHERE t1.deleted_at = ? AND t1.id IN (-1, ` + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")" - } - var skuInfos []*tStoreSkuBindAndVendorSkuID - if err = dao.GetRows(db, &skuInfos, sql, utils.DefaultTimeValue, jxStoreID, utils.DefaultTimeValue, vendorSkuIDs); err != nil { - globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku info for orderID:%s, error:%v", order.VendorOrderID, err) + l, err := dao.GetStoreSkuPriceAndWeight(db, order.VendorStoreID, order.VendorID, vendorSkuIDs) + if err != nil { return err } - skumapper := make(map[int64]*tStoreSkuBindAndVendorSkuID) - for _, v := range skuInfos { - skumapper[v.VendorSkuID] = v - } - + skumapper := storeSkuPriceAndWeight2Map(l) for _, v := range orderSkus { v.VendorOrderID = order.VendorOrderID v.VendorID = order.VendorID intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0) if intVendorSkuID != 0 && v.VendorSkuID != "-70000" { // todo hard code - skuBindInfo := skumapper[intVendorSkuID] + skuBindInfo := skumapper[v.VendorSkuID] if skuBindInfo == nil { globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku找不到门店价格(或商品映射),orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.VendorSkuID, v) } else { @@ -392,6 +361,14 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. return nil } +func storeSkuPriceAndWeight2Map(l []*dao.StoreSkuPriceAndWeight) (skuMapper map[string]*dao.StoreSkuPriceAndWeight) { + skuMapper = make(map[string]*dao.StoreSkuPriceAndWeight) + for _, v := range l { + skuMapper[v.VendorSkuID] = v + } + return skuMapper +} + func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) { jxStoreID := jxutils.GetShowStoreIDFromOrder(order) skuIDMap := make(map[int]int) diff --git a/business/jxcallback/orderman/order_afs.go b/business/jxcallback/orderman/order_afs.go index 776050f21..e020bbac0 100644 --- a/business/jxcallback/orderman/order_afs.go +++ b/business/jxcallback/orderman/order_afs.go @@ -1,7 +1,6 @@ package orderman import ( - "fmt" "strings" "git.rosy.net.cn/baseapi/utils" @@ -237,12 +236,11 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af return nil } orderSkus := order.Skus - vendorSkuIDs := make([]int64, 0) + var vendorSkuIDs []string skuIDMap := make(map[int]int) for _, v := range orderSkus { - intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0) - if intVendorSkuID != 0 { - vendorSkuIDs = append(vendorSkuIDs, intVendorSkuID) + if v.VendorSkuID != "" { + vendorSkuIDs = append(vendorSkuIDs, v.VendorSkuID) } if skuID := jxutils.GetSkuIDFromOrderSkuFinancial(v); skuID > 0 { @@ -250,26 +248,12 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af } } if len(vendorSkuIDs) > 0 { - tableName := "t2" - if model.MultiStoresVendorMap[order.VendorID] == 1 { - tableName = "t1" - } - fieldPrefix := dao.ConvertDBFieldPrefix(model.VendorNames[order.VendorID]) - sql := ` - SELECT %s.%s_id vendor_sku_id, t1.id sku_id, t2.price, t1.weight - FROM sku t1 - LEFT JOIN store_sku_bind t2 ON t1.id = t2.sku_id AND t2.deleted_at = ? AND t2.store_id = ? - WHERE t1.deleted_at = ? AND %s.%s_id IN (-1, ` + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")" - sql = fmt.Sprintf(sql, tableName, fieldPrefix, tableName, fieldPrefix) - var skuInfos []*tStoreSkuBindAndVendorSkuID - if err = dao.GetRows(db, &skuInfos, sql, utils.DefaultTimeValue, jxStoreID, utils.DefaultTimeValue, vendorSkuIDs); err != nil { - globals.SugarLogger.Errorf("updateAfsOrderSkuOtherInfo can not get sku info for orderID:%s, error:%v", order.VendorOrderID, err) + l, err := dao.GetStoreSkuPriceAndWeight(db, order.VendorStoreID, order.VendorID, vendorSkuIDs) + if err != nil { return err } - skumapper := make(map[int64]*tStoreSkuBindAndVendorSkuID) - for _, v := range skuInfos { - skumapper[v.VendorSkuID] = v - } + skumapper := storeSkuPriceAndWeight2Map(l) + var actStoreSkuMap *jxutils.ActStoreSkuMap if len(skuIDMap) > 0 { if order2, err2 := c.LoadOrder(order.VendorOrderID, order.VendorID); err2 == nil { @@ -292,7 +276,7 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0) if intVendorSkuID != 0 && v.VendorSkuID != "-70000" { // todo hard code - skuBindInfo := skumapper[intVendorSkuID] + skuBindInfo := skumapper[v.VendorSkuID] if skuBindInfo == nil { globals.SugarLogger.Infof("updateAfsOrderSkuOtherInfo [运营%s]%s订单sku找不到门店价格(或商品映射),orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.VendorSkuID, v) } else { diff --git a/business/jxstore/act/act.go b/business/jxstore/act/act.go index a1ca25b47..f80ada794 100644 --- a/business/jxstore/act/act.go +++ b/business/jxstore/act/act.go @@ -21,11 +21,6 @@ import ( const ( DefActSkuStock = 200 // 缺省活动库存 - - maxDiscount4SkuSecKill = 80 - maxDiscount4Sku = 98 - minDiscount4SkuDirectDown = 0 - minDiscount4SkuDirectDownMTWM = 30 ) type ActOrderRuleParam struct { @@ -64,11 +59,71 @@ type tPreCreateActInfo struct { ActStoreSku []*tPreCreateActStoreSku `json:"actStoreSku"` } +type tActRuleInfo struct { + MinDiscount int + MaxDiscount int +} + type ActManager struct { } var ( FixedActManager *ActManager + + actRuleMap = map[int]map[int]*tActRuleInfo{ + model.VendorIDJD: map[int]*tActRuleInfo{ + model.ActSkuFake: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 500, + }, + model.ActSkuDirectDown: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 99, + }, + model.ActSkuSecKill: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 80, + }, + }, + model.VendorIDMTWM: map[int]*tActRuleInfo{ + model.ActSkuFake: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 500, + }, + model.ActSkuDirectDown: &tActRuleInfo{ + MinDiscount: 30, + MaxDiscount: 99, + }, + model.ActSkuSecKill: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 30, + }, + }, + model.VendorIDEBAI: map[int]*tActRuleInfo{ + model.ActSkuFake: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 500, + }, + model.ActSkuDirectDown: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 99, + }, + }, + model.VendorIDJX: map[int]*tActRuleInfo{ + model.ActSkuFake: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 500, + }, + model.ActSkuDirectDown: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 99, + }, + model.ActSkuSecKill: &tActRuleInfo{ + MinDiscount: 0, + MaxDiscount: 80, + }, + }, + } ) func init() { @@ -256,11 +311,28 @@ func addActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actStoreSkuList [ return err } +func checkActUpdate(actID int, actMap map[int]*model.Act2) (err error) { + if len(actMap) == 0 { + return fmt.Errorf("活动%d不存在或已被取消", actID) + } + errList := errlist.New() + for vendorID, act := range actMap { + if vendorID == model.VendorIDEBAI && act.CreateType != model.ActCreateTypeAPI { + errList.AddErr(fmt.Errorf("饿百平台不支持修改或取消网页活动")) + } + } + return errList.GetErrListAsOne() +} + func AddActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSku []*ActStoreSkuParam) (err error) { actMap, err := dao.GetActVendorInfo(db, actID, nil) if err != nil { return err } + if err = checkActUpdate(actID, actMap); err != nil { + return err + } + vendorIDs := partner.GetVendorIDsFromActMap(actMap) var act *model.Act @@ -309,25 +381,33 @@ func AddActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actSto return err } +func getActRule(vendorID, actType int) (actRule *tActRuleInfo, err error) { + if actRuleMap[vendorID] != nil { + actRule = actRuleMap[vendorID][actType] + } + if actRule == nil { + err = fmt.Errorf("%s不支持%s活动", model.VendorChineseNames[vendorID], model.ActTypeName[actType]) + } + return actRule, err +} + func checkDiscountValidation(vendorIDs []int, actType int, pricePercentage float64) (err error) { pricePercentageMin := int(math.Floor(pricePercentage)) pricePercentageMax := int(math.Ceil(pricePercentage)) - if actType == model.ActSkuDirectDown && (pricePercentageMin < minDiscount4SkuDirectDown || pricePercentageMax > 99) { - if pricePercentageMin < minDiscount4SkuDirectDown { - err = fmt.Errorf("%s活动折扣必须大于:%d", model.ActTypeName[actType], minDiscount4SkuDirectDown) - } else if pricePercentageMax > maxDiscount4Sku { - err = fmt.Errorf("%s活动必须至少有%d折扣", model.ActTypeName[actType], maxDiscount4Sku) - } else if len(vendorIDs) > 0 && vendorIDs[0] == model.VendorIDMTWM && pricePercentageMin < minDiscount4SkuDirectDownMTWM { - err = fmt.Errorf("美团平台%s活动折扣必须大于:%d", model.ActTypeName[actType], minDiscount4SkuDirectDownMTWM) - } - } else if actType == model.ActSkuSecKill { - if len(vendorIDs) > 0 && vendorIDs[0] == model.VendorIDMTWM && pricePercentageMax > minDiscount4SkuDirectDownMTWM { - err = fmt.Errorf("美团平台%s活动折扣必须小于:%d", model.ActTypeName[actType], minDiscount4SkuDirectDownMTWM) - } else if pricePercentageMax > maxDiscount4SkuSecKill { - err = fmt.Errorf("%s活动折扣必须小于:%d", model.ActTypeName[actType], maxDiscount4SkuSecKill) + errList := errlist.New() + for _, vendorID := range vendorIDs { + actRule, err2 := getActRule(vendorID, actType) + if err2 == nil { + if pricePercentageMin < actRule.MinDiscount { + errList.AddErr(fmt.Errorf("%s%s活动折扣必须大于:%d", model.VendorChineseNames[vendorID], model.ActTypeName[actType], actRule.MinDiscount)) + } else if pricePercentageMax > actRule.MaxDiscount { + errList.AddErr(fmt.Errorf("%s%s活动折扣必须小于:%d", model.VendorChineseNames[vendorID], model.ActTypeName[actType], actRule.MaxDiscount)) + } + } else { + errList.AddErr(err2) } } - return err + return errList.GetErrListAsOne() } func checkActValidation(act *model.Act, vendorIDs []int) (err error) { @@ -644,8 +724,8 @@ func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, act if err != nil { return 0, err } - if len(actMap) == 0 { - return 0, fmt.Errorf("找不到活动:%d,或已被取消", actID) + if err = checkActUpdate(actID, actMap); err != nil { + return 0, err } actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil) @@ -958,6 +1038,7 @@ func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, s var wrongSkuList []*ActStoreSkuParam var storeSkuBindList []*model.StoreSkuBind + actRule, _ := getActRule(vendorID, actType) db := dao.GetDB() errList := errlist.New() for _, v := range storeSkuList { @@ -978,11 +1059,7 @@ func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, s } else { vendorPrice = dao.GetStoreSkuBindVendorPrice(storeSkuBind, vendorID) if checkDiscountValidation([]int{vendorID}, actType, float64(v.ActPrice)*100/float64(vendorPrice)) != nil { - if actType == model.ActSkuSecKill { - vendorPrice = int(v.ActPrice)*100/maxDiscount4SkuSecKill + 10 - } else if actType == model.ActSkuDirectDown { - vendorPrice = int(v.ActPrice) + 10 - } + vendorPrice = int(v.ActPrice)*100/actRule.MaxDiscount + 10 } else { storeSkuBind = nil } diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index 31ca29ecd..8af4e0d87 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -208,6 +208,13 @@ type SkuNameAndPlace struct { Type int `json:"type"` } +type StoreSkuPriceAndWeight struct { + VendorSkuID string `orm:"column(vendor_sku_id)"` + SkuID int `orm:"column(sku_id)"` + Weight int + Price int +} + // todo 应该通过需要同步的skuid来驱动同步分类,而不是当前这种分开的逻辑 // 单门店模式厂商适用 // 从store_sku_bind中,得到所有依赖的商家分类信息 @@ -632,6 +639,42 @@ func oldGetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSync return skus, err } +func GetStoreSkuPriceAndWeight(db *DaoDB, vendorStoreID string, vendorID int, vendorSkuIDs []string) (l []*StoreSkuPriceAndWeight, err error) { + var vendorSkuIDField, sqlThingMap string + var thingMapParams []interface{} + if vendorID == model.VendorIDJX { + vendorSkuIDField = "t1.id" + } else if model.MultiStoresVendorMap[vendorID] != 0 { + sqlThingMap = ` + LEFT JOIN thing_map t4 ON t4.thing_type = ? AND t4.thing_id = t1.id AND t4.deleted_at = ? AND t4.vendor_id = t3.vendor_id AND t4.vendor_org_code = t3.vendor_org_code` + thingMapParams = []interface{}{ + model.ThingTypeSku, utils.DefaultTimeValue, + } + vendorSkuIDField = "t4.vendor_thing_id" + } else { + vendorSkuIDField = fmt.Sprintf("t2.%s_id", ConvertDBFieldPrefix(model.VendorNames[vendorID])) + } + sql := fmt.Sprintf(` + SELECT %s vendor_sku_id, t1.id sku_id, t2.price, t1.weight + FROM sku t1 + LEFT JOIN store_sku_bind t2 ON t2.sku_id = t1.id AND t2.deleted_at = ? + LEFT JOIN store_map t3 ON t3.store_id = t2.store_id AND t3.vendor_id = ? AND t3.vendor_store_id = ? AND t2.deleted_at = ? + %s + WHERE %s IN (`+GenQuestionMarks(len(vendorSkuIDs))+`)`, vendorSkuIDField, sqlThingMap, vendorSkuIDField) + sqlParams := []interface{}{ + utils.DefaultTimeValue, + vendorID, vendorStoreID, utils.DefaultTimeValue, + } + sqlParams = append(sqlParams, thingMapParams...) + if vendorID == model.VendorIDJX { + sqlParams = append(sqlParams, utils.StringSlice2Int(vendorSkuIDs)) + } else { + sqlParams = append(sqlParams, vendorSkuIDs) + } + err = GetRows(db, &l, sql, sqlParams...) + return l, err +} + // 这个函数之前是要设置没有删除或同步标志不为0的,会导致将同步标志不为0且删除了的把标志去掉,现在改为只设置没有删除的 func SetStoreSkuSyncStatus(db *DaoDB, vendorID int, storeIDs []int, skuIDs []int, syncStatus int) (num int64, err error) { globals.SugarLogger.Debugf("SetStoreSkuSyncStatus, storeIDs:%v, vendorID:%d", storeIDs, vendorID)