diff --git a/business/auth2/auth2.go b/business/auth2/auth2.go index e725d1332..3377d3e40 100644 --- a/business/auth2/auth2.go +++ b/business/auth2/auth2.go @@ -52,6 +52,7 @@ type IUser interface { GetMobile() string GetEmail() string GetName() string + GetAvatar() string } const ( diff --git a/business/auth2/auth_info.go b/business/auth2/auth_info.go index f646e231f..e145747d5 100644 --- a/business/auth2/auth_info.go +++ b/business/auth2/auth_info.go @@ -18,6 +18,7 @@ type UserBasic struct { Mobile string `json:"mobile"` Email string `json:"email"` Name string `json:"name"` + Avatar string `json:"avatar"` } func (u *UserBasic) GetID() string { @@ -39,6 +40,10 @@ func (u *UserBasic) GetName() string { return u.Name } +func (u *UserBasic) GetAvatar() string { + return u.Avatar +} + func (u *UserBasic) UpdateByIUser(user IUser) { if user != nil { u.UserID = user.GetID() @@ -46,6 +51,7 @@ func (u *UserBasic) UpdateByIUser(user IUser) { u.Mobile = user.GetMobile() u.Email = user.GetEmail() u.Name = user.GetName() + u.Avatar = user.GetAvatar() } } diff --git a/business/auth2/authprovider/defauther.go b/business/auth2/authprovider/defauther.go index 2ec2af80b..80f026d29 100644 --- a/business/auth2/authprovider/defauther.go +++ b/business/auth2/authprovider/defauther.go @@ -137,9 +137,11 @@ func (a *DefAuther) GenerateVerifyCode(keyID string) (verifyCode string) { } func (a *DefAuther) VerifyCode(keyID, verifyCode string) (isSame bool) { - savedVerifyCode := a.LoadVerifyCode(keyID) - if isSame = (verifyCode != "" && savedVerifyCode != "" && verifyCode == savedVerifyCode); isSame { - a.DeleteVerifyCode(keyID) + if keyID != "" { + savedVerifyCode := a.LoadVerifyCode(keyID) + if isSame = (verifyCode != "" && savedVerifyCode != "" && verifyCode == savedVerifyCode); isSame { + a.DeleteVerifyCode(keyID) + } } return isSame } diff --git a/business/auth2/authprovider/weixin/weixin.go b/business/auth2/authprovider/weixin/weixin.go index 9dd914985..8caf13752 100644 --- a/business/auth2/authprovider/weixin/weixin.go +++ b/business/auth2/authprovider/weixin/weixin.go @@ -52,7 +52,8 @@ func (a *Auther) VerifySecret(state, code string) (authBindEx *auth2.AuthBindEx, if err = err2; err == nil { if authBindEx, err = a.UnionFindAuthBind(a.authType, []string{AuthTypeWeixin, AuthTypeMP, AuthTypeMini}, wxUserinfo.OpenID, wxUserinfo.UnionID, wxUserinfo); err == nil { authBindEx.UserHint = &auth2.UserBasic{ - Name: wxUserinfo.NickName, + Name: wxUserinfo.NickName, + Avatar: wxUserinfo.HeadImgURL, } } } diff --git a/business/auth2/authprovider/weixin/weixin_mini.go b/business/auth2/authprovider/weixin/weixin_mini.go index e9bb9825a..6e079b7ee 100644 --- a/business/auth2/authprovider/weixin/weixin_mini.go +++ b/business/auth2/authprovider/weixin/weixin_mini.go @@ -1,8 +1,8 @@ package weixin import ( - "encoding/base64" "errors" + "fmt" "strings" "git.rosy.net.cn/baseapi/platformapi/weixinapi" @@ -45,17 +45,34 @@ func (a *MiniAuther) VerifySecret(dummy, jsCode string) (authBindEx *auth2.AuthB } // 特殊接口 -func (a *MiniAuther) DecryptData(authInfo *auth2.AuthInfo, encryptedData, iv string) (decryptedDataBase64 string, err error) { - globals.SugarLogger.Debugf("weixin mini DecryptData encryptedData:%s, iv:%s", encryptedData, iv) - if authInfo.AuthBindInfo.Type != AuthTypeMini { - return "", ErrAuthTypeShouldBeMini +func (a *MiniAuther) DecryptData(authInfo *auth2.AuthInfo, jsCode, encryptedData, iv string) (decryptedDataBase64 string, err error) { + globals.SugarLogger.Debugf("weixin mini DecryptData jsCode:%s, encryptedData:%s, iv:%s", jsCode, encryptedData, iv) + var sessionKey string + if jsCode != "" { + sessionInfo, err := ProxySNSCode2Session(jsCode) + if err == nil { + if authBindEx, err := a.UnionFindAuthBind(AuthTypeMini, []string{AuthTypeMini}, sessionInfo.OpenID, "", nil); err == nil { + if authBindEx.UserID != authInfo.GetID() { + return "", fmt.Errorf("jsCode与token不匹配") + } + } else { + return "", err + } + sessionKey = sessionInfo.SessionKey + } else { + return "", err + } + } else { + if authInfo.AuthBindInfo.Type != AuthTypeMini { + return "", ErrAuthTypeShouldBeMini + } + sessionKey = authInfo.AuthBindInfo.UserData.(string) } - sessionKey := authInfo.AuthBindInfo.UserData.(string) decryptedData, err := ProxySNSDecodeMiniProgramData(encryptedData, sessionKey, iv) if err != nil { return "", err } - return base64.StdEncoding.EncodeToString(decryptedData), nil + return string(decryptedData), nil } func (a *MiniAuther) GetUserType() (userType int8) { @@ -76,6 +93,7 @@ func ProxySNSCode2Session(jsCode string) (sessionInfo *weixinapi.SessionInfo, er } func ProxySNSDecodeMiniProgramData(encryptedData, sessionKey, iv string) (decryptedData []byte, err error) { + globals.SugarLogger.Debugf("ProxySNSDecodeMiniProgramData, encryptedData:%s, sessionKey:%s, iv:%s", encryptedData, sessionKey, iv) decryptedData, err = api.WeixinMiniAPI.SNSDecodeMiniProgramData(encryptedData, sessionKey, iv) return decryptedData, err } diff --git a/business/cs/weimob_order.go b/business/cs/weimob_order.go index 1f2afd8e6..7d0b9c13f 100644 --- a/business/cs/weimob_order.go +++ b/business/cs/weimob_order.go @@ -46,6 +46,7 @@ func onOrderMsg(msg *weimobapi.CallbackMsg) (response *weimobapi.CallbackRespons func changeStoreSkusByOrder(order *weimobapi.OrderDetail) { globals.SugarLogger.Debugf("changeStoreSkusByOrder order:%s", utils.Format4Output(order, true)) receiverMobile := order.DeliveryDetail.LogisticsDeliveryDetail.ReceiverMobile + ctx := jxcontext.NewWithUserName(nil, utils.LimitStringLen(utils.Int64ToStr(order.OrderNo), 32), nil, nil) if storeList, err := GetStoreList4Mobile(dao.GetDB(), []string{receiverMobile}); err == nil { if len(storeList) >= 1 { var skuBindInfos []*cms.StoreSkuBindInfo @@ -63,19 +64,41 @@ func changeStoreSkusByOrder(order *weimobapi.OrderDetail) { IsSale: 1, }) } else { - globals.SugarLogger.Infof("[运营],微商城订单:%s,商品:%s没有设置正确的SkuName编码或单价,当前商家编码:%s,市场价:%s", order.OrderNo, v.SkuNum, v.SkuCode, jxutils.IntPrice2StandardString(jxutils.StandardPrice2Int(unitPrice))) + globals.SugarLogger.Infof("[运营],微商城订单:%d,商品:%s没有设置正确的SkuName编码或单价,当前商家编码:%s,市场价:%s", order.OrderNo, v.SkuNum, v.SkuCode, jxutils.IntPrice2StandardString(jxutils.StandardPrice2Int(unitPrice))) } } if len(skuBindInfos) > 0 { - cms.UpdateStoreSkus(jxcontext.NewWithUserName(nil, utils.LimitStringLen(utils.Int64ToStr(order.OrderNo), 32), nil, nil), storeID, skuBindInfos, true, true) + var nameIDs []int + for _, v := range skuBindInfos { + nameIDs = append(nameIDs, v.NameID) + } + if skuNamesInfo, err := cms.GetSkuNames(ctx, "", false, map[string]interface{}{ + "nameIDs": nameIDs, + }, 0, 0); err == nil { + for _, skuName := range skuNamesInfo.SkuNames { + if skuName.Status != model.SkuStatusNormal { + cms.UpdateSkuName(ctx, skuName.ID, map[string]interface{}{ + "status": model.SkuStatusNormal, + }) + } + for _, sku := range skuName.Skus { + if sku.Status != model.SkuStatusNormal { + cms.UpdateSku(ctx, sku.ID, map[string]interface{}{ + "status": model.SkuStatusNormal, + }) + } + } + } + } + cms.UpdateStoreSkus(ctx, storeID, skuBindInfos, true, true) } else { - globals.SugarLogger.Debugf("changeStoreSkusByOrder storeID:%d is empty", storeID) + globals.SugarLogger.Debugf("changeStoreSkusByOrder orderID:%d, storeID:%d is empty", order.OrderNo, storeID) } } else { - globals.SugarLogger.Infof("[运营],微商城订单:%s,手机:%s找不到唯一一个京西门店%d", order.OrderNo, receiverMobile, len(storeList)) + globals.SugarLogger.Infof("[运营],微商城订单:%d,手机:%s找不到唯一一个京西门店%d", order.OrderNo, receiverMobile, len(storeList)) } } else { - globals.SugarLogger.Warnf("changeStoreSkusByOrder receiverMobile:%s failed with err:%v", receiverMobile, err) + globals.SugarLogger.Warnf("changeStoreSkusByOrder orderNo:%d, receiverMobile:%s failed with err:%v", order.OrderNo, receiverMobile, err) } } diff --git a/business/jxcallback/orderman/order.go b/business/jxcallback/orderman/order.go index 303536042..afcdbb84d 100644 --- a/business/jxcallback/orderman/order.go +++ b/business/jxcallback/orderman/order.go @@ -1,14 +1,19 @@ package orderman import ( + "errors" "fmt" + "math" "strings" "time" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" @@ -257,7 +262,7 @@ func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao order.VendorStatus = orderStatus.VendorStatus order.StatusTime = orderStatus.StatusTime - jxutils.RefreshOrderSkuRelated(order) + // jxutils.RefreshOrderSkuRelated(order) } } } @@ -344,7 +349,6 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. skumapper[v.VendorSkuID] = v } - skuIDMap := make(map[int]int) for _, v := range orderSkus { v.VendorOrderID = order.VendorOrderID v.VendorID = order.VendorID @@ -364,33 +368,36 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. } } v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage) - - if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 { - skuIDMap[skuID] = 1 - } } + updateSingleOrderEarningPrice(order, db) + } + return nil +} - if len(skuIDMap) > 0 { - actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt) - if err != nil { - globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err) - return err - } - if actStoreSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false); actStoreSkuMap != nil { - for _, v := range orderSkus { - if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 { - if actStoreSku := actStoreSkuMap.GetActStoreSku(jxStoreID, skuID, order.VendorID); actStoreSku != nil { - v.EarningPrice = actStoreSku.EarningPrice - if true { //v.StoreSubName != "" { // 之前这里为什么要加判断? - v.StoreSubID = actStoreSku.ActID - } +func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) { + jxStoreID := jxutils.GetShowStoreIDFromOrder(order) + skuIDMap := make(map[int]int) + for _, v := range order.Skus { + skuIDMap[v.SkuID] = 1 + } + if len(skuIDMap) > 0 { + actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt) + if err != nil { + globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err) + } + if actStoreSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false); actStoreSkuMap != nil { + for _, v := range order.Skus { + if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 { + if actStoreSku := actStoreSkuMap.GetActStoreSku(jxStoreID, skuID, order.VendorID); actStoreSku != nil { + v.EarningPrice = actStoreSku.EarningPrice + if true { //v.StoreSubName != "" { // 之前这里为什么要加判断? + v.StoreSubID = actStoreSku.ActID } } } } } } - return nil } func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.DaoDB) (err error) { @@ -413,22 +420,22 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao } if err = c.updateOrderSkuOtherInfo(order, db, payPercentage); err == nil { jxutils.RefreshOrderSkuRelated(order) - caculateOrderEarningPrice(order, payPercentage) + // caculateOrderEarningPrice(order, payPercentage) } return err } // 计算结算给门店的金额 -func caculateOrderEarningPrice(order *model.GoodsOrder, storePayPercentage int) { - order.EarningPrice = 0 - for _, v := range order.Skus { - skuEarningPrice := v.EarningPrice - if skuEarningPrice == 0 { - skuEarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage) - } - order.EarningPrice += skuEarningPrice * int64(v.Count) - } -} +// func caculateOrderEarningPrice(order *model.GoodsOrder, storePayPercentage int) { +// order.EarningPrice = 0 +// for _, v := range order.Skus { +// skuEarningPrice := v.EarningPrice +// if skuEarningPrice == 0 { +// skuEarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage) +// } +// order.EarningPrice += skuEarningPrice * int64(v.Count) +// } +// } func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) { globals.SugarLogger.Debugf("addOrderStatus refOrderID:%s, orderID:%s", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID) @@ -605,3 +612,107 @@ func (c *OrderManager) UpdateOrderFields(order *model.GoodsOrder, fieldList []st }, "UpdateOrderFields orderID:%s failed with error:%v", order.VendorOrderID, err) return err } + +func (c *OrderManager) RefreshHistoryOrdersEarningPrice(ctx *jxcontext.Context, vendorOrderID string, actID int, vendorIDs []int, storeID int, fromDate, toDate string, isAsync, isContinueWhenError bool) (hint string, err error) { + var ( + orderList []*model.GoodsOrder + fromDateParam time.Time + toDateParam time.Time + beginAt time.Time + endAt time.Time + ) + db := dao.GetDB() + if actID > 0 { + if fromDate != "" && toDate != "" { + fromDateParam = utils.Str2Time(fromDate) + toDateParam = utils.Str2Time(toDate) + actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, 0, 0, time.Time{}, time.Time{}, time.Time{}, time.Time{}) + if len(actList.Data) > 0 { + actBeginAt := actList.Data[0].BeginAt + actEndAt := actList.Data[0].EndAt + if fromDateParam.Sub(actBeginAt) > 0 && fromDateParam.Sub(actEndAt) > 0 { + return "", errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致!,活动时间范围:[%v] 至 [%v] ,订单创建时间范围 :[%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam)) + } + if actBeginAt.Sub(toDateParam) > 0 && actEndAt.Sub(toDateParam) > 0 { + return "", errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致!,活动时间范围:[%v] 至 [%v] ,订单创建时间范围 :[%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam)) + } + if fromDateParam.Sub(actBeginAt) > 0 { + beginAt = fromDateParam + if toDateParam.Sub(actEndAt) > 0 { + endAt = actEndAt + } else { + endAt = toDateParam + } + } else { + beginAt = actBeginAt + if toDateParam.Sub(actEndAt) > 0 { + endAt = actEndAt + } else { + endAt = toDateParam + } + } + orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, beginAt, endAt) + } else { + return "", errors.New(fmt.Sprintf("未查询到相关结算活动,活动ID:[%d]", actID)) + } + } else if fromDate == "" && toDate == "" { + actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, 0, 0, time.Time{}, time.Time{}, time.Time{}, time.Time{}) + if len(actList.Data) > 0 { + orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, actList.Data[0].BeginAt, actList.Data[0].EndAt) + } else { + return "", errors.New(fmt.Sprintf("未查询到相关结算活动,活动ID:[%d]", actID)) + } + } else { + return "", errors.New(fmt.Sprintf("间隔时间必须完整!时间范围:[%v] 至 [%v]", fromDate, toDate)) + } + } else { + if fromDate != "" && toDate != "" { + fromDateParam = utils.Str2Time(fromDate) + toDateParam = utils.Str2Time(toDate) + //若未传入活动ID,且时间间隔大于10天则不允许查询 + if math.Ceil(toDateParam.Sub(fromDateParam).Hours()/24) > 10 { + return "", errors.New(fmt.Sprintf("查询间隔时间不允许大于10天!时间范围:[%v] 至 [%v]", fromDate, toDate)) + } + orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, fromDateParam, toDateParam) + } else { + return "", errors.New(fmt.Sprintf("若不按活动查询则间隔时间必须完整!时间范围:[%v] 至 [%v]", fromDate, toDate)) + } + } + if len(orderList) <= 0 { + return "", errors.New(fmt.Sprintf("未查询到订单!,vendorOrderID : %s, actID : %d, 时间范围:[%v] 至 [%v]", vendorOrderID, actID, fromDate, toDate)) + } + task := tasksch.NewParallelTask("刷新历史订单结算价", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + order := batchItemList[0].(*model.GoodsOrder) + db := dao.GetDB() + updateSingleOrderEarningPrice(order, db) + dao.Begin(db) + defer func() { + if r := recover(); r != nil || err != nil { + dao.Rollback(db) + if r != nil { + panic(r) + } + } + }() + for _, value := range order.Skus { + if _, err = dao.UpdateEntity(db, value, "EarningPrice", "StoreSubID"); err != nil { + return "", err + } + } + jxutils.RefreshOrderSkuRelated(order) + if _, err = dao.UpdateEntity(db, order, "EarningPrice"); err != nil { + return "", err + } + dao.Commit(db) + return retVal, err + }, orderList) + tasksch.HandleTask(task, nil, true).Run() + if !isAsync { + _, err = task.GetResult(0) + hint = "1" + } else { + hint = task.GetID() + } + return hint, err +} diff --git a/business/jxcallback/orderman/order_comment.go b/business/jxcallback/orderman/order_comment.go index d5dfcbe67..484d5ea7d 100644 --- a/business/jxcallback/orderman/order_comment.go +++ b/business/jxcallback/orderman/order_comment.go @@ -83,7 +83,7 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) ( if dao.IsNoRowsError(err) { err = nil isNewComment = true - if orderComment.IsReplied == 0 && time.Now().Sub(orderComment.CommentCreatedAt) < MAX_REAPLY_TIME { + if orderComment.IsReplied == 0 && time.Now().Sub(orderComment.CommentCreatedAt) < time.Duration(orderComment.ModifyDuration)*time.Hour { c.replyOrderComment(orderComment) } } @@ -107,6 +107,10 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) ( } else { orderComment.ConsigneeMobile = order.ConsigneeMobile } + } else { + if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, orderComment.VendorStoreID, orderComment.VendorID); err == nil { + orderComment.StoreID = storeDetail.ID + } } if orderComment.StoreID > 0 { comment2.Jxstoreid = utils.Int2Str(orderComment.StoreID) diff --git a/business/jxcallback/orderman/orderman_ext.go b/business/jxcallback/orderman/orderman_ext.go index cc7eb3abf..b41cef313 100644 --- a/business/jxcallback/orderman/orderman_ext.go +++ b/business/jxcallback/orderman/orderman_ext.go @@ -1169,7 +1169,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in if err = err2; err != nil && !isContinueWhenError { return "", err } - localOrders, err2 := dao.QueryOrders(db, vendorIDs, storeID, fromDate, toDate.Add(24*time.Hour-time.Second)) + localOrders, err2 := dao.QueryOrders(db, "", 0, vendorIDs, storeID, fromDate, toDate.Add(24*time.Hour-time.Second)) if err = err2; err != nil { return "", err } diff --git a/business/jxcallback/scheduler/basesch/basesch_ext.go b/business/jxcallback/scheduler/basesch/basesch_ext.go index ec01c4443..3ceada398 100644 --- a/business/jxcallback/scheduler/basesch/basesch_ext.go +++ b/business/jxcallback/scheduler/basesch/basesch_ext.go @@ -4,14 +4,12 @@ import ( "fmt" "git.rosy.net.cn/baseapi/utils/errlist" - "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" - "git.rosy.net.cn/jx-callback/business/partner/purchase/jx" "git.rosy.net.cn/jx-callback/globals" ) @@ -30,18 +28,16 @@ func (c *BaseScheduler) CreateWaybillOnProviders(ctx *jxcontext.Context, order * (excludeCourierVendorIDs == nil || excludeCourierVendorIDMap[storeCourier.VendorID] == 0) { if handler := partner.GetDeliveryPlatformFromVendorID(storeCourier.VendorID); handler != nil && handler.Use4CreateWaybill { courierVendorID := storeCourier.VendorID - if order.VendorID != model.VendorIDWSC || courierVendorID != model.VendorIDDada { // 达达作为微商城的自有配送,不参与配送竞争 - bill, err2 := c.CreateWaybill(courierVendorID, order, maxDeliveryFee) - if err = err2; err == nil { - globals.SugarLogger.Debugf("CreateWaybillOnProviders orderID:%s userName:%s vendorID:%d bill:%v", order.VendorOrderID, userName, courierVendorID, bill) - bills = append(bills, bill) - if createOnlyOne { - break - } - } else { - globals.SugarLogger.Debugf("CreateWaybillOnProviders orderID:%s userName:%s vendorID:%d failed with error:%v", order.VendorOrderID, userName, courierVendorID, err) - errList.AddErr(fmt.Errorf("平台:%s,%s", jxutils.GetVendorName(courierVendorID), err.Error())) + bill, err2 := c.CreateWaybill(courierVendorID, order, maxDeliveryFee) + if err = err2; err == nil { + globals.SugarLogger.Debugf("CreateWaybillOnProviders orderID:%s userName:%s vendorID:%d bill:%v", order.VendorOrderID, userName, courierVendorID, bill) + bills = append(bills, bill) + if createOnlyOne { + break } + } else { + globals.SugarLogger.Debugf("CreateWaybillOnProviders orderID:%s userName:%s vendorID:%d failed with error:%v", order.VendorOrderID, userName, courierVendorID, err) + errList.AddErr(fmt.Errorf("平台:%s,%s", jxutils.GetVendorName(courierVendorID), err.Error())) } } } @@ -67,9 +63,9 @@ func (c *BaseScheduler) SelfDeliveredAndUpdateStatus(ctx *jxcontext.Context, ven globals.SugarLogger.Infof("SelfDeliveredAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) if err == nil { - if c.GetStoreDeliveryType(order, nil) == scheduler.StoreDeliveryTypeByStore { + if model.IsOrderDeliveryByStore(order) { err = c.SelfDeliverDelivered(order, userName) - } else { + } else if model.IsOrderDeliveryByPlatform(order) { err = c.Swtich2SelfDelivered(order, userName) } if err == nil { @@ -93,7 +89,7 @@ func (c *BaseScheduler) PickupGoodsAndUpdateStatus(ctx *jxcontext.Context, vendo globals.SugarLogger.Infof("PickupGoodsAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) if err == nil { - err = c.PickupGoods(order, c.GetStoreDeliveryType(order, nil) == scheduler.StoreDeliveryTypeByStore, userName) + err = c.PickupGoods(order, model.IsOrderDeliveryByStore(order), userName) if err == nil { order.Status = model.OrderStatusFinishedPickup if err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order); err == nil { @@ -109,27 +105,6 @@ func (c *BaseScheduler) PickupGoodsAndUpdateStatus(ctx *jxcontext.Context, vendo return err } -func (c *BaseScheduler) GetStoreDeliveryType(order *model.GoodsOrder, storeMap *model.StoreMap) (deliveryType int) { - globals.SugarLogger.Debugf("GetStoreDeliveryType orderID:%s", order.VendorOrderID) - jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) - if storeMap == nil { - storeMap, _ = dao.FakeGetStoreMapByStoreID(nil, jxStoreID, order.VendorID) - } - - deliveryType = scheduler.StoreDeliveryTypeByPlatform // 缺省值 - if storeMap != nil { - deliveryType = int(storeMap.DeliveryType) - // 微盟订单,要确认有绑达达,才能是非自送的 - if order.VendorID == model.VendorIDWSC && deliveryType != scheduler.StoreDeliveryTypeByStore { - if courierMapList, _ := dao.GetOpenedStoreCouriersByStoreID(nil, jxStoreID, model.VendorIDDada); len(courierMapList) == 0 { - deliveryType = scheduler.StoreDeliveryTypeByStore - } - } - } - globals.SugarLogger.Debugf("GetStoreDeliveryType orderID:%s, deliveryType:%d", order.VendorOrderID, deliveryType) - return deliveryType -} - func (c *BaseScheduler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { if c.IsReallyCallPlatformAPI { err = partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).AdjustOrder(ctx, order, removedSkuList, reason) @@ -257,8 +232,6 @@ func (c *BaseScheduler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID st } } err = jd.CurPurchaseHandler.ConfirmSelfTake(ctx, vendorOrderID, selfTakeCode) - } else if vendorID == model.VendorIDJX { - err = jx.CurPurchaseHandler.ConfirmSelfTake(ctx, vendorOrderID, selfTakeCode) } else { err = fmt.Errorf("自提核销不支持%s平台订单", model.VendorChineseNames[vendorID]) } diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index 7baa08ef5..54d5b14df 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -67,7 +67,6 @@ type WatchOrderInfo struct { order *model.GoodsOrder // order里的信息是保持更新的 autoPickupTimeoutMinute int // 0表示禁用,1表示用缺省值time2AutoPickupMin,其它表示分钟数 - storeDeliveryType int isDeliveryCompetition bool isNeedCreate3rdWaybill bool @@ -107,7 +106,6 @@ type DefScheduler struct { func NewWatchOrderInfo(order *model.GoodsOrder) (retVal *WatchOrderInfo) { retVal = &WatchOrderInfo{ autoPickupTimeoutMinute: 1, - storeDeliveryType: scheduler.StoreDeliveryTypeCrowdSourcing, waybills: map[int]*model.Waybill{}, } retVal.SetOrder(order) @@ -130,14 +128,12 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) if jxStoreID > 0 { db := dao.GetDB() - storeMap, err2 := dao.FakeGetStoreMapByStoreID(db, jxStoreID, order.VendorID) + storeDetail, err2 := dao.GetStoreDetail(db, jxStoreID, order.VendorID) if err = err2; err != nil { return err } - s.autoPickupTimeoutMinute = int(storeMap.AutoPickup) - s.storeDeliveryType = FixedScheduler.GetStoreDeliveryType(order, storeMap) - s.isDeliveryCompetition = storeMap.DeliveryCompetition != 0 - globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d", order.VendorOrderID, s.storeDeliveryType) + s.autoPickupTimeoutMinute = int(storeDetail.AutoPickup) + s.isDeliveryCompetition = storeDetail.DeliveryCompetition != 0 } return err } @@ -229,7 +225,7 @@ func init() { TimeoutGap: 0, }, TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake { // 自配送商家使用 + if model.IsOrderDeliveryByStore(savedOrderInfo.order) { // 自配送商家使用 // 启动抢单TIMER sch.saveDeliveryFeeFromAndStartWatch(savedOrderInfo, savedOrderInfo.order.StatusTime) return sch.createWaybillOn3rdProviders(savedOrderInfo, 0, nil) @@ -237,7 +233,7 @@ func init() { return nil }, ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { - return savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake + return model.IsOrderDeliveryByStore(savedOrderInfo.order) }, }, }, @@ -251,7 +247,7 @@ func init() { TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) { // 饿百转自送的时机不太清楚,暂时禁用超时转自送,在饿百运单取消时还是会自动创建 if savedOrderInfo.isDeliveryCompetition && - savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && + model.IsOrderDeliveryByPlatform(savedOrderInfo.order) && savedOrderInfo.order.VendorID == bill.WaybillVendorID && savedOrderInfo.order.VendorID != model.VendorIDEBAI && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake { // 非自配送商家使用 @@ -261,7 +257,7 @@ func init() { }, ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { return savedOrderInfo.isDeliveryCompetition && - savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && + model.IsOrderDeliveryByPlatform(savedOrderInfo.order) && savedOrderInfo.order.VendorID == bill.WaybillVendorID && savedOrderInfo.order.VendorID != model.VendorIDEBAI && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake @@ -278,7 +274,7 @@ func init() { if (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) && savedOrderInfo.isDeliveryCompetition && savedOrderInfo.order.VendorID == bill.WaybillVendorID && - savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && + model.IsOrderDeliveryByPlatform(savedOrderInfo.order) && order.VendorID == model.VendorIDEBAI && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake { // 非自配送商家使用 return sch.createWaybillOn3rdProviders(savedOrderInfo, ebaiCancelWaybillMaxFee, nil) @@ -290,7 +286,7 @@ func init() { return (order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) && savedOrderInfo.isDeliveryCompetition && savedOrderInfo.order.VendorID == bill.WaybillVendorID && - savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && + model.IsOrderDeliveryByPlatform(savedOrderInfo.order) && order.VendorID == model.VendorIDEBAI && savedOrderInfo.order.DeliveryType != model.OrderDeliveryTypeSelfTake }, @@ -471,14 +467,13 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo s.cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) if model.IsWaybillPlatformOwn(bill) { - if bill.Status == model.WaybillStatusDelivering { + if bill.Status == model.WaybillStatusDelivering && order.Status < model.OrderStatusEndBegin { // 强制将订单状态置为配送中? order.Status = model.OrderStatusDelivering partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) } } else { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore || - model.IsSpecialOrderPlatformWaybill(bill) { + if model.IsOrderDeliveryByStore(savedOrderInfo.order) { if err := s.SelfDeliverDelivering(savedOrderInfo.order, bill.CourierMobile); err != nil { partner.CurOrderManager.OnOrderMsg(order, "自送出设置失败", err.Error()) } @@ -495,9 +490,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo if isBillAlreadyCandidate && !s.isWaybillCourierSame(savedOrderInfo, bill) && !model.IsWaybillPlatformOwn(bill) { s.notify3rdPartyWaybill(order, bill, isBillAlreadyCandidate) } - flag2Clear := model.WaybillVendorID2Mask(bill.WaybillVendorID) order.Flag &= ^model.OrderFlagMaskFailedGetGoods - order.DeliveryFlag &= ^flag2Clear err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) } case model.WaybillStatusAcceptCanceled: @@ -553,13 +546,11 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo if !isPending { var err2 error if !model.IsWaybillPlatformOwn(bill) { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + if model.IsOrderDeliveryByStore(order) { err2 = s.SelfDeliverDelivered(order, "") - } else { + } else if model.IsOrderDeliveryByPlatform(order) { err2 = s.Swtich2SelfDelivered(order, "") } - } else if model.IsSpecialOrderPlatformWaybill(bill) { - err2 = s.SelfDeliverDelivered(savedOrderInfo.order, "") } if err2 != nil { partner.CurOrderManager.OnOrderMsg(order, "送达设置失败", err2.Error()) @@ -769,7 +760,7 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa statusTime = bill.StatusTime } globals.SugarLogger.Debugf("resetTimer, orderID:%s statusType:%d status:%d", order.VendorOrderID, statusType, status) - if isStatusNewer(savedOrderInfo.timerStatusType, savedOrderInfo.timerStatus, statusType, status) { // 新设置的TIMER不能覆盖状态在其后的TIMER,如果状态回绕,需要注意 + if isStatusNewer(order.VendorID, savedOrderInfo.timerStatusType, savedOrderInfo.timerStatus, statusType, status) { // 新设置的TIMER不能覆盖状态在其后的TIMER,如果状态回绕,需要注意 config := s.mergeOrderStatusConfig(savedOrderInfo, statusTime, statusType, status) if config == nil || config.TimerType != partner.TimerTypeByPass { s.stopTimer(savedOrderInfo) @@ -819,10 +810,13 @@ func (s *DefScheduler) resetTimer(savedOrderInfo *WatchOrderInfo, bill *model.Wa } } -func isStatusNewer(curStatusType, curStatus, statusType, status int) bool { +func isStatusNewer(vendorID int, curStatusType, curStatus, statusType, status int) bool { // 拣货完成及之前的订单事件TIMER不能覆盖运单TIMER(一般是消息错序引起的) - if curStatusType == scheduler.TimerStatusTypeWaybill && statusType == scheduler.TimerStatusTypeOrder && status <= model.OrderStatusFinishedPickup { - return false + // 美团订单在接单后就会收到新运单事件,因当前只支持一个TIMER,暂时舍弃三方配送调度,而要自动拣货调度 + if vendorID != model.VendorIDMTWM { + if curStatusType == scheduler.TimerStatusTypeWaybill && statusType == scheduler.TimerStatusTypeOrder && status <= model.OrderStatusFinishedPickup { + return false + } } if curStatusType == scheduler.TimerStatusTypeWaybill { return curStatus != status @@ -990,8 +984,8 @@ func (s *DefScheduler) updateBillsInfo(savedOrderInfo *WatchOrderInfo, bill *mod } func (s *DefScheduler) autoPickupGood(savedOrderInfo *WatchOrderInfo) (err error) { - if err = s.PickupGoods(savedOrderInfo.order, savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore, ""); err == nil { - order := savedOrderInfo.order + order := savedOrderInfo.order + if err = s.PickupGoods(order, model.IsOrderDeliveryByStore(order), ""); err == nil { order.DeliveryFlag |= model.OrderDeliveryFlagMaskAutoPickup partner.CurOrderManager.UpdateOrderFields(order, []string{"DeliveryFlag"}) } else if err == scheduler.ErrOrderStatusAlreadySatisfyCurOperation { @@ -1062,9 +1056,9 @@ func (s *DefScheduler) saveDeliveryFeeFromAndStartWatch(savedOrderInfo *WatchOrd } func (s *DefScheduler) watchOrderWaybills(savedOrderInfo *WatchOrderInfo) { - if savedOrderInfo.storeDeliveryType != scheduler.StoreDeliveryTypeByStore && savedOrderInfo.isDeliveryCompetition || - savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { - order2 := savedOrderInfo.order + order2 := savedOrderInfo.order + if model.IsOrderDeliveryByPlatform(order2) && savedOrderInfo.isDeliveryCompetition || + model.IsOrderDeliveryByStore(order2) { if order, err := partner.CurOrderManager.LoadOrder(order2.VendorOrderID, order2.VendorID); err == nil { savedOrderInfo.SetOrder(order) if isNeedWatch3rdWaybill(order) { diff --git a/business/jxcallback/scheduler/defsch/defsch_ext.go b/business/jxcallback/scheduler/defsch/defsch_ext.go index 416820c54..3b875dbad 100644 --- a/business/jxcallback/scheduler/defsch/defsch_ext.go +++ b/business/jxcallback/scheduler/defsch/defsch_ext.go @@ -33,7 +33,7 @@ func (s *DefScheduler) SelfDeliveringAndUpdateStatus(ctx *jxcontext.Context, ven if err = s.isPossibleSwitch2SelfDelivery(order); err == nil { err = s.cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo, nil, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) if err == nil { - if savedOrderInfo.storeDeliveryType == scheduler.StoreDeliveryTypeByStore { + if model.IsOrderDeliveryByStore(order) { if order.Status < model.OrderStatusDelivering { storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), order.StoreID, order.VendorID) phone := userName @@ -91,7 +91,7 @@ func (s *DefScheduler) canOrderCreateWaybillNormally(order *model.GoodsOrder) (e } func (s *DefScheduler) isPossibleSwitch2SelfDelivery(order *model.GoodsOrder) (err error) { - if scheduler.StoreDeliveryTypeByStore != s.GetStoreDeliveryType(order, nil) { + if model.IsOrderDeliveryByPlatform(order) { if order.Status < model.OrderStatusFinishedPickup { err = fmt.Errorf("拣货完成后才能转自配送") } else if order.Status == model.OrderStatusFinishedPickup { diff --git a/business/jxstore/act/act.go b/business/jxstore/act/act.go index eef24edb7..60b6aa224 100644 --- a/business/jxstore/act/act.go +++ b/business/jxstore/act/act.go @@ -72,6 +72,18 @@ func init() { partner.InitActManager(FixedActManager) } +func getVendorPriceFromStoreSkuBind(bind *model.StoreSkuBind, vendorID int) (vendorPrice int) { + switch vendorID { + case model.VendorIDJD: + vendorPrice = bind.JdPrice + case model.VendorIDMTWM: + vendorPrice = bind.MtwmPrice + case model.VendorIDEBAI: + vendorPrice = bind.EbaiPrice + } + return vendorPrice +} + func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Act, vendorIDs []int, actStoreSku []*ActStoreSkuParam) (validVendorIDs []int, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) { wholeValidVendorMap := make(map[int]int) if len(actStoreSku) > 0 { @@ -93,6 +105,7 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac } storeIDs := jxutils.IntMap2List(storeIDMap) skuIDs := jxutils.IntMap2List(skuIDMap) + // 判断活动是否重叠的检查,当前忽略京东平台及所有结算信息 if !(len(vendorIDs) == 1 && vendorIDs[0] == model.VendorIDJD || act.Type == model.ActSkuFake) { effectActStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, storeIDs, skuIDs, act.BeginAt, act.EndAt) if err != nil { @@ -119,59 +132,60 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac for _, vendorID := range vendorIDs { storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID) if err = err2; err == nil { - for _, v := range oneStoreSkuParam { - validVendorMap[vendorID] = 1 - validSkuMap[v.SkuID] = 1 - v.ActID = act.ID - actSkuMap := &model.ActStoreSkuMap{ - ActID: act.ID, - StoreID: storeID, - SkuID: v.SkuID, - VendorID: vendorID, - } - v.OriginalPrice = actSkuMap.VendorPrice - storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] - if storeSkuInfo != nil { - jxPrice := storeSkuInfo.Price - pricePercentage := jxutils.GetPricePercentage(storeDetail.PricePercentagePackObj, jxPrice, int(storeDetail.PricePercentage)) - actSkuMap.VendorPrice = int64(jxutils.CaculateSkuVendorPrice(jxPrice, pricePercentage)) - v.OriginalPrice = int64(jxPrice) - } - var err2 error - if act.Type != model.ActSkuFake { - if storeSkuInfo == nil { - v.ErrMsg = fmt.Sprintf("门店:%d没有关注商品:%d", v.StoreID, v.SkuID) - wrongSkuList = append(wrongSkuList, v) - continue + if storeDetail.IsSync != 0 && storeDetail.Status != model.StoreStatusDisabled && storeDetail.VendorStatus != model.StoreStatusDisabled { + for _, v := range oneStoreSkuParam { + validVendorMap[vendorID] = 1 + validSkuMap[v.SkuID] = 1 + v.ActID = act.ID + actSkuMap := &model.ActStoreSkuMap{ + ActID: act.ID, + StoreID: storeID, + SkuID: v.SkuID, + VendorID: vendorID, } - actSkuMap.SyncStatus = model.SyncFlagNewMask - if v.ActPrice != 0 { - actSkuMap.ActualActPrice = v.ActPrice - } else { - percentage := act.PricePercentage - if v.PricePercentage != 0 { - percentage = v.PricePercentage + v.OriginalPrice = actSkuMap.VendorPrice + storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] + if storeSkuInfo != nil { + jxPrice := storeSkuInfo.Price + actSkuMap.VendorPrice = int64(getVendorPriceFromStoreSkuBind(storeSkuInfo, vendorID)) + v.OriginalPrice = int64(jxPrice) + } + var err2 error + if act.Type != model.ActSkuFake { // 非结算,要计算实际活动价格 + if storeSkuInfo == nil { + v.ErrMsg = fmt.Sprintf("门店:%d没有关注商品:%d", v.StoreID, v.SkuID) + wrongSkuList = append(wrongSkuList, v) + continue } - actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(int(actSkuMap.VendorPrice), percentage)) - if actSkuMap.ActualActPrice > 10 { - actSkuMap.ActualActPrice = int64(math.Round(float64(actSkuMap.ActualActPrice)/10) * 10) + actSkuMap.SyncStatus = model.SyncFlagNewMask + if v.ActPrice != 0 { + actSkuMap.ActualActPrice = v.ActPrice + } else { + percentage := act.PricePercentage + if v.PricePercentage != 0 { + percentage = v.PricePercentage + } + actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(int(actSkuMap.VendorPrice), percentage, 0)) + if actSkuMap.ActualActPrice > 10 { + actSkuMap.ActualActPrice = int64(math.Floor(float64(actSkuMap.ActualActPrice)/10) * 10) + } + } + if actSkuMap.ActualActPrice <= 0 { + actSkuMap.ActualActPrice = 1 + } + if err2 = checkDiscountValidation(act.Type, float64(actSkuMap.ActualActPrice)*100/float64(actSkuMap.VendorPrice)); err2 != nil { + v.ErrMsg = err2.Error() + v.ActualActPrice = actSkuMap.ActualActPrice + wrongSkuList = append(wrongSkuList, v) } } - if actSkuMap.ActualActPrice <= 0 { - actSkuMap.ActualActPrice = 1 - } - if err2 = checkDiscountValidation(act.Type, int(actSkuMap.ActualActPrice*100/actSkuMap.VendorPrice)); err2 != nil { - v.ErrMsg = err2.Error() - v.ActualActPrice = actSkuMap.ActualActPrice - wrongSkuList = append(wrongSkuList, v) + if err2 == nil { + dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName()) + actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap) } } - if err2 == nil { - dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName()) - actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap) - } + wholeValidVendorMap[vendorID] = 1 } - wholeValidVendorMap[vendorID] = 1 } else if !dao.IsNoRowsError(err) { return nil, nil, nil, err } else { @@ -268,26 +282,30 @@ func AddActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actSto if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil { return err } - for _, act := range actMap { - if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act), - map[string]interface{}{ - model.FieldSyncStatus: act.SyncStatus | model.SyncFlagModifiedMask, - }, ctx.GetUserName(), nil); err != nil { - return err + if act.Type != model.ActSkuFake { + for _, act := range actMap { + if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act), + map[string]interface{}{ + model.FieldSyncStatus: act.SyncStatus | model.SyncFlagModifiedMask, + }, ctx.GetUserName(), nil); err != nil { + return err + } } } dao.Commit(db) return err } -func checkDiscountValidation(actType int, pricePercentage int) (err error) { - if actType == model.ActSkuDirectDown && (pricePercentage < minDiscount4SkuDirectDown || pricePercentage > 99) { - if pricePercentage < minDiscount4SkuDirectDown { +func checkDiscountValidation(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 pricePercentage > 99 { + } else if pricePercentageMax > 99 { err = fmt.Errorf("%s活动必须有折扣", model.ActTypeName[actType]) } - } else if actType == model.ActSkuSecKill && pricePercentage > maxDiscount4SkuSecKill { + } else if actType == model.ActSkuSecKill && pricePercentageMax > maxDiscount4SkuSecKill { err = fmt.Errorf("%s活动折扣必须小于:%d", model.ActTypeName[actType], maxDiscount4SkuSecKill) } return err @@ -308,7 +326,7 @@ func checkActValidation(act *model.Act, vendorIDs []int) (err error) { if act.Type == model.ActSkuDirectDown || act.Type == model.ActSkuSecKill { if act.PricePercentage == 0 { errList.AddErr(fmt.Errorf("必须指定缺省活动折扣")) - } else if err = checkDiscountValidation(act.Type, act.PricePercentage); err != nil { + } else if err = checkDiscountValidation(act.Type, float64(act.PricePercentage)); err != nil { errList.AddErr(err) } else if act.Type == model.ActSkuSecKill && vendorIDMap[model.VendorIDMTWM] == 1 { errList.AddErr(fmt.Errorf("%s平台不支持%s活动", model.VendorChineseNames[model.VendorIDMTWM], model.ActTypeName[model.ActSkuSecKill])) @@ -501,6 +519,21 @@ func (a *ActManager) CreateActFromVendor(ctx *jxcontext.Context, act2 *model.Act } func createActFromVendor(ctx *jxcontext.Context, db *dao.DaoDB, act2 *model.Act2, actStoreSku []*model.ActStoreSku2) (actID int, err error) { + actMap := &model.ActMap{ + VendorID: act2.VendorID, + VendorActID: act2.VendorActID, + SyncStatus: 0, + } + dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName()) + if actMap.VendorActID != "" { + if err = dao.GetEntity(db, actMap, model.FieldVendorActID, model.FieldVendorID, model.FieldDeletedAt); err == nil { + return actMap.ActID, nil + } else if !dao.IsNoRowsError(err) { + return 0, err + } + err = nil + } + dao.Begin(db) defer func() { if r := recover(); r != nil { @@ -517,13 +550,7 @@ func createActFromVendor(ctx *jxcontext.Context, db *dao.DaoDB, act2 *model.Act2 return 0, err } - actMap := &model.ActMap{ - ActID: act.ID, - VendorID: act2.VendorID, - VendorActID: act2.VendorActID, - SyncStatus: 0, - } - dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName()) + actMap.ActID = act.ID err = dao.CreateEntity(db, actMap) if err != nil { dao.Rollback(db) @@ -673,11 +700,13 @@ func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, act syncStatus = model.SyncFlagDeletedMask } syncStatus |= act.SyncStatus - if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act), - map[string]interface{}{ - model.FieldSyncStatus: syncStatus, - }, ctx.GetUserName(), nil); err != nil { - return err + if act.Type != model.ActSkuFake { + if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act), + map[string]interface{}{ + model.FieldSyncStatus: syncStatus, + }, ctx.GetUserName(), nil); err != nil { + return err + } } } if isDeleteAll != isNeedCancelAct { diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index 346ca1a4f..d5acfc8aa 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -15,10 +15,10 @@ import ( "git.rosy.net.cn/jx-callback/business/auth2/authprovider/mobile" "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxutils" - "git.rosy.net.cn/jx-callback/business/jxutils/msg" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "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" @@ -97,6 +97,7 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { "configTypeName": model.ConfigTypeName, "autoSaleAt": AutoSaleAtStr, "userTypeName": model.UserTypeName, + "storePriceTypeName": model.StorePriceTypeName, }, } } @@ -180,7 +181,7 @@ func SendMsg2Somebody(ctx *jxcontext.Context, mobileNum, verifyCode, msgType, ms for _, v := range receiveMsgUsersMap[msgType] { user, err2 := dao.GetUserByID(db, "name", v) if err2 == nil { - msg.SendUserMessage(dingdingapi.MsgTyeText, user, msgType, msgContent) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.GetID(), msgType, msgContent) } else if err == nil { err = err2 } @@ -353,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/sku.go b/business/jxstore/cms/sku.go index f2c46b0a4..c809fa291 100644 --- a/business/jxstore/cms/sku.go +++ b/business/jxstore/cms/sku.go @@ -268,7 +268,6 @@ func DeleteCategoryMap(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int) (n return dao.DeleteEntityLogically(db, catMap, map[string]interface{}{ model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask, - model.FieldWscSyncStatus: model.SyncFlagDeletedMask, }, ctx.GetUserName(), map[string]interface{}{ model.FieldCategoryID: categoryID, model.FieldDeletedAt: utils.DefaultTimeValue, @@ -651,7 +650,8 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s return outSkuNameExt, err } -func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interface{}, userName string) (num int64, err error) { +func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interface{}) (num int64, err error) { + userName := ctx.GetUserName() skuName := &model.SkuName{} skuName.ID = nameID db := dao.GetDB() @@ -693,22 +693,10 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf } if globals.EnableStoreWrite { if valid["img"] != nil { - // imgContent, imgMD5, err2 := jxutils.DownloadFileByURL(valid["img"].(string)) - // if err = err2; err != nil { - // return 0, err - // } - // valid["ImgHashCode"] = imgMD5 - // imgHintMap, err := UploadImg2Platforms(ctx, nil, valid["img"].(string), imgContent, "") - // if err != nil { - // return 0, err - // } - // // valid["ImgWeimob"] = imgHintMap[model.VendorIDWSC] - // valid["ImgEbai"] = imgHintMap[model.VendorIDEBAI] dataRes, err2 := datares.TryRegisterDataResource(ctx, skuName.Name, valid["img"].(string), model.ImgTypeMain, false) if err = err2; err != nil { return 0, err } - // valid["ImgHashCode"] = dataRes.HashCode valid["ImgEbai"] = dataRes.EbaiURL } if valid["img2"] != nil { @@ -865,7 +853,8 @@ func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) return outSkuNameExt, err } -func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{}, userName string) (num int64, err error) { +func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{}) (num int64, err error) { + userName := ctx.GetUserName() sku := &model.Sku{} sku.ID = skuID db := dao.GetDB() @@ -996,7 +985,6 @@ func DeleteStoreSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int) (n storeSkuBind := &model.StoreSkuBind{} _, err = dao.DeleteEntityLogically(db, storeSkuBind, map[string]interface{}{ model.FieldJdSyncStatus: model.SyncFlagDeletedMask, - model.FieldWscSyncStatus: model.SyncFlagDeletedMask, model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, }, ctx.GetUserName(), map[string]interface{}{ model.FieldSkuID: v.ID, diff --git a/business/jxstore/cms/store.go b/business/jxstore/cms/store.go index 6c4adf249..5f2160e21 100644 --- a/business/jxstore/cms/store.go +++ b/business/jxstore/cms/store.go @@ -19,6 +19,7 @@ import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/excel" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/msg" @@ -66,6 +67,11 @@ type Store4User struct { OriginalName string `orm:"-" json:"originalName"` Name string `orm:"size(255)" json:"name"` + OpenTime1 int16 `json:"openTime1"` // 930就表示9点半,用两个的原因是为了支持中午休息,1与2的时间段不能交叉,为0表示没有 + CloseTime1 int16 `json:"closeTime1"` // 格式同上 + OpenTime2 int16 `json:"openTime2"` // 格式同上 + CloseTime2 int16 `json:"closeTime2"` // 格式同上 + Status int `json:"status"` CityCode int `orm:"default(0);null" json:"cityCode"` // todo ? DistrictCode int `orm:"default(0);null" json:"districtCode"` // todo ? Address string `orm:"size(255)" json:"address"` @@ -202,7 +208,9 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte sqlVendorStoreCond += " AND ( 1 = 0" } } - sqlFrom += "\nLEFT JOIN " + tableName + " " + tableAlias + " ON " + tableAlias + ".vendor_id = ? AND " + tableAlias + ".store_id = t1.id AND " + tableAlias + ".deleted_at = ?" + sqlFrom += "\nLEFT JOIN " + tableName + " " + tableAlias + " ON " + tableAlias + ".vendor_id = ? AND " + + tableAlias + ".store_id = t1.id AND " + tableAlias + ".deleted_at = ? AND " + + tableAlias + ".is_sync <> 0 " sqlFromParams = append(sqlFromParams, vendor, utils.DefaultTimeValue) if cond == 1 { sqlVendorStoreCond += " " + mapCond + " " + tableAlias + ".id IS NOT NULL" @@ -251,7 +259,7 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte if params["storeID"] != nil || params["storeIDs"] != nil { var storeIDs []int if params["storeIDs"] != nil { - if err = jxutils.Strings2Objs(utils.Interface2String("storeIDs"), &storeIDs); err != nil { + if err = jxutils.Strings2Objs(utils.Interface2String(params["storeIDs"]), &storeIDs); err != nil { return "", nil, "", nil, err } } @@ -310,7 +318,7 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte return sql, sqlParams, sqlFrom, sqlFromParams, nil } -func setStoreMapInfo(ctx *jxcontext.Context, db *dao.DaoDB, storesInfo *StoresInfo, storeIDs []int) (err error) { +func setStoreMapInfo(ctx *jxcontext.Context, db *dao.DaoDB, storesInfo *StoresInfo, storeIDs []int, briefLevel int) (err error) { storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, model.StoreStatusAll, model.StoreIsSyncAll, "") if err != nil { return err @@ -330,6 +338,14 @@ func setStoreMapInfo(ctx *jxcontext.Context, db *dao.DaoDB, storesInfo *StoresIn } for _, v := range storesInfo.Stores { + if briefLevel > 0 { + v.DeliveryRange = "" + v.IDCardFront = "" + v.IDCardBack = "" + v.IDCardHand = "" + v.Licence = "" + v.Licence2Image = "" + } for _, v2 := range storeMapMap[v.ID] { v.StoreMaps = append(v.StoreMaps, utils.Struct2FlatMap(v2)) } @@ -342,6 +358,7 @@ func setStoreMapInfo(ctx *jxcontext.Context, db *dao.DaoDB, storesInfo *StoresIn // todo 门店绑定信息可以考虑以数组形式返回,而不是现在这样 func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interface{}, offset, pageSize int, orderTimeFrom, orderTimeTo time.Time, orderCountFrom, orderCountTo int) (retVal *StoresInfo, err error) { + briefLevel := int(utils.ForceInterface2Int64(params["briefLevel"])) sql, sqlParams, _, _, err := getStoresSql(ctx, keyword, params, orderTimeFrom, orderTimeTo) if err != nil { @@ -447,7 +464,7 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa } if len(retVal.Stores) > 0 { - setStoreMapInfo(ctx, db, retVal, storeIDs) + setStoreMapInfo(ctx, db, retVal, storeIDs, briefLevel) retVal.MapCenterLng, retVal.MapCenterLat = getMapCenter(retVal.Stores) } return retVal, err @@ -759,6 +776,7 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa } else { dao.Commit(db) } + notifyStoreOperatorChanged(store, valid["operatorPhone"]) } } else { globals.SugarLogger.Debugf("UpdateStore track:%s, store:%s", ctx.GetTrackInfo(), utils.Format4Output(store, true)) @@ -766,6 +784,21 @@ func UpdateStore(ctx *jxcontext.Context, storeID int, payload map[string]interfa return num, err } +func notifyStoreOperatorChanged(store *model.Store, newOperator2 interface{}) { + if store.OperatorPhone != "" && newOperator2 != nil { + db := dao.GetDB() + if user, err := dao.GetUserByID(db, "mobile", store.OperatorPhone); err == nil { + curUserName := "" + if newOperator := utils.Interface2String(newOperator2); newOperator != "" { + if curUser, err := dao.GetUserByID(db, "mobile", newOperator); err == nil { + curUserName = curUser.GetName() + } + } + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.GetID(), "门店运营变更", fmt.Sprintf("门店:%d-%s,原运营:%s,变更为:%s", store.ID, store.Name, user.GetName(), curUserName)) + } + } +} + func SetStoreStatus(ctx *jxcontext.Context, storeID, status int) (err error) { payload := map[string]interface{}{ "status": status, @@ -1095,7 +1128,7 @@ func TmpGetJxBadCommentsNo(ctx *jxcontext.Context, storeID int) (count int, err return count, err } -func TmpGetJxBadCommentsByStoreId(ctx *jxcontext.Context, storeIDs []int, offset, pageSize, commentType int, fromTime, toTime time.Time) (retVal map[string]interface{}, err error) { +func TmpGetJxBadCommentsByStoreId(ctx *jxcontext.Context, keyword string, storeIDs []int, offset, pageSize, commentType int, fromTime, toTime time.Time) (retVal map[string]interface{}, err error) { db := dao.GetDB() sql := ` SELECT SQL_CALC_FOUND_ROWS @@ -1108,6 +1141,13 @@ func TmpGetJxBadCommentsByStoreId(ctx *jxcontext.Context, storeIDs []int, offset WHERE 1 = 1 ` sqlParams := []interface{}{} + if keyword != "" { + keywordLike := "%" + keyword + "%" + sql += ` + AND (t1.order_id LIKE ? OR t1.jxstoreid LIKE ? OR t1.userphone LIKE ? OR t1.scorecontent LIKE ? OR t1.vendertags LIKE ? OR t1.updated_scorecontent LIKE ? + OR t1.updated_vendertags LIKE ? OR t2.name LIKE ?)` + sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike) + } if len(storeIDs) > 0 { sql += " AND t1.jxstoreid IN (" + dao.GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) @@ -1494,7 +1534,7 @@ func GetStoresVendorSnapshot(ctx *jxcontext.Context, parentTask tasksch.ITask, v task := tasksch.NewParallelTask("GetStoresVendorSnapshot", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeMap := batchItemList[0].(*model.StoreMap) - if storeMap.VendorID != model.VendorIDWSC { + if model.IsVendorRemote(storeMap.VendorID) { if handler := partner.GetPurchasePlatformFromVendorID(storeMap.VendorID); handler != nil { store, err2 := handler.ReadStore(ctx, storeMap.VendorStoreID) if err = err2; err == nil { @@ -2076,21 +2116,8 @@ func GetStoreListByLocation(ctx *jxcontext.Context, lng, lat float64, needWalkDi if err = dao.GetRows(dao.GetDB(), &storeList1, sql, sqlParams...); err == nil { var storeList2 []*Store4User for _, v := range storeList1 { - isStoreOK := false - v.FloatLng = jxutils.IntCoordinate2Standard(v.Lng) - v.FloatLat = jxutils.IntCoordinate2Standard(v.Lat) - if v.DeliveryRangeType == model.DeliveryRangeTypeRadius { - maxDistance := int(utils.Str2Int64WithDefault(v.DeliveryRange, 0)) - v.Distance = int(jxutils.EarthDistance(lng, lat, v.FloatLng, v.FloatLat) * 1000) - isStoreOK = v.Distance <= maxDistance - } else { - points := jxutils.CoordinateStr2Points(v.DeliveryRange) - if utils.IsPointInPolygon(lng, lat, points) { - v.Distance = int(jxutils.EarthDistance(lng, lat, v.FloatLng, v.FloatLat) * 1000) - isStoreOK = true - } - } - if isStoreOK { + if distance := jxutils.Point2StoreDistance(lng, lat, v.Lng, v.Lat, v.DeliveryRangeType, v.DeliveryRange); distance > 0 { + v.Distance = distance storeList2 = append(storeList2, v) } } diff --git a/business/jxstore/cms/store_sku.go b/business/jxstore/cms/store_sku.go index 3f91a1525..88c6833da 100644 --- a/business/jxstore/cms/store_sku.go +++ b/business/jxstore/cms/store_sku.go @@ -54,24 +54,28 @@ type StoreSkuExt struct { StoreSkuStatus int `json:"storeSkuStatus"` EbaiID string `orm:"column(ebai_id);index" json:"ebaiID"` - MtwmID string `orm:"column(mtwm_id)" json:"mtwmID"` // 这个也不是必须的,只是为了DAO取数据语句一致 - WscID string `orm:"column(wsc_id);index" json:"wscID"` // 表示微盟skuId - WscID2 string `orm:"column(wsc_id2);index" json:"wscID2"` // 表示微盟goodsId + MtwmID string `orm:"column(mtwm_id)" json:"mtwmID"` // 这个也不是必须的,只是为了DAO取数据语句一致 + // WscID string `orm:"column(wsc_id);index" json:"wscID"` // 表示微盟skuId + // WscID2 string `orm:"column(wsc_id2);index" json:"wscID2"` // 表示微盟goodsId JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"` EbaiSyncStatus int8 `orm:"default(2)" json:"ebaiSyncStatus"` MtwmSyncStatus int8 `orm:"default(2)" json:"mtwmSyncStatus"` - WscSyncStatus int8 `orm:"default(2)" json:"wscSyncStatus"` + // WscSyncStatus int8 `orm:"default(2)" json:"wscSyncStatus"` 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"` - ActPrice int `json:"actPrice"` - EarningPrice int `json:"earningPrice"` + ActPrice int `json:"actPrice"` + ActID int `orm:"column(act_id)" json:"actID"` + + EarningPrice int `json:"earningPrice"` + EarningActID int `orm:"column(earning_act_id)" json:"earningActID"` + RealEarningPrice int `json:"realEarningPrice"` Count int `json:"count"` @@ -198,7 +202,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 = ?) @@ -441,9 +446,9 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo t2.comment, t2.category_id sku_category_id, t2.status sku_status, t4.created_at bind_created_at, t4.updated_at bind_updated_at, t4.last_operator bind_last_operator, t4.deleted_at bind_deleted_at, 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.wsc_id, t4.wsc_id2, - t4.jd_sync_status, t4.ebai_sync_status, t4.mtwm_sync_status, t4.wsc_sync_status, - t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.wsc_price + 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.jx_price ` + sql var tmpList []*tGetStoresSkusInfo beginTime := time.Now() @@ -486,8 +491,12 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo if true { //!(offset == 0 && pageSize == model.UnlimitedPageSize) { storeIDs, skuIDs = GetStoreAndSkuIDsFromInfo(skuNamesInfo) } + actVendorID := -1 + if params["actVendorID"] != nil { + actVendorID = int(utils.Interface2Int64WithDefault(params["actVendorID"], -1)) + } beginTime := time.Now() - err = updateActPrice4StoreSkuNameNew(db, storeIDs, skuIDs, skuNamesInfo) + err = updateActPrice4StoreSkuNameNew(db, storeIDs, skuIDs, skuNamesInfo, actVendorID) globals.SugarLogger.Debugf("GetStoresSkusNew updateActPrice4StoreSkuName:%v", time.Now().Sub(beginTime)) if !isFocus { err = updateUnitPrice4StoreSkuNameNew(db, skuNamesInfo) @@ -534,11 +543,15 @@ func updateUnitPrice4StoreSkuNameNew(db *dao.DaoDB, skuNamesInfo *StoreSkuNamesI } // skuIDs为空,会导致性能极低,所以要skuIDs必须有值 -func updateActPrice4StoreSkuNameNew(db *dao.DaoDB, storeIDs, skuIDs []int, skuNamesInfo *StoreSkuNamesInfo) (err error) { +func updateActPrice4StoreSkuNameNew(db *dao.DaoDB, storeIDs, skuIDs []int, skuNamesInfo *StoreSkuNamesInfo, actVendorID int) (err error) { if len(skuIDs) == 0 { return nil } - actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, nil, storeIDs, skuIDs, time.Now(), time.Now()) + var vendorIDs []int + if actVendorID >= 0 { + vendorIDs = []int{actVendorID} + } + actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, vendorIDs, storeIDs, skuIDs, time.Now(), time.Now()) if err != nil { globals.SugarLogger.Errorf("updateActPrice4StoreSkuNameNew can not get sku promotion info for error:%v", err) return err @@ -551,9 +564,11 @@ func updateActPrice4StoreSkuNameNew(db *dao.DaoDB, storeIDs, skuIDs []int, skuNa for _, v := range skuName.Skus2 { if actStoreSku := actStoreSkuMap4Act.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil { v.ActPrice = int(actStoreSku.ActualActPrice) + v.ActID = actStoreSku.ActID } if actStoreSku := actStoreSkuMap4EarningPrice.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil { v.EarningPrice = int(actStoreSku.EarningPrice) + v.EarningActID = actStoreSku.ActID } v.RealEarningPrice = v.EarningPrice @@ -924,6 +939,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 @@ -988,7 +1009,7 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs for _, v := range allBinds { var num int64 inSkuBind := inSkuBinsMap[v.RealSkuID] - isCanChangePrice := (isUserCanDirectChangePrice || v.ChangePriceType != model.StoreChangePriceTypeBossDisabled) + isCanChangePrice := (isUserCanDirectChangePrice || jxutils.TranslateStorePriceType(v.ChangePriceType) != model.StoreChangePriceTypeBossDisabled) // globals.SugarLogger.Debug(utils.Format4Output(inSkuBind, false)) var skuBind *model.StoreSkuBind if v.ID == 0 { @@ -1001,6 +1022,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 } @@ -1022,7 +1044,6 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask, - model.FieldWscSyncStatus: model.SyncFlagDeletedMask, }, userName, nil); err != nil { dao.Rollback(db) return nil, err @@ -1049,9 +1070,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 { @@ -1066,7 +1089,6 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs updateFieldMap[model.FieldJdSyncStatus] = 1 updateFieldMap[model.FieldEbaiSyncStatus] = 1 updateFieldMap[model.FieldMtwmSyncStatus] = 1 - updateFieldMap[model.FieldWscSyncStatus] = 1 updateFieldMap[model.FieldUpdatedAt] = 1 updateFieldMap[model.FieldLastOperator] = 1 @@ -1160,7 +1182,6 @@ func updateStoreSkusSaleWithoutSync(ctx *jxcontext.Context, storeID int, skuBind model.FieldJdSyncStatus: skuBind.JdSyncStatus | model.SyncFlagSaleMask, model.FieldEbaiSyncStatus: skuBind.EbaiSyncStatus | model.SyncFlagSaleMask, model.FieldMtwmSyncStatus: skuBind.MtwmSyncStatus | model.SyncFlagSaleMask, - model.FieldWscSyncStatus: skuBind.WscSyncStatus | model.SyncFlagSaleMask, } if utils.IsTimeZero(autoSaleTime) || skuBind.Status == model.SkuStatusNormal { kvs["AutoSaleAt"] = utils.DefaultTimeValue @@ -1270,9 +1291,9 @@ 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.wsc_sync_status = t1.wsc_sync_status | ?, t1.mtwm_sync_status = t1.mtwm_sync_status | ?, t1.ebai_sync_status = t1.ebai_sync_status | ? WHERE t1.store_id = ? AND t1.deleted_at = ? @@ -1285,7 +1306,7 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode now, pricePercentage, pricePercentage, - model.SyncFlagPriceMask, + pricePercentage, model.SyncFlagPriceMask, model.SyncFlagPriceMask, model.SyncFlagPriceMask, @@ -1312,14 +1333,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.wsc_sync_status = IF((t1.wsc_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{}{ @@ -1338,8 +1359,6 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode model.SyncFlagDeletedMask, model.SyncFlagNewMask, model.SyncFlagDeletedMask, - model.SyncFlagNewMask, - model.SyncFlagDeletedMask, toStoreID, utils.DefaultTimeValue, } @@ -1364,14 +1383,15 @@ 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 | ?, - t1.wsc_sync_status = t1.wsc_sync_status | ?, t1.mtwm_sync_status = t1.mtwm_sync_status | ?, t1.ebai_sync_status = t1.ebai_sync_status | ? WHERE t1.store_id = ? AND t1.deleted_at = ? AND t0.id IS NOT NULL @@ -1388,11 +1408,12 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode pricePercentage, pricePercentage, pricePercentage, + pricePercentage, + pricePercentage, isModifyStatus, syncStatus, syncStatus, syncStatus, - syncStatus, toStoreID, utils.DefaultTimeValue, } @@ -1407,11 +1428,12 @@ 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, - jd_sync_status, wsc_sync_status, ebai_sync_status, mtwm_sync_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), - IF(? = 0, ?, t1.status), ?, ?, ?, ? + 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 = ? JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? @@ -1425,12 +1447,13 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode pricePercentage, pricePercentage, pricePercentage, + pricePercentage, + pricePercentage, isModifyStatus, model.SkuStatusDontSale, model.SyncFlagNewMask, model.SyncFlagNewMask, model.SyncFlagNewMask, - model.SyncFlagNewMask, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, @@ -1459,7 +1482,7 @@ func shouldPendingStorePriceChange(ctx *jxcontext.Context, storeID int, skuBindI if err = dao.GetEntity(db, store); err != nil { return false, err } - return store.ChangePriceType == model.StoreChangePriceTypeNeedApprove, nil + return jxutils.TranslateStorePriceType(store.ChangePriceType) == model.StoreChangePriceTypeNeedApprove, nil } } return false, nil @@ -1798,7 +1821,6 @@ func setStoreSkuBindStatus(skuBind *model.StoreSkuBind, status int8) { skuBind.JdSyncStatus |= status skuBind.EbaiSyncStatus |= status skuBind.MtwmSyncStatus |= status - skuBind.WscSyncStatus |= status } func checkStoreExisting(db *dao.DaoDB, storeID int) (err error) { @@ -1900,10 +1922,10 @@ func RefreshStoresSkuByVendor(ctx *jxcontext.Context, storeIDs []int, vendorID i } } for _, v := range storeSkuList { - pricePercentage := jxutils.GetPricePercentageByVendorPrice(storeMap[v.StoreID].PricePercentagePackObj, v.Price, int(storeMap[v.StoreID].PricePercentage)) + pricePercentage, priceAdd := jxutils.GetPricePercentageByVendorPrice(storeMap[v.StoreID].PricePercentagePackObj, v.Price, int(storeMap[v.StoreID].PricePercentage)) skuName := skuNameMap[skuMap[v.SkuID].NameID] - v.Price = jxutils.CaculateSkuPriceFromVendor(v.Price, pricePercentage) - v.UnitPrice = jxutils.CaculateSkuPriceFromVendor(skuName.Price, pricePercentage) + v.Price = jxutils.CaculateSkuPriceFromVendor(v.Price, pricePercentage, priceAdd) + v.UnitPrice = jxutils.CaculateSkuPriceFromVendor(skuName.Price, pricePercentage, priceAdd) dao.WrapAddIDCULDEntity(v, ctx.GetUserName()) setStoreSkuBindStatus(v, model.SyncFlagNewMask) v.JdSyncStatus = 0 @@ -2057,3 +2079,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/store_sku_check.go b/business/jxstore/cms/store_sku_check.go index c93deca67..9ef91776c 100644 --- a/business/jxstore/cms/store_sku_check.go +++ b/business/jxstore/cms/store_sku_check.go @@ -542,15 +542,14 @@ func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, storeID := jxStoreInfoListValue.ID storeIDStr := utils.Int2Str(storeID) storeName := jxStoreInfoListValue.Name + jxSkuInfoDataSingle := &StoreSkuNamesInfo{} + jxSkuInfoDataMulti := &StoreSkuNamesInfo{} if jxStoreInfoListValue.StoreMaps != nil { var filterJxSkuInfoMapSingle map[int]*StoreSkuNameExt var filterJxSkuInfoMapMulti map[int]*StoreSkuNameExt for _, vendorListValue := range jxStoreInfoListValue.StoreMaps { vendorID := int(utils.MustInterface2Int64(vendorListValue["vendorID"])) - //京西的门店商品只取一次 - flag := false - jxSkuInfoDataSingle := &StoreSkuNamesInfo{} - jxSkuInfoDataMulti := &StoreSkuNamesInfo{} + var flag = false if partner.IsMultiStore(vendorID) { if flag == false { jxSkuInfoDataMulti, _ = GetStoreSkus(ctx, storeID, filterJxDepotUnSaleSkuIds, true, "", true, false, map[string]interface{}{}, 0, -1) diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index 50b7801cc..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 { // 避免重新计算 - pricePercentage = jxutils.GetPricePercentage(pricePercentagePack, int(inSku.Price), pricePercentage) - inSku.VendorPrice = int64(jxutils.CaculateSkuVendorPrice(int(inSku.Price), pricePercentage)) + 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 { @@ -447,6 +446,8 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, isFull bo } if err == nil { successList = batchedStoreSkuList + } else { + offlineList = append(offlineList, batchedStoreSkuList...) } if len(successList) > 0 { updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagDeletedMask) @@ -665,7 +666,10 @@ func amendAndPruneStoreStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, v case 1: if (opType == AmendPruneOnlyPrune || opType == AmendPruneAll) && len(sku2Delete) > 0 { _, err = putils.FreeBatchStoreSkuInfo("删除门店商品", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - _, err = handler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList) + if _, err = handler.DeleteStoreSkus(ctx, storeID, vendorStoreID, batchedStoreSkuList); err != nil { + // 如果删除失败,尝试设置不可售,假定删除批处理SIZE小于等于设置门店商品可售批处理SIZE + handler.UpdateStoreSkusStatus(ctx, storeID, vendorStoreID, batchedStoreSkuList, model.SkuStatusDontSale) + } return nil, 0, err }, ctx, task, sku2Delete, handler.GetStoreSkusBatchSize(partner.FuncDeleteStoreSkus), isContinueWhenError) } diff --git a/business/jxstore/cms/user2.go b/business/jxstore/cms/user2.go index 2adf97a1a..4f54b5b91 100644 --- a/business/jxstore/cms/user2.go +++ b/business/jxstore/cms/user2.go @@ -136,11 +136,14 @@ func RegisterUserWithMobile(ctx *jxcontext.Context, user *model.User, mobileVeri user.Type = model.UserTypeConsumer if inAuthInfo.AuthBindInfo.Type == dingding.AuthTypeStaff { user.Type |= model.UserTypeOperator - } else { + } else if user.Mobile != nil { user.Type |= model.UserTypeStoreBoss } createName += "," + inAuthInfo.GetAuthID() authType = inAuthInfo.GetAuthType() + if user.Avatar == "" { + user.Avatar = inAuthInfo.GetAvatar() + } } if err = CreateUser(user, utils.LimitUTF8StringLen(createName, 32)); err == nil { userProvider.UpdateLastLogin(user.GetID(), authType, ctx.GetRealRemoteIP()) @@ -637,7 +640,7 @@ func UpdateMyDeliveryAddress(ctx *jxcontext.Context, addressID int, payload map[ } func QueryUserDeliveryAddress(ctx *jxcontext.Context, userIDs []string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { - addressList, totalCount, err := dao.QueryUserDeliveryAddress(dao.GetDB(), userIDs, offset, pageSize) + addressList, totalCount, err := dao.QueryUserDeliveryAddress(dao.GetDB(), 0, userIDs, offset, pageSize) if err == nil { pagedInfo = &model.PagedInfo{ TotalCount: totalCount, @@ -649,7 +652,7 @@ func QueryUserDeliveryAddress(ctx *jxcontext.Context, userIDs []string, offset, func QueryMyDeliveryAddress(ctx *jxcontext.Context) (addressList []*dao.UserDeliveryAddressEx, err error) { _, userID := ctx.GetMobileAndUserID() - addressList, _, err = dao.QueryUserDeliveryAddress(dao.GetDB(), []string{userID}, 0, model.UnlimitedPageSize) + addressList, _, err = dao.QueryUserDeliveryAddress(dao.GetDB(), 0, []string{userID}, 0, model.UnlimitedPageSize) return addressList, err } @@ -702,3 +705,11 @@ func LoadUserCart(ctx *jxcontext.Context, userID string, storeIDs []int) (cartIt err = dao.GetRows(dao.GetDB(), &cartItems, sql, userID, storeIDs) return cartItems, err } + +func GetSelfInfo(ctx *jxcontext.Context) (user *model.User, err error) { + tokenInfo, err := auth2.GetTokenInfo(ctx.GetToken()) + if err == nil { + user, err = dao.GetUserByID(dao.GetDB(), "user_id", tokenInfo.GetID()) + } + return user, err +} diff --git a/business/jxstore/misc/store_score.go b/business/jxstore/misc/store_score.go index 5fd90ada7..aaa9c7f7d 100644 --- a/business/jxstore/misc/store_score.go +++ b/business/jxstore/misc/store_score.go @@ -220,17 +220,20 @@ func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeInfo := batchItemList[0].(*cms.StoreExt) storeID := storeInfo.ID - jxSkuInfoData, _ := cms.GetStoreSkus(ctx, storeID, []int{}, true, "", true, false,map[string]interface{}{}, 0, -1) - jxSkuPriceMapData := make(map[int]int) - for _, value := range jxSkuInfoData.SkuNames { - for _, skuInfo := range value.Skus2 { - saleStatus := jxutils.MergeSkuStatus(skuInfo.SkuStatus, skuInfo.StoreSkuStatus) - if saleStatus == model.SkuStatusNormal { - jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice + if jxSkuInfoData, err2 := cms.GetStoreSkus(ctx, storeID, []int{}, true, "", true, false, map[string]interface{}{}, 0, -1); jxSkuInfoData != nil { + jxSkuPriceMapData := make(map[int]int) + for _, value := range jxSkuInfoData.SkuNames { + for _, skuInfo := range value.Skus2 { + saleStatus := jxutils.MergeSkuStatus(skuInfo.SkuStatus, skuInfo.StoreSkuStatus) + if saleStatus == model.SkuStatusNormal { + jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice + } } } + allStoreSkusWrapper.SetData(storeID, jxSkuPriceMapData) + } else { + globals.SugarLogger.Warnf("store_score.GetAllStoreSkus %d return empty, err:%v", storeID, err2) } - allStoreSkusWrapper.SetData(storeID, jxSkuPriceMapData) return retVal, err } taskParallel := tasksch.NewParallelTask("得到所有门店商品", tasksch.NewParallelConfig().SetParallelCount(ParallelCount), ctx, taskFunc, storeList) diff --git a/business/jxstore/tempop/tempop.go b/business/jxstore/tempop/tempop.go index f9626cab8..7a20d959d 100644 --- a/business/jxstore/tempop/tempop.go +++ b/business/jxstore/tempop/tempop.go @@ -577,7 +577,7 @@ func DeleteWrongSpu(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) ( mapData := map[string]interface{}{ "name": skuNameList[step].Name, } - _, err = cms.UpdateSkuName(ctx, skuNameList[step].ID, mapData, ctx.GetUserName()) + _, err = cms.UpdateSkuName(ctx, skuNameList[step].ID, mapData) if err != nil { globals.SugarLogger.Debugf("DeleteWrongSpu failed nameid:%d, name:%s, with error:%v", skuNameList[step].ID, skuNameList[step].Name, err) } diff --git a/business/jxstore/yonghui/yonghui.go b/business/jxstore/yonghui/yonghui.go new file mode 100644 index 000000000..dcb52a49b --- /dev/null +++ b/business/jxstore/yonghui/yonghui.go @@ -0,0 +1,125 @@ +package yonghui + +import ( + "fmt" + "mime/multipart" + "unicode" + + "git.rosy.net.cn/baseapi/platformapi/jdapi" + "git.rosy.net.cn/baseapi/platformapi/weimobapi" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "github.com/360EntSecGroup-Skylar/excelize" +) + +var ( + sheetNames = []string{"蔬菜", "水果", "肉禽", "净配", "水产", "干货", "MINI肉禽价格"} +) + +//sheet1 蔬菜 +var ( + sheet1SkuIdCol = 0 + sheet1SkuPriceCol = 14 + sheet1OrgSkuIdCol = 5 + sheet1OrgSkuPriceCol = 8 +) + +func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader) (hint string, err error) { + var ( + // skuId string + // skuPrice string + skuMap = make(map[string]string) + ) + param := &weimobapi.QueryGoodsListParam{ + PageNum: 1, + PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds, + } + // if len(files) == 0 { + // return "", errors.New("没有文件上传!") + // } + xlsx, err := excelize.OpenFile("111.xlsx") + if err != nil { + fmt.Println(err) + return + } + for _, v := range sheetNames { + // goodsParam := &weimobapi.GoodsParameter{} + rows, _ := xlsx.GetRows(v) + switch v { + case "蔬菜": + for _, row := range rows { + for k, _ := range row { + if k == sheet1SkuIdCol { + + } + // if !IsChineseChar(colCell) { + + // } + } + fmt.Println() + } + } + } + + // xlFile, err := xlsx.OpenFile("111.xlsx") + // if err != nil { + // errors.New(err.Error()) + // } + // excelize + // for _, sheet := range xlFile.Sheets { + // if sheet.Name == "蔬菜" { + // for j := 0; j < len(sheet.Rows); j++ { + // cells := sheet.Rows[j].Cells + // for i := 0; i < len(cells); i++ { + // cell := cells[i] + // if i == 0 { + // if _, err := strconv.Atoi(cell.String()); err != nil || cell.String() == "" { + // continue + // } + // skuId = cell.String() + // } + // if i == 14 { + // skuPrice = cell.String() + // } + // skuMap[skuId] = skuPrice + // } + // } + // } + // } + for k, v := range skuMap { + fmt.Println(k) + fmt.Println(v) + } + + GetWeiMoGoodsList(param) + return "", err +} + +func GetWeiMoGoodsList(param *weimobapi.QueryGoodsListParam) { + // for { + // skuList, _, err2 := getAPI("").QuerySkuInfos(param) + // if err = err2; err != nil { + // return nil, err + // } + // if len(skuList) > 0 { + // batchSkuNameList := make([]*partner.SkuNameInfo, len(skuList)) + // for k, v := range skuList { + // batchSkuNameList[k] = vendorSku2Jx(v) + // } + // setSkuNameListPic(batchSkuNameList) + // skuNameList = append(skuNameList, batchSkuNameList...) + // } + // if len(skuList) < param.PageSize { + // break + // } + // param.PageNum++ + // } +} + +func IsChineseChar(str string) bool { + for _, r := range str { + if unicode.Is(unicode.Scripts["Han"], r) { + return true + } + } + return false +} diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index 549df3cda..b0469f187 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -80,18 +80,12 @@ func getJxStoreIDFromOrder(order *model.GoodsOrder) (retVal int) { // 此函数得到的是order的销售门店京西ID,与GetJxStoreIDFromOrder的区别是order.StoreID的解释不同,参考其它相关资料 func GetSaleStoreIDFromOrder(order *model.GoodsOrder) (retVal int) { - if order.VendorID != model.VendorIDWSC { - return getJxStoreIDFromOrder(order) - } - return order.StoreID + return getJxStoreIDFromOrder(order) } // 此函数得到的是order的商品的展示门店京西ID,与GetJxStoreIDFromOrder的区别是order.StoreID的解释不同,参考其它相关资料 func GetShowStoreIDFromOrder(order *model.GoodsOrder) (retVal int) { - if order.VendorID != model.VendorIDWSC { - return getJxStoreIDFromOrder(order) - } - return order.JxStoreID + return getJxStoreIDFromOrder(order) } func GetSkuIDFromOrderSku(sku *model.OrderSku) (skuID int) { @@ -241,7 +235,7 @@ func IntCoordinate2MarsStandard(gpsLng, gpsLat int, coordinateType int) (marsLng case model.CoordinateTypeGPS: coordSys = autonavi.CoordSysGPS case model.CoordinateTypeMars: - coordSys = autonavi.CoordSysAutonavi + return marsLng, marsLat, nil case model.CoordinateTypeBaiDu: coordSys = autonavi.CoordSysBaidu case model.CoordinateTypeMapbar: @@ -526,6 +520,7 @@ func RefreshOrderSkuRelated(order *model.GoodsOrder) *model.GoodsOrder { order.VendorPrice = 0 order.ShopPrice = 0 order.Weight = 0 + order.EarningPrice = 0 for _, sku := range order.Skus { if sku.SkuID > math.MaxInt32 { sku.SkuID = 0 @@ -538,6 +533,7 @@ func RefreshOrderSkuRelated(order *model.GoodsOrder) *model.GoodsOrder { order.SalePrice += sku.SalePrice * int64(sku.Count) order.VendorPrice += sku.VendorPrice * int64(sku.Count) order.ShopPrice += sku.ShopPrice * int64(sku.Count) + order.EarningPrice += sku.EarningPrice * int64(sku.Count) order.Weight += sku.Weight * sku.Count } return order @@ -783,3 +779,29 @@ func GetOneEmailFromStr(str string) (email string) { } return email } + +// 计算一个坐标点距离一个门店的距离,单位为米,如果不在有效范围内,则返回0 +func Point2StoreDistance(lng, lat float64, intStoreLng, intStoreLat int, deliveryRangeType int8, deliveryRange string) (distance int) { + storeLng := IntCoordinate2Standard(intStoreLng) + storeLat := IntCoordinate2Standard(intStoreLat) + if deliveryRangeType == model.DeliveryRangeTypeRadius { + maxDistance := int(utils.Str2Int64WithDefault(deliveryRange, 0)) + distance = int(EarthDistance(lng, lat, storeLng, storeLat) * 1000) + if distance > maxDistance { + distance = 0 + } + } else { + points := CoordinateStr2Points(deliveryRange) + if utils.IsPointInPolygon(lng, lat, points) { + distance = int(EarthDistance(lng, lat, storeLng, storeLat) * 1000) + } + } + return distance +} + +func TranslateStorePriceType(storePriceType int8) int8 { + if storePriceType == model.StoreChangePriceTypeManagedStore { + storePriceType = model.StoreChangePriceTypeBossDisabled + } + return storePriceType +} diff --git a/business/jxutils/jxutils_cms.go b/business/jxutils/jxutils_cms.go index f9e01d968..874682300 100644 --- a/business/jxutils/jxutils_cms.go +++ b/business/jxutils/jxutils_cms.go @@ -245,60 +245,80 @@ func CaculateUnitPrice(skuPrice int, specQuality float32, specUnit string, skuNa return unitPrice } -func CaculateSkuVendorPrice(price, percentage 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 } - vendorPrice = int(math.Round(float64(price*percentage) / 100)) + 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 } return vendorPrice } -func CaculateSkuPriceFromVendor(vendorPrice, percentage int) (price int) { - if percentage <= 10 || percentage >= 400 { - percentage = 100 - } - price = int(math.Round(float64(vendorPrice) * 100 / float64(percentage))) +func CaculateSkuPriceFromVendor(vendorPrice, percentage, priceAdd int) (price int) { + percentage = ConstrainPricePercentage(percentage) + price = int(math.Round(float64(vendorPrice-priceAdd) * 100 / float64(percentage))) if price < 0 { price = 0 } return price } -func GetPricePercentage(l model.PricePercentagePack, price int, defPricePercentage int) (pricePercentage int) { +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 + 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 + return pricePercentage, priceAdd } -func GetPricePercentageByVendorPrice(l model.PricePercentagePack, vendorPrice int, defPricePercentage int) (pricePercentage int) { +func GetPricePercentageByVendorPrice(l model.PricePercentagePack, vendorPrice int, defPricePercentage int) (pricePercentage, priceAdd int) { pricePercentage = defPricePercentage if len(l) > 0 { var lastItem *model.PricePercentageItem for _, v := range l { - if CaculateSkuVendorPrice(v.BeginPrice, v.PricePercentage) > vendorPrice { + if CaculateSkuVendorPrice(v.BeginPrice, v.PricePercentage, v.PriceAdd) > vendorPrice { break } lastItem = v } if lastItem != nil { pricePercentage = lastItem.PricePercentage + priceAdd = lastItem.PriceAdd } } - return pricePercentage + 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 { 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/jxutils/msg/msg.go b/business/jxutils/msg/msg.go index 8265d5da2..ceff07d1a 100644 --- a/business/jxutils/msg/msg.go +++ b/business/jxutils/msg/msg.go @@ -14,8 +14,6 @@ import ( "git.rosy.net.cn/jx-callback/globals" ) -const weixinTemplateID4StoreStatusChanged = "Fl0vOnBKTQqRFx3-shGKxdCnxMdQXNeODzgkuwd7oxw" - // todo msgType不依赖于钉钉 func SendUserMessage(msgType string, user *model.User, title, content string) (err error) { userID := user.GetID() diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 524ee428b..c23d6ec36 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -417,7 +417,7 @@ func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments, isBadComment b orderInfo = fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))], order.OrderSeq, comment.OrderId) consigneeName = order.ConsigneeName } else { - orderInfo = fmt.Sprintf("%s订单, %s", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))], comment.OrderId) + orderInfo = fmt.Sprintf("%s订单, %s", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))] /*comment.OrderId*/, "") } data := map[string]interface{}{ "first": map[string]interface{}{ diff --git a/business/model/const.go b/business/model/const.go index 4256a46a0..1a6030675 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -27,7 +27,8 @@ var ( VendorIDMTWM: "美好菜市", VendorIDELM: "好菜鲜生", VendorIDEBAI: "好菜鲜生", - VendorIDWSC: "京西菜市", + VendorIDJX: "京西商城", + VendorIDWSC: "微盟微商城", } OrderStatusName = map[int]string{ @@ -268,7 +269,8 @@ const ( OrderFlagMaskCallPMCourier = 64 // 取货失败后召唤平台配送 OrderFlagMaskSetDelivered = 128 // 设置送达 - OrderFlagMaskFake = 256 // 假订单,即刷单用的 + OrderFlagMaskFake = 256 // 假订单,即刷单用的 + OrderFlagMaskTempJX = 512 // 临时京西订单 ) const ( @@ -305,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 @@ -340,8 +350,8 @@ func IsOrderImportantStatus(status int) bool { return IsOrderMainStatus(status) || IsOrderLockStatus(status) || IsOrderUnlockStatus(status) } -func IsSpecialVendorID(vendorID int) bool { - return vendorID == VendorIDWSC || vendorID == VendorIDJX +func IsVendorRemote(vendorID int) bool { + return vendorID >= VendorIDJD && vendorID <= VendorIDEBAI } func WaybillVendorID2Mask(vendorID int) (mask int8) { @@ -356,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/dao_order.go b/business/model/dao/dao_order.go index 5933c8406..fd7e3e7ad 100644 --- a/business/model/dao/dao_order.go +++ b/business/model/dao/dao_order.go @@ -36,30 +36,139 @@ type OrderSkuWithActualPayPrice struct { PayPercentage int `json:"payPercentage"` } -func QueryOrders(db *DaoDB, vendorIDs []int, storeID int, orderCreatedAtBegin, orderCreatedAtEnd time.Time) (orderList []*model.GoodsOrder, err error) { +type tGoodsAndOrder struct { + model.GoodsOrder + OrderSkuID int64 `orm:"column(order_sku_id)" json:"orderSkuID"` + StoreSubID int `orm:"column(store_sub_id)" json:"storeSubID"` // 当前这个字段被当成结算活动ID用 + StoreSubName string `orm:"size(64)" json:"storeSubName"` // 当前这个字段被用作vendorActType + Count int `json:"count"` + VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` + SkuID int `orm:"column(sku_id)" json:"skuID"` // 外部系统里记录的 jxskuid + JxSkuID int `orm:"column(jx_sku_id)" json:"jxSkuID"` // 根据VendorSkuID在本地系统里查询出来的 jxskuid + SkuName string `orm:"size(255)" json:"skuName"` + SkuShopPrice int64 `json:"shopPrice"` // 京西价 + SkuVendorPrice int64 `json:"vendorPrice"` // 平台价 + SkuSalePrice int64 `json:"salePrice"` // 售卖价 + SkuEarningPrice int64 `json:"earningPrice"` // 活动商品设置,结算给门店老板的钱,如果结算活动ID为0,是按结算比例算的,否则就是结算表中的值 + Weight int `json:"weight"` // 单位为克 + SkuType int `json:"skuType"` // 当前如果为gift就为1,否则缺省为0 + PromotionType int `json:"promotionType"` // todo 当前是用于记录京东的PromotionType(生成jxorder用),没有做转换 +} + +//actID指结算活动的id +func QueryOrders(db *DaoDB, vendorOrderID string, actID int, vendorIDs []int, storeID int, fromDate, toDate time.Time) (orderList []*model.GoodsOrder, err error) { + sqlParams := []interface{}{} + var ( + orderNewList []*tGoodsAndOrder + orderNewMap map[string][]*model.OrderSku + ) sql := ` - SELECT t1.* - FROM goods_order t1 - WHERE t1.order_created_at >= ?` - sqlParams := []interface{}{ - orderCreatedAtBegin, + SELECT a.*, + b.id order_sku_id, b.store_sub_id, b.store_sub_name, b.count, b.vendor_sku_id, b.sku_id, b.jx_sku_id, b.sku_name, b.shop_price sku_shop_price, + b.vendor_price sku_vendor_price, b.sale_price sku_sale_price, b.earning_price sku_earning_price, b.weight, b.sku_type, b.promotion_type + FROM goods_order a + JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id + ` + if actID > 0 { + sql += ` + JOIN ( SELECT t4.vendor_order_id, t4.vendor_id + FROM act t1 + JOIN act_store_sku t2 ON t2.act_id = t1.id + JOIN order_sku t3 ON t3.sku_id = t2.sku_id + JOIN goods_order t4 ON t4.vendor_order_id = t3.vendor_order_id + AND t4.vendor_id = t3.vendor_id + AND t2.store_id = IF(t4.jx_store_id <> 0, t4.jx_store_id, t4.store_id) + AND t4.order_created_at BETWEEN t1.begin_at AND t1.end_at + WHERE t1.status = 1 + AND t1.type = ? + AND t1.id = ? + GROUP BY 1,2 + )s ON s.vendor_order_id = a.vendor_order_id AND s.vendor_id = a.vendor_id + ` + sqlParams = append(sqlParams, model.ActSkuFake, actID) + } + sql += ` + WHERE 1=1 + ` + if vendorOrderID != "" { + sql += " AND a.vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) } if len(vendorIDs) > 0 { - sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sql += " AND a.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, vendorIDs) } if storeID > 0 { - sql += " AND IF(t1.jx_store_id <> 0, t1.jx_store_id, t1.store_id) = ?" + sql += " AND IF(a.jx_store_id <> 0, a.jx_store_id, a.store_id) = ?" sqlParams = append(sqlParams, storeID) } - if !utils.IsTimeZero(orderCreatedAtEnd) { - sql += " AND t1.order_created_at <= ?" - sqlParams = append(sqlParams, orderCreatedAtEnd) + if !utils.IsTimeZero(fromDate) && !utils.IsTimeZero(toDate) { + sql += " AND a.order_created_at BETWEEN ? and ?" + sqlParams = append(sqlParams, fromDate, toDate) } - // sql += " ORDER BY t1.order_created_at DESC, t1.id DESC;" - return orderList, GetRows(db, &orderList, sql, sqlParams...) + err = GetRows(db, &orderNewList, sql, sqlParams...) + if len(orderNewList) > 0 { + orderNewMap = make(map[string][]*model.OrderSku) + for _, v := range orderNewList { + if orderNewMap[v.VendorOrderID] == nil { + orderList = append(orderList, &v.GoodsOrder) + } + orderNewMap[v.VendorOrderID] = append(orderNewMap[v.VendorOrderID], &model.OrderSku{ + ID: v.OrderSkuID, + VendorOrderID: v.VendorOrderID, + VendorID: v.VendorID, + StoreSubID: v.StoreSubID, + StoreSubName: v.StoreSubName, + Count: v.Count, + VendorSkuID: v.VendorSkuID, + SkuID: v.SkuID, + JxSkuID: v.JxSkuID, + SkuName: v.SkuName, + ShopPrice: v.SkuShopPrice, + VendorPrice: v.SkuVendorPrice, + SalePrice: v.SkuSalePrice, + EarningPrice: v.SkuEarningPrice, + Weight: v.Weight, + SkuType: v.SkuType, + PromotionType: v.PromotionType, + }) + } + for _, v := range orderList { + v.Skus = orderNewMap[v.VendorOrderID] + } + } + + return orderList, err } +// func QueryOrders(db *DaoDB, vendorOrderID string, vendorIDs []int, storeID int, orderCreatedAtBegin, orderCreatedAtEnd time.Time) (orderList []*model.GoodsOrder, err error) { +// sql := ` +// SELECT t1.* +// FROM goods_order t1 +// WHERE t1.order_created_at >= ?` +// sqlParams := []interface{}{ +// orderCreatedAtBegin, +// } +// if vendorOrderID != "" { +// sql += " AND t1.vendor_order_id = ?" +// sqlParams = append(sqlParams, vendorOrderID) +// } +// if len(vendorIDs) > 0 { +// sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" +// sqlParams = append(sqlParams, vendorIDs) +// } +// if storeID > 0 { +// sql += " AND IF(t1.jx_store_id <> 0, t1.jx_store_id, t1.store_id) = ?" +// sqlParams = append(sqlParams, storeID) +// } +// if !utils.IsTimeZero(orderCreatedAtEnd) { +// sql += " AND t1.order_created_at <= ?" +// sqlParams = append(sqlParams, orderCreatedAtEnd) +// } +// // sql += " ORDER BY t1.order_created_at DESC, t1.id DESC;" +// return orderList, GetRows(db, &orderList, sql, sqlParams...) +// } + func GetStoreOrderAfterTime(db *DaoDB, storeID int, orderTime time.Time, lastOrderSeqID int64) (orderList []*model.GoodsOrderExt, err error) { sql := ` SELECT t1.*, diff --git a/business/model/dao/dao_user2.go b/business/model/dao/dao_user2.go index d88e8249e..08e497ec7 100644 --- a/business/model/dao/dao_user2.go +++ b/business/model/dao/dao_user2.go @@ -158,7 +158,7 @@ func GetStoreListByMobileOrStoreIDs(db *DaoDB, mobile string, shortRoleNameList return storeList, err } -func QueryUserDeliveryAddress(db *DaoDB, userIDs []string, offset, pageSize int) (addressList []*UserDeliveryAddressEx, totalCount int, err error) { +func QueryUserDeliveryAddress(db *DaoDB, addressID int64, userIDs []string, offset, pageSize int) (addressList []*UserDeliveryAddressEx, totalCount int, err error) { sql := ` SELECT SQL_CALC_FOUND_ROWS t1.*, @@ -174,6 +174,10 @@ func QueryUserDeliveryAddress(db *DaoDB, userIDs []string, offset, pageSize int) sqlParams := []interface{}{ utils.DefaultTimeValue, } + if addressID > 0 { + sql += " AND t1.id = ? " + sqlParams = append(sqlParams, addressID) + } if len(userIDs) > 0 { sql += " AND t1.user_id IN (" + GenQuestionMarks(len(userIDs)) + ")" sqlParams = append(sqlParams, userIDs) diff --git a/business/model/dao/food_recipe.go b/business/model/dao/food_recipe.go index 8f6b27e65..5228c87c3 100644 --- a/business/model/dao/food_recipe.go +++ b/business/model/dao/food_recipe.go @@ -25,7 +25,7 @@ type FoodRecipeItemChoiceExt struct { Comment string `json:"-"` } -func QueryFoodRecipes(db *DaoDB, keyword string, recipeID int, authorID, userID string, offset, pageSize int) (recipeList []*FoodRecipeWithAction, totalCount int, err error) { +func QueryFoodRecipes(db *DaoDB, keyword string, recipeID int, authorID, userID string, skuIDs []int, offset, pageSize int) (recipeList []*FoodRecipeWithAction, totalCount int, err error) { var sql string var sqlParams []interface{} if userID != "" { @@ -64,6 +64,14 @@ func QueryFoodRecipes(db *DaoDB, keyword string, recipeID int, authorID, userID sql += " AND t1.author_id = ?" sqlParams = append(sqlParams, authorID) } + if len(skuIDs) > 0 { + sql += ` AND ( + SELECT COUNT(*) + FROM food_recipe_item_choice t11 + WHERE t11.recipe_id = t1.id AND t11.sku_id IN (` + GenQuestionMarks(len(skuIDs)) + `) + ) > 0` + sqlParams = append(sqlParams, skuIDs) + } offset = FormalizePageOffset(offset) pageSize = FormalizePageSize(pageSize) sql += ` @@ -80,7 +88,7 @@ func QueryFoodRecipes(db *DaoDB, keyword string, recipeID int, authorID, userID } func GetRecommendFoodRecipes(db *DaoDB, keyword, userID string, offset, pageSize int) (recipeList []*model.FoodRecipe, totalCount int, err error) { - list, totalCount, err := QueryFoodRecipes(db, keyword, 0, userID, "", offset, pageSize) + list, totalCount, err := QueryFoodRecipes(db, keyword, 0, userID, "", nil, offset, pageSize) if err == nil { recipeList = FoodRecipeWithActionList2Recipe(list) } diff --git a/business/model/dao/store.go b/business/model/dao/store.go index f6d45fc59..a603c7856 100644 --- a/business/model/dao/store.go +++ b/business/model/dao/store.go @@ -6,8 +6,6 @@ import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" - "git.rosy.net.cn/jx-callback/globals" - "github.com/astaxie/beego/orm" ) // 带购物平台信息的 @@ -97,13 +95,15 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto sql += " AND t2.vendor_store_id = ?" sqlParams = append(sqlParams, vendorStoreID) } - storeDetail = &StoreDetail{} - if err = GetRow(db, storeDetail, sql, sqlParams...); err == nil { + if err = GetRow(db, &storeDetail, sql, sqlParams...); err == nil { storeDetail.PricePercentagePackObj = PricePercentagePack2Obj(storeDetail.PricePercentagePackStr) storeDetail.FreightDeductionPackObj = FreightDeductionPack2Obj(storeDetail.FreightDeductionPackStr) - if vendorID == model.VendorIDJX { + if storeDetail.VendorStoreID == "" { storeDetail.VendorStatus = storeDetail.Status - storeDetail.PricePercentage = 100 + storeDetail.PricePercentage = model.DefVendorPricePercentage + storeDetail.AutoPickup = 1 + storeDetail.DeliveryType = model.StoreDeliveryTypeByStore + storeDetail.DeliveryCompetition = 1 } return storeDetail, nil } @@ -124,67 +124,6 @@ func GetStoreDetailByVendorStoreID(db *DaoDB, vendorStoreID string, vendorID int return storeDetail, err } -func GetPossibleStoresByPlaceName(db *DaoDB, cityName, provinceName string) (storeList []*StoreDetail, err error) { - sqlList := []string{ - ` - SELECT t1.*, t5.vendor_store_id - FROM store t1 - JOIN place t2 ON t2.code = t1.city_code AND t2.name = ? - LEFT JOIN store_map t5 ON t1.id = t5.store_id AND t5.vendor_id = ? AND t5.deleted_at = ? - WHERE t1.status = ? AND (SELECT COUNT(*) FROM store_map t10 WHERE t10.store_id = t1.id AND t10.deleted_at = ? AND t10.status <> ?) > 0 - `, - ` - SELECT t1.*, t5.vendor_store_id - FROM store t1 - JOIN place t2 ON t2.code = t1.city_code - JOIN place t3 ON t3.code = t2.parent_code AND t3.name = ? - LEFT JOIN store_map t5 ON t1.id = t5.store_id AND t5.vendor_id = ? AND t5.deleted_at = ? - WHERE t1.status = ? AND (SELECT COUNT(*) FROM store_map t10 WHERE t10.store_id = t1.id AND t10.deleted_at = ? AND t10.status <> ?) > 0 - `, - ` - SELECT t1.*, t5.vendor_store_id - FROM store t1 - LEFT JOIN store_map t5 ON t1.id = t5.store_id AND t5.vendor_id = ? AND t5.deleted_at = ? - WHERE t1.status = ? AND (SELECT COUNT(*) FROM store_map t10 WHERE t10.store_id = t1.id AND t10.deleted_at = ? AND t10.status <> ?) > 0 - `, - } - sqlParamsList := [][]interface{}{ - []interface{}{ - cityName, - model.VendorIDWSC, - utils.DefaultTimeValue, - model.StoreStatusOpened, - utils.DefaultTimeValue, - model.StoreStatusDisabled, - }, - []interface{}{ - provinceName, - model.VendorIDWSC, - utils.DefaultTimeValue, - model.StoreStatusOpened, - utils.DefaultTimeValue, - model.StoreStatusDisabled, - }, - []interface{}{ - model.VendorIDWSC, - utils.DefaultTimeValue, - model.StoreStatusOpened, - utils.DefaultTimeValue, - model.StoreStatusDisabled, - }, - } - for k := range sqlList { - if err = GetRows(db, &storeList, sqlList[k], sqlParamsList[k]); err != nil { - return nil, err - } - if len(storeList) > 0 { - return storeList, nil - } - } - // 正常是不应该达到这里的 - return storeList, err -} - // 这个返回的地点信息是城市 func GetStoreDetail2(db *DaoDB, storeID int, vendorStoreID string, vendorID int) (storeDetail *StoreDetail2, err error) { sql := ` @@ -244,10 +183,12 @@ func GetStoresMapList(db *DaoDB, vendorIDs, storeIDs []int, status, isSync int, sql := ` SELECT t1.* FROM store_map t1 + JOIN store t2 ON t2.id = t1.store_id AND t2.deleted_at = ? WHERE t1.deleted_at = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, + utils.DefaultTimeValue, } if len(vendorIDs) > 0 { sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" @@ -354,15 +295,31 @@ func GetRebindPrinterStoreList(db *DaoDB) (storeList []*model.Store, err error) return storeList, err } +// 容错用 +type tPricePercentageItemFloat struct { + BeginPrice float64 `json:"beginPrice"` // 起始价格区间(包括) + PricePercentage float64 `json:"pricePercentage"` // 调价比例 + PriceAdd float64 `json:"priceAdd"` // 调价额定值 +} + func PricePercentagePack2Obj(packStr string) (obj model.PricePercentagePack) { if packStr != "" { - if err := utils.UnmarshalUseNumber([]byte(packStr), &obj); err == nil { - for _, v := range obj { - if v.PricePercentage >= 500 || v.PricePercentage <= 80 { - return nil + var floatObj []*tPricePercentageItemFloat + if err := utils.UnmarshalUseNumber([]byte(packStr), &floatObj); err == nil { + if len(floatObj) > 0 { + obj = make(model.PricePercentagePack, len(floatObj)) + for k, v := range floatObj { + if v.PricePercentage >= 500 || v.PricePercentage <= 80 { + return nil + } + obj[k] = &model.PricePercentageItem{ + BeginPrice: int(v.BeginPrice), + PricePercentage: int(v.PricePercentage), + PriceAdd: int(v.PriceAdd), + } } + sort.Sort(obj) } - sort.Sort(obj) } } return obj @@ -374,7 +331,6 @@ func AddStoreCategoryMap(db *DaoDB, storeID, categoryID int, vendorID int, vendo CategoryID: categoryID, MtwmSyncStatus: model.SyncFlagNewMask, EbaiSyncStatus: model.SyncFlagNewMask, - WscSyncStatus: model.SyncFlagNewMask, } storeCat.DeletedAt = utils.DefaultTimeValue if err = GetEntity(db, storeCat, model.FieldStoreID, model.FieldCategoryID, model.FieldDeletedAt); err != nil && !IsNoRowsError(err) { @@ -383,15 +339,9 @@ func AddStoreCategoryMap(db *DaoDB, storeID, categoryID int, vendorID int, vendo if vendorID == model.VendorIDMTWM { storeCat.MtwmID = vendorCategoryID storeCat.MtwmSyncStatus = status - } else if vendorID == model.VendorIDEBAI || vendorID == model.VendorIDWSC { - intVendorCategoryID := utils.Str2Int64WithDefault(vendorCategoryID, 0) - if vendorID == model.VendorIDEBAI { - storeCat.EbaiID = intVendorCategoryID - storeCat.EbaiSyncStatus = status - } else { - storeCat.WscID = intVendorCategoryID - storeCat.WscSyncStatus = status - } + } else if vendorID == model.VendorIDEBAI { + storeCat.EbaiID = utils.Str2Int64WithDefault(vendorCategoryID, 0) + storeCat.EbaiSyncStatus = status } else { panic("unsupported vendor") } @@ -407,49 +357,6 @@ func AddStoreCategoryMap(db *DaoDB, storeID, categoryID int, vendorID int, vendo return err } -func GetStoreMapByStoreID(db *DaoDB, storeID, vendorID int) (storeMap *model.StoreMap, err error) { - if db == nil { - db = GetDB() - } - storeMap = &model.StoreMap{ - StoreID: storeID, - VendorID: vendorID, - } - storeMap.DeletedAt = utils.DefaultTimeValue - if err = GetEntity(db, storeMap, model.FieldStoreID, model.FieldVendorID, model.FieldDeletedAt); err != nil { - if err != orm.ErrNoRows { - globals.SugarLogger.Warnf("GetStoreMapByStoreID storeID:%d, vendorID:%d read storeMap failed with error:%v", storeID, vendorID, err) - } - return nil, err - } - return storeMap, nil -} - -func FakeGetStoreMapByStoreID(db *DaoDB, storeID, vendorID int) (storeMap *model.StoreMap, err error) { - vendorID2 := vendorID - if model.IsSpecialVendorID(vendorID) { - vendorID2 = model.VendorIDJD // 微商城与京西的属性以京东属性为准(以免再绑定) - } - if storeMap, err = GetStoreMapByStoreID(db, storeID, vendorID2); model.IsSpecialVendorID(vendorID) && IsNoRowsError(err) { - err = nil - storeMap = &model.StoreMap{ - StoreID: storeID, - VendorID: vendorID2, - Status: model.StoreStatusOpened, - PricePercentage: 100, - AutoPickup: 1, - DeliveryType: model.StoreDeliveryTypeByStore, - // DeliveryFee - DeliveryCompetition: 1, - IsSync: 1, - } - } - if storeMap != nil && vendorID == model.VendorIDJX { - storeMap.DeliveryType = model.StoreDeliveryTypeByStore - } - return storeMap, err -} - func GetOpenedStoreCouriersByStoreID(db *DaoDB, storeID, vendorID int) (storeMaps []*model.StoreCourierMap, err error) { if db == nil { db = GetDB() diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index 1b0b9be91..310e2ad7b 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -213,14 +213,10 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty boo if !isSingleStorePF { tableName = "t2" } - vendorSkuNameField := "0" - if vendorID == model.VendorIDWSC { - vendorSkuNameField = "t1.wsc_id2" - } fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` SELECT t1.id bind_id, t1.sku_id, t1.price, t1.unit_price, t1.status store_sku_status, %s.%s_id vendor_sku_id, - t1.%s_sync_status store_sku_sync_status, %s vendor_name_id, t1.store_id, t1.deleted_at bind_deleted_at, + t1.%s_sync_status store_sku_sync_status, t1.store_id, t1.deleted_at bind_deleted_at, t2.*, t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, IF(t11.%s <> '', t11.%s, t3.img) img, @@ -228,7 +224,7 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty boo t13.%s desc_img, t4.%s_category_id vendor_vendor_cat_id` fmtParams := []interface{}{ - tableName, fieldPrefix, fieldPrefix, vendorSkuNameField, + tableName, fieldPrefix, fieldPrefix, GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), diff --git a/business/model/model.go b/business/model/model.go index ecdd9febe..d37c43b69 100644 --- a/business/model/model.go +++ b/business/model/model.go @@ -17,7 +17,7 @@ const ( // FieldElmSyncStatus = "ElmSyncStatus" FieldEbaiSyncStatus = "EbaiSyncStatus" FieldMtwmSyncStatus = "MtwmSyncStatus" - FieldWscSyncStatus = "WscSyncStatus" + // FieldWscSyncStatus = "WscSyncStatus" FieldVendorID = "VendorID" FieldStoreID = "StoreID" @@ -31,8 +31,8 @@ const ( // FieldElmID = "ElmID" FieldEbaiID = "EbaiID" FieldMtwmID = "MtwmID" - FieldWscID = "WscID" - FieldWscID2 = "WscID2" + // FieldWscID = "WscID" + // FieldWscID2 = "WscID2" FieldSkuID = "SkuID" FieldLevel = "Level" diff --git a/business/model/order.go b/business/model/order.go index 5ea267da4..b11836029 100644 --- a/business/model/order.go +++ b/business/model/order.go @@ -245,7 +245,7 @@ type OrderComment struct { UserCommentID string `orm:"column(user_comment_id);size(48)" json:"userCommentID"` IsReplied int8 Status int8 - ModifyDuration int8 // 改评价的小时数 + ModifyDuration int16 // 改评价的小时数 TagList string Score int8 @@ -263,12 +263,7 @@ type OrderComment struct { // 判断是否是购买平台自有物流 // 对于京东,饿百来说,就是其自有的物流,对于微商城来说,是达达 func IsWaybillPlatformOwn(bill *Waybill) bool { - return bill.OrderVendorID == bill.WaybillVendorID || IsSpecialOrderPlatformWaybill(bill) -} - -// 是否是特殊物流 -func IsSpecialOrderPlatformWaybill(bill *Waybill) bool { - return (bill.OrderVendorID == VendorIDWSC && bill.WaybillVendorID == VendorIDDada) + return bill.OrderVendorID == bill.WaybillVendorID } // 订单是否已经有了有效运单 @@ -280,3 +275,23 @@ func IsOrderHaveWaybill(order *GoodsOrder) bool { func IsOrderHaveOwnWaybill(order *GoodsOrder) bool { return order.VendorID == order.WaybillVendorID && order.VendorWaybillID != "" } + +// 订单的初始配送方式是否是门店自配送 +func IsOrderDeliveryByStore(order *GoodsOrder) bool { + return order.DeliveryType == OrderDeliveryTypeStoreSelf +} + +// 订单的初始配送方式是否是平台负责配送 +func IsOrderDeliveryByPlatform(order *GoodsOrder) bool { + return order.DeliveryType == OrderDeliveryTypePlatform +} + +func IsOrderJXTemp(order *GoodsOrder) bool { + // return order.Flag&OrderFlagMaskTempJX != 0 + return true +} + +func IsAfsOrderJXTemp(order *AfsOrder) bool { + // return order.Flag&OrderFlagMaskTempJX != 0 + return true +} diff --git a/business/model/sku.go b/business/model/sku.go index 79dd52c62..cc8036ce2 100644 --- a/business/model/sku.go +++ b/business/model/sku.go @@ -74,7 +74,6 @@ var ( "长条", "鲜活宰杀", "惠", - "鱼腥草", "冰冻", "思念", "散装", diff --git a/business/model/store.go b/business/model/store.go index 2bbab4956..6319b6cad 100644 --- a/business/model/store.go +++ b/business/model/store.go @@ -43,9 +43,10 @@ const ( ) const ( - StoreChangePriceTypeDirect = 0 - StoreChangePriceTypeNeedApprove = 1 - StoreChangePriceTypeBossDisabled = 2 + StoreChangePriceTypeDirect = 0 // 普通门店 + StoreChangePriceTypeNeedApprove = 1 // 改价需要审核,暂时没用 + StoreChangePriceTypeBossDisabled = 2 // 完全禁止改价 + StoreChangePriceTypeManagedStore = 3 // 直营门店,禁止改价 ) var ( @@ -234,6 +235,11 @@ var ( StoreAuditStatusOnline: "上线", StoreAuditStatusRejected: "拒绝", } + StorePriceTypeName = map[int]string{ + StoreChangePriceTypeDirect: "可直接改价", + StoreChangePriceTypeBossDisabled: "禁止改价", + StoreChangePriceTypeManagedStore: "直营门店", + } ) type Store struct { @@ -258,12 +264,13 @@ type Store struct { AutoEnableAt *time.Time `orm:"type(datetime);null" json:"autoEnableAt"` // 自动营业时间(临时休息用) ChangePriceType int8 `json:"changePriceType"` // 修改价格类型,即是否需要审核 SMSNotify int8 `orm:"column(sms_notify);" json:"smsNotify"` // 是否通过短信接收订单消息 - PrinterDisabled int8 `orm:"default(0)" json:"printerDisabled"` // 是否禁用网络打印机 - PrinterFontSize int8 `orm:"default(0)" json:"printerFontSize"` // 打印字体-1:小,0:正常,1:大 - PrinterVendorID int `orm:"column(printer_vendor_id);" json:"printerVendorID"` - PrinterSN string `orm:"size(32);column(printer_sn);index" json:"printerSN"` - PrinterKey string `orm:"size(64)" json:"printerKey"` - PrinterBindInfo string `orm:"size(1024)" json:"-"` + + PrinterDisabled int8 `orm:"default(0)" json:"printerDisabled"` // 是否禁用网络打印机 + PrinterFontSize int8 `orm:"default(0)" json:"printerFontSize"` // 打印字体-1:小,0:正常,1:大 + PrinterVendorID int `orm:"column(printer_vendor_id);" json:"printerVendorID"` + PrinterSN string `orm:"size(32);column(printer_sn);index" json:"printerSN"` + PrinterKey string `orm:"size(64)" json:"printerKey"` + PrinterBindInfo string `orm:"size(1024)" json:"-"` IDCardFront string `orm:"size(255);column(id_card_front)" json:"idCardFront"` IDCardBack string `orm:"size(255);column(id_card_back)" json:"idCardBack"` @@ -465,6 +472,7 @@ func (v *VendorStoreSnapshot) CompareOperationTime(s2 *VendorStoreSnapshot) int type PricePercentageItem struct { BeginPrice int `json:"beginPrice"` // 起始价格区间(包括) PricePercentage int `json:"pricePercentage"` // 调价比例 + PriceAdd int `json:"priceAdd"` // 调价额定值 } type PricePercentagePack []*PricePercentageItem diff --git a/business/model/store_sku.go b/business/model/store_sku.go index a1b7ce926..9147b3646 100644 --- a/business/model/store_sku.go +++ b/business/model/store_sku.go @@ -45,13 +45,13 @@ type StoreSkuCategoryMap struct { // ElmID int64 `orm:"column(elm_id);index"` EbaiID int64 `orm:"column(ebai_id);index"` - MtwmID string `orm:"column(mtwm_id);index;size(16)"` // 美团外卖没有ID,保存名字 - WscID int64 `orm:"column(wsc_id);index"` + MtwmID string `orm:"column(mtwm_id);index;size(16)"` + // WscID int64 `orm:"column(wsc_id);index"` // ElmSyncStatus int8 `orm:"default(2)"` EbaiSyncStatus int8 `orm:"default(2)"` MtwmSyncStatus int8 `orm:"default(2)"` - WscSyncStatus int8 `orm:"default(2)"` + // WscSyncStatus int8 `orm:"default(2)"` } func (*StoreSkuCategoryMap) TableUnique() [][]string { @@ -95,20 +95,21 @@ type StoreSkuBind struct { // ElmID int64 `orm:"column(elm_id);index"` EbaiID int64 `orm:"column(ebai_id);index"` - MtwmID int64 `orm:"column(mtwm_id)"` // 这个也不是必须的,只是为了DAO取数据语句一致 - WscID int64 `orm:"column(wsc_id);index"` // 表示微盟skuId - WscID2 int64 `orm:"column(wsc_id2);index"` // 表示微盟goodsId + MtwmID int64 `orm:"column(mtwm_id)"` + // WscID int64 `orm:"column(wsc_id);index"` // 表示微盟skuId + // WscID2 int64 `orm:"column(wsc_id2);index"` // 表示微盟goodsId // ElmSyncStatus int8 `orm:"default(2)"` JdSyncStatus int8 `orm:"default(2)"` EbaiSyncStatus int8 `orm:"default(2)"` MtwmSyncStatus int8 `orm:"default(2)"` - WscSyncStatus int8 `orm:"default(2)"` + // WscSyncStatus int8 `orm:"default(2)"` JdPrice int `json:"jdPrice"` EbaiPrice int `json:"ebaiPrice"` MtwmPrice int `json:"mtwmPrice"` - WscPrice int `json:"wscPrice"` + JxPrice int `json:"jxPrice"` + // WscPrice int `json:"wscPrice"` AutoSaleAt time.Time `orm:"type(datetime);null" json:"autoSaleAt"` } diff --git a/business/model/user.go b/business/model/user.go index a4b3e198f..3613aaa72 100644 --- a/business/model/user.go +++ b/business/model/user.go @@ -35,6 +35,7 @@ type User struct { Name string `orm:"size(48);index" json:"name" compact:"name"` // 外部显示标识(当前可以重复) Mobile *string `orm:"size(32);null" json:"mobile" compact:"mobile"` Email *string `orm:"size(32);null" json:"email" compact:"email"` + Avatar string `orm:"size(255)" json:"avatar" compact:"avatar"` // 头像 Status int8 `json:"status" compact:"status"` Type int8 `json:"type" compact:"type"` // 用户类型 @@ -80,6 +81,10 @@ func (user *User) GetName() string { return user.Name } +func (user *User) GetAvatar() string { + return user.Avatar +} + type StoreBoss struct { ModelIDCULD UserID string `orm:"size(48);column(user_id);unique" json:"userID"` // 内部唯一标识 diff --git a/business/partner/delivery/delivery.go b/business/partner/delivery/delivery.go index d16030481..fa6851386 100644 --- a/business/partner/delivery/delivery.go +++ b/business/partner/delivery/delivery.go @@ -34,12 +34,11 @@ func CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee int64, order *model.Goo return err } -func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) { - globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID) +func CalculateDeliveryFee(db *dao.DaoDB, jxStoreID int, hint string, consigneeLng, consigneeLat, coordinateType, weight int, billTime time.Time) (deliveryFee, addFee int64, err error) { + globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", hint) if db == nil { db = dao.GetDB() } - jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) var lng, lat float64 priceInfo := &struct { CityPrice int64 @@ -63,21 +62,21 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db * deliveryFee = priceInfo.CityPrice } if deliveryFee == 0 { - globals.SugarLogger.Warnf("CalculateOrderDeliveryFee 查不到美团配送价格 orderID:%s", order.VendorOrderID) + globals.SugarLogger.Warnf("CalculateOrderDeliveryFee 查不到美团配送价格 orderID:%s", hint) deliveryFee = 650 } if lng == 0 || lat == 0 { - globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,门店:%d没有坐标信息", order.VendorOrderID, jxutils.GetSaleStoreIDFromOrder(order)) - return 0, 0, fmt.Errorf("找不到门店:%d的坐标", jxutils.GetSaleStoreIDFromOrder(order)) + globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,门店:%d没有坐标信息", hint, jxStoreID) + return 0, 0, fmt.Errorf("找不到门店:%d的坐标", jxStoreID) } - lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) + lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(consigneeLng, consigneeLat, coordinateType) var distanceAddFee, weightAddFee, timeAddFee int64 // 距离加价 distance := jxutils.WalkingDistance(lng, lat, lng2, lat2) if distance > warningDistance { - globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,距离%.3fkm太远,请检查门店坐标信息", order.VendorOrderID, distance) + globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,距离%.3fkm太远,请检查门店坐标信息", hint, distance) } distanceAddFee = int64(jxutils.CalcStageValue([][]float64{ []float64{ @@ -95,8 +94,8 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db * }, distance)) // 重量加价 - if order.Weight > warningWeight { - globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,重量:%dg太重,请检查商品属性", order.VendorOrderID, order.Weight) + if weight > warningWeight { + globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,重量:%dg太重,请检查商品属性", hint, weight) } weightAddFee = int64(jxutils.CalcStageValue([][]float64{ []float64{ @@ -111,7 +110,7 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db * 5, 50, }, - }, float64(order.Weight)/1000)) + }, float64(weight)/1000)) // 其它加价 hour, min, sec := billTime.Clock() @@ -123,10 +122,15 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db * timeAddFee = jxutils.StandardPrice2Int(3) } addFee = distanceAddFee + weightAddFee + timeAddFee - globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s, deliveryFee:%d addFee:%d, distance:%.3fkm distanceAddFee:%d, weight:%dg weightAddFee:%d, time:%s timeAddFee:%d", order.VendorOrderID, deliveryFee, addFee, distance, distanceAddFee, order.Weight, weightAddFee, utils.Time2TimeStr(billTime), timeAddFee) + globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s, deliveryFee:%d addFee:%d, distance:%.3fkm distanceAddFee:%d, weight:%dg weightAddFee:%d, time:%s timeAddFee:%d", + hint, deliveryFee, addFee, distance, distanceAddFee, weight, weightAddFee, utils.Time2TimeStr(billTime), timeAddFee) return deliveryFee + addFee, addFee, nil } +func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) { + return CalculateDeliveryFee(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType, order.Weight, billTime) +} + func CalculateBillDeliveryFee(bill *model.Waybill) (deliveryFee, addFee int64) { order, err := partner.CurOrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID) if err != nil { diff --git a/business/partner/purchase/ebai/order_comment.go b/business/partner/purchase/ebai/order_comment.go index 28a76014c..8a49a1e5c 100644 --- a/business/partner/purchase/ebai/order_comment.go +++ b/business/partner/purchase/ebai/order_comment.go @@ -22,11 +22,9 @@ const ( ) func (c *PurchaseHandler) StartRefreshComment() { - if globals.ReallyCallPlatformAPI { - utils.AfterFuncWithRecover(5*time.Second, func() { - c.refreshCommentOnce() - }) - } + utils.AfterFuncWithRecover(5*time.Second, func() { + c.refreshCommentOnce() + }) } func (c *PurchaseHandler) refreshCommentOnce() { diff --git a/business/partner/purchase/ebai/store_sku2.go b/business/partner/purchase/ebai/store_sku2.go index f7f304564..9b5465ae5 100644 --- a/business/partner/purchase/ebai/store_sku2.go +++ b/business/partner/purchase/ebai/store_sku2.go @@ -158,9 +158,7 @@ func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, v if globals.EnableEbaiStoreWrite { opResult, err2 := api.EbaiAPI.SkuDelete(ctx.GetTrackInfo(), utils.Int2Str(storeID), partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList(), nil) if err = err2; err2 != nil && opResult != nil { - if len(storeSkuList) == 1 && len(storeSkuList) == len(opResult.FailedList) { // 饿百现在删除不存在错,在上层通过IsErrSkuNotExist很难准备判断,暂时这里直接处理 - err = nil - } else { + if len(storeSkuList) > len(opResult.FailedList) { successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult)) } } diff --git a/business/partner/purchase/jx/localjx/order.go b/business/partner/purchase/jx/localjx/order.go new file mode 100644 index 000000000..df843ee0f --- /dev/null +++ b/business/partner/purchase/jx/localjx/order.go @@ -0,0 +1,133 @@ +package localjx + +import ( + "fmt" + "time" + + "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/model" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +type JxSkuInfo struct { + SkuID int `json:"skuID"` + Count int `json:"count"` + + Price int64 `json:"price,omitempty"` // 原价 + SalePrice int64 `json:"salePrice,omitempty"` // 售卖价 +} + +type JxOrderInfo struct { + Skus []*JxSkuInfo `json:"skus"` + + ExpectedDeliveredTime *time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间 + + TotalPrice int64 `json:"totalPrice"` // 单位为分 订单总价 + FreightPrice int64 `json:"freightPrice"` // 单位为分 订单配送费 + OrderPrice int64 `json:"orderPrice"` // 单位为分 订单商品价格 + ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付 +} + +func PreCreateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, ExpectedDeliveredTime *time.Time) (outJxOrder *JxOrderInfo, err error) { + return outJxOrder, err +} + +func formalizeSkus(skus []*JxSkuInfo) (outSkus []*JxSkuInfo) { + skuMap := make(map[int]int) + for _, v := range skus { + skuMap[v.SkuID] += v.Count + } + for skuID, skuCount := range skuMap { + outSkus = append(outSkus, &JxSkuInfo{ + SkuID: skuID, + Count: skuCount, + }) + } + return outSkus +} + +func isTimeInOpTime(openTime1, closeTime1, openTime2, closeTime2 int16, time2Check time.Time) bool { + timeStrList := []string{ + jxutils.OperationTime2StrWithSecond(openTime1), + jxutils.OperationTime2StrWithSecond(closeTime1), + } + if openTime1 > 0 { + timeStrList = append(timeStrList, + jxutils.OperationTime2StrWithSecond(openTime2), + jxutils.OperationTime2StrWithSecond(closeTime2), + ) + } + checkTimeStr := utils.Time2TimeStr(time2Check) + for i := 0; i < len(timeStrList); i += 2 { + if checkTimeStr >= timeStrList[i] && checkTimeStr <= timeStrList[i+1] { + return true + } + } + return false +} + +func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, storeID int, addressID int64, ExpectedDeliveredTime *time.Time) (outJxOrder *JxOrderInfo, err error) { + db := dao.GetDB() + + // 配送范围检查 + storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX) + if err != nil { + return nil, err + } + addressList, _, err := dao.QueryUserDeliveryAddress(db, addressID, []string{ctx.GetUserID()}, 0, 0) + if err != nil { + return nil, err + } + if len(addressList) == 0 { + return nil, fmt.Errorf("地址ID不正确") + } + deliveryAddress := addressList[0] + if distance := jxutils.Point2StoreDistance(deliveryAddress.Lng, deliveryAddress.Lat, storeDetail.Lng, storeDetail.Lat, storeDetail.DeliveryRangeType, storeDetail.DeliveryRange); distance == 0 { + return nil, fmt.Errorf("送货地址:%s不在门店%s的配送范围", deliveryAddress.DetailAddress, storeDetail.Name) + } + + // 营业状态及时间检查 + if storeDetail.Status == model.StoreStatusDisabled { + return nil, fmt.Errorf("门店:%s状态是:%s", storeDetail.Name, model.StoreStatusName[storeDetail.Status]) + } + checkTime := time.Now() + if ExpectedDeliveredTime == nil { + if storeDetail.Status != model.StoreStatusOpened { + return nil, fmt.Errorf("门店:%s不是营业状态,状态是:%s", storeDetail.Name, model.StoreStatusName[storeDetail.Status]) + } + } else { + checkTime = *ExpectedDeliveredTime + } + if !isTimeInOpTime(storeDetail.OpenTime1, storeDetail.CloseTime1, storeDetail.OpenTime2, storeDetail.CloseTime2, checkTime) { + return nil, fmt.Errorf("门店:%s不在营业时间范围", storeDetail.Name) + } + + skus := formalizeSkus(jxOrder.Skus) + var skuIDs []int + for _, v := range skus { + skuIDs = append(skuIDs, v.SkuID) + } + storeSkuList, err := dao.GetStoresSkusInfo(db, []int{storeID}, skuIDs) + if err != nil { + return nil, err + } + storeSkuMap := make(map[int]*model.StoreSkuBind) + for _, v := range storeSkuList { + storeSkuMap[v.SkuID] = v + } + + outJxOrder = &JxOrderInfo{} + for _, v := range skus { + outJxOrder.Skus = append(outJxOrder.Skus, &JxSkuInfo{ + SkuID: v.SkuID, + Count: v.Count, + Price: v.Price, + SalePrice: v.SalePrice, + }) + outJxOrder.TotalPrice += int64(v.Count) * v.SalePrice + } + + return outJxOrder, err +} diff --git a/business/partner/purchase/jx/order.go b/business/partner/purchase/jx/order.go index a12c86bce..51df85de2 100644 --- a/business/partner/purchase/jx/order.go +++ b/business/partner/purchase/jx/order.go @@ -3,77 +3,13 @@ package jx import ( "time" - "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/partner" - "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/phpjx" ) -type Data4Neworder struct { - model.GoodsOrder - Skus []*model.OrderSku `json:"skus"` -} - -func (c *PurchaseHandler) OnOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { - jxutils.CallMsgHandler(func() { - retVal, errCode, err = c.onOrderMsg(msg) - }, jxutils.ComposeUniversalOrderID(msg.ThingID, c.GetVendorID())) - return retVal, errCode, err -} - -func (c *PurchaseHandler) onOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { - subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) - if subMsgType == model.OrderStatusNew || subMsgType == model.OrderStatusAdjust { - var order *Data4Neworder - if err = utils.UnmarshalUseNumber([]byte(msg.Data), &order); err == nil { - if order.VendorStatus == "" { - order.VendorStatus = utils.Int2Str(order.Status) - } - retVal, errCode, err = c.onOrderNew(msg, subMsgType, order) - } - } else { - status := c.callbackMsg2Status(msg) - err = partner.CurOrderManager.OnOrderStatusChanged(status) - } - return retVal, errCode, err -} - -func (c *PurchaseHandler) callbackMsg2Status(msg *CallbackMsg) *model.OrderStatus { - orderStatus := &model.OrderStatus{ - VendorOrderID: msg.ThingID, - VendorID: model.VendorIDJX, - OrderType: model.OrderTypeOrder, - RefVendorOrderID: msg.ThingID, - RefVendorID: model.VendorIDJX, - VendorStatus: msg.SubMsgType, - Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), - StatusTime: utils.Timestamp2Time(msg.Timestamp), - Remark: "", - } - return orderStatus -} - -func (c *PurchaseHandler) onOrderNew(msg *CallbackMsg, subMsgType int, order *Data4Neworder) (retVal, errCode string, err error) { - globals.SugarLogger.Debugf("onOrderNew orderID:%s", msg.ThingID) - order.StoreID = int(utils.Str2Int64WithDefault(order.VendorStoreID, 0)) - order.GoodsOrder.Skus = order.Skus - order.VendorID = model.VendorIDJX - for _, v := range order.GoodsOrder.Skus { - v.SkuID = int(utils.Str2Int64WithDefault(v.VendorSkuID, 0)) - } - jxutils.RefreshOrderSkuRelated(&order.GoodsOrder) - orderStatus := model.Order2Status(&order.GoodsOrder) - if subMsgType == model.OrderStatusNew { - err = partner.CurOrderManager.OnOrderNew(&order.GoodsOrder, orderStatus) - } else if subMsgType == model.OrderStatusAdjust { - err = partner.CurOrderManager.OnOrderAdjust(&order.GoodsOrder, orderStatus) - } - return retVal, errCode, err -} - func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { return order } @@ -89,12 +25,16 @@ func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI } else { status = model.OrderStatusCanceled } - err = c.notifyOrderStatusChanged(order, status) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, status) + } return err } func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { - err = c.notifyOrderStatusChanged(order, model.OrderStatusFinishedPickup) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinishedPickup) + } return err } @@ -119,13 +59,16 @@ func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName } func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { - err = c.notifyOrderStatusChanged(order, model.OrderStatusDelivering) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusDelivering) + } return err } -// 京东送达接口都是一样的 func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { - err = c.notifyOrderStatusChanged(order, model.OrderStatusFinished) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished) + } return err } @@ -138,7 +81,9 @@ func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *mod } func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - err = c.notifyOrderStatusChanged(order, model.OrderStatusCanceled) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusCanceled) + } return err } @@ -161,16 +106,9 @@ func (c *PurchaseHandler) AddWaybillTip(ctx *jxcontext.Context, order *model.Goo func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID, selfTakeCode string) (err error) { order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX) if err == nil { - err = c.notifyOrderStatusChanged(order, model.OrderStatusFinished) - } - return err -} - -func (c *PurchaseHandler) notifyOrderStatusChanged(order *model.GoodsOrder, status int) (err error) { - orderMsg := *order - orderMsg.Status = status - if err = jxAPI.NotifyOrderStatusChanged(&orderMsg); err == nil { - c.postFakeMsg(orderMsg.VendorOrderID, orderMsg.Status) + if model.IsOrderJXTemp(order) { + err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished) + } } return err } diff --git a/business/partner/purchase/jx/order_afs.go b/business/partner/purchase/jx/order_afs.go index 51af9b84a..53319ea39 100644 --- a/business/partner/purchase/jx/order_afs.go +++ b/business/partner/purchase/jx/order_afs.go @@ -2,134 +2,13 @@ package jx import ( "fmt" - "time" - "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/model" "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/phpjx" ) -type Data4AfsOrderSku struct { - VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid - PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销) - Name string `orm:"size(255)" json:"name"` // 商品名 - SalePrice int64 `json:"salePrice"` // 售卖价 - Count int `json:"count"` // 订单下单数量 -} - -type Data4AfsOrder struct { - VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID - AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID - AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间 - VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid - - VendorStatus string `orm:"size(255)" json:"vendorStatus"` - VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` // 原始售后原因 - ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述 - ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片 - VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 原始售后方式 - Skus []*Data4AfsOrderSku -} - -func (c *PurchaseHandler) OnAfsOrderMsg(msg *CallbackMsg) (err error) { - jxutils.CallMsgHandlerAsync(func() { - err = c.onAfsOrderMsg(msg) - }, jxutils.ComposeUniversalOrderID(msg.ThingID, c.GetVendorID())) - return err -} - -func (c *PurchaseHandler) buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) { - var afsOrder *Data4AfsOrder - if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil { - outAfsOrder = &model.AfsOrder{ - VendorID: model.VendorIDJX, - AfsOrderID: afsOrder.AfsOrderID, - VendorOrderID: afsOrder.VendorOrderID, - VendorStoreID: afsOrder.VendorStoreID, - StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)), - AfsCreatedAt: afsOrder.AfsCreatedAt, - - VendorStatus: afsOrder.VendorStatus, - VendorReasonType: afsOrder.VendorReasonType, - ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)), - ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024), - ReasonImgList: afsOrder.ReasonImgList, - VendorAppealType: afsOrder.VendorAppealType, - AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)), - } - outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0)) - - for _, x := range afsOrder.Skus { - orderSku := &model.OrderSkuFinancial{ - Count: x.Count, - VendorSkuID: x.VendorSkuID, - SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)), - Name: x.Name, - } - if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal { - orderSku.StoreSubName = utils.Int2Str(x.PromotionType) - } - outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku) - } - } - return outAfsOrder, err -} - -func (c *PurchaseHandler) callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus { - orderStatus := &model.OrderStatus{ - VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 - VendorID: model.VendorIDJX, - OrderType: model.OrderTypeAfsOrder, - RefVendorOrderID: msg.ThingID, - RefVendorID: model.VendorIDJX, - VendorStatus: msg.SubMsgType, - Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), - StatusTime: utils.Timestamp2Time(msg.Timestamp), - Remark: "", - } - return orderStatus -} - -func (c *PurchaseHandler) onAfsOrderMsg(msg *CallbackMsg) (err error) { - subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) - status := c.callbackAfsMsg2Status(msg) - if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew { - afsOrder, err2 := c.buildAfsOrder(msg) - if err = err2; err == nil { - err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status) - } - } else { - err = partner.CurOrderManager.OnOrderStatusChanged(status) - } - return err -} - -func (p *PurchaseHandler) postFakeAfsMsg(orderNo, afsOrderID string, status int) { - msg := &CallbackMsg{ - AppKey: appKey, - MsgType: MsgTypeAfsOrder, - SubMsgType: utils.Int2Str(status), - ThingID: orderNo, - ThingID2: afsOrderID, - Timestamp: time.Now().Unix(), - } - utils.CallFuncAsync(func() { - OnCallbackMsg(msg) - }) -} - -func (c *PurchaseHandler) notifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) { - orderMsg := *order - orderMsg.Status = status - if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil { - c.postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status) - } - return err -} - // 审核售后单申请 func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { var status int @@ -138,7 +17,10 @@ func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *mod } else { status = model.AfsOrderStatusFinished } - return c.notifyAfsOrderStatusChanged(order, status) + if model.IsAfsOrderJXTemp(order) { + err = phpjx.NotifyAfsOrderStatusChanged(order, status) + } + return err } // 确认收到退货 diff --git a/business/partner/purchase/jx/callback.go b/business/partner/purchase/jx/phpjx/callback.go similarity index 85% rename from business/partner/purchase/jx/callback.go rename to business/partner/purchase/jx/phpjx/callback.go index 27e8cce7d..49dc06968 100644 --- a/business/partner/purchase/jx/callback.go +++ b/business/partner/purchase/jx/phpjx/callback.go @@ -1,4 +1,4 @@ -package jx +package phpjx import ( "fmt" @@ -34,14 +34,14 @@ func OnCallbackMsg(msg *CallbackMsg) (retVal, errCode string, err error) { return retVal, errCode, fmt.Errorf("无效的AppKey:%s", msg.AppKey) } if msg.MsgType == MsgTypeOrder { - retVal, errCode, err = CurPurchaseHandler.OnOrderMsg(msg) + retVal, errCode, err = OnOrderMsg(msg) } else if msg.MsgType == MsgTypeAfsOrder { - err = CurPurchaseHandler.OnAfsOrderMsg(msg) + err = OnAfsOrderMsg(msg) } return retVal, errCode, err } -func (p *PurchaseHandler) postFakeMsg(orderNo string, status int) { +func postFakeMsg(orderNo string, status int) { msg := &CallbackMsg{ AppKey: appKey, MsgType: MsgTypeOrder, diff --git a/business/partner/purchase/jx/jx_test.go b/business/partner/purchase/jx/phpjx/callback_test.go similarity index 94% rename from business/partner/purchase/jx/jx_test.go rename to business/partner/purchase/jx/phpjx/callback_test.go index d56875ecf..361777628 100644 --- a/business/partner/purchase/jx/jx_test.go +++ b/business/partner/purchase/jx/phpjx/callback_test.go @@ -1,4 +1,4 @@ -package jx +package phpjx import ( "testing" @@ -33,7 +33,7 @@ func TestBuildNewJxOrder(t *testing.T) { msg := &CallbackMsg{ AppKey: appKey, MsgType: MsgTypeOrder, - SubMsgType: SubMsgTypeOrderNew, + SubMsgType: utils.Int2Str(model.OrderStatusNew), ThingID: order.VendorOrderID, Data: utils.Format4Output(order2, true), } diff --git a/business/partner/purchase/jx/jxapi.go b/business/partner/purchase/jx/phpjx/jxapi.go similarity index 99% rename from business/partner/purchase/jx/jxapi.go rename to business/partner/purchase/jx/phpjx/jxapi.go index 89f30856f..1c6cd25a4 100644 --- a/business/partner/purchase/jx/jxapi.go +++ b/business/partner/purchase/jx/phpjx/jxapi.go @@ -1,4 +1,4 @@ -package jx +package phpjx import ( "fmt" diff --git a/business/partner/purchase/jx/jxapi_order.go b/business/partner/purchase/jx/phpjx/jxapi_order.go similarity index 98% rename from business/partner/purchase/jx/jxapi_order.go rename to business/partner/purchase/jx/phpjx/jxapi_order.go index e451dab83..ef2befb2f 100644 --- a/business/partner/purchase/jx/jxapi_order.go +++ b/business/partner/purchase/jx/phpjx/jxapi_order.go @@ -1,4 +1,4 @@ -package jx +package phpjx import ( "git.rosy.net.cn/jx-callback/business/model" @@ -42,3 +42,4 @@ func (a *API) NotifyAfsOrderStatusChanged(afsOrder *model.AfsOrder) (err error) } return err } + diff --git a/business/partner/purchase/jx/jxapi_order_test.go b/business/partner/purchase/jx/phpjx/jxapi_order_test.go similarity index 96% rename from business/partner/purchase/jx/jxapi_order_test.go rename to business/partner/purchase/jx/phpjx/jxapi_order_test.go index be0939963..d74be9133 100644 --- a/business/partner/purchase/jx/jxapi_order_test.go +++ b/business/partner/purchase/jx/phpjx/jxapi_order_test.go @@ -1,4 +1,4 @@ -package jx +package phpjx import ( "testing" diff --git a/business/partner/purchase/jx/phpjx/order.go b/business/partner/purchase/jx/phpjx/order.go new file mode 100644 index 000000000..0b513e4b4 --- /dev/null +++ b/business/partner/purchase/jx/phpjx/order.go @@ -0,0 +1,82 @@ +package phpjx + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" +) + +func NotifyOrderStatusChanged(order *model.GoodsOrder, status int) (err error) { + orderMsg := *order + orderMsg.Status = status + if err = jxAPI.NotifyOrderStatusChanged(&orderMsg); err == nil { + postFakeMsg(orderMsg.VendorOrderID, orderMsg.Status) + } + return err +} + +type Data4Neworder struct { + model.GoodsOrder + Skus []*model.OrderSku `json:"skus"` +} + +func OnOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { + jxutils.CallMsgHandler(func() { + retVal, errCode, err = onOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX)) + return retVal, errCode, err +} + +func onOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) { + subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) + if subMsgType == model.OrderStatusNew || subMsgType == model.OrderStatusAdjust { + var order *Data4Neworder + if err = utils.UnmarshalUseNumber([]byte(msg.Data), &order); err == nil { + if order.VendorStatus == "" { + order.VendorStatus = utils.Int2Str(order.Status) + } + retVal, errCode, err = onOrderNew(msg, subMsgType, order) + } + } else { + status := callbackMsg2Status(msg) + err = partner.CurOrderManager.OnOrderStatusChanged(status) + } + return retVal, errCode, err +} + +func callbackMsg2Status(msg *CallbackMsg) *model.OrderStatus { + orderStatus := &model.OrderStatus{ + VendorOrderID: msg.ThingID, + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeOrder, + RefVendorOrderID: msg.ThingID, + RefVendorID: model.VendorIDJX, + VendorStatus: msg.SubMsgType, + Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), + StatusTime: utils.Timestamp2Time(msg.Timestamp), + Remark: "", + } + return orderStatus +} + +func onOrderNew(msg *CallbackMsg, subMsgType int, order *Data4Neworder) (retVal, errCode string, err error) { + globals.SugarLogger.Debugf("onOrderNew orderID:%s", msg.ThingID) + order.StoreID = int(utils.Str2Int64WithDefault(order.VendorStoreID, 0)) + order.DeliveryType = model.OrderDeliveryTypeStoreSelf + order.GoodsOrder.Skus = order.Skus + order.VendorID = model.VendorIDJX + order.Flag = model.OrderFlagMaskTempJX + for _, v := range order.GoodsOrder.Skus { + v.SkuID = int(utils.Str2Int64WithDefault(v.VendorSkuID, 0)) + } + jxutils.RefreshOrderSkuRelated(&order.GoodsOrder) + orderStatus := model.Order2Status(&order.GoodsOrder) + if subMsgType == model.OrderStatusNew { + err = partner.CurOrderManager.OnOrderNew(&order.GoodsOrder, orderStatus) + } else if subMsgType == model.OrderStatusAdjust { + err = partner.CurOrderManager.OnOrderAdjust(&order.GoodsOrder, orderStatus) + } + return retVal, errCode, err +} diff --git a/business/partner/purchase/jx/phpjx/order_afs.go b/business/partner/purchase/jx/phpjx/order_afs.go new file mode 100644 index 000000000..bb604c9aa --- /dev/null +++ b/business/partner/purchase/jx/phpjx/order_afs.go @@ -0,0 +1,130 @@ +package phpjx + +import ( + "time" + + "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/model" + "git.rosy.net.cn/jx-callback/business/partner" +) + +type Data4AfsOrderSku struct { + VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid + PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销) + Name string `orm:"size(255)" json:"name"` // 商品名 + SalePrice int64 `json:"salePrice"` // 售卖价 + Count int `json:"count"` // 订单下单数量 +} + +type Data4AfsOrder struct { + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID + AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID + AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间 + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid + + VendorStatus string `orm:"size(255)" json:"vendorStatus"` + VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` // 原始售后原因 + ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述 + ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片 + VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 原始售后方式 + Skus []*Data4AfsOrderSku +} + +func OnAfsOrderMsg(msg *CallbackMsg) (err error) { + jxutils.CallMsgHandlerAsync(func() { + err = onAfsOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX)) + return err +} + +func buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) { + var afsOrder *Data4AfsOrder + if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil { + outAfsOrder = &model.AfsOrder{ + VendorID: model.VendorIDJX, + AfsOrderID: afsOrder.AfsOrderID, + VendorOrderID: afsOrder.VendorOrderID, + VendorStoreID: afsOrder.VendorStoreID, + StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)), + AfsCreatedAt: afsOrder.AfsCreatedAt, + + VendorStatus: afsOrder.VendorStatus, + VendorReasonType: afsOrder.VendorReasonType, + ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)), + ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024), + ReasonImgList: afsOrder.ReasonImgList, + VendorAppealType: afsOrder.VendorAppealType, + AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)), + Flag: model.OrderFlagMaskTempJX, + } + outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0)) + + for _, x := range afsOrder.Skus { + orderSku := &model.OrderSkuFinancial{ + Count: x.Count, + VendorSkuID: x.VendorSkuID, + SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)), + Name: x.Name, + } + if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal { + orderSku.StoreSubName = utils.Int2Str(x.PromotionType) + } + outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku) + } + } + return outAfsOrder, err +} + +func callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus { + orderStatus := &model.OrderStatus{ + VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: msg.ThingID, + RefVendorID: model.VendorIDJX, + VendorStatus: msg.SubMsgType, + Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), + StatusTime: utils.Timestamp2Time(msg.Timestamp), + Remark: "", + } + return orderStatus +} + +func onAfsOrderMsg(msg *CallbackMsg) (err error) { + subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) + status := callbackAfsMsg2Status(msg) + if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew { + afsOrder, err2 := buildAfsOrder(msg) + if err = err2; err == nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status) + } + } else { + err = partner.CurOrderManager.OnOrderStatusChanged(status) + } + return err +} + +func postFakeAfsMsg(orderNo, afsOrderID string, status int) { + msg := &CallbackMsg{ + AppKey: appKey, + MsgType: MsgTypeAfsOrder, + SubMsgType: utils.Int2Str(status), + ThingID: orderNo, + ThingID2: afsOrderID, + Timestamp: time.Now().Unix(), + } + utils.CallFuncAsync(func() { + OnCallbackMsg(msg) + }) +} + +func NotifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) { + orderMsg := *order + orderMsg.Status = status + if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil { + postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status) + } + return err +} diff --git a/business/partner/purchase/mtwm/order.go b/business/partner/purchase/mtwm/order.go index 82ee31b6b..5aa5a41a5 100644 --- a/business/partner/purchase/mtwm/order.go +++ b/business/partner/purchase/mtwm/order.go @@ -11,7 +11,6 @@ import ( "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/utils" - "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "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" @@ -23,9 +22,9 @@ import ( ) const ( - FakeMsgTypeOrderReceived = "orderReceived" - FakeMsgTypeOrderDelivering = "orderDelivering" + FakeMsgType = "fakeMsgType" + fakeFinishedPickup = "fake_finished_pickup" fakeUserApplyCancel = "fake_user_apply_cancel" fakeMerchantAgreeApplyCancel = "fake_merchant_agree_apply_cancel" fakeRefuseUserApplyCancel = "fake_refuse_user_apply_cancel" @@ -38,11 +37,11 @@ const ( ) const ( - // pickupOrderDelay = 260 * time.Second - pickupOrderDelay = 1 * time.Second +// pickupOrderDelay = 260 * time.Second +// pickupOrderDelay = 1 * time.Second - callDeliveryDelay = 10 * time.Minute - callDeliveryDelayGap = 30 +// callDeliveryDelay = 10 * time.Minute +// callDeliveryDelayGap = 30 ) var ( @@ -53,13 +52,16 @@ var ( VendorStatus2StatusMap = map[string]int{ mtwmapi.OrderStatusUserCommitted: model.OrderStatusUnknown, mtwmapi.OrderStatusNew: model.OrderStatusNew, - mtwmapi.OrderStatusReceived: model.OrderStatusAccepted, - mtwmapi.OrderStatusAccepted: model.OrderStatusFinishedPickup, - mtwmapi.OrderStatusDelivering: model.OrderStatusDelivering, - mtwmapi.OrderStatusDelivered: model.OrderStatusUnknown, // 以mtwmapi.OrderStatusFinished为结束状态,这个当成一个中间状态(且很少看到这个状态) - mtwmapi.OrderStatusFinished: model.OrderStatusFinished, - mtwmapi.OrderStatusCanceled: model.OrderStatusCanceled, + // mtwmapi.OrderStatusReceived: model.OrderStatusAccepted, + // mtwmapi.OrderStatusAccepted: model.OrderStatusFinishedPickup, + mtwmapi.OrderStatusAccepted: model.OrderStatusAccepted, + mtwmapi.OrderStatusDelivering: model.OrderStatusDelivering, + mtwmapi.OrderStatusDelivered: model.OrderStatusUnknown, // 以mtwmapi.OrderStatusFinished为结束状态,这个当成一个中间状态(且很少看到这个状态) + mtwmapi.OrderStatusFinished: model.OrderStatusFinished, + mtwmapi.OrderStatusCanceled: model.OrderStatusCanceled, + + fakeFinishedPickup: model.OrderStatusFinishedPickup, fakeOrderAdjustFinished: model.OrderStatusAdjust, fakeRefuseUserApplyCancel: model.OrderStatusUnlocked, fakeUserApplyCancel: model.OrderStatusApplyCancel, @@ -142,9 +144,10 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo if openUID > 0 { order.VendorUserID = utils.Int64ToStr(openUID) } - if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) { - order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 美团外卖要求在5分钟内拣货,不然订单会被取消 - } + // 不设置最晚拣货时间,以缺省值为准 + // if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) { + // order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 美团外卖要求在5分钟内拣货,不然订单会被取消 + // } order.Status = p.getStatusFromVendorStatus(order.VendorStatus) if utils.IsTimeZero(order.ExpectedDeliveredTime) { order.BusinessType = model.BusinessTypeImmediate @@ -347,7 +350,7 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *mtwmapi.CallbackMsg) (orderSta case mtwmapi.MsgTypeOrderCanceled: vendorStatus = mtwmapi.OrderStatusCanceled remark = msg.FormData.Get("reason") - case mtwmapi.MsgTypeNewOrder, FakeMsgTypeOrderReceived, mtwmapi.MsgTypeOrderAccepted, FakeMsgTypeOrderDelivering, mtwmapi.MsgTypeOrderFinished: + case FakeMsgType, mtwmapi.MsgTypeNewOrder, mtwmapi.MsgTypeOrderAccepted, mtwmapi.MsgTypeOrderFinished: vendorStatus = msg.FormData.Get("status") statusTime = utils.Str2Int64(msg.FormData.Get("utime")) case mtwmapi.MsgTypeOrderRefund, mtwmapi.MsgTypeOrderPartialRefund: @@ -414,11 +417,15 @@ func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI globals.SugarLogger.Debugf("mtwm AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) if isAcceptIt { if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderReceived(utils.Str2Int64(order.VendorOrderID)) - } - if err == nil { - c.postFakeMsg(order.VendorOrderID, FakeMsgTypeOrderReceived, mtwmapi.OrderStatusReceived) + // err = api.MtwmAPI.OrderReceived(utils.Str2Int64(order.VendorOrderID)) + err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID)) + if err != nil { + globals.SugarLogger.Warnf("mtwm AcceptOrRefuseOrder orderID:%s failed with err:%v", order.VendorOrderID, err) + } } + // if err == nil { + // c.postFakeMsg(order.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusReceived) + // } } else { if globals.EnableMtwmStoreWrite { err = c.CancelOrder(jxcontext.AdminCtx, order, "bu") @@ -429,10 +436,14 @@ func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { globals.SugarLogger.Debugf("mtwm PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery) - if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID)) - } else { - c.postFakeMsg(order.VendorOrderID, mtwmapi.MsgTypeOrderAccepted, mtwmapi.OrderStatusAccepted) + if !isSelfDelivery { + if globals.EnableMtwmStoreWrite { + // err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID)) + err = api.MtwmAPI.PreparationMealComplete(utils.Str2Int64(order.VendorOrderID)) + } + } + if err == nil { + c.postFakeMsg(order.VendorOrderID, FakeMsgType, fakeFinishedPickup) } return err } @@ -495,19 +506,19 @@ func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *mode return mobile, err } -func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) { - if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted { - params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效,美团外卖要求在5分钟内拣货,不然订单会被取消 - Timeout: pickupOrderDelay, - } - } else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup { - params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送 - Timeout: callDeliveryDelay, - TimeoutGap: callDeliveryDelayGap, - } - } - return params -} +// func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) { +// if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted { +// params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效,美团外卖要求在5分钟内拣货,不然订单会被取消 +// Timeout: pickupOrderDelay, +// } +// } else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup { +// params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送 +// Timeout: callDeliveryDelay, +// TimeoutGap: callDeliveryDelayGap, +// } +// } +// return params +// } func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { if globals.EnableMtwmStoreWrite { diff --git a/business/partner/purchase/mtwm/order_comment.go b/business/partner/purchase/mtwm/order_comment.go index d64162e12..f68ab3e2d 100644 --- a/business/partner/purchase/mtwm/order_comment.go +++ b/business/partner/purchase/mtwm/order_comment.go @@ -1,11 +1,13 @@ package mtwm import ( + "strings" "time" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" @@ -16,17 +18,15 @@ import ( ) const ( - RefreshCommentTime = 36 * time.Hour + RefreshCommentTime = 7 * 24 * time.Hour // 此值必须大于24小时 RefreshCommentTimeInterval = 60 * time.Minute - BAD_COMMENTS_MAX_MODIFY_TIME = 24 // 小时 + BAD_COMMENTS_MAX_MODIFY_TIME = 24 * 6 // 小时 ) func (c *PurchaseHandler) StartRefreshComment() { - if globals.ReallyCallPlatformAPI { - utils.AfterFuncWithRecover(5*time.Second, func() { - c.refreshCommentOnce() - }) - } + utils.AfterFuncWithRecover(5*time.Second, func() { + c.refreshCommentOnce() + }) } func (c *PurchaseHandler) refreshCommentOnce() { @@ -36,43 +36,75 @@ func (c *PurchaseHandler) refreshCommentOnce() { }) } +func formalizeTagList(mtwmTagList string) (outTagList string) { + if mtwmTagList != "" { + outTagList = string(utils.Format4Output(strings.Split(mtwmTagList, ","), true)) + } + return outTagList +} + func (c *PurchaseHandler) RefreshComment(fromTime, toTime time.Time) (err error) { - if globals.EnableMtwmStoreWrite { - storeMapList, err2 := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDMTWM}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") - if err = err2; err != nil { - return err - } - task := tasksch.NewParallelTask("mtwm RefreshComment", nil, jxcontext.AdminCtx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - storeMap := batchItemList[0].(*model.StoreMap) - startDateStr := time.Now().Format("20060102") - endDateStr := time.Now().Add(-RefreshCommentTime).Format("20060102") - commentList, err2 := api.MtwmAPI.CommentQuery(storeMap.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusAll) - if err = err2; err != nil { - return nil, err - } - return commentList, nil - }, storeMapList) - task.Run() - resultList, err2 := task.GetResult(0) - if err = err2; err != nil { - return err - } - var orderCommentList []*model.OrderComment - for _, result := range resultList { - mtwmComment := result.(*mtwmapi.OrderComment) - orderComment := &model.OrderComment{ - VendorID: model.VendorIDMTWM, - TagList: mtwmComment.CommentLables, - Score: int8(mtwmComment.FoodCommentScore), + storeMapList, err2 := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDMTWM}, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + if err = err2; err != nil { + return err + } + task := tasksch.NewParallelTask("mtwm RefreshComment", nil, jxcontext.AdminCtx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeMap := batchItemList[0].(*model.StoreMap) + endDateStr := time.Now().Add(-24 * time.Hour).Format("20060102") + startDateStr := time.Now().Add(-RefreshCommentTime).Format("20060102") + commentList, err2 := api.MtwmAPI.CommentQuery(storeMap.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusAll) + + var orderCommentList []*model.OrderComment + if err = err2; err != nil { + return nil, err } - orderCommentList = append(orderCommentList, orderComment) - } + for _, mtwmComment := range commentList { + createdTime, err := utils.TryStr2Time(mtwmComment.CommentTime) + if err == nil { + orderComment := &model.OrderComment{ + VendorOrderID: utils.Int64ToStr(mtwmComment.CommentID), // 美团评价不能得到订单号,以评价ID代替 + VendorID: model.VendorIDMTWM, + UserCommentID: utils.Int64ToStr(mtwmComment.CommentID), + VendorStoreID: storeMap.VendorStoreID, + TagList: formalizeTagList(mtwmComment.CommentLables), + Score: int8(mtwmComment.FoodCommentScore), + ModifyDuration: BAD_COMMENTS_MAX_MODIFY_TIME, + OriginalMsg: string(utils.MustMarshal(mtwmComment)), + IsReplied: int8(mtwmComment.ReplyStatus), + } + if orderComment.IsReplied == 0 { + orderComment.Content = mtwmComment.CommentContent + orderComment.CommentCreatedAt = createdTime + } else { + orderComment.Content = mtwmComment.AddComment + if updatedTime, err := utils.TryStr2Time(mtwmComment.CommentTime); err == nil { + orderComment.CommentCreatedAt = updatedTime + } + } + orderCommentList = append(orderCommentList, orderComment) + } + } + return orderCommentList, nil + }, storeMapList) + task.Run() + resultList, err2 := task.GetResult(0) + if err = err2; err != nil { + return err + } + var orderCommentList []*model.OrderComment + for _, result := range resultList { + orderComment := result.(*model.OrderComment) + orderCommentList = append(orderCommentList, orderComment) + } + if len(orderCommentList) > 0 { + err = partner.CurOrderManager.OnOrderComments(orderCommentList) } return err } func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, orderComment *model.OrderComment, replyComment string) (err error) { + globals.SugarLogger.Debugf("mtwm ReplyOrderComment, orderComment:%s, replyComment:%s", utils.Format4Output(orderComment, true), replyComment) if globals.EnableMtwmStoreWrite { err = api.MtwmAPI.CommentAddReply(orderComment.VendorStoreID, utils.Str2Int64(orderComment.UserCommentID), replyComment) } diff --git a/business/partner/purchase/mtwm/store_sku2.go b/business/partner/purchase/mtwm/store_sku2.go index a6220d317..28468214d 100644 --- a/business/partner/purchase/mtwm/store_sku2.go +++ b/business/partner/purchase/mtwm/store_sku2.go @@ -36,7 +36,7 @@ func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice: batchSize = mtwmapi.MaxStoreSkuBatchSize case partner.FuncDeleteStoreSkus: - batchSize = 1 // 可考虑用批量操作 + batchSize = mtwmapi.MaxBatchDeleteSize case partner.FuncCreateStoreSkus: batchSize = 1 // 可考虑用批量操作 case partner.FuncUpdateStoreSkus: @@ -284,7 +284,7 @@ func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, v err = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID) } else { // todo 部分失败 - err = api.MtwmAPI.RetailCatSkuBatchDelete(ctx.GetTrackInfo(), vendorStoreID, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) + err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) } } return nil, err @@ -403,7 +403,7 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) { prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(appFood.Name) vendorSku := appFood.SkuList[0] - weight := vendorSku.Weight + weight := int(utils.Str2Int64WithDefault(vendorSku.Weight, 0)) if weight <= 0 { weight = jxutils.FormatSkuWeight(specQuality, specUnit) } diff --git a/business/partner/purchase/mtwm/waybill.go b/business/partner/purchase/mtwm/waybill.go index be3b39f66..4c44081a6 100644 --- a/business/partner/purchase/mtwm/waybill.go +++ b/business/partner/purchase/mtwm/waybill.go @@ -1,9 +1,6 @@ package mtwm import ( - "net/url" - "time" - "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" @@ -33,17 +30,7 @@ func (c *PurchaseHandler) onWaybillMsg(msg *mtwmapi.CallbackMsg) (response *mtwm waybill := c.callbackMsg2Waybill(msg) err := partner.CurOrderManager.OnWaybillStatusChanged(waybill) if err == nil && waybill.Status == model.WaybillStatusDelivering { - msg := &mtwmapi.CallbackMsg{ - Cmd: FakeMsgTypeOrderDelivering, - FormData: url.Values{}, - } - msg.FormData.Set("timestamp", utils.Int64ToStr(time.Now().Unix())) - msg.FormData.Set("utime", msg.FormData.Get("timestamp")) - msg.FormData.Set(mtwmapi.KeyOrderID, waybill.VendorOrderID) - msg.FormData.Set("status", mtwmapi.OrderStatusDelivering) - utils.CallFuncAsync(func() { - c.onOrderMsg(msg) - }) + c.postFakeMsg(waybill.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusDelivering) } return mtwmapi.Err2CallbackResponse(err, "") } diff --git a/business/partner/purchase/weimob/wsc/order.go b/business/partner/purchase/weimob/wsc/order.go index 86b315f09..57416ab9e 100644 --- a/business/partner/purchase/weimob/wsc/order.go +++ b/business/partner/purchase/weimob/wsc/order.go @@ -2,7 +2,6 @@ package wsc import ( "errors" - "sort" "time" "git.rosy.net.cn/baseapi/platformapi/weimobapi" @@ -263,75 +262,7 @@ func (p *PurchaseHandler) postFakeMsg(orderNo int64, fakeStatus string) { } func (p *PurchaseHandler) arrangeSaleStore(order *model.GoodsOrder, cityName, provinceName string) { - globals.SugarLogger.Debugf("arrangeSaleStore orderID:%s cityName:%s, provinceName:%s", order.VendorOrderID, cityName, provinceName) - const ( - maxTryStoreWhenArrange = 5 - ) - db := dao.GetDB() - var selectedStore *model.Store - if true { - if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, model.VendorIDWSC); err == nil { - selectedStore = &storeDetail.Store - } - } else { - storeList, err := dao.GetPossibleStoresByPlaceName(db, cityName, provinceName) - if err != nil { - globals.SugarLogger.Errorf("arrangeSaleStore failed with error:%v", err) - } - globals.SugarLogger.Debugf("arrangeSaleStore possible stores orderID:%s", order.VendorOrderID) - for _, store := range storeList { - globals.SugarLogger.Debugf("orderID:%s %s:%d", order.VendorOrderID, store.Name, store.ID) - } - if len(storeList) > 0 { - distanceList := make(utils.SortList, 0) - userLng := jxutils.IntCoordinate2Standard(order.ConsigneeLng) - userLat := jxutils.IntCoordinate2Standard(order.ConsigneeLat) - for k, store := range storeList { - // 展示门店自身不参与派单 - if store.VendorStoreID != order.VendorStoreID { - sortItem := &utils.SortItem{ - CompareValue: int64(jxutils.EarthDistance(userLng, userLat, jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat)) * 1000), - Index: k, - } - distanceList = append(distanceList, sortItem) - } - } - sort.Sort(distanceList) - globals.SugarLogger.Debugf("arrangeSaleStore distance list orderID:%s", order.VendorOrderID) - for _, dist := range distanceList { - globals.SugarLogger.Debugf("orderID:%s %s:%d, distance:%d", order.VendorOrderID, storeList[dist.Index].Name, storeList[dist.Index].ID, dist.CompareValue) - } - if len(distanceList) > maxTryStoreWhenArrange { - distanceList = distanceList[:maxTryStoreWhenArrange] - } - for _, v := range distanceList { - selectedStore = &storeList[v.Index].Store - if selectedStore.DeliveryRangeType == model.DeliveryRangeTypeRadius { - distance := v.CompareValue - if distance < utils.Str2Int64(selectedStore.DeliveryRange) { - break - } else { - globals.SugarLogger.Debugf("arrangeSaleStore orderID:%s distance:%d, deliveryRange:%d", order.VendorOrderID, distance, utils.Str2Int64(selectedStore.DeliveryRange)) - } - } else { - points := jxutils.CoordinateStr2Points(selectedStore.DeliveryRange) - if utils.IsPointInPolygon(userLng, userLat, points) { - break - } else { - globals.SugarLogger.Debugf("arrangeSaleStore orderID:%s userLng:%f, userLat:%f, deliveryRange:%s", order.VendorOrderID, userLng, userLat, selectedStore.DeliveryRange) - } - } - selectedStore = nil - } - } - } - if selectedStore != nil { - order.StoreID = selectedStore.ID - order.StoreName = selectedStore.Name - globals.SugarLogger.Debugf("arrangeSaleStore orderID:%s arranged to store:%d", order.VendorOrderID, selectedStore.ID) - } else { - globals.SugarLogger.Errorf("arrangeSaleStore orderID:%s 找不到门店", order.VendorOrderID) - } + } func (p *PurchaseHandler) setStoreOrderSeq(order *model.GoodsOrder) { diff --git a/business/userstore/food_recipe.go b/business/userstore/food_recipe.go index 541921db3..af0254ad8 100644 --- a/business/userstore/food_recipe.go +++ b/business/userstore/food_recipe.go @@ -200,9 +200,9 @@ func tryRegisterDataRes4Recipe(ctx *jxcontext.Context, name, mainImg string, ste return errList.GetErrListAsOne() } -func QueryFoodRecipes(ctx *jxcontext.Context, keyword, authorID string, offset, pageSize int) (recipeInfo *model.PagedInfo, err error) { +func QueryFoodRecipes(ctx *jxcontext.Context, keyword, authorID string, skuIDs []int, offset, pageSize int) (recipeInfo *model.PagedInfo, err error) { _, userID := ctx.GetMobileAndUserID() - recipeList, totalCount, err := dao.QueryFoodRecipes(dao.GetDB(), keyword, 0, authorID, userID, offset, pageSize) + recipeList, totalCount, err := dao.QueryFoodRecipes(dao.GetDB(), keyword, 0, authorID, userID, skuIDs, offset, pageSize) if err == nil { recipeInfo = &model.PagedInfo{ TotalCount: totalCount, @@ -227,7 +227,7 @@ func GetRecommendFoodRecipes(ctx *jxcontext.Context, keyword string, offset, pag func GetRecipeDetail(ctx *jxcontext.Context, recipeID int) (recipeDetail *FoodRecipeDetail, err error) { _, userID := ctx.GetMobileAndUserID() db := dao.GetDB() - recipeList, _, err := dao.QueryFoodRecipes(db, "", recipeID, "", userID, 0, 0) + recipeList, _, err := dao.QueryFoodRecipes(db, "", recipeID, "", userID, nil, 0, 0) if err != nil { return nil, err } @@ -275,7 +275,7 @@ func VoteFoodRecipe(ctx *jxcontext.Context, recipeID, voteType int) (err error) } db := dao.GetDB() - recipeList, _, err := dao.QueryFoodRecipes(db, "", recipeID, "", userID, 0, 0) + recipeList, _, err := dao.QueryFoodRecipes(db, "", recipeID, "", userID, nil, 0, 0) if err != nil { return err } diff --git a/controllers/cms.go b/controllers/cms.go index 4114e181b..e0c5d79ed 100644 --- a/controllers/cms.go +++ b/controllers/cms.go @@ -18,7 +18,6 @@ type CmsController struct { // @Title 得到地点(省,城市,区)信息 // @Description 得到地点(省,城市,区)信息。 -// @Param token header string true "认证token" // @Param keyword query string false "查询关键字(可以为空,为空表示不限制)" // @Param parentCode query int false "上级地点code,这个指的是国家标准CODE(中国为:100000,北京为:110000,北京市为:110100),不是数据库中的ID" // @Param level query int false "地点级别:省为1,市为2,区为3,注意直辖市也要分省与市级" @@ -222,10 +221,10 @@ func (c *CmsController) FakeNewOrder() { // @Title 发送消息给相关人员 // @Description 发送消息给相关人员 -// @Param mobile formData string true "手机号" -// @Param verifyCode formData string false "验证码" // @Param msgType formData string true "消息类型" // @Param msgContent formData string true "消息内容" +// @Param mobile formData string false "手机号" +// @Param verifyCode formData string false "验证码" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /SendMsg2Somebody [post] diff --git a/controllers/cms_food_recipe.go b/controllers/cms_food_recipe.go index d94e23de8..c5017f30c 100644 --- a/controllers/cms_food_recipe.go +++ b/controllers/cms_food_recipe.go @@ -72,9 +72,9 @@ func (c *FoodRecipeController) UpdateFoodRecipe() { // @Title 查询菜谱列表 // @Description 查询菜谱列表 -// @Param token header string true "认证token" // @Param keyword query string false "关键字" // @Param authorID query string false "创建者ID" +// @Param skuIDs query string false "skuID列表" // @Param offset query int false "菜谱列表起始序号(以0开始,缺省为0)" // @Param pageSize query int false "菜谱列表页大小(缺省为50,-1表示全部)" // @Success 200 {object} controllers.CallResult @@ -82,14 +82,16 @@ func (c *FoodRecipeController) UpdateFoodRecipe() { // @router /QueryFoodRecipes [get] func (c *FoodRecipeController) QueryFoodRecipes() { c.callQueryFoodRecipes(func(params *tFoodrecipeQueryFoodRecipesParams) (retVal interface{}, errCode string, err error) { - retVal, err = userstore.QueryFoodRecipes(params.Ctx, params.Keyword, params.AuthorID, params.Offset, params.PageSize) + var skuIDs []int + if err = jxutils.Strings2Objs(params.SkuIDs, &skuIDs); err == nil { + retVal, err = userstore.QueryFoodRecipes(params.Ctx, params.Keyword, params.AuthorID, skuIDs, params.Offset, params.PageSize) + } return retVal, "", err }) } // @Title 得到我的推荐菜谱列表 // @Description 得到我的推荐菜谱列表 -// @Param token header string true "认证token" // @Param keyword query string false "关键字" // @Param offset query int false "菜谱列表起始序号(以0开始,缺省为0)" // @Param pageSize query int false "菜谱列表页大小(缺省为50,-1表示全部)" @@ -105,7 +107,6 @@ func (c *FoodRecipeController) GetRecommendFoodRecipes() { // @Title 得到菜谱详情 // @Description 得到菜谱详情 -// @Param token header string true "认证token" // @Param recipeID query int true "菜谱ID" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult diff --git a/controllers/cms_sku.go b/controllers/cms_sku.go index 11e26496c..e94bf11ec 100644 --- a/controllers/cms_sku.go +++ b/controllers/cms_sku.go @@ -31,7 +31,6 @@ func (c *SkuController) GetVendorCategories() { // @Title 得到商品类别 // @Description 得到商品类别(区别于厂商家SKU类别) -// @Param token header string true "认证token" // @Param parentID query int false "父ID,-1表示所有,缺省为-1" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult @@ -152,7 +151,7 @@ func (c *SkuController) SyncCategory() { // @Param isBySku query bool false "是否将sku拆开,缺省为false" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult -// @router /GetSkuNames [get] +// @router /GetSkuNames [get,post] func (c *SkuController) GetSkuNames() { c.callGetSkuNames(func(params *tSkuGetSkuNamesParams) (retVal interface{}, errCode string, err error) { retVal, err = cms.GetSkuNames(params.Ctx, params.Keyword, params.IsBySku, params.MapData, params.Offset, params.PageSize) @@ -191,7 +190,7 @@ func (c *SkuController) UpdateSkuName() { // dummySkuName := &model.SkuName{} payload := make(map[string]interface{}) if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { - retVal, err = cms.UpdateSkuName(params.Ctx, params.NameID, payload, params.Ctx.GetUserName()) + retVal, err = cms.UpdateSkuName(params.Ctx, params.NameID, payload) } return retVal, "", err }) @@ -241,7 +240,7 @@ func (c *SkuController) UpdateSku() { c.callUpdateSku(func(params *tSkuUpdateSkuParams) (retVal interface{}, errCode string, err error) { payload := make(map[string]interface{}) if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { - retVal, err = cms.UpdateSku(params.Ctx, params.SkuID, payload, params.Ctx.GetUserName()) + retVal, err = cms.UpdateSku(params.Ctx, params.SkuID, payload) } return retVal, "", err }) diff --git a/controllers/cms_store.go b/controllers/cms_store.go index b6b27bde7..22d1b4420 100644 --- a/controllers/cms_store.go +++ b/controllers/cms_store.go @@ -39,6 +39,7 @@ type StoreController struct { // @Param orderTimeTo query string false "订单创建结束时间" // @Param orderCountFrom query int false "订单量起始" // @Param orderCountTo query int false "订单量结束" +// @Param briefLevel query int false "返回信息精简模式" // @Param offset query int false "门店列表起始序号(以0开始,缺省为0)" // @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" // @Success 200 {object} controllers.CallResult @@ -236,7 +237,7 @@ func (c *StoreController) TmpGetJxBadCommentsByStoreId() { if err = err2; err == nil { pageSize := jxutils.FormalizePageSize(params.Size) offset := (params.Page - 1) * pageSize - retVal, err = cms.TmpGetJxBadCommentsByStoreId(params.Ctx, []int{params.JxStoreId}, offset, pageSize, params.Type, timeList[0], timeList[1]) + retVal, err = cms.TmpGetJxBadCommentsByStoreId(params.Ctx, "", []int{params.JxStoreId}, offset, pageSize, params.Type, timeList[0], timeList[1]) } return retVal, "", err }) @@ -246,11 +247,12 @@ func (c *StoreController) TmpGetJxBadCommentsByStoreId() { // @Description 得到门店评价列表(多店) // @Param token header string true "认证token" // @Param type query int true "评论类型,0:差评,1:所有,2:已解决" +// @Param keyword query string false "关键字" // @Param storeIDs query string false "门店I列表" -// @Param offset query int false "起始页,从1开始" -// @Param pageSize query int false "页大小(-1表示无限大)" // @Param fromTime query string false "创建起始时间" // @Param toTime query string false "创建结束时间" +// @Param offset query int false "起始页,从1开始" +// @Param pageSize query int false "页大小(-1表示无限大)" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /TmpGetJxBadComments [get] @@ -260,7 +262,7 @@ func (c *StoreController) TmpGetJxBadComments() { if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err == nil { timeList, err2 := jxutils.BatchStr2Time(params.FromTime, params.ToTime) if err = err2; err == nil { - retVal, err = cms.TmpGetJxBadCommentsByStoreId(params.Ctx, storeIDs, params.Offset, params.PageSize, params.Type, timeList[0], timeList[1]) + retVal, err = cms.TmpGetJxBadCommentsByStoreId(params.Ctx, params.Keyword, storeIDs, params.Offset, params.PageSize, params.Type, timeList[0], timeList[1]) } } return retVal, "", err @@ -532,7 +534,6 @@ func (c *StoreController) SyncStoresCourierInfo() { // @Title 根据位置得到推荐门店列表 // @Description 根据位置得到推荐门店列表 -// @Param token header string true "认证token" // @Param lng query float64 true "经度" // @Param lat query float64 true "纬度" // @Param needWalkDistance query bool false "是否需要返回步行距离(且以步行距离排序)" diff --git a/controllers/cms_store_sku.go b/controllers/cms_store_sku.go index 7f495a0ab..3aa15fb22 100644 --- a/controllers/cms_store_sku.go +++ b/controllers/cms_store_sku.go @@ -40,6 +40,7 @@ type StoreSkuController struct { // @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" // @Param isBySku query bool false "是否按SKU分拆" // @Param isAct query bool false "是否活动商品(包括正常活动与补贴)" +// @Param actVendorID query int false "要得到哪个平台的活动信息(缺省不限制,非零最小值)" // @Param jdSyncStatus query int false "京东同步标识" // @Param ebaiSyncStatus query int false "饿百同步标识" // @Param mtwmSyncStatus query int false "美团外卖同步标识" @@ -58,7 +59,6 @@ func (c *StoreSkuController) GetStoreSkus() { // @Title 得到商家商品信息 // @Description 得到商家商品信息,如下条件之间是与的关系。对于没有认领的商品,按城市限制。但对于已经认领的商品就不限制了,因为已经在平台上可售,可以操作(改价等等) -// @Param token header string true "认证token" // @Param storeIDs query string false "门店ID" // @Param isFocus query bool true "是否已关注(认领)" // @Param keyword query string false "查询关键字(可以为空,为空表示不限制)" @@ -80,6 +80,7 @@ func (c *StoreSkuController) GetStoreSkus() { // @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" // @Param isBySku query bool false "是否按SKU分拆" // @Param isAct query bool false "是否活动商品(包括正常活动与补贴)" +// @Param actVendorID query int false "要得到哪个平台的活动信息(缺省不限制,非零最小值)" // @Param jdSyncStatus query int false "京东同步标识" // @Param ebaiSyncStatus query int false "饿百同步标识" // @Param mtwmSyncStatus query int false "美团外卖同步标识" diff --git a/controllers/cms_user2.go b/controllers/cms_user2.go index e0b3a6d7f..71cd2d452 100644 --- a/controllers/cms_user2.go +++ b/controllers/cms_user2.go @@ -1,13 +1,16 @@ package controllers import ( + "git.rosy.net.cn/baseapi/platformapi/weixinapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/auth2" + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/authz" "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" "github.com/astaxie/beego" ) @@ -361,3 +364,50 @@ func (c *User2Controller) SaveMyCart() { return retVal, "", err }) } + +// @Title 得到用户自己的信息 +// @Description 得到用户自己的信息 +// @Param token header string true "认证token" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetSelfInfo [get] +func (c *User2Controller) GetSelfInfo() { + c.callGetSelfInfo(func(params *tUser2GetSelfInfoParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetSelfInfo(params.Ctx) + return retVal, "", err + }) +} + +// @Title 根据小程序jsCode修改用户信息 +// @Description 根据小程序jsCode修改用户信息 +// @Param token header string true "认证token" +// @Param jsCode query string true "小程序jsCode" +// @Param data query string true "加密数据" +// @Param iv query string true "iv" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateUserByMiniInfo [put] +func (c *Auth2Controller) UpdateUserByMiniInfo() { + c.callUpdateUserByMiniInfo(func(params *tAuth2UpdateUserByMiniInfoParams) (retVal interface{}, errCode string, err error) { + authInfo, err := params.Ctx.GetV2AuthInfo() + if err == nil { + decryptedDataBase64, err2 := weixin.AutherObjMini.DecryptData(authInfo, GetComposedCode(&c.Controller, params.JsCode), params.Data, params.Iv) + if err = err2; err == nil { + var userInfo *weixinapi.MiniUserInfo + if err = utils.UnmarshalUseNumber([]byte(decryptedDataBase64), &userInfo); err == nil { + retVal = userInfo + if user := params.Ctx.GetFullUser(); user != nil { + if userInfo.AvatarURL != "" { + user.Avatar = userInfo.AvatarURL + } + if userInfo.PurePhoneNumber != "" { + user.Mobile = utils.String2Pointer(userInfo.PurePhoneNumber) + } + dao.UpdateEntity(dao.GetDB(), user) + } + } + } + } + return retVal, "", err + }) +} diff --git a/controllers/jx_order.go b/controllers/jx_order.go index 703b4571c..4fe21002f 100644 --- a/controllers/jx_order.go +++ b/controllers/jx_order.go @@ -741,6 +741,30 @@ func (c *OrderController) AmendMissingOrders() { }) } +// @Title 同步刷新历史订单的结算价按订单 +// @Description 同步刷新历史订单的结算价按订单 +// @Param token header string true "认证token" +// @Param fromTime formData string false "订单起始时间 (yyyy-mm-dd hh:ms:ss)" +// @Param toTime formData string false "订单结束时间 (yyyy-mm-dd hh:ms:ss)" +// @Param vendorOrderID formData string false "订单号" +// @Param vendorIDs formData string false "平台ID列表[0,1,3]" +// @Param actID formData int false "活动ID" +// @Param storeID formData int false "门店ID" +// @Param isAsync formData bool false "是否异步操作" +// @Param isContinueWhenError formData bool false "单个失败是否继续,缺省true" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /RefreshHistoryOrdersEarningPrice [post] +func (c *OrderController) RefreshHistoryOrdersEarningPrice() { + c.callRefreshHistoryOrdersEarningPrice(func(params *tOrderRefreshHistoryOrdersEarningPriceParams) (retVal interface{}, errCode string, err error) { + var vendorIDList []int + if err = jxutils.Strings2Objs(params.VendorIDs, &vendorIDList); err == nil { + retVal, err = orderman.FixedOrderManager.RefreshHistoryOrdersEarningPrice(params.Ctx, params.VendorOrderID, params.ActID, vendorIDList, params.StoreID, params.FromTime, params.ToTime, params.IsAsync, params.IsContinueWhenError) + } + return retVal, "", err + }) +} + // @Title 商家主动发起部分退款售后 // @Description 商家主动发起部分退款售后 // @Param token header string true "认证token" diff --git a/controllers/jxshop_callback.go b/controllers/jxshop_callback.go index 89ad0d73a..911f9a365 100644 --- a/controllers/jxshop_callback.go +++ b/controllers/jxshop_callback.go @@ -1,7 +1,7 @@ package controllers import ( - "git.rosy.net.cn/jx-callback/business/partner/purchase/jx" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/phpjx" "github.com/astaxie/beego" ) @@ -21,7 +21,7 @@ type JxShopController struct { // @router /JxMsg [post] func (c *JxShopController) JxMsg(msgType string) { c.callJxMsg(func(params *tJxshopJxMsgParams) (retVal interface{}, errCode string, err error) { - retVal, errCode, err = jx.OnCallbackMsg(&jx.CallbackMsg{ + retVal, errCode, err = phpjx.OnCallbackMsg(&phpjx.CallbackMsg{ AppKey: params.AppKey, MsgType: params.MsgType, SubMsgType: params.SubMsgType, diff --git a/controllers/yonghui.go b/controllers/yonghui.go new file mode 100644 index 000000000..3e75306ff --- /dev/null +++ b/controllers/yonghui.go @@ -0,0 +1,27 @@ +package controllers + +import ( + "git.rosy.net.cn/jx-callback/business/jxstore/yonghui" + "github.com/astaxie/beego" +) + +//读取永辉excelAPI +type YongHuiController struct { + beego.Controller +} + +// @Title 读取永辉excel文件 +// @Description 读取永辉excel文件 +// @Param token header string true "认证token" +// @Param isAsync query bool false "是否异步,缺省是同步" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /LoadExcelByYongHui [post] +func (c *YongHuiController) LoadExcelByYongHui() { + c.callLoadExcelByYongHui(func(params *tYonghuiLoadExcelByYongHuiParams) (retVal interface{}, errCode string, err error) { + r := c.Ctx.Request + files := r.MultipartForm.File["userfiles"] + retVal, err = yonghui.SendFilesToStores(params.Ctx, files) + return retVal, "", err + }) +} diff --git a/main.go b/main.go index 4088c347f..9b0d8d912 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxstore/misc" "git.rosy.net.cn/jx-callback/business/jxutils/tasks" "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" + "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/globals/api2" @@ -32,7 +33,7 @@ import ( _ "git.rosy.net.cn/jx-callback/business/partner/printer/zhongwu" _ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" - _ "git.rosy.net.cn/jx-callback/business/partner/purchase/elm" + _ "git.rosy.net.cn/jx-callback/business/partner/purchase/jx" _ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" _ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" _ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc" @@ -66,6 +67,7 @@ func Init() { if globals.IsProductEnv() { ebai.CurPurchaseHandler.StartRefreshComment() + mtwm.CurPurchaseHandler.StartRefreshComment() } misc.Init() } diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index c8a8106c4..004fe4213 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -169,6 +169,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:Auth2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:Auth2Controller"], + beego.ControllerComments{ + Method: "UpdateUserByMiniInfo", + Router: `/UpdateUserByMiniInfo`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:Auth2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:Auth2Controller"], beego.ControllerComments{ Method: "WeixinMPOAuth2", @@ -918,6 +927,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "RefreshHistoryOrdersEarningPrice", + Router: `/RefreshHistoryOrdersEarningPrice`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "RefreshOrderFinancial", @@ -1084,7 +1102,7 @@ func init() { beego.ControllerComments{ Method: "GetSkuNames", Router: `/GetSkuNames`, - AllowHTTPMethods: []string{"get"}, + AllowHTTPMethods: []string{"get","post"}, MethodParams: param.Make(), Filters: nil, Params: nil}) @@ -1890,6 +1908,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], + beego.ControllerComments{ + Method: "GetSelfInfo", + Router: `/GetSelfInfo`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetStoreRoleList", @@ -1971,4 +1998,13 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:YongHuiController"], + beego.ControllerComments{ + Method: "LoadExcelByYongHui", + Router: `/LoadExcelByYongHui`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + } diff --git a/routers/router.go b/routers/router.go index c06ea8bc8..834a8e1c1 100644 --- a/routers/router.go +++ b/routers/router.go @@ -126,6 +126,11 @@ func init() { &controllers.ReportController{}, ), ), + beego.NSNamespace("/yonghui", + beego.NSInclude( + &controllers.YongHuiController{}, + ), + ), ) beego.AddNamespace(ns)