From dffa68612edf4e7d9278e1923e05d3430c73f700 Mon Sep 17 00:00:00 2001 From: gazebo Date: Mon, 24 Dec 2018 11:59:29 +0800 Subject: [PATCH] - add changePriceType to model.Store - send weixin msg when op request handled. --- business/jxstore/cms/store_sku.go | 127 +++++++++++++++++------- business/jxutils/weixinmsg/weixinmsg.go | 48 +++++++++ business/model/store.go | 6 ++ conf/app.conf | 1 + globals/api/api.go | 4 + 5 files changed, 148 insertions(+), 38 deletions(-) diff --git a/business/jxstore/cms/store_sku.go b/business/jxstore/cms/store_sku.go index dfda9cffe..67ec8c619 100644 --- a/business/jxstore/cms/store_sku.go +++ b/business/jxstore/cms/store_sku.go @@ -12,6 +12,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxcallback/auth/weixin" "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/weixinmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" @@ -902,15 +903,19 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID, toStoreID int, copyMode return num, err } -func shouldPendingStorePriceChange(ctx *jxcontext.Context, storeID int, skuBindInfo *StoreSkuBindInfo) bool { +func shouldPendingStorePriceChange(ctx *jxcontext.Context, storeID int, skuBindInfo *StoreSkuBindInfo) (shouldPending bool, err error) { if globals.EnablePendingChange { - if ctx.GetLoginType() == weixin.LoginType || ctx.GetUserName() == "fakeboss" { - // storeDetail, err := dao.GetStoreDetail() - // skuBindInfo.IsFocus != 1 && - return true + if skuBindInfo.IsFocus != 1 && ctx.GetLoginType() == weixin.LoginType || ctx.GetUserName() == "fakeboss" { + db := dao.GetDB() + store := &model.Store{} + store.ID = storeID + if err = dao.GetEntity(db, store); err != nil { + return false, err + } + return store.ChangePriceType == model.StoreChangePriceTypeNeedApprove, nil } } - return false + return false, nil } func filterStorePriceChange(ctx *jxcontext.Context, storeIDs []int, skuBindInfos []*StoreSkuBindInfo) (filteredStoreIDs []int, filteredSkuBindInfos []*StoreSkuBindInfo, err error) { @@ -921,7 +926,10 @@ func filterStorePriceChange(ctx *jxcontext.Context, storeIDs []int, skuBindInfos defer dao.Rollback(db) for _, storeID := range storeIDs { for _, skuBindInfo := range skuBindInfos { - shouldPending := shouldPendingStorePriceChange(ctx, storeID, skuBindInfo) + shouldPending, err2 := shouldPendingStorePriceChange(ctx, storeID, skuBindInfo) + if err = err2; err != nil { + return nil, nil, err + } if shouldPending && (skuBindInfo.UnitPrice != 0 || skuBindInfo.IsFocus == 1) { var ( opInfoList []*StoreOpRequestInfo @@ -1026,40 +1034,38 @@ func AcceptStoreOpRequests(ctx *jxcontext.Context, reqIDs []int) (err error) { if globals.EnablePendingChange { if len(reqIDs) > 0 { subErrors := make(map[int]error) - db := dao.GetDB() - for _, reqID := range reqIDs { - op := &model.StoreOpRequest{} - op.ID = reqID - if err2 := dao.GetEntity(db, op); err2 != nil { - subErrors[reqID] = err2 - } else { - if op.Status == model.RequestStatusNew { - skuBindInfo := &StoreSkuBindInfo{ - NameID: op.ItemID, - UnitPrice: op.IntParam1, - IsSale: op.IntParam2, + infoMap, err2 := getStoreOpRequestsInfo(reqIDs) + if err = err2; err != nil { + return err + } + for reqID, op := range infoMap { + if op.Status == model.RequestStatusNew { + skuBindInfo := &StoreSkuBindInfo{ + NameID: op.ItemID, + UnitPrice: op.IntParam1, + IsSale: op.IntParam2, + } + if op.Type == model.RequestTypeFocusSkuName { + skuBindInfo.IsFocus = 1 + } + if op.JsonParam != "" { + if err2 = utils.UnmarshalUseNumber([]byte(op.JsonParam), &skuBindInfo.Skus); err2 != nil { + subErrors[reqID] = err2 } - if op.Type == model.RequestTypeFocusSkuName { - skuBindInfo.IsFocus = 1 - } - if op.JsonParam != "" { - if err2 = utils.UnmarshalUseNumber([]byte(op.JsonParam), &skuBindInfo.Skus); err2 != nil { - subErrors[reqID] = err2 + } + if err2 == nil { + _, err2 := UpdateStoresSkus(ctx, []int{op.StoreID}, []*StoreSkuBindInfo{skuBindInfo}) + isLocalSucess := true + if err2 != nil { + subErrors[reqID] = err2 + if !isSyncError(err2) { + isLocalSucess = false } } - if err2 == nil { - _, err2 := UpdateStoresSkus(ctx, []int{op.StoreID}, []*StoreSkuBindInfo{skuBindInfo}) - isLocalSucess := true - if err2 != nil { + if isLocalSucess { + weixinmsg.NotifyStoreOpRequestStatus(true, op.StoreID, op.ItemID, jxutils.ComposeSpuName(op.SkuNamePrefix, op.SkuNameName, 0), op.UnitPrice, op.IntParam1, "") + if err2 := changeStoreOpStatus(ctx, []int{reqID}, model.RequestStatusAccepted, ""); err2 != nil { subErrors[reqID] = err2 - if !isSyncError(err2) { - isLocalSucess = false - } - } - if isLocalSucess { - if err2 := changeStoreOpStatus(ctx, []int{reqID}, model.RequestStatusAccepted, ""); err2 != nil { - subErrors[reqID] = err2 - } } } } @@ -1078,7 +1084,16 @@ func AcceptStoreOpRequests(ctx *jxcontext.Context, reqIDs []int) (err error) { } func RejectStoreOpRequests(ctx *jxcontext.Context, reqIDs []int, rejectReason string) (err error) { - return changeStoreOpStatus(ctx, reqIDs, model.RequestStatusRejected, rejectReason) + infoMap, err := getStoreOpRequestsInfo(reqIDs) + if err != nil { + return err + } + if err = changeStoreOpStatus(ctx, reqIDs, model.RequestStatusRejected, rejectReason); err == nil { + for _, info := range infoMap { + weixinmsg.NotifyStoreOpRequestStatus(false, info.StoreID, info.ItemID, jxutils.ComposeSpuName(info.SkuNamePrefix, info.SkuNameName, 0), info.UnitPrice, info.IntParam1, rejectReason) + } + } + return err } // 当前些函数只针对type为: RequestTypeChangePrice与RequestTypeFocusSkuName的查询才有效 @@ -1156,6 +1171,42 @@ func GetStoreOpRequests(ctx *jxcontext.Context, fromTime, toTime time.Time, keyw return nil, err } +func getStoreOpRequestsInfo(reqIDs []int) (infoMap map[int]*StoreOpRequestInfo, err error) { + infoMap = make(map[int]*StoreOpRequestInfo) + if len(reqIDs) > 0 { + sql := ` + SELECT t1.*, t4.name store_name, t2.prefix sku_name_prefix, t2.name sku_name_name, t3.unit_price + FROM store_op_request t1 + JOIN sku_name t2 ON t2.id = t1.item_id + LEFT JOIN store_sku_bind t3 ON t3.store_id = t1.store_id AND t3.sku_id = t2.id AND t3.deleted_at = ? + JOIN store t4 ON t4.id = t1.store_id + WHERE t1.id IN (` + dao.GenQuestionMarks(len(reqIDs)) + ")" + sqlParams := []interface{}{ + utils.DefaultTimeValue, + reqIDs, + } + db := dao.GetDB() + var infoList []*StoreOpRequestInfo + if err = dao.GetRows(db, &infoList, sql, sqlParams...); err == nil { + for _, v := range infoList { + infoMap[v.ID] = v + } + if len(reqIDs) > len(infoMap) { + missingReqIDs := []int{} + for _, reqID := range reqIDs { + if infoMap[reqID] == nil { + missingReqIDs = append(missingReqIDs, reqID) + } + } + err = fmt.Errorf("不能找到如下的请求ID:%s", utils.Format4Output(missingReqIDs, true)) + } + } + } else { + err = errors.New("没有找到指定的请求ID") + } + return infoMap, err +} + func changeStoreOpStatus(ctx *jxcontext.Context, reqIDs []int, status int8, rejectReason string) (err error) { globals.SugarLogger.Debugf("changeStoreOpStatus, reqIDs:%v", reqIDs) if globals.EnablePendingChange { diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 2ec49451f..ab6cbc6c4 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -18,6 +18,7 @@ const ( // WX_TO_ORDER_PAGE_URL = "http://www.jxc4.com/jx/h5/#/?jxStoreId=" // WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://www.jxc4.com/jx/h5/#/assess-list?jxStoreId=" //展示差评详情的页面 WX_TO_ORDER_PAGE_URL = "http://wx.jxc4.com/#/?jxStoreId=" + WX_TO_STORE_SKU_PAGE_URL = "http://wx.jxc4.com/#/shop?jxStoreId=" WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://wx.jxc4.com/#/assess-list?jxStoreId=" //展示差评详情的页面 //新订单模板消息文字颜色 WX_NEW_ORDER_TEMPLATE_COLOR = "#173177" @@ -289,6 +290,53 @@ func NotifySaleBill(storeID int, fileURL string) (err error) { return SendMsgToStore(storeID, WX_SALE_BILL_TEMPLATE_ID, fileURL, data) } +func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName string, originalUnitPrice, unitPrice int, rejectReason string) (err error) { + globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason) + templateID := "" + fileURL := fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID) + data := make(map[string]interface{}) + if isAccepted { + templateID = "gIG2olBZtQbjXmp6doNB_dESu60By5xuXYOGxksLv3Y" + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": fmt.Sprintf("%s%s元,修改为%s元,已经通过审核。^_^", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice))), + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": "审核通过", + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.Time2Str(time.Now()), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "点击查看详情", + }, + } + } else { + templateID = "tn2QXWi4HtSIwaztmtN6Bb2uzNL-jBxWltCZTDNJuYE" + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": fmt.Sprintf("您好!抱歉的通知您。%s%s元,修改为%s元,未通过审核。原因:%s", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice)), rejectReason), + "color": "#E80000", + }, + "keyword1": map[string]interface{}{ + "value": "1", + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.Time2Str(time.Now()), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "请您及时到商品管理修改价格,修改后请重新提交。", + }, + } + } + return SendMsgToStore(storeID, templateID, fileURL, data) +} + func FormatDeliveryTime(order *model.GoodsOrder) string { var tmpTime time.Time if order.ExpectedDeliveredTime == utils.DefaultTimeValue { diff --git a/business/model/store.go b/business/model/store.go index aa3993fc7..d2f42dd9d 100644 --- a/business/model/store.go +++ b/business/model/store.go @@ -23,6 +23,11 @@ const ( StoreDeliveryTypeByStore = 2 //完全门店自送 ) +const ( + StoreChangePriceTypeDirect = 0 + StoreChangePriceTypeNeedApprove = 1 +) + var ( StoreStatusName = map[int]string{ StoreStatusDisabled: "禁用", @@ -122,6 +127,7 @@ type Store struct { DeliveryRangeType int8 `json:"deliveryRangeType"` // 参见相关常量定义 DeliveryRange string `orm:"type(text)" json:"deliveryRange"` // 如果DeliveryRangeType为DeliveryRangeTypePolygon,则为逗号分隔坐标,分号分隔的坐标点(坐标与Lng和Lat一样,都是整数),比如 121361504,31189308;121420555,31150238。否则为半径,单位为米 Status int `json:"status"` + ChangePriceType int8 `json:"changePriceType"` IDCardFront string `orm:"size(255);column(id_card_front)" json:"idCardFront"` IDCardBack string `orm:"size(255);column(id_card_back)" json:"idCardBack"` diff --git a/conf/app.conf b/conf/app.conf index 24f3f1bb1..57cec3b55 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -58,6 +58,7 @@ dadaSourceID = "73753" weixinAppID = "wxbf235770edaabc5c" weixinSecret = "ba32b269a068a5b72486a0beafd171e8" +weixinToken = "16_B70uVmPKcF7GYvwAIKscYYYB3DEmJDJ_M4SY8v9qmjwidciGEiuiJCuxKUTVf5nghCbeQOLzLrjnKUend6o8wtBFsn_lr5S1zBpAlUI43O53zHnAGUzwcMXT5T2sIHomUGTLV2OnTYJhFDJhEVKhADAULA" dbConnectStr = "root:WebServer@1@tcp(127.0.0.1:3306)/jxd_dev_0?charset=utf8mb4&loc=Local&parseTime=true" diff --git a/globals/api/api.go b/globals/api/api.go index 7411e4362..b1275ea54 100644 --- a/globals/api/api.go +++ b/globals/api/api.go @@ -50,6 +50,10 @@ func Init() { } if !beego.AppConfig.DefaultBool("disableWeixin", false) { WeixinAPI = weixinapi.New(beego.AppConfig.String("weixinAppID"), beego.AppConfig.String("weixinSecret")) + // 这个主要是用于调试阶段使用,生产环境中用的是自动刷新那套 + if weixinToken := beego.AppConfig.DefaultString("weixinToken", ""); weixinToken != "" { + WeixinAPI.SetToken(weixinToken) + } } AutonaviAPI = autonavi.New(beego.AppConfig.String("autonaviKey")) QiniuAPI = qbox.NewMac(beego.AppConfig.String("qiniuAK"), beego.AppConfig.String("qiniuSK"))