From e2b41bf9db660b3ab1349546bb9961c9ea00df98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=AE=97=E6=A5=A0?= Date: Wed, 21 Sep 2022 10:03:21 +0800 Subject: [PATCH] 1 --- .../jxcallback/scheduler/basesch/basesch.go | 1 + business/model/api_config.go | 1 - business/model/store.go | 13 +- business/partner/purchase/gomei/act.go | 15 - business/partner/purchase/gomei/callback.go | 502 ---------- .../partner/purchase/gomei/callback_test.go | 34 - business/partner/purchase/gomei/gomei.go | 120 --- business/partner/purchase/gomei/key.go | 78 -- business/partner/purchase/gomei/order.go | 334 ------- business/partner/purchase/gomei/order_afs.go | 138 --- .../partner/purchase/gomei/order_comment.go | 5 - business/partner/purchase/gomei/store.go | 87 -- business/partner/purchase/gomei/store_sku.go | 911 ------------------ .../partner/purchase/gomei/store_sku_other.go | 393 -------- .../partner/purchase/tiktok_store/callback.go | 18 +- .../purchase/tiktok_store/financial_test.go | 54 ++ .../purchase/tiktok_store/interface_call.go | 267 ----- .../tiktok_store/{tiktok.go => mtwm.go} | 2 +- .../purchase/tiktok_store/mtwm_test.go | 50 + .../partner/purchase/tiktok_store/order.go | 855 ++++++++++++++-- .../purchase/tiktok_store/order_afs.go | 449 +++++++++ .../purchase/tiktok_store/order_comment.go | 113 +++ .../purchase/tiktok_store/order_test.go | 35 + .../partner/purchase/tiktok_store/store.go | 487 ++++++++++ .../purchase/tiktok_store/store_sku2.go | 716 ++++++++++++++ .../purchase/tiktok_store/store_sku2_test.go | 64 ++ .../purchase/tiktok_store/store_sku_test.go | 46 + .../purchase/tiktok_store/store_test.go | 43 + .../partner/purchase/tiktok_store/waybill.go | 59 ++ conf/app.conf | 12 - controllers/tiktok_store.go | 38 +- globals/api/api.go | 7 +- globals/api/apimanager/apimanager.go | 4 - 33 files changed, 2919 insertions(+), 3032 deletions(-) delete mode 100644 business/partner/purchase/gomei/act.go delete mode 100644 business/partner/purchase/gomei/callback.go delete mode 100644 business/partner/purchase/gomei/callback_test.go delete mode 100644 business/partner/purchase/gomei/gomei.go delete mode 100644 business/partner/purchase/gomei/key.go delete mode 100644 business/partner/purchase/gomei/order.go delete mode 100644 business/partner/purchase/gomei/order_afs.go delete mode 100644 business/partner/purchase/gomei/order_comment.go delete mode 100644 business/partner/purchase/gomei/store.go delete mode 100644 business/partner/purchase/gomei/store_sku.go delete mode 100644 business/partner/purchase/gomei/store_sku_other.go create mode 100644 business/partner/purchase/tiktok_store/financial_test.go delete mode 100644 business/partner/purchase/tiktok_store/interface_call.go rename business/partner/purchase/tiktok_store/{tiktok.go => mtwm.go} (99%) create mode 100644 business/partner/purchase/tiktok_store/mtwm_test.go create mode 100644 business/partner/purchase/tiktok_store/order_afs.go create mode 100644 business/partner/purchase/tiktok_store/order_comment.go create mode 100644 business/partner/purchase/tiktok_store/order_test.go create mode 100644 business/partner/purchase/tiktok_store/store.go create mode 100644 business/partner/purchase/tiktok_store/store_sku2.go create mode 100644 business/partner/purchase/tiktok_store/store_sku2_test.go create mode 100644 business/partner/purchase/tiktok_store/store_sku_test.go create mode 100644 business/partner/purchase/tiktok_store/store_test.go create mode 100644 business/partner/purchase/tiktok_store/waybill.go diff --git a/business/jxcallback/scheduler/basesch/basesch.go b/business/jxcallback/scheduler/basesch/basesch.go index 79165dbf8..5e441c46e 100644 --- a/business/jxcallback/scheduler/basesch/basesch.go +++ b/business/jxcallback/scheduler/basesch/basesch.go @@ -137,6 +137,7 @@ func (c *BaseScheduler) SelfDeliverDelivering(order *model.GoodsOrder, userName partner.CurOrderManager.OnOrderMsg(order, "美团外卖转自送成功.", "") } else if strings.Contains(err.Error(), "包裹不存在") || strings.Contains(err.Error(), "运单不存在") || strings.Contains(err.Error(), "1071") || strings.Contains(err.Error(), "1014") || strings.Contains(err.Error(), "invalid character 'o' looking for beginning of value") { partner.CurOrderManager.OnOrderMsg(order, "美团外卖转自送可能成功,异常:", err.Error()) + err = nil } else { bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) c.CancelWaybill(bill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) diff --git a/business/model/api_config.go b/business/model/api_config.go index ee5541af1..09ab1fbc9 100644 --- a/business/model/api_config.go +++ b/business/model/api_config.go @@ -105,7 +105,6 @@ var ( VendorIDQiNiuCloud: "Qiniu", VendorIDJDWL: "Jdwl", - VendorGoMei: "GoMei", } VendorTypeName = map[int]string{ diff --git a/business/model/store.go b/business/model/store.go index 58bb4da7a..544e0f5ad 100644 --- a/business/model/store.go +++ b/business/model/store.go @@ -35,8 +35,7 @@ const ( BrandOpenSMS = 8 //短信 BrandOpenVoice = 16 //语音 - BrandBalanceLimit = 1000 - GoMeiMaxCountNumber = 50 // 国美最大数据返回条数 + BrandBalanceLimit = 1000 ) const ( @@ -87,13 +86,11 @@ const ( ) const ( - ExdStoreName = "饿鲜达" - MatterStoreID = 666666 - JdShopMainVendorStoreID = "9999999" // 三方平台总商户id - GoMeiShopMainVendorStoreID = "GMJ-MS-XOMRF-1J1" // 三方平台总商户id + ExdStoreName = "饿鲜达" + MatterStoreID = 666666 + JdShopMainVendorStoreID = "9999999" // 三方平台总商户id // JdShopMainVendorStoreID2 = "9999999" - JdShopMainStoreID = 100000 // 本地商户门店地 - GoMeiShopMainStoreID = 200000 // 本店商户门店id + JdShopMainStoreID = 100000 // 本地商户门店地 // JdShopMainStoreID2 = 100000 VendorStoreTel = "18011597879" diff --git a/business/partner/purchase/gomei/act.go b/business/partner/purchase/gomei/act.go deleted file mode 100644 index 8c9cf5861..000000000 --- a/business/partner/purchase/gomei/act.go +++ /dev/null @@ -1,15 +0,0 @@ -package gomei - -import ( - "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" -) - -func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) { - return err -} - -func (c *PurchaseHandler) GetActAmple(ctx *jxcontext.Context, vendorStoreID, vendorOrgCode string) (ample int, err error) { - return ample, err -} diff --git a/business/partner/purchase/gomei/callback.go b/business/partner/purchase/gomei/callback.go deleted file mode 100644 index 37b4695d7..000000000 --- a/business/partner/purchase/gomei/callback.go +++ /dev/null @@ -1,502 +0,0 @@ -package gomei -// -//import ( -// "bytes" -// "encoding/base64" -// "encoding/hex" -// "encoding/json" -// "fmt" -// "math" -// "strings" -// "time" -// -// "git.rosy.net.cn/jx-callback/business/authz/autils" -// "git.rosy.net.cn/jx-callback/business/partner/delivery/dada" -// -// "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" -// beego "github.com/astaxie/beego/server/web" -// -// "git.rosy.net.cn/baseapi/platformapi/dadaapi" -// "git.rosy.net.cn/baseapi/platformapi/dingdingapi" -// "git.rosy.net.cn/baseapi/platformapi/jcqapi" -// "git.rosy.net.cn/baseapi/platformapi/jdshopapi" -// "git.rosy.net.cn/baseapi/utils" -// "git.rosy.net.cn/jx-callback/business/jxutils" -// "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" -// "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/globals" -// "git.rosy.net.cn/jx-callback/globals/api" -// "git.rosy.net.cn/jx-callback/globals/api2" -//) -// -////TODO 以下是京东商城云顶推送消息使用的代码,现在都是以网页爬取的形式拿订单了,下面的都不用了 -////TODO 位置在 orderman/order.go 的 SaveJdsOrders -//func OnCallbackMsg(msg *jdshopapi.CallBackResult) (err error) { -// msgType := msg.MsgType -// switch msgType { -// case jcqapi.TopicOrderPay: -// utils.CallFuncAsync(func() { -// SaveJdsOrders(msg) -// }) -// case jcqapi.TopicOrderCancel: -// utils.CallFuncAsync(func() { -// order := getRealOrderID(msg.OrderID) -// if order != nil { -// if order.Status != model.OrderStatusCanceled { -// CurPurchaseHandler.CancelOrder(jxcontext.AdminCtx, order, "系统取消") -// } -// } -// }) -// case jcqapi.TopicOrderOut: -// utils.CallFuncAsync(func() { -// globals.SugarLogger.Debugf("jdsOrderOut", utils.Format4Output(msg, false)) -// orders := getAllRealOrderID(msg.OrderID) -// if len(orders) > 0 { -// for _, order := range orders { -// if order.ActualPayPrice == 0 { -// if jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) == 0 { -// order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderTotalPrice) + utils.Str2Float64(msg.FreightPrice) - utils.Str2Float64(msg.SellerDiscount)) -// } else { -// order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) -// } -// order.TotalShopMoney = utils.Float64TwoInt64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage) -// partner.CurOrderManager.UpdateOrderFields(order, []string{"ActualPayPrice", "TotalShopMoney"}) -// } -// } -// } -// }) -// default: -// return fmt.Errorf("暂不支持的topic类型!topic: %v", msgType) -// } -// return err -//} -// -//func SaveJdsOrders(msg *jdshopapi.CallBackResult) (err error) { -// if msg.OrderState == "TRADE_CANCELED" { -// return nil -// } //清洗脏数据 部分数据按照 -// order, err := result2Orders(msg) -// if err != nil && order == nil { -// return err -// } -// globals.SugarLogger.Debugf("SaveJdsOrders : %v", utils.Format4Output(order, false)) -// partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) -// noticeMsg := fmt.Sprintf("京东商城新订单,订单号:[%v] ,将要发到的门店id:[%v] , 门店名:[%v]", order.VendorOrderID, order.StoreID, order.StoreName) -// if order.OrderType == model.OrderTypeAddressErr { -// noticeMsg += " 此订单地址有问题,需要矫正坐标!" -// } -// var role = autils.NewRole("jdshop", 0) -// userIDList, err := api2.RoleMan.GetRoleUserList(role) -// for _, v := range userIDList { -// ddmsg.SendUserMessage(dingdingapi.MsgTyeText, v, "京东商城来新订单了!", noticeMsg) -// } -// // ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "京东商城来新订单了!", noticeMsg) -// return err -//} -// -//func result2Orders(msg *jdshopapi.CallBackResult) (order *model.GoodsOrder, err error) { -// var ( -// db = dao.GetDB() -// ) -// //有可能是库里已经有这个订单了 -// orderE, err := partner.CurOrderManager.LoadOrder(msg.OrderID+"00000001", model.VendorIDJDShop) -// if orderE != nil { -// return order, fmt.Errorf("已经存在此订单!") -// } -// order = &model.GoodsOrder{ -// VendorOrderID2: msg.OrderID, -// VendorOrderID: msg.OrderID + "00000001", -// VendorID: model.VendorIDJDShop, -// BaseFreightMoney: jxutils.StandardPrice2Int(utils.Str2Float64(msg.FreightPrice)), -// VendorStatus: msg.OrderState, -// VendorUserID: msg.Pin, -// BuyerComment: msg.OrderRemark, -// PickDeadline: utils.DefaultTimeValue, -// OriginalData: string(utils.MustMarshal(msg)), -// OrderCreatedAt: utils.Str2Time(msg.OrderStartTime), -// ConsigneeAddress: Decrypt(msg.ConsigneeInfo.FullAddress, msg.VendorOrgCode), -// ConsigneeName: Decrypt(msg.ConsigneeInfo.Fullname, msg.VendorOrgCode), -// // ConsigneeMobile: Decrypt(msg.ConsigneeInfo.Mobile), -// // ConsigneeMobile2: Decrypt(msg.ConsigneeInfo.Telephone), -// ActualPayPrice: jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)), -// Status: model.OrderStatusNew, -// TotalShopMoney: utils.Float64TwoInt64(math.Round(float64(jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment))) * jdshopapi.JdsPayPercentage)), -// DeliveryType: model.OrderDeliveryTypeStoreSelf, -// StatusTime: utils.Str2Time(msg.OrderStartTime), -// OrderSeq: 0, -// VendorOrgCode: msg.VendorOrgCode, -// } -// if utils.Str2Float64(msg.BalanceUsed) != 0 { -// order.ActualPayPrice += jxutils.StandardPrice2Int(utils.Str2Float64(msg.BalanceUsed)) -// order.TotalShopMoney += utils.Float64TwoInt64(math.Round(float64(jxutils.StandardPrice2Int(utils.Str2Float64(msg.BalanceUsed))) * jdshopapi.JdsPayPercentage)) -// } -// if len(msg.ConsigneeInfo.Mobile) != 11 { -// order.ConsigneeMobile = Decrypt(msg.ConsigneeInfo.Mobile, msg.VendorOrgCode) -// } else { -// order.ConsigneeMobile = msg.ConsigneeInfo.Mobile -// } -// if len(msg.ConsigneeInfo.Telephone) != 11 { -// order.ConsigneeMobile2 = Decrypt(msg.ConsigneeInfo.Telephone, msg.VendorOrgCode) -// } else { -// order.ConsigneeMobile2 = msg.ConsigneeInfo.Telephone -// } -// if order.TotalShopMoney < 100 { -// order.TotalShopMoney = 100 -// } -// if order.ConsigneeAddress != "" { -// var cityCode int -// place, err := dao.GetPlaceByJdsCode(db, utils.Str2Int(msg.ConsigneeInfo.CityID)) -// if place == nil { -// cityCode = 510100 -// } else { -// if place.Level == 3 { -// cityCode = place.ParentCode -// } else if place.Level == 2 { -// cityCode = place.Code -// } -// } -// lng, lat, err2 := api.AutonaviAPI.GetCoordinateFromAddressByPage(order.ConsigneeAddress, cityCode) -// if err = err2; err != nil { -// globals.SugarLogger.Infof("高德page err: %v", err) -// } -// lng2, lat2, _ := api.AutonaviAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "") -// distance := jxutils.EarthDistance(lng, lat, lng2, lat2) -// if distance > 1 { -// order.OrderType = model.OrderTypeAddressErr -// } -// if err == nil && lng != 0 && lat != 0 { -// order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng) -// order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat) -// } else { -// order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng2) -// order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat2) -// } -// order.CoordinateType = model.CoordinateTypeMars -// } -// // storeList, err := common.GetStoreListByLocation(jxcontext.AdminCtx, jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), 3000, false, true, 0) -// // if err != nil { -// // globals.SugarLogger.Debugf("jds GetStoreListByLocation error: %v", err.Error()) -// // return order, err -// // } -// // if len(storeList) > 0 { -// // for _, store := range storeList { -// for _, v := range msg.ItemInfoList { -// sku := &model.OrderSku{ -// VendorID: model.VendorIDJDShop, -// VendorOrderID: order.VendorOrderID, -// Count: utils.Str2Int(v.ItemTotal), -// VendorSkuID: v.SkuID, -// SkuName: v.SkuName, -// VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)), -// SalePrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)), -// // SkuID: utils.Str2Int(v.OuterSkuID), -// } -// if v.OuterSkuID != "" { -// sku.SkuID = utils.Str2Int(v.OuterSkuID) -// } -// _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.SkuName) -// sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit) -// order.Skus = append(order.Skus, sku) -// } -// if order.ActualPayPrice > 100000 { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 8") -// } -// var store *dao.StoreDetail -// if msg.OrderExt != "" { -// orderExt := &jdshopapi.OrderExt{} -// if err = json.Unmarshal([]byte(msg.OrderExt), &orderExt); err == nil { -// order.VendorStoreID = orderExt.SiteID -// if store, err = dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, model.VendorIDJDShop, ""); store != nil && err == nil { -// order.StoreID = store.ID -// order.JxStoreID = store.ID -// order.StoreName = store.Name -// globals.SugarLogger.Debugf("jds GetStoreListByLocation, orderID: %v storeID :%v", order.VendorOrderID, order.StoreID) -// //结算类型 -// if store.PayPercentage < 50 { -// order.EarningType = model.EarningTypePoints -// } else { -// order.EarningType = model.EarningTypeQuote -// } -// var ( -// shopPriceSum int -// // saleNormalSum int -// ) -// for _, sku := range order.Skus { -// storeSkuList, _ := dao.GetStoresSkusInfo(db, []int{order.StoreID}, []int{sku.SkuID}) -// if len(storeSkuList) > 0 { -// // if storeSkuList[0].Status == model.StoreSkuBindStatusNormal { -// // saleNormalSum += 1 -// // } -// shopPriceSum += storeSkuList[0].Price * sku.Count -// sku.ShopPrice = int64(storeSkuList[0].Price) -// } else { -// shopPriceSum += int(sku.SalePrice) * 70 / 100 -// } -// } -// //可售数小于一半就不行 -// // if math.Mod(float64(len(order.Skus)), float64(2)) == 0 { -// // if saleNormalSum < len(order.Skus)/2 { -// // buildOrderTo102919(order) -// // globals.SugarLogger.Debugf("resultjdsOrders return 1") -// // } else { -// if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 2") -// } -// // } -// // } else { -// // if saleNormalSum <= len(order.Skus)/2 { -// // buildOrderTo102919(order) -// // globals.SugarLogger.Debugf("resultjdsOrders return 3") -// // } else { -// // if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { -// // buildOrderTo102919(order) -// // globals.SugarLogger.Debugf("resultjdsOrders return 4") -// // } -// // } -// // } -// } else { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 5") -// } -// } else { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 6") -// } -// } else { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 7") -// } -// // 如果是暂停,表示是预订单g -// if msg.OrderState == jdshopapi.OrderStatusPause || msg.OrderState == jdshopapi.OrderStatusPopPause { -// order.BusinessType = model.BusinessTypeDingshida -// if time2, err := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil { -// if time2 == "" { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// } else { -// order.ExpectedDeliveredTime = utils.Str2Time(time2) -// } -// } else { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// err = nil -// } -// order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour) -// } else if msg.OrderState == jdshopapi.OrderStatusWait || msg.OrderState == "WAIT_GOODS_RECEIVE_CONFIRM" || msg.OrderState == "FINISHED_L" { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// order.BusinessType = model.BusinessTypeImmediate -// } else if msg.OrderState == "UN_KNOWN" { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// order.BusinessType = model.BusinessTypeImmediate -// } else { -// globals.SugarLogger.Debugf("暂不支持的京东商城订单类型!type: %v", msg.OrderState) -// return nil, err -// } -// -// if msg.IDSopShipmenttype == jdshopapi.IdSopShipmenttypeTC { -// if msg.VendorOrgCode == "1" { -// if time2, err := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil { -// order.BusinessType = model.BusinessTypeDingshida -// if time2 == "" { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// } else { -// order.ExpectedDeliveredTime = utils.Str2Time(time2) -// } -// } -// } else { -// order.BusinessType = model.BusinessTypeImmediate -// if time2, err := getAPI(msg.VendorOrgCode).GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil { -// if time2 == "" { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// } else { -// order.ExpectedDeliveredTime = utils.Str2Time(time2) -// } -// } else { -// order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) -// } -// } -// } -// setJdsOrderSeq(order) -// if order.OrderType == model.OrderTypeAddressErr { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 9") -// } -// // billParams, _ := GetDaDaBillParams(db, order) -// // if result, err := api.DadaAPI.QueryDeliverFee(billParams); err == nil { -// // if result.Fee > 10 { -// // buildOrderTo102919(order) -// // globals.SugarLogger.Debugf("resultjdsOrders return 10") -// // } -// // } -// if store != nil { -// distance := jxutils.EarthDistance(jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat)) -// if distance > 4 { -// buildOrderTo102919(order) -// globals.SugarLogger.Debugf("resultjdsOrders return 4") -// } -// } -// if order.ExpectedDeliveredTime.Sub(order.OrderCreatedAt) <= time.Hour+time.Minute { -// order.BusinessType = model.BusinessTypeImmediate -// } -// // buildOrderTo102919(order) -// return order, err -//} -// -//func buildOrderTo102919(order *model.GoodsOrder) { -// // if order.VendorOrgCode == "1" { -// // order.StoreID = 102919 -// // order.JxStoreID = 102919 -// // order.StoreName = "商城模板(成都发货)" -// // order.VendorStoreID = model.JdShopMainVendorStoreID -// // } else { -// order.StoreID = model.JdShopMainStoreID -// order.JxStoreID = model.JdShopMainStoreID -// order.StoreName = "商城模板店2" -// order.VendorStoreID = model.JdShopMainVendorStoreID -// // } -// order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled -//} -// -//func setJdsOrderSeq(order *model.GoodsOrder) (err error) { -// type tCount struct { -// Count int `json:"count"` -// } -// var count = &tCount{} -// sql := ` -// SELECT count(*) count FROM goods_order WHERE store_id = ? AND order_create_at >= ? AND order_create_at <= ? AND vendor_id = ? -// ` -// sqlParams := []interface{}{ -// order.StoreID, utils.Time2Date(time.Now()), utils.Time2Date(time.Now().AddDate(0, 0, 1)), order.VendorID, -// } -// err = dao.GetRow(dao.GetDB(), &count, sql, sqlParams) -// order.OrderSeq = count.Count + 1 -// return err -//} -// -//func Decrypt(p, vendorOrgCode string) (result string) { -// if p == "" { -// return "" -// } -// data, _ := base64.StdEncoding.DecodeString(strings.ReplaceAll(p, " ", "+")) -// key := GetKey(hex.EncodeToString(data)[4:36], vendorOrgCode) -// globals.SugarLogger.Debugf("Decrypt keys : %v", key) -// data2, _ := base64.StdEncoding.DecodeString(key) -// b := bytes.NewBuffer(data) -// b.Next(18) -// iv := make([]byte, 16) -// b.Read(iv) -// main := make([]byte, len(data)-18-16) -// b.Read(main) -// decryptedData, _ := utils.AESCBCDecpryt(main, data2[:16], iv) -// return string(decryptedData) -//} -// -//func getRealOrderID(orderID string) (order *model.GoodsOrder) { -// var ( -// db = dao.GetDB() -// ) -// sql := ` -// SELECT * FROM goods_order WHERE vendor_order_id2 = ? ORDER BY vendor_order_id DESC LIMIT 1 -// ` -// sqlParams := []interface{}{ -// orderID, -// } -// dao.GetRow(db, &order, sql, sqlParams) -// return order -//} -// -//func getAllRealOrderID(orderID string) (orders []*model.GoodsOrder) { -// var ( -// db = dao.GetDB() -// ) -// sql := ` -// SELECT * FROM goods_order WHERE vendor_order_id2 = ? -// ` -// sqlParams := []interface{}{ -// orderID, -// } -// dao.GetRows(db, &orders, sql, sqlParams) -// return orders -//} -// -//func GetDaDaBillParams(db *dao.DaoDB, order *model.GoodsOrder) (billParams *dadaapi.OperateOrderParams, err error) { -// billParams = &dadaapi.OperateOrderParams{ -// OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), -// CargoPrice: jxutils.IntPrice2Standard(limitOrderPrice(order.ActualPayPrice)), -// IsPrepay: 0, -// ReceiverName: utils.FilterMb4(order.ConsigneeName), -// ReceiverAddress: utils.FilterMb4(order.ConsigneeAddress), -// ReceiverPhone: order.ConsigneeMobile, -// } -// if billParams.ShopNo, err = getDadaShopID(order, db); err == nil { -// if billParams.CityCode, err = getDataCityCodeFromOrder(order, db); err == nil { -// // storeTel := "" -// // storeID := jxutils.GetSaleStoreIDFromOrder(order) -// // storeDeatail, _ := dao.GetStoreDetail(db, storeID, order.VendorID) -// // if storeDeatail.Tel2 != "" { -// // storeTel = ",门店电话:" + storeDeatail.Tel2 -// // } -// billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) -// billParams.Info = fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, utils.FilterMb4("客户电话:"+order.ConsigneeMobile+","+order.BuyerComment+"取货失败或配送遇到问题请联系18048531223,禁止未配送直接完成定单!")) -// billParams.CargoType = dadaapi.CargoTypeFresh -// billParams.CargoWeight = float64(jxutils.IntWeight2Float(limitOrderWeight(order.Weight))) -// billParams.CargoNum = order.GoodsCount -// } -// } -// return billParams, err -//} -// -//func limitOrderPrice(price int64) int64 { -// var maxOrderPrice int64 = 6399 -// if price > maxOrderPrice { -// return maxOrderPrice -// } -// return price -//} -// -//func limitOrderWeight(weight int) int { -// maxOrderWeight := 5000 // 5公斤 -// if weight > maxOrderWeight { -// return maxOrderWeight -// } -// return weight -//} -// -//func getDadaShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) { -// saleStoreID := jxutils.GetSaleStoreIDFromOrder(order) -// storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDDada) -// if err = err2; err != nil && !dao.IsNoRowsError(err) { -// return "", err -// } -// if len(storeCourierList) == 0 { -// return "", partner.ErrStoreHaveNoCourier -// } -// retVal = storeCourierList[0].VendorStoreID -// if beego.BConfig.RunMode == "dev" { -// retVal = "test_0001" -// } -// return retVal, nil -//} -// -//func getDataCityCodeFromOrder(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) { -// jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) -// sql := ` -// SELECT t2.tel_code -// FROM store t1 -// JOIN place t2 on t1.city_code = t2.code -// WHERE t1.id = ? -// ` -// codeInfo := &struct { -// TelCode string -// }{} -// if err = dao.GetRow(db, codeInfo, sql, jxStoreID); err != nil { -// globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, error:%v", order.VendorID, order.VendorStoreID, err) -// if err == nil { -// err = dada.ErrCanNotFindDadaCityCode -// } -// return "", err -// } -// return codeInfo.TelCode, nil -//} diff --git a/business/partner/purchase/gomei/callback_test.go b/business/partner/purchase/gomei/callback_test.go deleted file mode 100644 index 5301bb558..000000000 --- a/business/partner/purchase/gomei/callback_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package gomei -// -//import ( -// "fmt" -// "git.rosy.net.cn/baseapi/platformapi/jdshopapi" -// "testing" -//) -// -//func TestSaveJdsOrders(t *testing.T) { -// type args struct { -// msg *jdshopapi.CallBackResult -// } -// tests := []struct { -// name string -// args args -// wantErr bool -// }{ -// // TODO: Add test cases. -// } -// fmt.Println("测试1") -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// if err := SaveJdsOrders(tt.args.msg); (err != nil) != tt.wantErr { -// t.Errorf("SaveJdsOrders() error = %v, wantErr %v", err, tt.wantErr) -// } -// }) -// } -// fmt.Println("测试2") -//} -// -//func TestDecrypt(t *testing.T) { -// InitKey() -// fmt.Println(Decrypt("dGeoMeGNcXeT8iCHn3hTrCFYY8qfMnOptNcMFzAJA2/Dx/CPiZ526ec0NN0kWKs4+HwEGCLu9hAB9D0MIf8UB6q4G8IVgD3oXlOb89CFgGe0yO1HA9j51ESPFXh8=", "1")) -//} diff --git a/business/partner/purchase/gomei/gomei.go b/business/partner/purchase/gomei/gomei.go deleted file mode 100644 index 41248b37e..000000000 --- a/business/partner/purchase/gomei/gomei.go +++ /dev/null @@ -1,120 +0,0 @@ -package gomei - -import ( - "encoding/base64" - gomei "git.rosy.net.cn/baseapi/platformapi/gome_live_show" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - "git.rosy.net.cn/baseapi/utils" - "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/putils" - "git.rosy.net.cn/jx-callback/globals" - "git.rosy.net.cn/jx-callback/globals/api" -) - -var ( - CurPurchaseHandler *PurchaseHandler -) - -type PurchaseHandler struct { - partner.BasePurchasePlatform - putils.DefSingleStorePlatform -} - -func init() { - if api.GuoMeiApi != nil { - CurPurchaseHandler = New() - partner.RegisterPurchasePlatform(CurPurchaseHandler) - } -} - -func New() (obj *PurchaseHandler) { - obj = new(PurchaseHandler) - obj.ISingleStoreStoreSkuHandler = obj - return obj -} - -func getAPI(appOrgCode string) (apiObj *gomei.API) { - if appOrgCode == "" { - globals.SugarLogger.Warnf("getAPI appOrgCode is empty") - } - - return partner.CurAPIManager.GetAPI(model.VendorGoMei, appOrgCode).(*gomei.API) -} - -func GetAPI(appOrgCode string) (apiObj *jdshopapi.API) { - apiObj = partner.CurAPIManager.GetAPI(model.VendorGoMei, appOrgCode).(*jdshopapi.API) - if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie2", model.ConfigTypeCookie, ""); err == nil { - apiObj.SetCookieWithStr(configs[0].Value) - } - return apiObj -} - -func (p *PurchaseHandler) GetVendorID() int { - return model.VendorGoMei -} - -func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) { - if globals.EnableJdShopWrite { - if imgType > model.ImgTypeLocal { - result, err := getAPI(vendorOrgCode).UploadPicture(base64.StdEncoding.EncodeToString(imgData), 0, imgName) - if err == nil { - imgHint = result.Data.Url - } - } - } else { - imgHint = utils.GetUpperUUID() - } - return imgHint, err -} - -// 获取国美商户的分类标签,官方未提供接口.->查询所有门店分类,去重复!目前国美分类只有一级 -func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) { - storeList, err := getAPI(string(model.VendorGoMei)).QueryStoreList(&gomei.GetStoreListReq{ - Page: gomei.Page{ - PageSize: model.BrandBalanceLimit, - PageNumber: 1, - }, - }) - if err != nil { - return nil, err - } - - if storeList.Data.Total == 0 { - return nil, nil - } - - result := make(map[string]*model.SkuVendorCategory, 0) - for _, v := range storeList.Data.Records { - storeCategoryList, err := GetAllStoreCategories(string(model.VendorGoMei), v.StoreCode) - //storeCategoryList, err := api.GuoMeiApi.QueryStoreCategoryList(&gomei.QueryStoreGoodsCategoryListReq{ - // Page: gomei.Page{PageNumber: 1, PageSize: model.BrandBalanceLimit}, - // StoreCode: v.StoreCode, - //}) - if err != nil || len(storeCategoryList) <= 0 { - continue - } - for _, c := range storeCategoryList { - cat := &model.SkuVendorCategory{ - VendorID: model.VendorGoMei, - Name: c.CategoryName, - Level: 1, - VendorCategoryID: c.CategoryCode, - ParentID: "", - IsLeaf: 0, - } - result[cat.Name] = cat - } - } - - for _, v := range result { - vendorCats = append(vendorCats, v) - } - return vendorCats, err -} - -func (p *PurchaseHandler) GetOrderRider(vendorOrgCode, vendorStoreID string, param map[string]interface{}) (err error) { - return nil -} diff --git a/business/partner/purchase/gomei/key.go b/business/partner/purchase/gomei/key.go deleted file mode 100644 index f8f93d861..000000000 --- a/business/partner/purchase/gomei/key.go +++ /dev/null @@ -1,78 +0,0 @@ -package gomei - -import ( - "encoding/base64" - "encoding/hex" - "encoding/json" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - - "git.rosy.net.cn/jx-callback/globals" -) - -var ( - KeyList []*Key - KeyList2 []*Key -) - -type Key struct { - ID string `json:"id"` - KeyExp int64 `json:"key_exp"` - KeyStatus int `json:"key_status"` - KeyDigest string `json:"key_digest"` - KeyType string `json:"key_type"` - KeyString string `json:"key_string"` - KeyEffective int64 `json:"key_effective"` - Version int `json:"version"` -} - -func InitKey() { - newapi := jdshopapi.New("37d36b62c0d14bd4b872f948b335c95czinj", "E1D746D42474D5F1F1A10CECE75D99F6", "efa7e1d1a22640fa990e6cf164b28608") - keyResult, err := newapi.KeyGet() - if err != nil { - return - } - for _, v := range keyResult.Response.ServiceKeyList[0].Keys { - data, _ := json.Marshal(v) - vv := &Key{} - err = json.Unmarshal(data, &vv) - KeyList = append(KeyList, vv) - } - keyResult2, err := jdshopapi.New("f9c5ce9a5ce24218936924f7c4864cc9owe1", "E1D746D42474D5F1F1A10CECE75D99F6", "efa7e1d1a22640fa990e6cf164b28608").KeyGet() - if err != nil { - return - } - for _, v := range keyResult2.Response.ServiceKeyList[0].Keys { - data, _ := json.Marshal(v) - vv := &Key{} - err = json.Unmarshal(data, &vv) - KeyList2 = append(KeyList2, vv) - } - globals.SugarLogger.Debugf("jdshop key refreshed..") -} - -func GetKey(keySign, vendorOrgCode string) (key string) { - if vendorOrgCode == "1" { - for _, v := range KeyList { - data, _ := base64.StdEncoding.DecodeString(v.ID) - if keySign == hex.EncodeToString(data) { - return v.KeyString - } - } - } else { - for _, v := range KeyList2 { - //data, _ := base64.StdEncoding.DecodeString(v.ID) - //if keySign == hex.EncodeToString(data) { - return v.KeyString - } - } - // } else { - // for _, v := range KeyList2 { - // data, _ := base64.StdEncoding.DecodeString(v.ID) - // if keySign == hex.EncodeToString(data) { - // return v.KeyString - // } - // } - // } - globals.SugarLogger.Debugf("no key can equal..") - return key -} diff --git a/business/partner/purchase/gomei/order.go b/business/partner/purchase/gomei/order.go deleted file mode 100644 index c7582b119..000000000 --- a/business/partner/purchase/gomei/order.go +++ /dev/null @@ -1,334 +0,0 @@ -package gomei - -import ( - "fmt" - "git.rosy.net.cn/jx-callback/globals" - "net/http" - "strings" - "time" - - "git.rosy.net.cn/jx-callback/business/model/dao" - - "git.rosy.net.cn/baseapi" - "git.rosy.net.cn/baseapi/platformapi" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - "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/api" -) - -func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) { - return err -} - -func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { - result := &jdshopapi.AllOrdersResult{} - if err := utils.Map2StructByJson(orderData, &result, false); err != nil { - return nil - } - - jdsOrder := result.OrderList[0] - order = &model.GoodsOrder{ - VendorOrderID: utils.Int64ToStr(jdsOrder.OrderID), - VendorID: model.VendorIDJDShop, - BaseFreightMoney: jxutils.StandardPrice2Int(jdsOrder.Freight), - VendorStatus: utils.Int2Str(jdsOrder.OrderStatus), - VendorUserID: jdsOrder.UserPin, - BuyerComment: jdsOrder.UserRemark, - PickDeadline: utils.DefaultTimeValue, - OriginalData: string(utils.MustMarshal(jdsOrder)), - Status: status2Jxstatus(jdsOrder.OrderStatus), - } - return order -} -func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) { - resultOrders, err := api.JdShopAPI.AllOrders(&jdshopapi.AllOrdersParam{ - OrderID: vendorOrderID, - Current: 1, - PageSize: 10, - }) - if err != nil { - return nil, err - } - return p.Map2Order(utils.Struct2FlatMap(resultOrders)), err -} -func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { - //jdsOrder, err := GetJdsOrder(vendorOrderID, vendorOrgCode) - //jdsOrder, err := GetJdsOrder2(vendorOrderID, vendorOrgCode) - //r := regexp.MustCompile(`"orderState":"(.*)","orderType`) - //if len(r.FindStringSubmatch(jdsOrder)) > 0 { - // return status2Jxstatus(r.FindStringSubmatch(jdsOrder)[1]), err - //} - if order, err := p.GetOrder(vendorOrgCode, vendorOrderID, ""); err == nil && order != nil { - return order.Status, err - } - return 0, err -} - -func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { - //var ( - // status int - // remark string - //) - //if isAcceptIt { - // status = model.OrderStatusAccepted - // //京东商城第二个号要自动接单 - // if order.VendorOrgCode == "2" { - // err = getAPI(order.VendorOrgCode).SetOrderStateToWait(utils.Str2Int64(order.VendorOrderID2)) - // } - //} else { - // status = model.OrderStatusCanceled - //} - //return ChangeOrderStatus(order.VendorOrderID, status, remark) - return err -} -func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { - status, err := p.GetOrderStatus(order.VendorOrgCode, order.VendorOrderID2) - if err != nil { - globals.SugarLogger.Debug("jdShop GetOrders err := ", err) - return err - } - //说明此时该订单在平台上已经取消了 - if status == model.OrderStatusCanceled { - err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单在京东商城已被取消!") - } else { - if jxutils.GetSaleStoreIDFromOrder(order) != model.JdShopMainStoreID { - //可能还没接单? - if status == model.OrderStatusNew { - p.AcceptOrRefuseOrder(order, true, "") - } - err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "自动拣货完成") - //if status == model.OrderStatusAccepted { - err = p.OrderExport(jxcontext.AdminCtx, order.VendorOrderID, order.VendorOrderID, true) - //} - } - } - return err -} - -func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { - return err -} // 取货失败后再次招唤平台配送 -func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { - return err -} // 投递失败后确认收到退货 -func (p *PurchaseHandler) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) { - return isCan, err -} -func (p *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { - return err -} -func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { - return err -} -func (p *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { - ChangeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "") - return err -} -func (p *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { - //ChangeOrderStatus(order.VendorOrderID, model.OrderStatusFinished, "") - //if order.VendorOrgCode == "2" { - // getAPI(order.VendorOrgCode).SetOrderStateToFinish(utils.Str2Int64(order.VendorOrderID2)) - //} - return err -} -func (p *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) { - return mobile, err -} -func (p *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) { - return err -} -func (p *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { - return err -} -func (p *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, reason) - if order.EclpOutID != "" { - _, err = api.JdEclpAPI.CancelOrder(order.EclpOutID) - } - return err -} -func (p *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { - var ( - db = dao.GetDB() - diffShopPrice int64 - diffSalePrice int64 - ) - if order.Status >= model.OrderStatusDelivering { - return fmt.Errorf("配送中以后的订单无法进行售前退款!") - } - //1、删除原order_sku 中售前调整的商品 - for _, sku := range removedSkuList { - sql := `DELETE FROM order_sku WHERE vendor_order_id = ? AND vendor_id = ? AND sku_id = ?` - sqlParams := []interface{}{order.VendorOrderID, order.VendorID, sku.SkuID} - dao.ExecuteSQL(db, sql, sqlParams) - - diffShopPrice += sku.ShopPrice - diffSalePrice += sku.SalePrice - } - //2、修改goods_order 中的shopprice,若是扣点的订单,还要改new_earning_price和total_shop_money - order.AdjustCount += 1 - order.ShopPrice = order.ShopPrice - diffShopPrice - if order.EarningType == model.EarningTypePoints { - order.TotalShopMoney = utils.Float64TwoInt64(float64(float64(order.TotalShopMoney)/jdshopapi.JdsPayPercentage-float64(diffSalePrice)) * jdshopapi.JdsPayPercentage) - jxutils.RefreshOrderEarningPrice2(order, order.OrderPayPercentage) - partner.CurOrderManager.UpdateOrderFields(order, []string{"TotalShopMoney", "NewEarningPrice"}) - } - partner.CurOrderManager.UpdateOrderFields(order, []string{"AdjustCount", "ShopPrice"}) - return err -} - -func (p *PurchaseHandler) GetJdsOrders(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd string, current, pageSize int) (orderResult *jdshopapi.AllOrdersResult, err error) { - //jdsapi := getAPI("2") - //globals.SugarLogger.Debugf("此时的cookie , %d", jdsapi.GetCookieCount()) - //orderResult, err = jdsapi.AllOrders(&jdshopapi.AllOrdersParam{ - // Current: current, - // PageSize: pageSize, - // OrderCreateDateRange: []string{orderCreatedStart, orderCreatedEnd}, - //}) - return orderResult, err -} - -func ChangeOrderStatus(vendorOrderID string, status int, remark string) (err error) { - orderStatus := &model.OrderStatus{ - VendorOrderID: vendorOrderID, - VendorID: model.VendorIDJDShop, - OrderType: model.OrderTypeOrder, - RefVendorOrderID: vendorOrderID, - RefVendorID: model.VendorIDJDShop, - VendorStatus: utils.Int2Str(status), - Status: status, - StatusTime: time.Now(), - Remark: remark, - } - jxutils.CallMsgHandlerAsync(func() { - err = partner.CurOrderManager.OnOrderStatusChanged("", orderStatus) - }, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJDShop)) - return err -} - -func (p *PurchaseHandler) OrderExport(ctx *jxcontext.Context, vendorOrderID, vendorWaybillID string, isAuto bool) (err error) { - //companyID := jdshopapi.JdsDeliveryCompany3rd - ////表示是门店手动发京东 - //if !isAuto { - // companyID = jdshopapi.JdsDeliveryCompanyJD - //} - //if order, _ := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJDShop); order != nil { - // err = getAPI(order.VendorOrgCode).OrderShipment(utils.Str2Int64(order.VendorOrderID2), companyID, vendorWaybillID) - //} - return err -} - -func (p *PurchaseHandler) OrderTransfer(ctx *jxcontext.Context, vendorOrderID, vendorWaybillID string, isAuto bool) (err error) { - companyID := jdshopapi.JdsDeliveryCompany3rd - //表示是门店手动发京东 - if !isAuto { - companyID = jdshopapi.JdsDeliveryCompanyJD - } - err = api.JdShopAPI.UpdateWaybill(vendorOrderID[:12], companyID, vendorOrderID) - return err -} - -func status2Jxstatus(status int) (statusJx int) { - //if status == jdshopapi.OrderStatusPopPause || status == jdshopapi.OrderStatusPause { - // statusJx = model.OrderStatusNew - //} else if status == jdshopapi.OrderStatusWait { - // statusJx = model.OrderStatusAccepted - //} else if status == jdshopapi.OrderStatusCancel { - // statusJx = model.OrderStatusCanceled - //} - if status == jdshopapi.OrderStatusFinishedPickup { - statusJx = model.OrderStatusAccepted - } else if status == jdshopapi.OrderStatusNew { - statusJx = model.OrderStatusNew - } else if status == jdshopapi.OrderStatusCancelm2 { - statusJx = model.OrderStatusCanceled - } - return statusJx -} - -const ( - ProdURL = "http://116.196.82.188:8080/v2/" -) - -func apiToYd(url string, params map[string]interface{}) (retVal map[string]interface{}, err error) { - cl := &http.Client{} - err = platformapi.AccessPlatformAPIWithRetry(cl, - func() *http.Request { - request, _ := http.NewRequest(http.MethodPost, ProdURL+url, strings.NewReader(utils.Map2URLValues(params).Encode())) - request.Header.Set("Content-Type", "application/x-www-form-urlencoded") - return request - }, - nil, - func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { - if jsonResult1 == nil { - return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") - } - if err == nil { - if jsonResult1["code"] != nil { - if utils.Interface2Int64WithDefault(jsonResult1["code"], 0) != 0 { - errLevel = platformapi.ErrLevelGeneralFail - err = utils.NewErrorCode(jsonResult1["desc"].(string), jsonResult1["code"].(string)) - baseapi.SugarLogger.Debugf("yd AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true)) - } - } - retVal = jsonResult1 - } - return errLevel, err - }) - return retVal, err -} - -func GetJdsOrder(vendorOrderID, vendorOrgCode string) (jdsOrder *jdshopapi.GetEnOrderResult, err error) { - jdmcshopapi := jdshopapi.New("f9c5ce9a5ce24218936924f7c4864cc9owe1", "E1D746D42474D5F1F1A10CECE75D99F6", "efa7e1d1a22640fa990e6cf164b28608") - result, err := jdmcshopapi.GetOrderById(utils.Str2Int64(vendorOrderID[0:12]), false) - if err != nil { - return nil, err - } - return result, err -} - -func GetJdsOrder2(vendorOrderID, vendorOrgCode string) (jdsOrder string, err error) { - params := make(map[string]interface{}) - params["orderID"] = vendorOrderID - params["token"] = jdshopapi.JdsYdToken - params["vendorOrgCode"] = vendorOrgCode - result, err := apiToYd("order/GetJdsOrder", params) - //jdsOrder2 := &jdshopapi.GetOrderResult{} - return strings.ReplaceAll(result["data"].(string), "\\", ""), err -} - -func (c *PurchaseHandler) GetSelfTakeCode(ctx *jxcontext.Context, order *model.GoodsOrder) (selfTakeCode string, err error) { - return selfTakeCode, err -} - -func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, order *model.GoodsOrder, selfTakeCode string) (err error) { - return err -} - -func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) { - return vendorOrderIDs, err -} - -func (c *PurchaseHandler) ComplaintRider(vendorOrderId string, resonID int, resonContent string) (err error) { - return err -} - -// 转自配送时取消非专送混合送门店取消理由 -func (c *PurchaseHandler) GetCancelDeliveryReason(order *model.GoodsOrder) (string, error) { - return "", nil -} - -// 取消美团外卖理由转使用三方配送 -func (c *PurchaseHandler) CancelLogisticsByWmOrderId(order *model.GoodsOrder, reasonCode, detailContent, appPoiCode, orderId string) error { - return nil -} - -// 获取订单配送状态 -func (c *PurchaseHandler) OrderLogisticsStatus(orderId int64) (int64, error) { - return 0, nil -} diff --git a/business/partner/purchase/gomei/order_afs.go b/business/partner/purchase/gomei/order_afs.go deleted file mode 100644 index 6e3344826..000000000 --- a/business/partner/purchase/gomei/order_afs.go +++ /dev/null @@ -1,138 +0,0 @@ -package gomei - -import ( - "crypto/md5" - "fmt" - "math" - "time" - - "git.rosy.net.cn/jx-callback/business/model/dao" - - "git.rosy.net.cn/baseapi/utils" - "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/globals" -) - -func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, afsOrder *model.AfsOrder, approveType int, reason string) (err error) { - var status int - if approveType == partner.AfsApproveTypeRefused { - status = model.AfsOrderStatusFailed - } else { - status = model.AfsOrderStatusFinished - - } - orderStatus := &model.OrderStatus{ - VendorOrderID: afsOrder.AfsOrderID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 - VendorID: afsOrder.VendorID, - OrderType: model.OrderTypeAfsOrder, - RefVendorOrderID: afsOrder.VendorOrderID, - RefVendorID: afsOrder.VendorID, - VendorStatus: utils.Int2Str(status), - Status: status, - StatusTime: time.Now(), - Remark: reason, - } - partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) - return err -} - -// 确认收到退货 -func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { - err = fmt.Errorf("京东商城当前不支持ConfirmReceivedReturnGoods") - return err -} - -// 发起全款退款 -func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - err = c.PartRefundOrder(ctx, order, order.Skus, reason) - return err -} - -// 发起部分退款 -func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { - globals.SugarLogger.Debugf("PartRefundOrder jdshop, order :%v", utils.Format4Output(order, true)) - var ( - skuMap = make(map[int]*model.OrderSku) - salePrice int64 - db = dao.GetDB() - ) - for _, sku := range order.Skus { - skuMap[sku.SkuID] = sku - } - orderStatus := buildOrderStatus(ctx, order, reason) - afsOrder := &model.AfsOrder{ - VendorID: order.VendorID, - AfsOrderID: orderStatus.VendorOrderID, - VendorOrderID: orderStatus.RefVendorOrderID, - // VendorStoreID: order.VendorStoreID, - // StoreID: jxutils.GetSaleStoreIDFromOrder(order), - AfsCreatedAt: time.Now(), - VendorAppealType: "", - AppealType: model.AfsAppealTypeRefund, - VendorReasonType: utils.Int2Str(model.AfsReasonNotOthers), - ReasonType: model.AfsReasonNotOthers, - ReasonDesc: utils.LimitUTF8StringLen(reason, 1024), - ReasonImgList: "", - RefundType: model.AfsTypePartRefund, - - VendorOrgCode: "", - } - for _, sku := range refundSkuList { - orderSku := &model.OrderSkuFinancial{ - Count: sku.Count, - VendorSkuID: utils.Int2Str(sku.SkuID), - SkuID: sku.SkuID, - } - storeSkus, _ := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, []int{sku.SkuID}) - if len(storeSkus) > 0 { - orderSku.VendorSkuID = utils.Int64ToStr(storeSkus[0].JdsID) - } - if skuMap[sku.SkuID] != nil { - orderSku.Name = skuMap[sku.SkuID].SkuName - orderSku.UserMoney = skuMap[sku.SkuID].SalePrice * int64(sku.Count) - salePrice += skuMap[sku.SkuID].SalePrice * int64(sku.Count) - } - afsOrder.SkuUserMoney += orderSku.UserMoney - afsOrder.Skus = append(afsOrder.Skus, orderSku) - } - err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) - return err -} - -func buildOrderStatus(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (orderStatus *model.OrderStatus) { - orderStatus = &model.OrderStatus{ - VendorOrderID: utils.Int64ToStr(GenAfsOrderNo(ctx)), // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 - VendorID: order.VendorID, - OrderType: model.OrderTypeAfsOrder, - RefVendorOrderID: order.VendorOrderID, - RefVendorID: order.VendorID, - VendorStatus: utils.Int2Str(model.AfsOrderStatusWait4Approve), - Status: model.AfsOrderStatusWait4Approve, - StatusTime: time.Now(), - Remark: reason, - } - orderStatus.Status = model.AfsOrderStatusWait4Approve - return orderStatus -} - -func GenAfsOrderNo(ctx *jxcontext.Context) (orderNo int64) { - const prefix = 70 - const randPartNum = 100 - orderNoBeginTimestamp := utils.Str2Time("2010-01-01 00:00:00").Unix() - orderNo = time.Now().Unix() - orderNoBeginTimestamp - orderNo = orderNo * randPartNum - md5Bytes := md5.Sum([]byte(utils.GetUUID())) - randPart := 0 - for k, v := range md5Bytes { - randPart += int(v) << ((k % 3) * 8) - } - orderNo += int64(randPart % randPartNum) - orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix - return orderNo -} - -func (c *PurchaseHandler) GetOrderAfsInfo(ctx *jxcontext.Context, vendorOrderID, afsOrderID string) (orderAfsInfo *partner.OrderAfsInfo, err error) { - return &partner.OrderAfsInfo{}, err -} diff --git a/business/partner/purchase/gomei/order_comment.go b/business/partner/purchase/gomei/order_comment.go deleted file mode 100644 index 906073b16..000000000 --- a/business/partner/purchase/gomei/order_comment.go +++ /dev/null @@ -1,5 +0,0 @@ -package gomei - -func (c *PurchaseHandler) StartRefreshComment() { - -} diff --git a/business/partner/purchase/gomei/store.go b/business/partner/purchase/gomei/store.go deleted file mode 100644 index c56ee622a..000000000 --- a/business/partner/purchase/gomei/store.go +++ /dev/null @@ -1,87 +0,0 @@ -package gomei - -import ( - "fmt" - gomei "git.rosy.net.cn/baseapi/platformapi/gome_live_show" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - "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/model/dao" - "git.rosy.net.cn/jx-callback/globals/api" -) - -func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorStoreName string) (storeDetail *dao.StoreDetail, err error) { - if vendorStoreName != "" { - result2, _ := api.GuoMeiApi.QueryStoreList(&gomei.GetStoreListReq{ - StoreName: vendorStoreName, - }) - if len(result2.Data.Records) != model.YES { - return storeDetail, fmt.Errorf("国美未查询到该平台门店,平台门店ID:[%v]", vendorStoreID) - } - storeDetail = &dao.StoreDetail{} - storeDetail.Name = result2.Data.Records[0].StoreName - storeDetail.Lat = jxutils.StandardCoordinate2Int(utils.Str2Float64("0.000")) - storeDetail.Lng = jxutils.StandardCoordinate2Int(utils.Str2Float64("0.000")) - } - return storeDetail, err -} - -// stoerIDs为nil表示所有 -func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { - return nil -} - -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { - return "", err -} - -func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) { - return err -} - -func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { - return hint, err -} - -func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) { - return storeStatus, err -} - -func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) { - return err -} - -func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) { - err = api.JdShopAPI.UpdateStatus(utils.Str2Int(vendorStoreID), jxStatus2JdsStatus(status)) - return err -} - -func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) { - return err -} - -func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) { - return vendorStoreIDs, err -} - -func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) { - return err -} - -func jxStatus2JdsStatus(status int) (result int) { - if status == model.StoreStatusOpened { - result = jdshopapi.JdsStoreStatusOnline - } else if status == model.StoreStatusHaveRest || status == model.StoreStatusClosed { - result = jdshopapi.JdsStoreStatusRest - } else { - result = jdshopapi.JdsStoreStatusDisable - } - return result -} - -func (c *PurchaseHandler) UpdateStoreLineStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, lineStatus int) (err error) { - return err -} diff --git a/business/partner/purchase/gomei/store_sku.go b/business/partner/purchase/gomei/store_sku.go deleted file mode 100644 index 40d595241..000000000 --- a/business/partner/purchase/gomei/store_sku.go +++ /dev/null @@ -1,911 +0,0 @@ -package gomei - -import "regexp" - -// -//import ( -// "fmt" -// gomei "git.rosy.net.cn/baseapi/platformapi/gome_live_show" -// "regexp" -// "strings" -// "time" -// -// "git.rosy.net.cn/baseapi/platformapi/jdshopapi" -// -// "git.rosy.net.cn/jx-callback/globals/api" -// -// "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" -// "git.rosy.net.cn/jx-callback/business/partner" -// "git.rosy.net.cn/jx-callback/business/partner/putils" -// "git.rosy.net.cn/jx-callback/globals" -//) -// -const ( - deleteErr1 = "已经删除的不能直接下架" - deleteErr2 = "SKU" - deleteErr3 = "已删除" -) - -var ( - sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`) -) - -//func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { -// if globals.EnableJdShopWrite { -// if vendorStoreID == model.GoMeiShopMainVendorStoreID { -// for _, v := range storeSkuList { -// //判断京东商城上是否有这个商品了,如果有就是添加规格而不是创建商品 -// //如果是京东商城2,是下架的商品,弄上架 ,先改为有下架的不管,重新建 -// name := filterSensitiveWord(v.Name) -// flag := false -// result, err := getAPI(v.VendorOrgCode).SearchWare4Valid(name, 1, 100) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") -// return failedList, err -// } -// for _, v := range result.Data { -// if v.Title == name { -// flag = true -// //下架 -// if v.WareStatus == 2 || v.WareStatus == 1028 { -// flag = false -// //wareStatusUpdateWareID = utils.Int64ToStr(v.WareID) -// } -// break -// } -// } -// if flag { -// wareSaveParam := &jdshopapi.WareSaveParam{ -// WareID: result.Data[0].WareID, -// Title: v.Name, -// CategoryID: int(v.VendorVendorCatID), -// VenderID: jdshopapi.VendorID2, -// Length: 200, -// Wide: 100, -// Height: 100, -// Weight: "1", -// BrandID: jdshopapi.BrandIdNO, -// ShopCategorys: []int{utils.Str2Int(v.VendorCatID)}, -// PromiseID: -1, -// MultiCateProps: []interface{}{}, -// PropsSet: []interface{}{}, -// SaleAttrs: []interface{}{}, -// WareStatus: 8, -// } -// var wareSaveSkus []*jdshopapi.WareSaveSkus -// //先把已有的规格放进去 -// wareResult, _ := getAPI(v.VendorOrgCode).FindWareById(wareSaveParam.WareID) -// if wareResult != nil { -// for _, v := range wareResult.Images { -// wareSaveParam.ImageMap.Num0000000000 = append(wareSaveParam.ImageMap.Num0000000000, &jdshopapi.CreateSkuParamImages{ -// ColorID: v.ColorID, -// ImgURL: v.ImgURL, -// ImgIndex: v.ImgIndex, -// }) -// } -// } -// skus, _, _ := getAPI(v.VendorOrgCode).SearchSkuList2([]int{int(wareSaveParam.WareID)}) -// if len(skus) > 0 { -// for _, vv := range skus { -// sku := &jdshopapi.WareSaveSkus{ -// SkuID: vv.SkuID, -// JdPrice: utils.Float64ToStr(vv.JdPrice), -// StockNum: vv.StockNum, -// Props: []*jdshopapi.WareSaveSkusProp{ -// &jdshopapi.WareSaveSkusProp{ -// AttrID: utils.Str2Int(vv.SaleAttrs[0].AttrID), -// AttrValues: utils.Str2Int64(vv.SaleAttrs[0].AttrValues[0]), -// AttrValueAlias: vv.SaleAttrs[0].AttrValueAlias[0], -// }, -// }, -// OuterID: vv.OuterID, -// } -// wareSaveSkus = append(wareSaveSkus, sku) -// } -// } -// // } -// for _, vv := range v.StoreSkuSyncInfoJds { -// v.JdsWareID = result.Data[0].WareID -// vv.JdsWareID = result.Data[0].WareID -// _, wareSaveSku, err := buildUpdateSkusParam(v, vv, true) -// wareSaveSkus = append(wareSaveSkus, wareSaveSku) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") -// return failedList, err -// } -// -// wareSaveParam.Skus = wareSaveSkus -// if wareResult, err2 := getAPI(v.VendorOrgCode).WareSave(wareSaveParam); err2 == nil { -// for _, vvv := range wareResult { -// if vvv.OuterID == wareSaveSku.OuterID { -// vv.VendorSkuID = utils.Int64ToStr(vvv.SkuID) -// break -// } -// } -// //创建商品后要上架,改价,库存,门店关注商品等 -// if err = getAPI(v.VendorOrgCode).WareDoUpdate("up", utils.Int64ToStr(wareSaveParam.WareID)); err == nil { -// err = getAPI(v.VendorOrgCode).StoreSkuBindStore(true, []string{vv.VendorSkuID}, nil) -// } -// } -// // } -// } -// } else { -// // 商品不存在,直接添加商品,添加分类,添加规格,门店关注上线 -// otherImg := make([]string, 0, 0) -// if v.Img2 != "" { -// otherImg = append(otherImg, v.Img2) -// } -// if v.Img3 != "" { -// otherImg = append(otherImg, v.Img3) -// } -// if v.Img4 != "" { -// otherImg = append(otherImg, v.Img4) -// } -// if v.Img5 != "" { -// otherImg = append(otherImg, v.Img5) -// } -// -// // 规格集合 -// spec := &gomei.SpecProperty{ -// SpecCode: v.VendorNameID, -// SpecName: v.Unit, -// SpecValues: nil, -// } -// specValuesList := make([]*gomei.SpecValues, 0, 0) -// for _, c := range v.StoreSkuSyncInfoJds { -// specValues := &gomei.SpecValues{ -// SpecValueCode: c.JdsStockSwitch, -// SpecValueName: fmt.Sprintf("%f", c.SpecQuality) + c.SpecUnit, -// } -// specValuesList = append(specValuesList, specValues) -// } -// spec.SpecValues = append(spec.SpecValues, specValuesList...) -// specProperty := append(make([]*gomei.SpecProperty, 0, 0), spec) -// -// api.GuoMeiApi.CreateMerchantGoodsOnStore(&gomei.CreateGoodsListToStore{ -// GoodsName: v.SkuName, -// MainPictureURL: v.Img, -// Detail: v.Name, -// Cat3Code: v.VendorCatID, -// SpecProperty: specProperty, // 规格集合 -// SkuSaleList: nil, // 售卖组 -// GoodsType: v.SkuVendorCatID, -// OtherPictureURL: otherImg, -// VideoURL: "", -// SpecCode: "", -// SpecName: "", -// SpecValues: "", -// SpecValueCode: "", -// SpecValueName: "", -// Specification: "", // 规格集合 -// MarketPrice: utils.Int64ToFloat64(v.Price), -// ThirdSkuCode: string(v.SkuID), -// }) -// _, _, wareSaveParam, err := buildCreateWareParam(v) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") -// return failedList, err -// } -// var ( -// wareID int64 -// resultAttrs = make(map[string]int64) -// ) -// var createSkuResult []*jdshopapi.WareSaveResult -// createSkuResult, err = getAPI(v.VendorOrgCode).WareSave(wareSaveParam) -// wareID = createSkuResult[0].WareID -// -// var paramAttrs = make(map[string]*jdshopapi.WareSaveSkus) -// for _, vv := range wareSaveParam.Skus { -// for _, vvv := range vv.Props { -// paramAttrs[vvv.AttrValueAlias] = vv -// } -// } -// for _, vv1 := range createSkuResult { -// for _, vvv1 := range vv1.Props { -// if paramAttrs[vvv1.AttrValueAlias] != nil { -// resultAttrs[paramAttrs[vvv1.AttrValueAlias].OuterID] = vv1.SkuID -// } -// } -// } -// for _, vv2 := range v.StoreSkuSyncInfoJds { -// vv2.JdsWareID = createSkuResult[0].WareID -// if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 { -// vv2.VendorSkuID = utils.Int64ToStr(resultAttrs[utils.Int2Str(vv2.SkuID)]) -// } -// } -// //创建商品后要上架,改价,库存,门店关注商品等 -// if err = getAPI(v.VendorOrgCode).WareDoUpdate("up", utils.Int64ToStr(wareID)); err == nil { -// for _, vv2 := range v.StoreSkuSyncInfoJds { -// if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 { -// err = getAPI(v.VendorOrgCode).StoreSkuBindStore(true, []string{utils.Int64ToStr(resultAttrs[utils.Int2Str(vv2.SkuID)])}, nil) -// } -// } -// } -// // } -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") -// return failedList, err -// } else { -// //追加商品透图 -// imageURL := "" -// img := v.Img -// if img != "" { -// suffix := img[strings.LastIndex(img, "."):] -// if suffix != ".png" { -// if resBinary, _, _ := jxutils.DownloadFileByURL(img + model.SkuNameImgToPng); err == nil { -// downloadURL, _ := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())) -// imageURL, _ = uploadImg(downloadURL, name, "tou", v.VendorOrgCode) -// } -// } else { -// imageURL, _ = uploadImg(img, name, "tou", v.VendorOrgCode) -// } -// } -// if v.VendorOrgCode == "1" { -// api.JdShopAPI.TransparentImageAdd(wareID, imageURL) -// } -// } -// } -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") -// return failedList, err -// } -// -// } -// } else { -// //如果是普通店关注商品 -// for _, v := range storeSkuList { -// for _, vv := range v.StoreSkuSyncInfoJds { -// storeSkus, _ := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.GoMeiShopMainStoreID}, []int{vv.SkuID}) -// if len(storeSkus) > 0 { -// for _, storeSku := range storeSkus { -// if storeSku.JdsID != 0 { -// status := vv.Status -// stock := vv.Stock -// price := vv.VendorPrice -// // 商品上架 -// if status == model.StoreSkuBindStatusNormal { -// _, err = getAPI(vv.VendorOrgCode).OnOffLineGoodsOnStore(&gomei.ShelfGoodsForStoreReq{ -// StoreCode: vendorStoreID, -// SkuCode: []string{storeSku.GmID}, -// ShelveStatus: gomei.PutOnTheShelf, -// }) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorGoMei], "国美商品已经存在,关注商品") -// return failedList, err -// } -// } -// // 修改库存 -// if stock != 0 { -// _, err = getAPI(vv.VendorOrgCode).UpdateStockForStore(&gomei.StoreGoodsStockUpdateReq{ -// StoreCode: vendorStoreID, -// ItemStocks: []*gomei.StoreSkuNum{{SkuCode: storeSku.GmID, StockNum: gomei.GoMeiMaxStock}}, -// }) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "国美修改商品库存") -// return failedList, err -// } -// } -// // 同步价格 -// _, err = getAPI(v.VendorOrgCode).UpdateOnGoodsPriceForStore(&gomei.StoreGoodsPriceUpdateReq{ -// StoreCode: vendorStoreID, -// SkuCode: storeSku.GmID, -// SalePrice: utils.Int64ToFloat64(price), -// }) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "国美关注商品价格同步") -// return failedList, err -// } -// } -// } -// } -// } -// } -// } -// } -// return failedList, err -//} -// -//func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { -// if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { -// if vendorStoreID == model.JdShopMainVendorStoreID { -// for _, v := range storeSkuList { -// name := filterSensitiveWord(v.Name) -// updateWareParam := &jdshopapi.UpdateWareParam{ -// WareID: v.JdsWareID, -// Title: name, -// VenderID: jdshopapi.VenderID, -// // PromiseID: jdshopapi.JdsPromiseID, -// ShopCategorys: []int{utils.Str2Int(v.VendorCatID)}, -// JdPrice: jxutils.IntPrice2Standard(v.UnitPrice), -// } -// if v.VendorVendorCatID != jdshopapi.JdsOtherMeatCatID { -// updateWareParam.PromiseID = jdshopapi.JdsPromiseID -// } -// var desc string -// if v.DescImg != "" { -// pic3, err2 := uploadImg2(v.DescImg, name, "desc", v.VendorOrgCode) -// err = err2 -// desc = `



` -// } else { -// desc = `



` -// } -// updateWareParam.Introduction = desc -// updateWareParam.MobileDesc = desc -// img := "" -// if v.ImgMix != "" { -// img = v.ImgMix -// } else { -// img = v.Img -// } -// if img != "" { -// pic1, err2 := uploadImg2(img, name, "1", v.VendorOrgCode) -// err = err2 -// err = getAPI(v.VendorOrgCode).ImageUpdate(v.JdsWareID, 1, pic1) -// if v.Img2 != "" { -// pic2, err2 := uploadImg2(v.Img2, name, "2", v.VendorOrgCode) -// err = err2 -// err = getAPI(v.VendorOrgCode).ImageUpdate(v.JdsWareID, 2, pic2) -// } else { -// err = getAPI(v.VendorOrgCode).ImageUpdate(v.JdsWareID, 2, pic1) -// } -// err = getAPI(v.VendorOrgCode).ImageUpdate(v.JdsWareID, 3, pic1) -// } -// var features = []*jdshopapi.CreateSkuParamFeatures{ -// &jdshopapi.CreateSkuParamFeatures{ -// Key: "is7ToReturn", //不支持7天无理由退货 -// Value: "0", -// }, -// &jdshopapi.CreateSkuParamFeatures{ -// Key: "tssp", //支持自提 -// Value: "", -// }, -// // &jdshopapi.CreateSkuParamFeatures{ -// // Key: "fdms", //分单? -// // Value: "1", -// // }, -// } -// updateWareParam.Features = features -// err = getAPI(v.VendorOrgCode).UpdateWare(updateWareParam) -// if err == nil { -// //追加商品透图 -// imageURL := "" -// img := v.Img -// if img != "" { -// suffix := img[strings.LastIndex(img, "."):] -// if suffix != ".png" { -// if resBinary, _, err := jxutils.DownloadFileByURL(img + model.SkuNameImgToPng); err == nil { -// downloadURL, err2 := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())) -// err = err2 -// imageURL, err = uploadImg(downloadURL, name, "tou", v.VendorOrgCode) -// } -// } else { -// imageURL, err = uploadImg(img, name, "tou", v.VendorOrgCode) -// } -// } -// if v.VendorOrgCode == "1" { -// api.JdShopAPI.TransparentImageAdd(v.JdsWareID, imageURL) -// } -// } -// for _, vv := range v.StoreSkuSyncInfoJds { -// updateSkusParam, _, err := buildUpdateSkusParam(v, vv, false) -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "更新商品基础信息") -// return failedList, err -// } -// _, err = getAPI(v.VendorOrgCode).UpdateSkus(updateSkusParam) -// } -// } -// } else { -// for _, v := range storeSkuList { -// var wareSaveSkus []*jdshopapi.WareSaveSkus -// name := filterSensitiveWord(v.Name) -// //jds2 -// wareSaveParam := &jdshopapi.WareSaveParam{ -// WareID: v.JdsWareID, -// Title: name, -// CategoryID: int(v.VendorVendorCatID), -// VenderID: jdshopapi.VendorID2, -// Length: 100, -// Wide: 100, -// Height: 100, -// Weight: utils.Int2Str(v.Weight), -// BrandID: jdshopapi.BrandIdNO, -// ShopCategorys: []int{utils.Str2Int(v.VendorCatID)}, -// PromiseID: -1, -// MultiCateProps: []interface{}{}, -// PropsSet: []interface{}{}, -// SaleAttrs: []interface{}{}, -// } -// var desc string -// if v.DescImg != "" { -// pic3, err2 := uploadImg2(v.DescImg, name, "desc", v.VendorOrgCode) -// err = err2 -// desc = `



` -// } else { -// desc = `



` -// } -// wareSaveParam.Notes = desc -// //上传京东图片 -// //规则,有两张就传两张,没有就重复传一张 -// pic1, _ := uploadImg(v.Img, name, "1", v.VendorOrgCode) -// img1 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 1, -// ImgURL: pic1, -// } -// img2 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 2, -// } -// if v.Img2 == "" { -// img2.ImgURL = pic1 -// } else { -// pic2, err2 := uploadImg(v.Img, name, "2", v.VendorOrgCode) -// err = err2 -// img2.ImgURL = pic2 -// } -// img3 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 3, -// ImgURL: pic1, -// } -// //jds2图片 -// wareSaveParam.ImageMap.Num0000000000 = append(wareSaveParam.ImageMap.Num0000000000, img1, img2, img3) -// for _, vv := range v.StoreSkuSyncInfoJds { -// _, wareSaveSku, err2 := buildUpdateSkusParam(v, vv, true) -// err = err2 -// wareSaveSku.SkuID = utils.Str2Int64(vv.VendorSkuID) -// wareSaveSkus = append(wareSaveSkus, wareSaveSku) -// } -// getAPI("2").WareSave(wareSaveParam) -// } -// } -// if err != nil { -// failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "更新商品基础信息") -// } -// } -// return failedList, err -//} -// -//func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInfo, vendorStoreId string, isCreate bool) (updateSkusParam *jdshopapi.UpdateSkusParam, wareSku *jdshopapi.WareSaveSkus, err error) { -// // 判断分类是否存在 -// storeCategoriesList, err := GetAllStoreCategories(string(model.VendorGoMei), vendorStoreId) -// if err != nil { -// return nil, nil, err -// } -// isHaveCategory := false -// for _, sc := range storeCategoriesList { -// if sc.CategoryCode == string(storeSku.VendorVendorCatID) { -// isHaveCategory = true -// break -// } -// } -// // 分类不存在则,创建分类 -// if !isHaveCategory { -// if _, err := api.GuoMeiApi.AddStoreCategory(&gomei.StoreAddGoodsCategory{ -// StoreCode: vendorStoreId, -// CategoryName: storeSku.CategoryName, -// Rank: 0, -// }); err != nil { -// return nil, nil, err -// } -// } -// -// // 规格组,规格设置(获取分类下的所有规格),线上规格 -// attrsList, err := GetAllSpecSizeList(&gomei.QueryGoodsSpecSizeReq{ -// Cat3Code: string(storeSku.VendorVendorCatID), -// SpecName: "", -// Page: gomei.Page{ -// PageNumber: gomei.PageNumber, -// PageSize: gomei.PageSize, -// }, -// }) -// if err != nil { -// return nil, nil, err -// } -// // 本地规格 -// var ggValueID string //规格的属性id -// var ggValueName string //规格名 -// // 判断本地规格和在线上是否存在 -// for _, goMeiSize := range attrsList { -// if goMeiSize.SpecName == v.Unit { -// ggValueID = goMeiSize.SpecCode -// ggValueName = goMeiSize.SpecName -// break -// } -// } -// if ggValueID == "" { -// // 规格不存在,创建规格,规格只有一个,规格属性有多个! -// specList := make([]*gomei.SpecValueName, 0, 0) -// for _, sl := range storeSku.StoreSkuSyncInfoJds { -// data1 := &gomei.SpecValueName{SpecValueName: utils.Float64ToStr(float64(sl.SpecQuality)) + sl.Unit} -// specList = append(specList, data1) -// } -// _, err = api.GuoMeiApi.CreateGoodsSpceList(&gomei.CreateSpecDetailParam{ -// SpecName: ggValueName, -// SpecValues: specList, // 多个规格属性 -// Cat3Code: string(storeSku.VendorVendorCatID), -// Remark: "", -// }) -// if err != nil { -// return nil, nil, err -// } -// } else { -// // 存在规格,判断里面,规格属性是否充足 -// -// } -// -//} -// -//func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *jdshopapi.CreateSkuParamWare, createSkuParamSkus []*jdshopapi.CreateSkuParamSkus, wareSaveParam *jdshopapi.WareSaveParam, err error) { -// var ( -// images []*jdshopapi.CreateSkuParamImages -// vendorCatID int -// ) -// if storeSku.VendorCatID == "0" { -// resultCat, _ := getAPI(storeSku.VendorOrgCode).FindShopCategories() // 查询商家所有店内分类 -// for _, v := range resultCat { -// if v.Name == storeSku.CategoryName { -// vendorCatID = int(v.CID) -// break -// } -// } -// } else { -// vendorCatID = utils.Str2Int(storeSku.VendorCatID) -// } -// -// name := filterSensitiveWord(storeSku.Name) -// wareSaveParam = &jdshopapi.WareSaveParam{ -// WareID: 0, -// Title: name, -// CategoryID: int(storeSku.VendorVendorCatID), -// LastCategoryID: int(storeSku.VendorVendorCatID), -// VenderID: jdshopapi.VendorID2, -// Length: 200, -// Wide: 100, -// Height: 100, -// Weight: "1", -// BrandID: jdshopapi.BrandIdNO, -// WareStatus: 8, //上架待审核,没用,建好了都要再上架一次 -// ShopCategorys: []int{vendorCatID}, -// PromiseID: 0, -// MultiCateProps: []interface{}{}, -// PropsSet: []interface{}{}, -// SaleAttrs: []interface{}{}, -// TransparentImageAudit: []interface{}{}, -// OptionType: 1, -// AvailableFeatures: []interface{}{}, -// CharacteristicService: []interface{}{}, -// ExtendFeatures: []interface{}{}, -// TempID: "10569615110055200", //必须要这个东西,不知道是啥 -// } -// createSkuParamWare = &jdshopapi.CreateSkuParamWare{ -// Title: name, -// ShopCategorys: []int{vendorCatID}, -// CategoryID: int(storeSku.VendorVendorCatID), -// BrandID: jdshopapi.JxBrandId, -// // TransportID: jdshopapi.TransportID, -// WareStatus: 8, //上架待审核 -// OuterID: utils.Int2Str(storeSku.NameID), -// // VenderID: jdshopapi.VenderID, -// Length: 100, -// Width: 100, -// Height: 100, -// Weight: 0.5, -// JdPrice: jxutils.IntPrice2Standard(storeSku.UnitPrice), -// // MarketPrice: jxutils.IntPrice2Standard(storeSku.UnitPrice), -// // PromiseID: jdshopapi.JdsPromiseID, -// } -// -// if storeSku.VendorOrgCode == "1" { -// createSkuParamWare.VenderID = jdshopapi.VenderID -// } -// -// if storeSku.VendorVendorCatID != jdshopapi.JdsOtherMeatCatID { -// createSkuParamWare.PromiseID = jdshopapi.JdsPromiseID -// } -// -// if storeSku.VendorVendorCatID == jdshopapi.JdsBeefCatID { -// createSkuParamWare.MultiCategoryID = jdshopapi.JdsBeefLastCatID -// } -// -// //上传京东图片 -// //规则,有两张就传两张,没有就重复传一张 -// pic1, err := uploadImg(storeSku.Img, name, "1", storeSku.VendorOrgCode) -// img1 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 1, -// ImgURL: pic1, -// } -// img2 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 2, -// } -// if storeSku.Img2 == "" { -// img2.ImgURL = pic1 -// } else { -// pic2, err2 := uploadImg(storeSku.Img, name, "2", storeSku.VendorOrgCode) -// err = err2 -// img2.ImgURL = pic2 -// } -// img3 := &jdshopapi.CreateSkuParamImages{ -// ColorID: "0000000000", -// ImgIndex: 3, -// ImgURL: pic1, -// } -// images = append(images, img1) -// images = append(images, img2) -// images = append(images, img3) -// createSkuParamWare.Images = images -// //jds2图片 -// // img4 := img1 -// // img4.ImgZoneID = "0000000000" -// // img5 := img2 -// // img5.ImgZoneID = "0000000000" -// // img6 := img3 -// // img6.ImgZoneID = "0000000000" -// wareSaveParam.ImageMap.Num0000000000 = append(wareSaveParam.ImageMap.Num0000000000, img1, img2, img3) -// -// //商品详情拼接 -// var desc string -// if storeSku.DescImg != "" { -// pic3, err2 := uploadImg(storeSku.DescImg, name, "desc", storeSku.VendorOrgCode) -// err = err2 -// desc = `



` -// } else { -// desc = `



` -// } -// createSkuParamWare.MobileDesc = desc -// createSkuParamWare.Introduction = desc -// wareSaveParam.Notes = desc -// -// //设置商品属性值 -// var ( -// attrIDs = make(map[string]int) //贮存方式,净含量,保质期IDs -// zctjValueID int64 //贮存条件冷藏0-4的id -// gcjkValueID int64 //国产,进口的id -// lbValueID int64 //类别的ID -// bcztValueID int64 //保存状态ID -// rmsjValueID int64 //热卖时间ID -// attrsProp []*jdshopapi.CreateSkuParamAttrs -// ) -// attrs, err := getAPI(storeSku.VendorOrgCode).FindAttrs(int(storeSku.VendorVendorCatID)) -// for _, v := range attrs { -// if v.Name == "保质期" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "贮存条件" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "净含量" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "规格" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "国产/进口" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "类别" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "保存状态" { -// attrIDs[v.Name] = v.ID -// } else if v.Name == "热卖时间" { -// attrIDs[v.Name] = v.ID -// } -// } -// values, _, err := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["贮存条件"]) -// for _, v := range values { -// if v.Name == "冷藏 0-4℃" { -// zctjValueID = v.ID -// } -// } -// if attrIDs["国产/进口"] != 0 { -// values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["国产/进口"]) -// err = err2 -// for _, v := range values2 { -// if v.Name == "国产" { -// gcjkValueID = v.ID -// } -// } -// attrgcjk := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["国产/进口"]), -// AttrValues: []string{utils.Int64ToStr(gcjkValueID)}, -// } -// attrsProp = append(attrsProp, attrgcjk) -// } -// if attrIDs["保存状态"] != 0 { -// values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["保存状态"]) -// err = err2 -// for _, v := range values2 { -// if v.Name == "冷藏" || v.Name == "活鲜" { -// bcztValueID = v.ID -// } -// } -// attrbczt := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["保存状态"]), -// AttrValues: []string{utils.Int64ToStr(bcztValueID)}, -// } -// attrsProp = append(attrsProp, attrbczt) -// } -// if attrIDs["热卖时间"] != 0 { -// values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["热卖时间"]) -// err = err2 -// for _, v := range values2 { -// if v.Name == "12月" { -// rmsjValueID = v.ID -// } -// } -// attrrmsj := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["热卖时间"]), -// AttrValues: []string{utils.Int64ToStr(rmsjValueID)}, -// } -// attrsProp = append(attrsProp, attrrmsj) -// } -// //牛肉创建不一样 -// if storeSku.VendorVendorCatID == jdshopapi.JdsBeefCatID { -// var exValueID int64 -// values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(150390) -// err = err2 -// for _, v := range values2 { -// if v.Name == "其它" { -// exValueID = v.ID -// } -// } -// attrex := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(150390), -// AttrValues: []string{utils.Int64ToStr(exValueID)}, -// } -// attrsProp = append(attrsProp, attrex) -// wareSaveParam.LastCategoryID = 17902 -// } -// attrZctj := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["贮存条件"]), -// AttrValues: []string{utils.Int64ToStr(zctjValueID)}, -// } -// attrJhl := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["净含量"]), -// AttrValues: []string{"0.5"}, -// } -// attrBzq := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["保质期"]), -// AttrValues: []string{"5"}, -// } -// attrsProp = append(attrsProp, attrZctj) -// attrsProp = append(attrsProp, attrJhl) -// attrsProp = append(attrsProp, attrBzq) -// createSkuParamWare.MultiCateProps = attrsProp -// var features = []*jdshopapi.CreateSkuParamFeatures{ -// &jdshopapi.CreateSkuParamFeatures{ -// Key: "is7ToReturn", //不支持7天无理由退货 -// Value: "0", -// }, -// // &jdshopapi.CreateSkuParamFeatures{ -// // Key: "tssp", //支持自提 -// // Value: "", -// // }, -// // &jdshopapi.CreateSkuParamFeatures{ -// // Key: "fdms", //分单? -// // Value: "1", -// // }, -// } -// createSkuParamWare.Features = features -// //组合sku -// var ( -// vendorPrice int64 = 0 -// wareSaveSkus []*jdshopapi.WareSaveSkus -// ) -// -// for _, v := range storeSku.StoreSkuSyncInfoJds { -// var ( -// ggValueID int64 //规格的属性id -// ggValueName string //规格的属性名 -// attrsPropSku []*jdshopapi.CreateSkuParamAttrs -// attrsPropSku2 []*jdshopapi.WareSaveSkusProp //jds2 -// multiPropSku []*jdshopapi.CreateSkuParamAttrs -// specQuality string -// ) -// valuesSku, maxNo, _ := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["规格"]) -// if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] { -// specQuality = strings.TrimRight(fmt.Sprintf("%.2f", float64(v.SpecQuality)), "0.") + v.SpecUnit -// } else { -// specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit -// } -// if v.Comment != "" { -// specQuality = v.Comment -// } -// for _, v := range valuesSku { -// if v.Name == specQuality { -// ggValueID = v.ID -// ggValueName = v.Name -// } -// } -// if ggValueID == 0 { //说明没有建这个规格,要建上 -// catID, _ := getAPI(storeSku.VendorOrgCode).SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1) -// ggValueID = catID -// ggValueName = specQuality -// } -// //jds1 -// attrSku := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["规格"]), -// AttrValues: []string{utils.Int64ToStr(ggValueID)}, -// } -// attrsPropSku = append(attrsPropSku, attrSku) -// //jds2 -// attrSku2 := &jdshopapi.WareSaveSkusProp{ -// AttrID: attrIDs["规格"], -// AttrValues: ggValueID, -// AttrValueAlias: ggValueName, -// } -// attrsPropSku2 = append(attrsPropSku2, attrSku2) -// -// //jds1 -// sku := &jdshopapi.CreateSkuParamSkus{ -// JdPrice: jxutils.IntPrice2Standard(v.VendorPrice), -// // StockNum: 9999, -// Type: "com.jd.pop.ware.ic.api.domain.sku", -// Type2: "com.jd.pop.ware.ic.api.domain.Sku", -// OuterID: utils.Int2Str(v.SkuID), -// } -// sku.SaleAttrs = attrsPropSku -// //jds2 -// sku2 := &jdshopapi.WareSaveSkus{ -// JdPrice: utils.Float64ToStr(jxutils.IntPrice2Standard(v.VendorPrice)), -// OuterID: utils.Int2Str(v.SkuID), -// } -// sku2.Props = attrsPropSku2 -// -// if attrIDs["类别"] != 0 { -// values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["类别"]) -// err = err2 -// lbValueID = values2[len(values2)-1].ID -// attrlb := &jdshopapi.CreateSkuParamAttrs{ -// AttrID: utils.Int2Str(attrIDs["类别"]), -// AttrValues: []string{utils.Int64ToStr(lbValueID)}, -// } -// multiPropSku = append(multiPropSku, attrlb) -// } -// sku.MultiCateProps = multiPropSku -// createSkuParamSkus = append(createSkuParamSkus, sku) -// -// if v.VendorPrice > vendorPrice { -// vendorPrice = v.VendorPrice -// } -// if v.Status == model.SkuStatusNormal { -// sku.StockNum = 9999 -// sku2.StockNum = 9999 -// } else { -// sku.StockNum = 0 -// sku2.StockNum = 0 -// } -// wareSaveSkus = append(wareSaveSkus, sku2) -// } -// //市场价固定500 -// createSkuParamWare.MarketPrice = 500 -// wareSaveParam.Skus = wareSaveSkus -// return createSkuParamWare, createSkuParamSkus, wareSaveParam, err -//} -// -//// 国美获取线上所有规格列表 -//func GetAllSpecSizeList(param *gomei.QueryGoodsSpecSizeReq) ([]*gomei.QueryGoodsSpecSizeRecords, error) { -// attrs, err := api.GuoMeiApi.QueryGoodsSizeList(param) -// if err != nil { -// return nil, err -// } -// -// goMeiSizeList := make([]*gomei.QueryGoodsSpecSizeRecords, 0, 0) -// for i := 1; i <= attrs.Data.PageTotal; i++ { -// attrs, err := api.GuoMeiApi.QueryGoodsSizeList(&gomei.QueryGoodsSpecSizeReq{ -// Cat3Code: param.Cat3Code, -// SpecName: "", -// Page: gomei.Page{ -// PageNumber: i, -// PageSize: gomei.PageSize, -// }, -// }) -// if err != nil { -// return nil, err -// } -// goMeiSizeList = append(goMeiSizeList, attrs.Data.Records...) -// } -// return goMeiSizeList, nil -//} diff --git a/business/partner/purchase/gomei/store_sku_other.go b/business/partner/purchase/gomei/store_sku_other.go deleted file mode 100644 index d15c39c4f..000000000 --- a/business/partner/purchase/gomei/store_sku_other.go +++ /dev/null @@ -1,393 +0,0 @@ -package gomei - -import ( - "encoding/base64" - "fmt" - gomei "git.rosy.net.cn/baseapi/platformapi/gome_live_show" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - "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/model/dao" - "git.rosy.net.cn/jx-callback/business/partner" - "git.rosy.net.cn/jx-callback/business/partner/putils" - "git.rosy.net.cn/jx-callback/globals" - "regexp" - "strings" - "time" -) - -// 删除不在使用商品(下架之后在删除) ok -func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.GoMeiShopMainVendorStoreID { - for _, v := range storeSkuList { - if v.IsDeletedBySku && storeID != 0 { // 如果门店id存在,则将该门店商品下架,所有门店该商品处于下架才可以删除! - _, err = getAPI(v.VendorOrgCode).OnOffLineGoodsOnStore(&gomei.ShelfGoodsForStoreReq{ - StoreCode: vendorStoreID, - SkuCode: []string{v.VendorSkuID}, - ShelveStatus: gomei.DownOnTheShelf, - }) - } - if err == nil { - _, err = getAPI(v.VendorOrgCode).DeleteGoodsOnStore(v.VendorSkuID) - } - if err != nil { - failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorGoMei], "删除商品")...) - } - } - } - return failedList, err -} - - - -// 获取门店商品列表 -func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) { - var ( - pageNo = 1 - pageSize = 50 - ) - result, err := getAPI(string(model.VendorGoMei)).QueryGoodsListById(&gomei.QueryGoodsListForStoreReq{ - Page: gomei.Page{ - PageNumber: pageNo, - PageSize: pageSize, - }, - }) - if err != nil { - return nil, err - } - - for ; pageNo <= result.Data.Total/pageSize+1; pageNo++ { - result2, err := getAPI(string(model.VendorGoMei)).QueryGoodsListById(&gomei.QueryGoodsListForStoreReq{ - Page: gomei.Page{ - PageNumber: pageNo, - PageSize: pageSize, - }, - }) - if err != nil { - return nil, err - } - - for _, v := range result2.Data.Records { - if skuName := vendorSku2Jx2(v); skuName != nil { - skuNameList = append(skuNameList, skuName) - } - } - } - - return skuNameList, err -} - -// 修改门店商品状态 -func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite { - for _, v := range storeSkuList { - if vendorSkuID, err := getMainStoreVendorSkuID(model.GoMeiShopMainStoreID, v.SkuID); err == nil && vendorSkuID != "" { - storeSku := &gomei.ShelfGoodsForStoreReq{ - StoreCode: vendorStoreID, - SkuCode: []string{vendorSkuID}, - } - if status == 0 { - storeSku.ShelveStatus = gomei.PutOnTheShelf - } else { - storeSku.ShelveStatus = gomei.DownOnTheShelf - } - _, err = getAPI(v.VendorOrgCode).OnOffLineGoodsOnStore(storeSku) - } - } - if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorGoMei], "修改商品库存") - } - } - return failedList, err -} - -// 修改门店商品价格维护 -func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite { - for _, v := range storeSkuList { - if vendorSkuID, err := getMainStoreVendorSkuID(model.GoMeiShopMainStoreID, v.SkuID); err == nil && vendorSkuID != "" { - _, err = getAPI(v.VendorOrgCode).UpdateOnGoodsPriceForStore(&gomei.StoreGoodsPriceUpdateReq{ - StoreCode: vendorStoreID, - SkuCode: vendorSkuID, - SalePrice: utils.Int64ToFloat64(v.VendorPrice), - }) - } - if err != nil { - failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品价格")...) - } - } - } - return failedList, err -} - -// 门店商品库存维护 -func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite { - for _, v := range storeSkuList { - if vendorSkuID, err := getMainStoreVendorSkuID(model.GoMeiShopMainStoreID, v.SkuID); err == nil && vendorSkuID != "" { - _, err = getAPI(v.VendorOrgCode).UpdateStockForStore(&gomei.StoreGoodsStockUpdateReq{ - StoreCode: vendorStoreID, - ItemStocks: []*gomei.StoreSkuNum{ - {SkuCode: vendorSkuID, StockNum: int64(v.Stock)}, - }, - }) - } - } - if err != nil { - failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品库存")...) - } - } - return failedList, err -} - -// 获取门店所有的分类 -func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { - var ( - pageNo = 1 - pageSize = 50 - ) - result, err := getAPI(string(model.VendorGoMei)).QueryStoreCategoryList(&gomei.QueryStoreGoodsCategoryListReq{ - Page: gomei.Page{ - PageNumber: pageNo, - PageSize: pageSize, - }, - StoreCode: vendorStoreID, - }) - for ; pageNo <= result.Data.Total/pageSize+1; pageNo++ { - result2, err := getAPI(string(model.VendorGoMei)).QueryStoreCategoryList(&gomei.QueryStoreGoodsCategoryListReq{ - Page: gomei.Page{ - PageNumber: pageNo, - PageSize: pageSize, - }, - StoreCode: vendorStoreID, - }) - if err != nil { - return nil, err - } - - for _, v := range result2.Data.Records { - var cat = &partner.BareCategoryInfo{ - VendorCatID: v.CategoryCode, - Name: v.CategoryName, - } - cat.Level = 1 - cats = append(cats, cat) - } - } - - return cats, err -} - -// 修改或者更新门店分类信息 -func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - if globals.EnableJdShopWrite { - _, status, err2 := updateOrCreateCategories(storeCat, vendorStoreID, false) - err = err2 - if status == -1 { - return fmt.Errorf("京东商城店内分类更新失败!") - } - } - return err -} - -func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - if globals.EnableJdShopWrite { - allCategoryList, status, err2 := updateOrCreateCategories(storeCat, vendorStoreID, true) - err = err2 - if status == -1 { - return fmt.Errorf("国美商城店内分类创建失败!") - } - if err != nil { - return err - } - time.Sleep(time.Second * 2) - - for _, v := range allCategoryList { - if v.CategoryName == storeCat.Name { - storeCat.VendorCatID = v.CategoryCode - break - } - } - if storeCat.VendorCatID == "" { - return fmt.Errorf("国美商城店内分类创建可能失败了!storeID: %v", storeID) - } - } - return err -} - -func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { - if globals.EnableJdShopWrite { - _, err = getAPI(string(model.VendorGoMei)).DeleteStoreGoodsCategory(vendorStoreID, vendorCatID) - } - return err -} - -func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) { - return false -} - -func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { - return false -} - -func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { - return false -} - -func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { - return 1 -} - -func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { - return sensitiveWordRegexp -} - -func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { - if strings.Contains(err.Error(), deleteErr1) || (strings.Contains(err.Error(), deleteErr2) && strings.Contains(err.Error(), deleteErr3)) { - return true - } - return false -} - -func GetAllStoreCategories(vendorOrgCode, vendorStoreId string) ([]*gomei.StoreGoodsCategoryListRecord, error) { - var ( - pageNo = 1 - pageSize = 50 - ) - - result, err := getAPI(vendorOrgCode).QueryStoreCategoryList(&gomei.QueryStoreGoodsCategoryListReq{ - Page: gomei.Page{ - PageSize: pageSize, - PageNumber: pageNo, - }, - StoreCode: vendorStoreId, - }) - if err != nil { - return nil, err - } - createShopCategoryParams := make([]*gomei.StoreGoodsCategoryListRecord, 0, 0) - for ; pageNo <= result.Data.Total/pageSize+1; pageNo++ { - result2, err := getAPI(vendorOrgCode).QueryStoreCategoryList(&gomei.QueryStoreGoodsCategoryListReq{ - Page: gomei.Page{ - PageNumber: pageNo, - PageSize: pageSize, - }, - StoreCode: vendorStoreId, - }) - if err != nil { - return nil, err - } - - for _, v := range result2.Data.Records { - createShopCategoryParams = append(createShopCategoryParams, &gomei.StoreGoodsCategoryListRecord{ - CategoryCode: v.CategoryCode, - CategoryName: v.CategoryName, - Rank: v.Rank, - }) - } - } - - return createShopCategoryParams, nil -} - -// 创建或者修改分类 -func updateOrCreateCategories(storeCat *dao.SkuStoreCatInfo, vendorStoreId string, isCreate bool) (createShopCategoryParams []*gomei.StoreGoodsCategoryListRecord, status int64, err error) { - createShopCategoryParams, err = GetAllStoreCategories(storeCat.VendorOrgCode, vendorStoreId) - if err != nil { - return nil, -1, err - } - - if isCreate { // 创建分类 - _, err = getAPI(storeCat.VendorOrgCode).AddStoreCategory(&gomei.StoreAddGoodsCategory{ - StoreCode: vendorStoreId, - CategoryName: storeCat.VendorCategoryName, // storeCat.StoreCatName - Rank: 0, - }) - if err != nil { - return nil, -1, err - } - } else { // 修改分类,无法新增和修改排序,排序结构需要在国美系统上获取 - // 查询当前分类 - for _, v := range createShopCategoryParams { - if v.CategoryCode != storeCat.VendorCatID { - continue - } - _, err = getAPI(storeCat.VendorOrgCode).ModifyStoreGoodsCategory(&gomei.StoreModifyGoodsCategory{ - StoreCode: vendorStoreId, - CategoryCode: storeCat.VendorCatID, // storeCat.StoreCatName - CategoryName: storeCat.VendorCategoryName, // storeCat.StoreCatName - Rank: v.Rank, - }) - if err != nil { - return nil, -1, err - } - } - } - return -} - -// 将平台商品信息转化为本地商品信息 -func vendorSku2Jx2(result *gomei.QueryGoodsListForStoreRecordRes) (skuName *partner.SkuNameInfo) { - if result == nil { - globals.SugarLogger.Warnf("vendorSku2Jx, strange result:%s", utils.Format4Output(result, true)) - return nil - } - skuName = &partner.SkuNameInfo{ - Name: result.GoodsName, - SkuList: []*partner.SkuInfo{ - &partner.SkuInfo{ - StoreSkuInfo: partner.StoreSkuInfo{ - VendorSkuID: result.SkuCode, - Stock: result.StockNum, - VendorPrice: jxutils.StandardPrice2Int(result.SalePrice), - }, - }, - }, - } - - if result.ShelveStatus == gomei.PutOnTheShelf { - skuName.Status = 1 - } else { - skuName.Status = 0 - } - - return skuName -} - -// 获取当前门店第三方商品id -func getMainStoreVendorSkuID(mainStoreID int, skuID int) (vendorSkuID string, err error) { - var ( - db = dao.GetDB() - ) - storeSkus, err := dao.GetStoresSkusInfo(db, []int{mainStoreID}, []int{skuID}) - if len(storeSkus) > 0 { - //vendorSkuID = storeSkus[0].GmID - } - return vendorSkuID, err -} - -// 国美上传图片,转bese64字符串在上传,图片要求长宽和大小 -func uploadImg(img, name, index, vendorOrgCode string) (imgURL string, err error) { - data, _, err := jxutils.DownloadFileByURL(img) - if err != nil { - return "", err - } - // 获取图片地址 - uploadResult, err := getAPI(vendorOrgCode).UploadPicture(base64.StdEncoding.EncodeToString(data), 1, name+string(time.Now().Unix())) - if err != nil { - return "", err - } - return uploadResult.Data.Url, err -} - -func filterSensitiveWord(name string) (result string) { - for _, v := range jdshopapi.SensitiveWordMap { - if strings.Contains(name, v) { - return strings.ReplaceAll(name, v, "") - } - } - return name -} diff --git a/business/partner/purchase/tiktok_store/callback.go b/business/partner/purchase/tiktok_store/callback.go index 5c446f9d4..b7458f509 100644 --- a/business/partner/purchase/tiktok_store/callback.go +++ b/business/partner/purchase/tiktok_store/callback.go @@ -3,22 +3,24 @@ package tiktok_store import ( "git.rosy.net.cn/baseapi/platformapi/mtwmapi" tiktokShop "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" - "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" ) -// 美团回调接口 -func OnCallbackMsg(msg *tiktokShop.CreateOrderCallback) (resp *mtwmapi.CallbackResponse) { +// OnCallbackMsg 抖音 +func OnCallbackMsg(msg *tiktokShop.OrderCallback) (response *tiktokShop.CallbackResponse) { if CurPurchaseHandler != nil { - switch msg.Tag { - case tiktokShop.CallbackMsgTagId: - + if msg.Data != "" && len(msg.Body) > 0 { + jxutils.CallMsgHandler(func() { + response = CurPurchaseHandler.onOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(msg.MsgId, model.VendorIDDD)) } } return response } -func GetOrderIDFromMsg(msg *tiktokShop.CreateOrderCallback) string { - return utils.Int64ToStr(msg.Data.PId) +func GetOrderIDFromMsg(msg *mtwmapi.CallbackMsg) string { + return msg.FormData.Get(mtwmapi.KeyOrderID) } func GetVendorStoreIDFromMsg(msg *mtwmapi.CallbackMsg) string { diff --git a/business/partner/purchase/tiktok_store/financial_test.go b/business/partner/purchase/tiktok_store/financial_test.go new file mode 100644 index 000000000..b055fd09c --- /dev/null +++ b/business/partner/purchase/tiktok_store/financial_test.go @@ -0,0 +1,54 @@ +package tiktok_store + +import ( + "fmt" + "net/url" + "testing" + "time" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/partner" +) + +func TestOnFinancialMsg(t *testing.T) { + msg := &mtwmapi.CallbackMsg{ + Cmd: "orderRefund", + FormData: url.Values{}, + } + msg.FormData.Set("timestamp", utils.Int64ToStr(time.Now().Unix())) + msg.FormData.Set("order_id", "33762863167364867") + msg.FormData.Set("notify_type", "agree") + msg.FormData.Set("money", "23.56") + food := []map[string]interface{}{ + map[string]interface{}{ + "app_food_code": "123", + "food_name": "商品1", + "sku_id": "123", + "refund_price": 3.14, + "count": 2, + "box_num": 1, + "box_price": 1, + }, + map[string]interface{}{ + "app_food_code": "124", + "food_name": "商品2", + "sku_id": "124", + "refund_price": 3.15, + "count": 2, + "box_num": 1, + "box_price": 1, + }, + } + msg.FormData.Set("food", string(utils.MustMarshal(food))) + res := CurPurchaseHandler.onAfsOrderMsg(msg) + fmt.Println(res) +} + +func TestOnOrderDetail(t *testing.T) { + result := map[string]interface{}{ + "app_order_code": "", "app_poi_code": "2828472", "avg_send_time": 2410, "backup_recipient_phone": "[\"13164714130_7645\"]", "caution": " 【如遇缺货】: 缺货时电话与我沟通 收餐人隐私号 13049813276_5307,手机号 139****5027", "city_id": 440300, "ctime": 1555036346, "day_seq": 1, "delivery_time": 0, "detail": "[{\"app_food_code\":\"27262\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"红管鱿鱼约250g/份\",\"food_property\":\"\",\"price\":23.54,\"quantity\":1,\"sku_id\":\"27262\",\"spec\":\"250g\",\"unit\":\"份\"},{\"app_food_code\":\"24987\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"带皮猪梅花肉约250g/份\",\"food_property\":\"\",\"price\":15.84,\"quantity\":1,\"sku_id\":\"24987\",\"spec\":\"250g\",\"unit\":\"份\"},{\"app_food_code\":\"27179\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"[畅销]龙骨约250g/份\",\"food_property\":\"\",\"price\":18.59,\"quantity\":1,\"sku_id\":\"27179\",\"spec\":\"250g\",\"unit\":\"份\"}]", "dinners_number": 0, "expect_deliver_time": 0, "extras": "[{\"act_detail_id\":664795195,\"mt_charge\":0,\"poi_charge\":5,\"reduce_fee\":5,\"remark\":\"满46.0元减5.0元\",\"type\":2},{\"act_detail_id\":665051798,\"mt_charge\":0,\"poi_charge\":4,\"reduce_fee\":4,\"remark\":\"减配送费4.0元\",\"type\":25},{\"act_detail_id\":274839715,\"mt_charge\":0.5,\"poi_charge\":0,\"reduce_fee\":0.5,\"remark\":\"用户使用了支付红包减0.5元\",\"type\":9},{\"mt_charge\":0,\"poi_charge\":0,\"reduce_fee\":0,\"remark\":\"送30元商家代金券\",\"type\":100},{}]", "has_invoiced": 0, "invoice_title": "", "is_favorites": false, "is_poi_first_order": true, "is_pre": 0, "is_third_shipping": 0, "latitude": 22.530194, "logistics_code": "1001", "longitude": 114.08372, "order_id": 28284722536001020, "order_send_time": 1555036356, "original_price": 63.97, "package_bag_money": 0, "pay_type": 2, "pick_type": 0, "poi_receive_detail": "{\"actOrderChargeByMt\":[{\"comment\":\"活动款\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":50}],\"actOrderChargeByPoi\":[{\"comment\":\"满46.0元减5.0元\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":500},{\"comment\":\"减配送费4.0元\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":400}],\"foodShareFeeChargeByPoi\":490,\"logisticsFee\":600,\"onlinePayment\":5447,\"wmPoiReceiveCent\":4406}", "recipient_address": "汇港名苑 (南2区1005)@#广东省深圳市福田区滨河大道滨河大道3119号汇港名苑", "recipient_name": "颜(女士)", "recipient_phone": "13049813276_5307", "remark": "", "result": "ok", "shipper_phone": "", "shipping_fee": 6, "shipping_type": 0, "source_id": 3, "status": 2, "taxpayer_id": "", "total": 54.47, "utime": 1555036346, "wm_order_id_view": 28284722536001020, "wm_poi_address": "深圳市福田区南园街道南华社区滨河路2037号下小庙南区70栋101号滨河街市场", "wm_poi_id": 2828472, "wm_poi_name": "京西菜市(华强南店)", "wm_poi_phone": "13724313878", + } + err := new(PurchaseHandler).OnOrderDetail(result, partner.CreatedPeration) + fmt.Println(err) +} diff --git a/business/partner/purchase/tiktok_store/interface_call.go b/business/partner/purchase/tiktok_store/interface_call.go deleted file mode 100644 index c7e38bd05..000000000 --- a/business/partner/purchase/tiktok_store/interface_call.go +++ /dev/null @@ -1,267 +0,0 @@ -package tiktok_store - -import ( - "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/model/dao" - "git.rosy.net.cn/jx-callback/business/partner" - "regexp" - "time" -) - -func (c *PurchaseHandler) GetStoreSkusBatchSize(funcID int) int { return 0 } - -func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) { - return nil, err -} - -// 此接口要求实现为不限制批处理大小的 -func (c *PurchaseHandler) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) { - return nil, err -} -func (c *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} - -func (c *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { - return err -} -func (c *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (outSkuNameList []*partner.SkuNameInfo, err error) { - return nil, err -} -func (c *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - return nil, err -} -func (c *PurchaseHandler) DeleteStoreAllSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) { - return err -} -func (c *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) { return true } -func (c *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { return true } - -func (c *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { - return nil, err -} -func (c *PurchaseHandler) GetStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, catName string) (cat *partner.BareCategoryInfo, err error) { - return nil, err -} -func (c *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - return err -} -func (c *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - return err -} -func (c *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { - return err -} -func (c *PurchaseHandler) DeleteStoreAllCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, isContinueWhenError bool) (err error) { - return err -} - -func (c *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { return true } -func (c *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { return true } - -func (c *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { return nil } - -func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetCancelDeliveryReason(order *model.GoodsOrder) (string, error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) CancelLogisticsByWmOrderId(order *model.GoodsOrder, reasonCode, detailContent, appPoiCode, orderId string) error { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) OrderLogisticsStatus(orderId int64) (int64, error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetSelfTakeCode(ctx *jxcontext.Context, order *model.GoodsOrder) (code string, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, order *model.GoodsOrder, selfTakeCode string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetOrderAfsInfo(ctx *jxcontext.Context, vendorOrderID, afsOrderID string) (orderAfsInfo *partner.OrderAfsInfo, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ComplaintRider(vendorOrderId string, resonID int, resonContent string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetOrderRider(vendorOrgCode, vendorStoreID string, param map[string]interface{}) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorStoreName string) (store *dao.StoreDetail, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { - //TODO implement me - panic("implement me") -} - -func (c *PurchaseHandler) UpdateStoreLineStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, lineStatus int) (err error) { - //TODO implement me - panic("implement me") -} diff --git a/business/partner/purchase/tiktok_store/tiktok.go b/business/partner/purchase/tiktok_store/mtwm.go similarity index 99% rename from business/partner/purchase/tiktok_store/tiktok.go rename to business/partner/purchase/tiktok_store/mtwm.go index 0c5167b7b..08eefc605 100644 --- a/business/partner/purchase/tiktok_store/tiktok.go +++ b/business/partner/purchase/tiktok_store/mtwm.go @@ -44,7 +44,7 @@ func New() (obj *PurchaseHandler) { } func (c *PurchaseHandler) GetVendorID() int { - return model.VendorIDDD + return model.VendorIDMTWM } func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) { diff --git a/business/partner/purchase/tiktok_store/mtwm_test.go b/business/partner/purchase/tiktok_store/mtwm_test.go new file mode 100644 index 000000000..2eb215723 --- /dev/null +++ b/business/partner/purchase/tiktok_store/mtwm_test.go @@ -0,0 +1,50 @@ +package tiktok_store + +//import ( +// "git.rosy.net.cn/jx-callback/business/model" +// "git.rosy.net.cn/jx-callback/business/model/dao" +// "testing" +// "time" +// +// "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" +// +// "git.rosy.net.cn/baseapi/utils" +// _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" +// "git.rosy.net.cn/jx-callback/globals/testinit" +//) +// +//const ( +// testShopVendorID = "2523687" +// testShopID = 2 +//) +// +//func init() { +// testinit.Init() +//} +// +//// 获取平台分类属性(三级分类标签) +//func TestGetVendorCategories(t *testing.T) { +// result, err := new(PurchaseHandler).GetVendorCategories(jxcontext.AdminCtx) +// if err != nil { +// t.Fatal(err) +// } +// for _, v := range result { +// data := model.SkuVendorCategory{ +// ModelIDCUL: model.ModelIDCUL{ +// CreatedAt: time.Now(), +// UpdatedAt: time.Now(), +// LastOperator: "刘磊", +// }, +// VendorCategoryID: v.VendorCategoryID, +// VendorID: v.VendorID, +// Name: v.Name, +// IsLeaf: v.IsLeaf, +// Level: v.Level, +// ParentID: v.ParentID, +// } +// if err := dao.CreateEntity(dao.GetDB(), &data); err != nil { +// t.Log(utils.Format4Output(err, false)) +// } +// } +// t.Log(utils.Format4Output(result, false)) +//} diff --git a/business/partner/purchase/tiktok_store/order.go b/business/partner/purchase/tiktok_store/order.go index 80eaa2aab..134264d95 100644 --- a/business/partner/purchase/tiktok_store/order.go +++ b/business/partner/purchase/tiktok_store/order.go @@ -1,87 +1,404 @@ package tiktok_store import ( - "git.rosy.net.cn/baseapi/platformapi/ebaiapi" - "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "errors" + "fmt" tiktokShop "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" + "math" + "net/url" + "regexp" + "strings" + "time" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "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/model/dao" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" ) -func (c *PurchaseHandler) onOrderMsg(msg *tiktokShop.CreateOrderCallback) (response *mtwmapi.CallbackResponse) { - var err error - //if c.isAfsMsg(msg) { - // response = c.OnAfsOrderMsg(msg) // 退单 - //} else { - status := c.callbackMsg2Status(msg) - if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 { - return nil +const ( + FakeMsgType = "fakeMsgType" + + fakeFinishedPickup = "fake_finished_pickup" + fakeUserApplyCancel = "fake_user_apply_cancel" + fakeMerchantAgreeApplyCancel = "fake_merchant_agree_apply_cancel" + fakeRefuseUserApplyCancel = "fake_refuse_user_apply_cancel" + fakeUserUndoApplyCancel = "fake_user_undo_apply_cancel" + fakeOrderAdjustFinished = "fake_order_adjust_finished" + + keyVendorOrgCode = "vendorOrgCode" +) + +const ( + SelfDeliveryCarrierNo = 1 // 美团配送方式:0-美团专送,1-商家自送 +) + +const ( +// pickupOrderDelay = 260 * time.Second +// pickupOrderDelay = 1 * time.Second + +// callDeliveryDelay = 10 * time.Minute +// callDeliveryDelayGap = 30 +) + +var ( + specPat = regexp.MustCompile(`(\d+)(.+)`) +) + +var ( + VendorStatus2StatusMap = map[string]int{ + mtwmapi.OrderStatusUserCommitted: model.OrderStatusUnknown, + mtwmapi.OrderStatusNew: model.OrderStatusNew, + 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.OrderStatusVendorRejectCancel, + fakeUserApplyCancel: model.OrderStatusApplyCancel, + fakeUserUndoApplyCancel: model.OrderStatusUndoApplyCancel, + fakeMerchantAgreeApplyCancel: model.OrderStatusCanceled, } - if msg.Cmd == mtwmapi.MsgTypeNewOrder { // 新订单 - order, orderMap, err2 := c.getOrder(msg.AppID, GetOrderIDFromMsg(msg), GetVendorStoreIDFromMsg(msg)) - if err = err2; err == nil { - err = partner.CurOrderManager.OnOrderNew(order, c.callbackMsg2Status(msg)) - if err == nil { - utils.CallFuncAsync(func() { - if msg.Cmd == mtwmapi.MsgTypeNewOrder { - c.OnOrderDetail(orderMap, partner.CreatedPeration) - } else { - c.OnOrderDetail(orderMap, partner.UpdatedPeration) - } - }) + + skuActTypeMap = map[int]int{ + mtwmapi.ExtrasPromotionTypeTeJiaCai: 1, + mtwmapi.ExtrasPromotionTypeZheKouCai: 1, + mtwmapi.ExtrasPromotionTypeSecondHalfPrice: 1, + } +) + +func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int { + if status, ok := VendorStatus2StatusMap[vendorStatus]; ok { + return status + } + return model.OrderStatusUnknown +} + +func (p *PurchaseHandler) getOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) { + result, err := getAPI(vendorOrgCode, 0, vendorStoreID).OrderGetOrderDetail(utils.Str2Int64(vendorOrderID), true) + if err == nil { + result[keyVendorOrgCode] = vendorOrgCode + order = p.Map2Order(result) + } + return order, result, err +} + +func (p *PurchaseHandler) getOrderRider(vendorOrgCode, vendorStoreID string, param map[string]interface{}) (err error) { + return getAPI(vendorOrgCode, 0, vendorStoreID).OrderStatusAndPsInfo(param) +} + +func (p *PurchaseHandler) GetOrderRider(vendorOrgCode, vendorStoreID string, param map[string]interface{}) (err error) { + return p.getOrderRider(vendorOrgCode, vendorStoreID, param) +} + +func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) { + order, _, err = p.getOrder(vendorOrgCode, vendorOrderID, vendorStoreID) + return order, err +} + +func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { + if order, _ := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDMTWM); order != nil { + status, err = getAPI(vendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderViewStatus(utils.Str2Int64(vendorOrderID)) + } + if err == nil { + status = p.getStatusFromVendorStatus(utils.Int2Str(status)) + } + return status, err +} + +func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { + result := orderData + vendorOrderID := utils.Int64ToStr(utils.MustInterface2Int64(result["order_id"])) + // 因为美团外卖不能自动设置商家门店号,且只能通过商家门店号来访问门店, + // 为了在后台设置简单一致,把app_poi_code直接当成平台门店号使用(即在后台设置时,平台门店号与商家门店号一样) + // 订单中wm_poi_id实际来平台门店号,app_poi_code为商家门店号,这样一来,这两个就相同了 + order = &model.GoodsOrder{ + VendorOrderID: vendorOrderID, + // VendorOrderID2: utils.Int64ToStr(utils.MustInterface2Int64(result["wm_order_id_view"])), + VendorID: model.VendorIDMTWM, + VendorStoreID: result["app_poi_code"].(string), + StoreID: 0, + // VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["wm_poi_id"])), + // StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["app_poi_code"]), 0)), + StoreName: result["wm_poi_name"].(string), + ConsigneeName: result["recipient_name"].(string), + ConsigneeMobile: jxutils.FormalizeMobile(result["recipient_phone"].(string)), + ConsigneeAddress: result["recipient_address"].(string), + CoordinateType: model.CoordinateTypeMars, + BuyerComment: utils.TrimBlankChar(utils.Interface2String(result["caution"])), + ExpectedDeliveredTime: getTimeFromTimestamp(utils.Interface2Int64WithDefault(result["delivery_time"], 0)), + PickDeadline: utils.DefaultTimeValue, + VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(result["status"])), + OrderSeq: int(utils.MustInterface2Int64(result["day_seq"])), + StatusTime: getTimeFromTimestamp(utils.MustInterface2Int64(result["ctime"])), + OrderCreatedAt: getTimeFromTimestamp(utils.MustInterface2Int64(result["ctime"])), + // OrderFinishedAt: getTimeFromTimestamp(utils.MustInterface2Int64(result["order_completed_time"])), + OriginalData: string(utils.MustMarshal(result)), + ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["total"])), + BaseFreightMoney: jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["shipping_fee"], 0)), + + InvoiceTitle: utils.Interface2String(result["invoice_title"]), + InvoiceTaxerID: utils.Interface2String(result["taxpayer_id"]), + InvoiceEmail: jxutils.GetOneEmailFromStr(utils.Interface2String(result["caution"])), + + VendorOrgCode: utils.Interface2String(result[keyVendorOrgCode]), + } + if result["order_completed_time"] != nil { + order.OrderFinishedAt = getTimeFromTimestamp(utils.MustInterface2Int64(result["order_completed_time"])) + } else { + order.OrderFinishedAt = utils.DefaultTimeValue + } + pickType := int(utils.Interface2Int64WithDefault(result["pick_type"], 0)) + if pickType == mtwmapi.OrderPickTypeSelf { + order.DeliveryType = model.OrderDeliveryTypeSelfTake + } else { + logisticsCode := utils.Interface2String(result["logistics_code"]) + if logisticsCode == mtwmapi.PeiSongTypeSelf || logisticsCode == mtwmapi.PeiSongTypeMTZSPT { + order.DeliveryType = model.OrderDeliveryTypeStoreSelf + } else { + order.DeliveryType = model.OrderDeliveryTypePlatform + } + } + openUID := utils.Interface2Int64WithDefault(result["openUid"], 0) + if openUID > 0 { + order.VendorUserID = utils.Int64ToStr(openUID) + } + // 不设置最晚拣货时间,以缺省值为准 + // 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 + } else { + order.BusinessType = model.BusinessTypeDingshida + } + + originalLng := utils.MustInterface2Float64(result["longitude"]) + originalLat := utils.MustInterface2Float64(result["latitude"]) + order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng) + order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat) + + var detail []map[string]interface{} + if err := utils.UnmarshalUseNumber([]byte(result["detail"].(string)), &detail); err != nil { + panic(fmt.Sprintf("mtwm Map2Order vendorID:%s failed with error:%v", vendorOrderID, err)) + } + + // 添加需要赠送的东西 + if result["extras"] != nil { + var extraList []*mtwmapi.OrderExtraInfo + if err := utils.UnmarshalUseNumber([]byte(result["extras"].(string)), &extraList); err != nil { + panic(fmt.Sprintf("mtwm Map2Order vendorID:%s failed with error:%v", vendorOrderID, err)) + } + for _, extra := range extraList { + order.DiscountMoney += jxutils.StandardPrice2Int(extra.ReduceFee) + if extra.Type == mtwmapi.ExtrasPromotionTypeTaoCanZeng || extra.Type == mtwmapi.ExtrasPromotionTypeManZeng { + sku := &model.OrderSku{ + VendorOrderID: order.VendorOrderID, + VendorID: model.VendorIDMTWM, + Count: 1, + SkuID: 0, + VendorSkuID: "", + SkuName: extra.Remark, + Weight: 0, + SalePrice: 0, + StoreSubName: utils.Int2Str(extra.Type), + } + order.Skus = append(order.Skus, sku) } } + } + + if poiReceiveDetailStr := utils.Interface2String(result["poi_receive_detail"]); poiReceiveDetailStr != "" { + var poiReceiveDetail *mtwmapi.PoiReceiveDetailInfo + utils.UnmarshalUseNumber([]byte(poiReceiveDetailStr), &poiReceiveDetail) + if poiReceiveDetail != nil { + order.TotalShopMoney = poiReceiveDetail.WmPoiReceiveCent + for _, v := range poiReceiveDetail.ActOrderChargeByMt { + order.PmSubsidyMoney += v.MoneyCent + } + } + } + + var skuBenefitDetailMap map[string]*mtwmapi.SkuBenefitDetailInfo + if skuBenefitDetai := utils.Interface2String(result["sku_benefit_detail"]); skuBenefitDetai != "" { + skuBenefitDetailMap = make(map[string]*mtwmapi.SkuBenefitDetailInfo) + var skuBenefitDetailList []*mtwmapi.SkuBenefitDetailInfo + utils.UnmarshalUseNumber([]byte(skuBenefitDetai), &skuBenefitDetailList) + for _, v := range skuBenefitDetailList { + skuBenefitDetailMap[v.SkuID] = v + } + } + ignoreSkuMap := make(map[int]int) + // detail := result["detail"].([]interface{}) + multiSkuMap := make(map[int]int) + for _, product := range detail { + // product := product2.(map[string]interface{}) + skuName := product["food_name"].(string) + skuID := utils.Interface2String(product["sku_id"]) + sku := &model.OrderSku{ + VendorOrderID: order.VendorOrderID, + VendorID: model.VendorIDMTWM, + Count: int(utils.MustInterface2Float64(product["quantity"])), + SkuID: int(utils.Str2Int64WithDefault(skuID, 0)), + VendorSkuID: skuID, + SkuName: skuName, + Weight: getSkuWeight(product), + VendorPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])), + SalePrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])), + } + if product["upc"] != nil && product["upc"].(string) != "" { + sku.Upc = product["upc"].(string) + } + if sku.VendorSkuID == "" { + if !strings.Contains(product["app_food_code"].(string), "mtcode") { + sku.VendorSkuID = product["app_food_code"].(string) + } else { + sku.VendorSkuID = utils.Int64ToStr(utils.Interface2Int64WithDefault(product["mt_sku_id"], 0)) + } + } + if sku.Weight == 0 { + sku.Weight = 222 // 如果名字里找不到缺省给半斤左右的一个特别值 + } + if skuBenefitDetailMap != nil && skuBenefitDetailMap[sku.VendorSkuID] != nil && ignoreSkuMap[sku.SkuID] == 0 /* && sku.Count == 1 */ { + for _, v := range skuBenefitDetailMap[sku.VendorSkuID].WmAppOrderActDetails { + if /*skuActTypeMap[v.Type] == 1 && */ strings.Index(v.Remark, skuName) >= 0 && sku.Count == v.Count { + if sku.SalePrice-jxutils.StandardPrice2Int(v.MtCharge+v.PoiCharge) < 0 { + continue + } else { + ignoreSkuMap[sku.SkuID] = 1 + sku.SalePrice -= jxutils.StandardPrice2Int(v.MtCharge + v.PoiCharge) + } + sku.StoreSubName = utils.Int2Str(v.Type) + } + } + } + if sku.SalePrice < 0 { + sku.SalePrice = jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])) + } + // if product["isGift"].(bool) { + // sku.SkuType = 1 + // } + order.Skus = append(order.Skus, sku) + multiSkuMap[sku.SkuID]++ + } + for _, v := range order.Skus { + if multiSkuMap[v.SkuID] > 1 && v.SalePrice == v.VendorPrice { + v.IsVendorAct = model.YES + } + } + + jxutils.RefreshOrderSkuRelated(order) + return order +} + +func getRefundSkuDetailList(msg *mtwmapi.CallbackMsg, order *model.GoodsOrder) (skuList []*mtwmapi.RefundSkuDetail, err error) { + if false { + skuList = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").GetRefundSkuDetailFromMsg(msg) } else { - if status != nil { - var order *model.GoodsOrder - if order, err = partner.CurOrderManager.LoadOrder(GetOrderIDFromMsg(msg), model.VendorIDMTWM); err == nil { - // if order, err = c.GetOrder(msg.AppID, GetOrderIDFromMsg(msg)); err == nil { - if status.Status == model.OrderStatusAdjust { - skuList, err2 := getRefundSkuDetailList(msg, order) - if err = err2; err == nil { - var removedSkuList []*model.OrderSku - for _, mtwmSku := range skuList { - order.ActualPayPrice -= jxutils.StandardPrice2Int(mtwmSku.RefundPrice) * int64(mtwmSku.Count) - removedSkuList = append(removedSkuList, &model.OrderSku{ - SkuID: int(utils.Str2Int64WithDefault(mtwmSku.SkuID, 0)), - Count: mtwmSku.Count, + refundOrderDetailList, err2 := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").GetOrderRefundDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), mtwmapi.RefundTypePart) + if err = err2; err == nil { + for _, v := range refundOrderDetailList { + skuList = append(skuList, v.WmAppRetailForOrderPartRefundList...) + } + } + } + globals.SugarLogger.Debugf("getRefundSkuDetailList orderID:%s skuList:%s", GetOrderIDFromMsg(msg), utils.Format4Output(skuList, true)) + return skuList, err +} + +func getSkuWeight(product map[string]interface{}) (weight int) { + if weight = int(utils.Interface2Int64WithDefault(product["weight"], 0)); weight == 0 { + searchResult := specPat.FindStringSubmatch(product["spec"].(string)) + if len(searchResult) == 3 { + weight = jxutils.FormatSkuWeight(float32(utils.Str2Float64WithDefault(searchResult[1], 0)), utils.TrimBlankChar(searchResult[2])) + } + if weight == 0 { + _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(product["food_name"].(string)) + weight = jxutils.FormatSkuWeight(specQuality, specUnit) + } + } + return weight +} + +func (c *PurchaseHandler) onOrderMsg(msg *tiktokShop.OrderCallback) (response *tiktokShop.CallbackResponse) { + var err error + if c.isAfsMsg(msg) { + response = c.OnAfsOrderMsg(msg) + } else { + status := c.callbackMsg2Status(msg) + if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 { + return nil + } + if msg.Cmd == mtwmapi.MsgTypeNewOrder { + order, orderMap, err2 := c.getOrder(msg.AppID, GetOrderIDFromMsg(msg), GetVendorStoreIDFromMsg(msg)) + if err = err2; err == nil { + err = partner.CurOrderManager.OnOrderNew(order, c.callbackMsg2Status(msg)) + if err == nil { + utils.CallFuncAsync(func() { + if msg.Cmd == mtwmapi.MsgTypeNewOrder { + c.OnOrderDetail(orderMap, partner.CreatedPeration) + } else { + c.OnOrderDetail(orderMap, partner.UpdatedPeration) + } + }) + } + } + } else { + if status != nil { + var order *model.GoodsOrder + if order, err = partner.CurOrderManager.LoadOrder(GetOrderIDFromMsg(msg), model.VendorIDMTWM); err == nil { + // if order, err = c.GetOrder(msg.AppID, GetOrderIDFromMsg(msg)); err == nil { + if status.Status == model.OrderStatusAdjust { + skuList, err2 := getRefundSkuDetailList(msg, order) + if err = err2; err == nil { + var removedSkuList []*model.OrderSku + for _, mtwmSku := range skuList { + order.ActualPayPrice -= jxutils.StandardPrice2Int(mtwmSku.RefundPrice) * int64(mtwmSku.Count) + removedSkuList = append(removedSkuList, &model.OrderSku{ + SkuID: int(utils.Str2Int64WithDefault(mtwmSku.SkuID, 0)), + Count: mtwmSku.Count, + }) + } + order = jxutils.RemoveSkuFromOrder(order, removedSkuList) + jxutils.RefreshOrderSkuRelated(order) + err = partner.CurOrderManager.OnOrderAdjust(order, status) + } + } else { + if status.Status == model.OrderStatusDelivering { + // 美团订单即使时在配送状态时,如果之前没有调用过拣货完成,也会对门店指标生成影响,这里强制再调用拣货完成,且忽略错误 + utils.CallFuncAsync(func() { + if globals.EnableMtwmStoreWrite { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").PreparationMealComplete(utils.Str2Int64(status.VendorOrderID)) + } + }) + } + err = partner.CurOrderManager.OnOrderStatusChanged(msg.AppID, status) + if err == nil && msg.Cmd == mtwmapi.MsgTypeOrderFinished { + utils.CallFuncAsync(func() { + orderMap, err := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderGetOrderDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), true) + if err == nil && utils.MustInterface2Int64(orderMap["is_third_shipping"]) == SelfDeliveryCarrierNo { + c.OnOrderDetail(orderMap, partner.UpdatedPeration) + } }) } - order = jxutils.RemoveSkuFromOrder(order, removedSkuList) - jxutils.RefreshOrderSkuRelated(order) - err = partner.CurOrderManager.OnOrderAdjust(order, status) - } - } else { - if status.Status == model.OrderStatusDelivering { - // 美团订单即使时在配送状态时,如果之前没有调用过拣货完成,也会对门店指标生成影响,这里强制再调用拣货完成,且忽略错误 - utils.CallFuncAsync(func() { - if globals.EnableMtwmStoreWrite { - err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").PreparationMealComplete(utils.Str2Int64(status.VendorOrderID)) - } - }) - } - err = partner.CurOrderManager.OnOrderStatusChanged(msg.AppID, status) - if err == nil && msg.Cmd == mtwmapi.MsgTypeOrderFinished { - utils.CallFuncAsync(func() { - orderMap, err := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderGetOrderDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), true) - if err == nil && utils.MustInterface2Int64(orderMap["is_third_shipping"]) == SelfDeliveryCarrierNo { - c.OnOrderDetail(orderMap, partner.UpdatedPeration) - } - }) - } + } } } } } - //} return mtwmapi.Err2CallbackResponse(err, "") } -func (c *PurchaseHandler) callbackMsg2Status(msg *tiktokShop.CreateOrderCallback) (orderStatus *model.OrderStatus) { +func (c *PurchaseHandler) callbackMsg2Status(msg *mtwmapi.CallbackMsg) (orderStatus *model.OrderStatus) { orderID := GetOrderIDFromMsg(msg) vendorStatus := msg.Cmd remark := "" @@ -148,52 +465,386 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *tiktokShop.CreateOrderCallback return orderStatus } -func (c *PurchaseHandler) callbackMsg2Status(msg *tiktokShop.CreateOrderCallback) (orderStatus *model.OrderStatus) { - orderID := GetOrderIDFromMsg(msg) - orderStatus = &model.OrderStatus{ - VendorOrderID: orderID, - VendorID: model.VendorIDDD, - OrderType: model.OrderTypeOrder, - RefVendorOrderID: orderID, - RefVendorID: model.VendorIDDD, - StatusTime: utils.Timestamp2Time(msg.Timestamp), - VendorStatus: msg.Cmd, +func (c *PurchaseHandler) postFakeMsg(vendorOrderID, cmd, vendorStatus string) { + msg := &mtwmapi.CallbackMsg{ + Cmd: cmd, + FormData: make(url.Values), } - if msg.Cmd == ebaiapi.CmdOrderUserCancel { - msgType := int(utils.MustInterface2Int64(msg.Body["type"])) - cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"])) - orderStatus.Remark = buildFullReason(utils.Interface2String(msg.Body["cancel_reason"]), utils.Interface2String(msg.Body["addition_reason"])) - orderStatus.VendorStatus = msg.Cmd + "-" + utils.Int2Str(msgType) - if cancelType == ebaiapi.OrderUserCancelTypeBeforeSale { - if msgType == ebaiapi.OrderUserCancelApply /* || msgType == ebaiapi.OrderUserCancelCSIntervene */ { - orderStatus.Status = model.OrderStatusApplyCancel - } else if msgType == ebaiapi.OrderUserCancelCSRefused || - msgType == ebaiapi.OrderUserCancelMerchantRefused { - orderStatus.Status = model.OrderStatusVendorRejectCancel - } else if msgType == ebaiapi.OrderUserCancelInvalid { - orderStatus.Status = model.OrderStatusUndoApplyCancel - } else if msgType == ebaiapi.OrderUserCancelCSAgreed || - msgType == ebaiapi.OrderUserCancelMerchantAgreed { - orderStatus.Status = model.OrderStatusVendorAgreeCancel + timeStr := utils.Int64ToStr(time.Now().Unix()) + msg.FormData.Set(mtwmapi.KeyOrderID, vendorOrderID) + msg.FormData.Set("status", vendorStatus) + msg.FormData.Set("timestamp", timeStr) + msg.FormData.Set("utime", timeStr) + utils.CallFuncAsync(func() { + c.onOrderMsg(msg) + }) +} + +func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { + 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)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderConfirm(utils.Str2Int64(order.VendorOrderID)) + if err != nil { + if utils.IsErrMatch(err, utils.Int2Str(mtwmapi.ErrCodeOpFailed), []string{ + "订单已经确认过了", + }) { + err = nil + } else { + globals.SugarLogger.Warnf("mtwm AcceptOrRefuseOrder orderID:%s failed with err:%v", order.VendorOrderID, err) + } } } - } else if msg.Cmd == ebaiapi.CmdOrderPartRefund { - msgType := int(utils.MustInterface2Int64(msg.Body["type"])) - status := int(utils.MustInterface2Int64(msg.Body["status"])) - orderStatus.Remark = buildFullReason(utils.Interface2String(msg.Body["reason"]), utils.Interface2String(msg.Body["addition_reason"])) - if msgType == ebaiapi.OrderPartRefuncTypeMerchant && status == ebaiapi.OrderPartRefundSuccess { - orderStatus.VendorStatus = fakeOrderAdjustFinished + // if err == nil { + // c.postFakeMsg(order.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusReceived) + // } + } else { + if globals.EnableMtwmStoreWrite { + err = c.CancelOrder(jxcontext.AdminCtx, order, "bu") } - } else if status, ok := msg.Body["status"]; ok { - if vendorStatus, ok := status.(string); ok { - orderStatus.VendorStatus = vendorStatus - } else { - orderStatus.VendorStatus = utils.Int64ToStr(utils.MustInterface2Int64(status)) - } - orderStatus.Remark = utils.Interface2String(msg.Body["reason"]) } - if orderStatus.Status == 0 { - orderStatus.Status = c.getStatusFromVendorStatus(orderStatus.VendorStatus) - } - return orderStatus + return err +} + +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 !isSelfDelivery { + if globals.EnableMtwmStoreWrite { + // err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").PreparationMealComplete(utils.Str2Int64(order.VendorOrderID)) + } + } + if err == nil { + c.postFakeMsg(order.VendorOrderID, FakeMsgType, fakeFinishedPickup) + } + return err +} + +func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) { + return err +} + +func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送 + return err +} + +func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货 + return err +} + +// 美团预定单不能转商家自送 +func (c *PurchaseHandler) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) { + return order.BusinessType != model.BusinessTypeDingshida, nil +} + +func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { + globals.SugarLogger.Debugf("mtwm Swtich2SelfDeliver orderID:%s", order.VendorOrderID) + if globals.EnableMtwmStoreWrite { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderLogisticsChange2Self(utils.Str2Int64(order.VendorOrderID)) + } + return err +} + +func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { + globals.SugarLogger.Debugf("mtwm Swtich2SelfDelivered orderID:%s", order.VendorOrderID) + if globals.EnableMtwmStoreWrite { + // 您好,之前的答复已经更正为,调用变更配送状态的接口,会校验门店的配送类型。美团配送的门店即便转自配后因门店配送类型是美团配送所以无法调用接口变更配送状态。可提醒顾客点击确认收货。谢谢 + // 非自配送门店订单调用OrderArrived好像会报错:{"data":"ng","error":{"code":1038,"msg":"只允许商家配送调用该接口"}} + // err = api.MtwmAPI.OrderArrived(utils.Str2Int64(order.VendorOrderID)) + } + return err +} + +func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { + globals.SugarLogger.Debugf("mtwm SelfDeliverDelivering orderID:%s", order.VendorOrderID) + if globals.EnableMtwmStoreWrite { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderDelivering(utils.Str2Int64(order.VendorOrderID)) + } + return err +} + +func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { + globals.SugarLogger.Debugf("mtwm SelfDeliverDelivered orderID:%s", order.VendorOrderID) + if globals.EnableMtwmStoreWrite { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderArrived(utils.Str2Int64(order.VendorOrderID)) + } + return err +} + +func getTimeFromTimestamp(timeStamp int64) time.Time { + if timeStamp < 1538103149 { // 立即达订单给的是1(而不是空,0),1538103149不是特殊值,只是一个任意之前的时间,这样写可以处理 + return utils.DefaultTimeValue + } + return utils.Timestamp2Time(timeStamp) +} + +func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) { + err = errors.New("美团外卖还未实现GetOrderRealMobile") + return mobile, err +} + +func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { + if globals.EnableMtwmStoreWrite { + if isAgree { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) + } else { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) + } + } + return err +} + +func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + if globals.EnableMtwmStoreWrite { + if err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderCancel(utils.Str2Int64(order.VendorOrderID), reason, mtwmapi.CancelReasonOther); err == nil { + // 调用开放平台接口取消订单,不推送取消订单消息和退款消息。 + c.postFakeMsg(order.VendorOrderID, mtwmapi.MsgTypeOrderCanceled, mtwmapi.OrderStatusCanceled) + } + } + return err +} + +func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) { + // 美团外卖必须要确认订单后才能调整单 + if order.Status < model.OrderStatusFinishedPickup { + err = c.PickupGoods(order, false, ctx.GetUserName()) + } + if err == nil { + var skuList []*mtwmapi.RefundSku + for _, sku := range removedSkuList { + skuID := utils.Int2Str(jxutils.GetSkuIDFromOrderSku(sku)) + skuList = append(skuList, &mtwmapi.RefundSku{ + AppFoodCode: skuID, + SkuID: skuID, + Count: sku.Count, + }) + } + if globals.EnableMtwmStoreWrite { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderApplyPartRefund(utils.Str2Int64(order.VendorOrderID), reason, skuList) + } + } + return err +} + +func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) { + if utils.IsTimeZero(queryDate) { + return nil, fmt.Errorf("queryDate必须指定") + } + queryDate = utils.Time2Date(queryDate) + + var vendorStoreIDs []string + if vendorStoreID == "" { + vendorStoreIDs, err = c.GetAllStoresVendorID(ctx, vendorOrgCode) + if err != nil { + return nil, err + } + } else { + vendorStoreIDs = []string{vendorStoreID} + } + task := tasksch.NewParallelTask("mtwm ListOrders", nil, ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + vendorStoreID := batchItemList[0].(string) + var orderIDs []string + seqStart := 1 + i := 0 + for { + batchSize := int(math.Min(math.Pow(2, float64(i*3)), float64(mtwmapi.MaxGap4GetOrderIdByDaySeq))) + seqEnd := seqStart + batchSize - 1 + var tmpOrderIDs []int64 + if seqStart == seqEnd { + if vendorOderID, err2 := getAPI(vendorOrgCode, 0, vendorStoreID).GetOrderIdByDaySeqSingle(vendorStoreID, queryDate, seqStart); err2 == nil { + tmpOrderIDs = []int64{vendorOderID} + } + } else { + tmpOrderIDs, err = getAPI(vendorOrgCode, 0, vendorStoreID).GetOrderIdByDaySeq(vendorStoreID, queryDate, seqStart, seqEnd) + } + if len(tmpOrderIDs) > 0 { + for _, v := range tmpOrderIDs { + orderIDs = append(orderIDs, utils.Int64ToStr(v)) + } + } + if err != nil || len(tmpOrderIDs) < batchSize { + err = nil + break + } + seqStart = seqEnd + 1 + i++ + } + retVal = orderIDs + return retVal, nil + }, vendorStoreIDs) + tasksch.HandleTask(task, parentTask, true).Run() + orderList, err := task.GetResult(0) + if err == nil && len(orderList) > 0 { + vendorOrderIDs = make([]string, len(orderList)) + for k, v := range orderList { + vendorOrderIDs[k] = v.(string) + } + } + return vendorOrderIDs, err +} + +// func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee int64) (err error) { +// if globals.EnableMtwmStoreWrite { +// err = api.MtwmAPI.OrderUpdateTip(utils.Str2Int64(order.VendorOrderID), jxutils.IntPrice2Standard(tipFee)) +// } +// return err +// } + +func (p *PurchaseHandler) GetOrderConsigneeNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) { + offset := 0 + for { + store, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, "") + result, err2 := getAPI(store.VendorOrgCode, storeID, "").OrderBatchPullPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit) + if err = err2; err == nil { + for _, v := range result { + v2 := &partner.OrderPhoneNumberInfo{ + VendorOrderID: utils.Int64ToStr(v.OrderID), + PhoneNumber: v.RealPhoneNumber, + } + if v2.PhoneNumber == "" { + v2.PhoneNumber = v.RealOrderPhoneNumber + } + numberList = append(numberList, v2) + } + if len(result) <= mtwmapi.MaxBatchPullPhoneNumberLimit { + break + } + offset += mtwmapi.MaxBatchPullPhoneNumberLimit + } else { + break + } + } + return numberList, err +} + +func (p *PurchaseHandler) GetOrderCourierNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) { + offset := 0 + for { + store, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, "") + result, err2 := getAPI(store.VendorOrgCode, 0, "").OrderGetRiderInfoPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit) + if err = err2; err == nil { + for _, v := range result { + numberList = append(numberList, &partner.OrderPhoneNumberInfo{ + VendorOrderID: utils.Int64ToStr(v.OrderID), + PhoneNumber: v.RiderRealPhoneNumber, + }) + } + if len(result) <= mtwmapi.MaxBatchPullPhoneNumberLimit { + break + } + offset += mtwmapi.MaxBatchPullPhoneNumberLimit + } else { + break + } + } + return numberList, err +} + +func (p *PurchaseHandler) onNumberDowngrade(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) { + userNumberMap := make(map[string]*partner.OrderPhoneNumberInfo) + courierNumberMap := make(map[string]*partner.OrderPhoneNumberInfo) + orderMap := make(map[string]int) + ctx := jxcontext.AdminCtx + task := tasksch.NewParallelTask("美团外卖平台处理隐私号降级通知", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + step := batchItemList[0].(int) + switch step { + case 0: + userNumberList, err2 := p.GetOrderConsigneeNumber(ctx, 0, "") + if err = err2; err == nil { + for _, v := range userNumberList { + userNumberMap[v.VendorOrderID] = v + orderMap[v.VendorOrderID] = 1 + } + } + case 1: + courierNumberList, err2 := p.GetOrderCourierNumber(ctx, 0, "") + if err = err2; err == nil { + for _, v := range courierNumberList { + courierNumberMap[v.VendorOrderID] = v + orderMap[v.VendorOrderID] = 1 + } + } + case 2: + orderList := jxutils.StringMap2List(orderMap) + if len(orderList) > 0 { + updateTask := tasksch.NewParallelTask("美团外卖平台处理隐私号降级通知/处理订单", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + vendorOrderID := batchItemList[0].(string) + db := dao.GetDB() + if userNumberMap[vendorOrderID] != nil { + _, err = dao.UpdateEntityByKV(db, &model.GoodsOrder{}, map[string]interface{}{ + "ConsigneeMobile": userNumberMap[vendorOrderID].PhoneNumber, + "ConsigneeMobile2": userNumberMap[vendorOrderID].PhoneNumber, + }, map[string]interface{}{ + model.FieldVendorOrderID: vendorOrderID, + model.FieldVendorID: model.VendorIDMTWM, + }) + } + if courierNumberMap[vendorOrderID] != nil { + _, err = dao.UpdateEntityByKV(db, &model.Waybill{}, map[string]interface{}{ + "CourierMobile": courierNumberMap[vendorOrderID].PhoneNumber, + }, map[string]interface{}{ + "VendorWaybillID": vendorOrderID, + "WaybillVendorID": model.VendorIDMTWM, + }) + } + return retVal, err + }, orderList) + tasksch.HandleTask(updateTask, task, true).Run() + _, err = updateTask.GetResult(0) + } + } + return retVal, err + }, []int{0, 1, 2}) + tasksch.HandleTask(task, nil, true).Run() + return response +} + +func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) { + orderInfo, err := getAPI(vendorOrgCode, 0, vendorStoreID).GetDistributeOrderDetail(vendorOrderID, vendorStoreID) + if err == nil { + tipFee = jxutils.StandardPrice2Int(orderInfo.TipAmount) + } + return tipFee, err +} + +func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) { + if globals.EnableMtwmStoreWrite { + err = getAPI(vendorOrgCode, 0, vendorStoreID).OrderModityTips(vendorOrderID, vendorStoreID, jxutils.IntPrice2Standard(tipFee)) + } + return err +} + +func (c *PurchaseHandler) GetSelfTakeCode(ctx *jxcontext.Context, order *model.GoodsOrder) (selfTakeCode string, err error) { + return selfTakeCode, err +} + +func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, order *model.GoodsOrder, selfTakeCode string) (err error) { + return err +} + +func (c *PurchaseHandler) ComplaintRider(vendorOrderId string, resonID int, resonContent string) (err error) { + return err +} + +// 转自配送时取消非专送混合送门店取消理由 +func (c *PurchaseHandler) GetCancelDeliveryReason(order *model.GoodsOrder) (string, error) { + reason, err := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").GetCancelDeliveryReason(utils.Str2Int64(order.VendorOrderID), order.VendorStoreID) + if err != nil { + return "", err + } + return reason, nil +} + +// 取消美团外卖理由转使用三方配送 +func (c *PurchaseHandler) CancelLogisticsByWmOrderId(order *model.GoodsOrder, reasonCode, detailContent, appPoiCode, orderId string) error { + return getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").CancelLogisticsByWmOrderId(reasonCode, detailContent, appPoiCode, orderId) +} + +// 获取订单配送状态 +func (c *PurchaseHandler) OrderLogisticsStatus(orderId int64) (int64, error) { + return 0, nil } diff --git a/business/partner/purchase/tiktok_store/order_afs.go b/business/partner/purchase/tiktok_store/order_afs.go new file mode 100644 index 000000000..6f4b64e54 --- /dev/null +++ b/business/partner/purchase/tiktok_store/order_afs.go @@ -0,0 +1,449 @@ +package tiktok_store + +import ( + "fmt" + tiktokShop "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" + "git.rosy.net.cn/jx-callback/globals/api" + "net/url" + "strings" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "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" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" +) + +var ( + AfsVendorStatus2StatusMap = map[string]int{ + tiktokShop.CallbackRefundOrderMsgTagId: model.AfsOrderStatusWait4Approve, // 发起售后申请待审核 + tiktokShop.CallbackUpdateRefundOrderMsgTagId: model.AfsOrderStatusWait4Approve, // 修改售后待审核 + tiktokShop.CallbackRefundOrderSuccessMsgTagId: model.AfsOrderStatusFinished, // 退款成功 + tiktokShop.CallbackRefundOrderRefuseMsgTagId: model.AfsOrderStatusFailed, // 拒绝退款 + tiktokShop.CallbackRefundShopMsgTagId: model.AfsOrderStatusFailed, // 拒绝退货 + tiktokShop.CallbackReturnApplyAgreedMsgTagId: model.AfsOrderStatusFinished, // 同意退货 + tiktokShop.CallbackReturnRefundAgreedMsgTagId: model.AfsOrderStatusFinished, // 同意退款 + } + + AfsTagIDMap = map[string]string{ + tiktokShop.CallbackRefundOrderMsgTagId: "1", + tiktokShop.CallbackUpdateRefundOrderMsgTagId: "1", + tiktokShop.CallbackRefundOrderSuccessMsgTagId: "1", + tiktokShop.CallbackRefundOrderRefuseMsgTagId: "1", + tiktokShop.CallbackRefundShopMsgTagId: "1", + tiktokShop.CallbackReturnApplyAgreedMsgTagId: "1", + tiktokShop.CallbackReturnRefundAgreedMsgTagId: "1", + tiktokShop.CallbackExchangeComfirmedMsgTagId: "1", + tiktokShop.CallbackArbitrateDiscussUploadMsgTagId: "1", + tiktokShop.CallbackArbitrateServiceInterveneMsgTagId: "1", + tiktokShop.CallbackArbitrateCancelledMsgTagId: "1", + tiktokShop.CallbackArbitrateAuditedMsgTagId: "1", + tiktokShop.CallbackArbitrateSubmitedMsgTagId: "1", + tiktokShop.CallbackArbitrateSubmitingMsgTagId: "1", + tiktokShop.CallbackArbitrateAppliedMsgTagId: "1", + tiktokShop.CallbackExpirationChangeMsgTagId: "1", + tiktokShop.CallbackRefundClosedMsgTagId: "1", + tiktokShop.CallbackBuyerReturnGoodsMsgTagId: "1", + tiktokShop.CallbackSpecialRefundMsgTagId: "1", + tiktokShop.CallbackSpecialRefundSuccessMsgTagId: "1", + tiktokShop.CallbackAuditAgreeResendMsgTagId: "1", + tiktokShop.CallbackResendFillLogisticsMsgTagId: "1", + } + + // ReasonCodeMap 申请退货理由,可能会更新 + ReasonCodeMap = map[int]string{ + 1: "商品已发出,如买家不再需要请拒收后申请仅退款或收到后申请退货退款", + 2: "商品已经签收,如买家不再需要可以申请退货退款", + 3: "买家误操作/取消申请", + 4: "问题已解决,待用户收货", + 5: "商品已发出,如买家不再需要请拒收后申请仅退款或收到后申请退货退款", + 6: "买家误操作/取消申请", + 7: "协商一致,用户取消退款", + 8: "已与买家协商补偿,包括差价、赠品、额外补偿", + 9: "已与买家协商补发商品", + 10: "已与买家协商换货", + 11: "买家上传的单号有误,商家尚未收到货,请核实正确物流单号后重新上传", + 12: "退货与原订单不符(商品不符、退货地址不符)", + 13: "退回商品影响二次销售", + 14: "买家误操作/取消申请", + 15: "协商一致,用户取消退款", + 16: "买家误操作/取消申请", + 17: "协商一致,用户取消退款", + 18: "商品影响二次销售", + 19: "定制商品不支持七天无理由退货,定制商品不接受质量问题以外的退货", + 20: "定制商品不支持七天无理由退货,定制商品不接受质量问题以外的退货", + 21: "买家申请的金额有误", + 22: "运费未协商一致", + 23: "商品没问题,买家未举证或凭证无效", + 24: "已在约定时间发货", + 25: "运费未协商一致", + 26: "商品已经签收,如买家不再需要可以申请退货退款", + 27: "商品没问题,买家未举证或举证无效", + 28: "已在约定时间发货", + 29: "买家申请的金额有误", + 30: "发票没问题,买家未举证", + 31: "发票已补寄", + 32: "买家发票信息不完整", + 33: "运费未协商一致", + 34: "申请时间已超7天无理由退换货时间", + 35: "不支持买家主观原因退换货", + 36: "买家填错号码", + 37: "已完成服务,买家未提供凭证或凭证无效", + 38: "买家填错号码", + 39: "已完成服务,买家未提供凭证或凭证无效", + 40: "和达人达成一致,取消终止", + 41: "其他", + 42: "其他", + 43: "未收到货/退货单号有误", + 44: "退货与原订单不符(商品不符、退货地址不符)", + 45: "商家已发货", + 46: "商品已经签收,如买家不再需要可以申请退货退款", + 47: "已与买家协商一致仅退款", + 48: "问题已解决,待用户确认收货", + 49: "已与买家协商一致延迟发货", + 50: "未少发漏发", + 51: "已与买家协商补偿,包括差价、赠品、额外补偿", + 52: "已与买家协商一致延迟发货", + 53: "其他", + 54: "本单已购买【养死包赔】保险,请从保险理赔入口申请理赔", + 55: "本单已购买【开箱无忧】保险,请从保险理赔入口申请理赔", + 56: "商品没问题,买家未举证或举证无效", + 57: "已完成服务,买家未举证或举证无效", + 58: "本单已购买【食安保】保险,请从保险理赔入口申请理赔", + } +) + +// 是否为售后消息 +func (c *PurchaseHandler) isAfsMsg(msg *tiktokShop.OrderCallback) bool { + _, ok := AfsTagIDMap[msg.MsgId] + return ok +} + +func (c *PurchaseHandler) OnAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwmapi.CallbackResponse) { + jxutils.CallMsgHandlerAsync(func() { + retVal = c.onAfsOrderMsg(msg) + }, jxutils.ComposeUniversalOrderID(GetOrderIDFromMsg(msg), model.VendorIDEBAI)) + return retVal +} + +// todo 对于退款与部分退款,order.go与这个文件中对于状态的处理不一致 +func (c *PurchaseHandler) onAfsOrderMsg(msg *tiktokShop.OrderCallback) (retVal *tiktokShop.CallbackResponse) { + var err error + orderStatus := c.callbackAfsMsg2Status(msg) + for _, v := range orderStatus { + needCallNew := v.Status == model.AfsOrderStatusWait4Approve || v.Status == model.AfsOrderStatusNew + if !needCallNew { + if _, err := partner.CurOrderManager.LoadAfsOrder(v.VendorOrderID, v.VendorID); err != nil { + if dao.IsNoRowsError(err) { + needCallNew = true + } else { + return tiktokShop.Err2CallbackResponse(err, "") + } + } + } + + if needCallNew { + var afsOrder *model.AfsOrder + refundData := msg.Data.(*mtwmapi.CallbackRefundInfo) + if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund { + afsOrder = &model.AfsOrder{ + VendorID: model.VendorIDMTWM, + AfsOrderID: orderStatus.VendorOrderID, + VendorOrderID: orderStatus.RefVendorOrderID, + VendorStoreID: "", + StoreID: 0, + AfsCreatedAt: utils.Timestamp2Time(refundData.Timestamp), + VendorAppealType: "", + AppealType: model.AfsAppealTypeRefund, + VendorReasonType: "", + ReasonType: model.AfsReasonNotOthers, + ReasonDesc: utils.LimitUTF8StringLen(refundData.Reason, 1024), + ReasonImgList: utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024), + RefundType: model.AfsTypePartRefund, + + VendorOrgCode: msg.AppID, + } + for _, sku := range refundData.FoodList { + orderSku := &model.OrderSkuFinancial{ + Count: sku.Count, + VendorSkuID: sku.SkuID, + SkuID: int(utils.Str2Int64WithDefault(sku.SkuID, 0)), + Name: sku.FoodName, + UserMoney: jxutils.StandardPrice2Int(sku.RefundPrice)*int64(sku.Count) + jxutils.StandardPrice2Int(sku.BoxPrice)*int64(sku.BoxNum), + } + afsOrder.SkuUserMoney += orderSku.UserMoney + afsOrder.Skus = append(afsOrder.Skus, orderSku) + } + } else { + if afsOrder = c.createAfsOrder(msg.FormData); afsOrder != nil { + afsOrder.AfsOrderID = orderStatus.VendorOrderID + afsOrder.RefundType = model.AfsTypeFullRefund + afsOrder.AppealType = model.AfsAppealTypeRefund + afsOrder.VendorReasonType = "" + afsOrder.ReasonType = model.AfsReasonNotOthers + afsOrder.ReasonDesc = utils.LimitUTF8StringLen(refundData.Reason, 1024) + afsOrder.ReasonImgList = utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024) + } + } + if afsOrder != nil { + //直接就来一个新的售后单,并且还是售后完成的 + if orderStatus.Status == model.AfsOrderStatusFinished { + afsOrder.AfsFinishedAt = afsOrder.AfsCreatedAt + } + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } + } else { + err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + } + } + + return mtwmapi.Err2CallbackResponse(err, "") +} + +func (p *PurchaseHandler) createAfsOrder(orderData url.Values) (afsOrder *model.AfsOrder) { + afsOrder, err := partner.CurOrderManager.CreateAfsOrderFromOrder(orderData.Get("order_id"), model.VendorIDMTWM) + if err == nil { + afsOrder.AfsOrderID = orderData.Get("refund_id") + afsOrder.AfsCreatedAt = utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp"))) + if afsOrder.AfsOrderID == "" { + afsOrder.AfsOrderID = afsOrder.VendorOrderID + } + } else { + afsOrder = nil + } + return afsOrder +} + +func (c *PurchaseHandler) callbackAfsMsg2Status(msg *tiktokShop.OrderCallback) (orderStatus []*model.OrderStatus) { + switch msg.MsgId { + case tiktokShop.CallbackRefundOrderMsgTagId: // 买家发起售后申请消息 + for _, v := range msg.Body[tiktokShop.CallbackRefundOrderMsgTagId] { + refundOrder := v.(*tiktokShop.BuyerRefundCreatedData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "create"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackRefundOrderMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.ApplyTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackUpdateRefundOrderMsgTagId: // 买家修改售后申请消息 + for _, v := range msg.Body[tiktokShop.CallbackUpdateRefundOrderMsgTagId] { + refundOrder := v.(*tiktokShop.BuyerRefundModifiedData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "update"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackUpdateRefundOrderMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.ModifyTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackRefundOrderSuccessMsgTagId: // 退款成功消息 + for _, v := range msg.Body[tiktokShop.CallbackRefundOrderSuccessMsgTagId] { + refundOrder := v.(*tiktokShop.BusinessRefundSuccessData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "refund_success"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackUpdateRefundOrderMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.SuccessTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackRefundOrderRefuseMsgTagId: // 拒绝退款消息 + for _, v := range msg.Body[tiktokShop.CallbackRefundOrderSuccessMsgTagId] { + refundOrder := v.(*tiktokShop.BusinessRefundSuccessData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "refund_money_fail"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackUpdateRefundOrderMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.SuccessTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackRefundShopMsgTagId: // 拒绝退货申请消息 + for _, v := range msg.Body[tiktokShop.CallbackRefundShopMsgTagId] { + refundOrder := v.(*tiktokShop.BusinessNotReturnApplyRefusedData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "refuse_shop_fail"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackRefundShopMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.RefuseTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackReturnApplyAgreedMsgTagId: // 同意退货申请消息 + for _, v := range msg.Body[tiktokShop.CallbackReturnApplyAgreedMsgTagId] { + refundOrder := v.(*tiktokShop.BusinessRefundSuccessData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "refund_shop_success"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackReturnApplyAgreedMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.SuccessTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + case tiktokShop.CallbackReturnRefundAgreedMsgTagId: // 同意退款消息 + for _, v := range msg.Body[tiktokShop.CallbackReturnRefundAgreedMsgTagId] { + refundOrder := v.(*tiktokShop.BusinessRefundSuccessData) + orderMsg := &model.OrderStatus{ + VendorID: model.VendorIDDD, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: utils.Int64ToStr(refundOrder.PId), + RefVendorID: model.VendorIDDD, + VendorStatus: fmt.Sprintf("%s:%s", "order", "refund_money_success"), + Status: c.GetAfsStatusFromVendorStatus(refundOrder.AftersaleType, tiktokShop.CallbackReturnRefundAgreedMsgTagId), + StatusTime: utils.Timestamp2Time(int64(refundOrder.SuccessTime)), + } + if k, ok := ReasonCodeMap[refundOrder.ReasonCode]; ok { + orderMsg.Remark = k + } else { + orderMsg.Remark = "抖音reason_code对应reason不足,需要更新.code:" + string(refundOrder.ReasonCode) + } + if refundOrder.AftersaleId > 0 { + orderMsg.VendorOrderID = utils.Int64ToStr(refundOrder.AftersaleId) + } else { + orderMsg.VendorOrderID = orderMsg.RefVendorOrderID + } + orderStatus = append(orderStatus, orderMsg) + } + default: + return nil + } + + return orderStatus +} + +func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(resType int, notifyType string) int { + status := AfsVendorStatus2StatusMap[notifyType] + if status == model.AfsOrderStatusWait4Approve && resType != mtwmapi.ResTypePending { + status = model.AfsOrderStatusNew + } + return status +} + +// 审核售后单申请 +func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { + if globals.EnableMtwmStoreWrite { + if approveType == partner.AfsApproveTypeRefused { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) + } else { + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) + } + } + return err +} + +// 确认收到退货 +func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { + err = fmt.Errorf("内部错误,美团外卖平台不支持确认收到退货操作") + return err +} + +// 发起全款退款 +func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + return fmt.Errorf("%s不支持售后全额退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDMTWM]) +} + +// 发起部分退款 +func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { + return c.AdjustOrder(ctx, order, refundSkuList, reason) +} + +func (c *PurchaseHandler) GetOrderAfsInfo(ctx *jxcontext.Context, vendorOrderID, afsOrderID string) (orderAfsInfo *partner.OrderAfsInfo, err error) { + orderAfsInfo = &partner.OrderAfsInfo{} + var afsTotalShopMoney int64 + if list, err := api.MtwmAPI.GetOrderRefundDetail(utils.Str2Int64(vendorOrderID), 0); err == nil { + for _, v := range list { + if v.RefundPartialEstimateCharge.SettleAmount != "" { + afsTotalShopMoney += jxutils.StandardPrice2Int(utils.Str2Float64(v.RefundPartialEstimateCharge.SettleAmount)) + } + } + } + if order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDMTWM); err == nil { + orderAfsInfo.AfsTotalShopMoney = order.TotalShopMoney + afsTotalShopMoney + } + return orderAfsInfo, err +} diff --git a/business/partner/purchase/tiktok_store/order_comment.go b/business/partner/purchase/tiktok_store/order_comment.go new file mode 100644 index 000000000..1a0d89eb9 --- /dev/null +++ b/business/partner/purchase/tiktok_store/order_comment.go @@ -0,0 +1,113 @@ +package tiktok_store + +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" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals" +) + +const ( + RefreshCommentTime = 7 * 24 * time.Hour // 此值必须大于24小时 + RefreshCommentTimeInterval = 60 * time.Minute + BAD_COMMENTS_MAX_MODIFY_TIME = 24 * 6 // 小时 +) + +func (c *PurchaseHandler) StartRefreshComment() { + utils.AfterFuncWithRecover(5*time.Second, func() { + c.refreshCommentOnce() + }) +} + +func (c *PurchaseHandler) refreshCommentOnce() { + c.RefreshComment(time.Now().Add(-RefreshCommentTime), time.Now()) + utils.AfterFuncWithRecover(RefreshCommentTimeInterval, func() { + c.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) { + //storeMapList, err2 := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDMTWM}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") + //if err = err2; err != nil { + // return err + //} + endDateStr := time.Now().Add(-24 * time.Hour).Format("20060102") + startDateStr := time.Now().Add(-RefreshCommentTime).Format("20060102") + storeIDs, _ := dao.GetOrderStoreIDs(dao.GetDB(), fromTime, toTime, model.VendorIDMTWM) + task := tasksch.NewParallelTask("mtwm RefreshComment", nil, jxcontext.AdminCtx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeID := batchItemList[0].(int) + storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, "") + commentList, err2 := getAPI(storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID).CommentQuery(storeDetail.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusNotReplied) + var orderCommentList []*model.OrderComment + if err = err2; err != nil { + return nil, err + } + 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: storeDetail.VendorStoreID, + TagList: formalizeTagList(mtwmComment.CommentLables), + Score: int8(mtwmComment.FoodCommentScore), + ModifyDuration: BAD_COMMENTS_MAX_MODIFY_TIME, + OriginalMsg: string(utils.MustMarshal(mtwmComment)), + IsReplied: int8(mtwmComment.ReplyStatus), + StoreID: storeDetail.ID, + } + 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 + }, storeIDs) + 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, vendorOrgCode string, 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 = getAPI(vendorOrgCode, orderComment.StoreID, orderComment.VendorStoreID).CommentAddReply(orderComment.VendorStoreID, utils.Str2Int64(orderComment.UserCommentID), replyComment) + } + return err +} diff --git a/business/partner/purchase/tiktok_store/order_test.go b/business/partner/purchase/tiktok_store/order_test.go new file mode 100644 index 000000000..4900c4dc4 --- /dev/null +++ b/business/partner/purchase/tiktok_store/order_test.go @@ -0,0 +1,35 @@ +package tiktok_store + +import ( + "testing" + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + + "git.rosy.net.cn/baseapi/utils" + _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" +) + +func TestGetOrder(t *testing.T) { + // result, err := CurPurchaseHandler.GetOrder("", "33437032333978492") + // if err != nil { + // t.Fatal(err) + // } + //t.Log(utils.Format4Output(result, false)) +} + +func TestGetOrderStatus(t *testing.T) { + result, err := CurPurchaseHandler.GetOrderStatus("", "71884881906304496") + if err != nil { + t.Fatal(err) + } + t.Log(utils.Format4Output(result, false)) +} + +func TestListOrders(t *testing.T) { + result, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "5873", nil, time.Now(), "14038247") + if err != nil { + t.Fatal(err) + } + t.Log(utils.Format4Output(result, false)) +} diff --git a/business/partner/purchase/tiktok_store/store.go b/business/partner/purchase/tiktok_store/store.go new file mode 100644 index 000000000..072b79781 --- /dev/null +++ b/business/partner/purchase/tiktok_store/store.go @@ -0,0 +1,487 @@ +package tiktok_store + +import ( + "encoding/json" + "errors" + "fmt" + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/baseapi/utils/errlist" + "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" + "git.rosy.net.cn/jx-callback/business/jxstore/event" + "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/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" + "math" + "regexp" + "strings" +) + +var ( + opTimeErrReg = regexp.MustCompile(`当前配送营业时间为:([\d:~,]*)`) + storeVendorOrgCodeMap = map[string]map[string]string{ + "589": map[string]string{ + "firstTag": mtwmapi.MtwmC4Tag, //经营品类 + "settlementID": "7030017", //结算ID + "poiCert": "1,2,5", //资质列表 + }, + "5873": map[string]string{ + "firstTag": mtwmapi.MtwmSCTag, + "settlementID": "", + "poiCert": "1,2,5,6", + }, + "4123": map[string]string{ + "firstTag": mtwmapi.MtwmSGTag, + "settlementID": "6572945", + "poiCert": "1,5", + }, + } + poiCertMap = map[string]string{ + "1": "门脸图", + "2": "环境图", + "5": "营业执照", + "6": "食品经营许可证", + } +) + +type tEbaiStoreInfo struct { + model.Store + VendorStoreID string `orm:"column(vendor_store_id)"` + RealLastOperator string + EbaiStoreStatus int + SyncStatus int + + ProvinceID int `orm:"column(province_id)"` + CityID int `orm:"column(city_id)"` + DistrictID int `orm:"column(district_id)"` +} + +func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorStoreName string) (retVal *dao.StoreDetail, err error) { + result, err := getAPIWithoutToken(vendorOrgCode).PoiGet(vendorStoreID) + if err == nil { + // globals.SugarLogger.Debug(utils.Format4Output(result, false)) + retVal = &dao.StoreDetail{ + Store: model.Store{ + Address: result.Address, + Tel1: result.Phone, + }, + } + retVal.OriginalName = result.Name + _, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, globals.StoreNameMtwm) + + retVal.SetOpTime(openTimeMtwm2JX(result.ShippingTime)) + retVal.Status = bizStatusMtwm2JX(result.OpenLevel, result.IsOnline) + + tel2 := result.StandbyTel + if tel2 != "" && tel2 != retVal.Tel1 { + retVal.Tel2 = tel2 + } + + retVal.Lng = int(result.Longitude) + retVal.Lat = int(result.Latitude) + + lng := jxutils.IntCoordinate2Standard(retVal.Lng) + lat := jxutils.IntCoordinate2Standard(retVal.Lat) + db := dao.GetDB() + retVal.DistrictCode = api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat) + city, err := dao.GetPlaceByCode(db, result.CityID) + retVal.CityName = city.Name + retVal.CityCode = result.CityID + + poiCode := result.AppPoiCode + retVal.VendorStoreID = vendorStoreID + retVal.ID = int(utils.Str2Int64WithDefault(poiCode, 0)) + retVal.DeliveryRangeType = model.DeliveryRangeTypePolygon + var deliveryRangeInfo []map[string]interface{} + deliveryRangeInfo, err = getAPIWithoutToken(vendorOrgCode).ShippingFetch(poiCode) + if err != nil { + deliveryRangeInfo, err = getAPIWithoutToken(vendorOrgCode).ShippingList(poiCode) + } + if err == nil { + if len(deliveryRangeInfo) > 0 { + retVal.DeliveryRange = rangeMtwm2JX(deliveryRangeInfo[0]["area"].(string)) + logisticsCode := utils.Interface2String(deliveryRangeInfo[0]["logistics_code"]) + if logisticsCode == "" || logisticsCode == mtwmapi.PeiSongTypeSelf { + retVal.DeliveryType = scheduler.StoreDeliveryTypeByStore + } else { + retVal.DeliveryType = scheduler.StoreDeliveryTypeByPlatform + } + } + } + return retVal, nil + } + return nil, err +} +func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName string) (err error) { + return p.UpdateStore(db, storeID, userName) +} + +func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { + vendorOrgCode := params["vendorOrgCode"].(string) + if vendorOrgCode == "" { + return "", fmt.Errorf("平台账号必传!") + } + cityName := storeDetail.CityName + if strings.Contains(cityName, "市") { + cityName = strings.Replace(cityName, "市", "", strings.LastIndex(cityName, "市")) + } + shippingTime := "" + if storeDetail.OpenTime1 != 0 && storeDetail.CloseTime1 != 0 { + shippingTime += jxutils.JxOperationTime2StrTime(storeDetail.OpenTime1) + shippingTime += "-" + shippingTime += jxutils.JxOperationTime2StrTime(storeDetail.CloseTime1) + if storeDetail.OpenTime2 != 0 && storeDetail.CloseTime2 != 0 { + shippingTime += "," + shippingTime += jxutils.JxOperationTime2StrTime(storeDetail.OpenTime2) + shippingTime += "-" + shippingTime += jxutils.JxOperationTime2StrTime(storeDetail.CloseTime2) + } + } + vendorInfoMap := storeVendorOrgCodeMap[vendorOrgCode] + poiSettleSaveParam := &mtwmapi.PoiSettleSaveParam{ + Type: 1, //创建 + ApplyInfos: []*mtwmapi.ApplyInfo{ + &mtwmapi.ApplyInfo{ + AppPoiCode: utils.Int2Str(storeDetail.ID), + SettlementID: utils.Str2Int(vendorInfoMap["settlementID"]), //结算ID,暂时还没得 + MultiPoiBasicInfo: &mtwmapi.MultiPoiBasicInfo{ + Name: params["vendorStoreName"].(string), + City: cityName, + Address: storeDetail.Address, + Longitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng)), + Latitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat)), + FirstTag: vendorInfoMap["firstTag"], + CallCenter: storeDetail.Tel1, + ContactPhone: storeDetail.Tel1, + ContactName: storeDetail.IDName, + EcommerceAccountPhone: "18048531223", //石总的手机 + ShippingTime: shippingTime, + }, + MultiPoiShippingInfo: &mtwmapi.MultiPoiShippingInfo{ + ShippingType: 5, //1:商家自配 5:美团专送,101:美团快送 + //美团专送不需要输下面这俩 + // MinPrice: params["minPrice"].(float64), + // ShippingFee: params["shippingFee"].(float64), + }, + //资质 + }, + }, + } + switchCertType := func(certType string) (licensePic, licenseSocialCreditCode, licenseNumber, licenseLegalPerson, licenseAddress, licenseValidStartDate, licenseValidity string, isLongTime int) { + switch certType { + case "1": + licensePic = storeDetail.StoreFrontPic + case "2": + licensePic = storeDetail.StoreInPic + case "5": + licensePic = storeDetail.Licence + licenseSocialCreditCode = storeDetail.LicenceCode + licenseNumber = storeDetail.LicenceCode + licenseLegalPerson = storeDetail.LicenceOwnerName + licenseAddress = storeDetail.LicenceAddress + licenseValidStartDate = storeDetail.LicenceValid + if storeDetail.LicenceExpire == "" { + isLongTime = 1 + } else { + licenseValidity = storeDetail.LicenceExpire + } + case "6": + licensePic = storeDetail.Licence2Image + licenseSocialCreditCode = storeDetail.Licence2Code + licenseNumber = storeDetail.Licence2Code + licenseLegalPerson = storeDetail.LicenceOwnerName + licenseAddress = storeDetail.LicenceAddress + licenseValidStartDate = storeDetail.Licence2Valid + if storeDetail.Licence2Expire == "" { + isLongTime = 1 + } else { + licenseValidity = storeDetail.Licence2Expire + } + } + return licensePic, licenseSocialCreditCode, licenseNumber, licenseLegalPerson, licenseAddress, licenseValidStartDate, licenseValidity, isLongTime + } + var certs []*mtwmapi.MultiPoiCertInfo + for _, v := range strings.Split(vendorInfoMap["poiCert"], ",") { + cert := &mtwmapi.MultiPoiCertInfo{ + Type: utils.Str2Int(v), + LicenseName: poiCertMap[v], + } + cert.LicensePic, cert.LicenseSocialCreditCode, cert.LicenseNumber, cert.LicenseLegalPerson, cert.LicenseAddress, cert.LicenseValidStartDate, cert.LicenseValidity, cert.IsLongTime = switchCertType(v) + certs = append(certs, cert) + } + poiSettleSaveParam.ApplyInfos[0].MultiPoiCertInfos = certs + mtapi := getAPIWithoutToken(vendorOrgCode) + if vendorStoreID, err = mtapi.PoiSettleSave(poiSettleSaveParam); err == nil { + err = mtapi.PoiSettleAuditSubmit([]string{vendorStoreID}) + } + return vendorStoreID, err +} + +func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) { + return err +} + +func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { + var name string + if db == nil { + db = dao.GetDB() + } + mtapi := getAPI(getStoreVendorOrgCode(storeID), storeID, "") + storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM, "") + if err != nil { + return err + } + errList := errlist.New() + + remoteStoreInfo, err := mtapi.PoiGet(storeDetail.VendorStoreID) + if err != nil { + return err + } + mergedStoreStatus := jxutils.MergeStoreStatus(storeDetail.Status, storeDetail.VendorStatus) + name = remoteStoreInfo.Name + if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 { + if storeDetail.VendorStoreName != "" { + name = storeDetail.VendorStoreName + } + // else { + // name = jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM) + // } + } + store := fmt.Sprintf("门店id:%d,门店名称:%s,第三方门店状态:%d,本地修改前门店状态%d,本地门店修改后状态:%d,第三方平台Id(美团):%s", storeID, remoteStoreInfo.Name, remoteStoreInfo.IsOnline, storeDetail.Status, mergedStoreStatus, storeDetail.VendorOrgCode) + event.AddOperateEvent(jxcontext.AdminCtx, jxcontext.AdminCtx.GetTrackInfo(), store, "", "", 10, "UpdateStore") + // openLevel, isOnline := bizStatusJX2Mtwm(mergedStoreStatus) + //TODO 美团暂时不用那个电话 + phone := storeDetail.Tel1 + // if storeDetail.MarketManPhone != "" { + // phone = storeDetail.MarketManPhone + // } else { + // phone = model.VendorStoreTel + // } + params := map[string]interface{}{ + "name": name, //jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM), + "address": storeDetail.Address, // 美团好像地址也不能改的? + "longitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Longitude)), + "latitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Latitude)), + "phone": phone, + "shipping_fee": remoteStoreInfo.ShippingFee, + "shipping_time": remoteStoreInfo.ShippingTime, + "open_level": remoteStoreInfo.OpenLevel, + "is_online": remoteStoreInfo.IsOnline, + "third_tag_name": remoteStoreInfo.ThirdTagName, + "promotion_info": storeDetail.PromoteInfo, + } + // globals.SugarLogger.Debug(utils.Format4Output(params, false)) + if globals.EnableMtwmStoreWrite { + errList.AddErr(mtapi.PoiSave(storeDetail.VendorStoreID, params)) + } + // PoiSave有时会报错:商家已接入美团配送,不可修改门店配送相关信息,这里放弃信息修改 + // if err != nil { + // if utils.IsErrMatch(err, utils.Int2Str(mtwmapi.ErrCodeCanNotModifyStoreDeliveryInfo), nil) { + // globals.SugarLogger.Infof("mtwm UpdateStore vendorStoreID:%s, params:%s failed with err:%v", storeDetail.VendorStoreID, utils.Format4Output(params, true), err) + // if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 { + // err = p.UpdateStoreStatus(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, mergedStoreStatus) + // } else { + // err = nil + // } + // } + // errList.AddErr(err) + // } + if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 { + errList.AddErr(p.UpdateStoreStatus(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, mergedStoreStatus)) + } + errList.AddErr(p.UpdateStoreOpTime(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, storeDetail.GetOpTimeList())) + // errList.AddErr(p.UpdateStoreBoxFee(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID)) + return errList.GetErrListAsOne() +} + +func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { + return "", errors.New("美团外卖不支持此操作") +} + +func (p *PurchaseHandler) onStoreStatusChanged(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) { + var err error + vendorStoreID := msg.FormData.Get("app_poi_code") + storeStatus := 0 + if msg.Cmd == mtwmapi.MsgTypeStoreStatusChanged { + poiStatus := int(utils.Str2Int64(msg.FormData.Get("poi_status"))) + if poiStatus == mtwmapi.MsgPoiStatusOpened { + storeStatus = model.StoreStatusOpened + } else if poiStatus == mtwmapi.MsgPoiStatusClosed { + storeStatus = model.StoreStatusClosed + } else if poiStatus == mtwmapi.MsgPoiStatusOffline { + storeStatus = model.StoreStatusDisabled + } else { + storeStatus, err = p.GetStoreStatus(jxcontext.AdminCtx, "", 0, vendorStoreID) + } + } else if msg.Cmd == mtwmapi.MsgTypeStoreAuditStatusChanged { + auditDetails := []map[string]interface{}{} + auditDetail := msg.FormData.Get("audit_detail") + openFlag := false + openCount := 0 + closeFlag := false + if err = json.Unmarshal([]byte(auditDetail), &auditDetails); err == nil { + for _, v := range auditDetails { + if v["module_status"].(string) == "3" || v["module_status"].(string) == "5" || v["module_status"].(string) == "7" { + closeFlag = true + break + } + if v["module_status"].(string) == "6" { + openCount++ + } + } + if openCount == len(auditDetails) { + openFlag = true + } + if closeFlag { + storeStatus = model.StoreStatusDisabled + } else if openFlag { + storeStatus = model.StoreStatusOpened + } else { + storeStatus = model.StoreStatusClosed + } + } + } + + if err == nil { + err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDMTWM, storeStatus) + } + response = mtwmapi.Err2CallbackResponse(err, "") + // 操作日志(美团外卖) + ctx := jxcontext.AdminCtx + store := fmt.Sprintf("美团外卖回调门店改变回调(营业状态/审核状态):门店id:%s,美团门店状态:%d.[121营业,120休息,18上线,19下线],本地修改后状态[%d]", vendorStoreID, int(utils.Str2Int64(msg.FormData.Get("poi_status"))), storeStatus) + event.AddOperateEvent(ctx, ctx.GetTrackInfo(), store, "", "", 10, "UpdateStore") + return response +} + +func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) { + result, err := getAPI(vendorOrgCode, storeID, "").PoiGet(vendorStoreID) + if err == nil { + return bizStatusMtwm2JX(result.OpenLevel, result.IsOnline), nil + } + return 0, err +} + +func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) { + return err +} + +func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) { + openLevel, isOnline := bizStatusJX2Mtwm(status) + if globals.EnableMtwmStoreWrite { + if isOnline != mtwmapi.PoiStatusOnline { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOffline(vendorStoreID) + } else { + if err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOnline(vendorStoreID); err == nil { // 这个函数成功返回也并不表示上线成功。。。 + remoteStoreInfo, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).PoiGet(vendorStoreID) + if err = err2; err != nil { + return err + } + if remoteStoreInfo.IsOnline == mtwmapi.PoiStatusOnline { + if openLevel == mtwmapi.PoiOpenLevelHaveRest { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiClose(vendorStoreID) + } else { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOpen(vendorStoreID) + } + } else { + err = errors.New("门店还未上线,不能修改营业状态") + } + store := fmt.Sprintf("美团外卖回调门店改变回调(营业状态/审核状态):门店id:%s,美团门店状态:%d.[121营业,120休息,18上线,19下线],本地修改后状态[%d]", vendorStoreID, remoteStoreInfo.OpenLevel, openLevel) + event.AddOperateEvent(ctx, ctx.GetTrackInfo(), store, "", "", 10, "UpdateStore") + } + } + } + return err +} + +func errOpStr2Int16(str string) []int16 { + list := strings.Split(str, "~") + if len(list) >= 2 { + return []int16{jxutils.StrTime2JxOperationTime(list[0]+":00", 0), jxutils.StrTime2JxOperationTime(list[1]+":00", 2359)} + } + return nil +} + +func getOpTimeListFromErr(err error) (opTimeList []int16) { + if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == mtwmapi.ErrCodeOpFailed { + if result := opTimeErrReg.FindStringSubmatch(errExt.ErrMsg()); len(result) >= 2 { + timeStrList := strings.Split(result[1], ",") + for _, v := range timeStrList { + v = utils.TrimBlankChar(v) + if len(v) == len("00:00~02:00") { + opTimeList = append(opTimeList, errOpStr2Int16(v)...) + } + } + } + } + return opTimeList +} + +// 此函数只是简单实现,不支持区间切分,只做单一区间限制 +func constrainOpTimeList(opTimeList, validOpTimeList []int16) (newOpTimeList []int16) { + for k := 0; k < len(opTimeList); k += 2 { + beginTime := opTimeList[k] + endTime := opTimeList[k+1] + for k2 := 0; k2 < len(validOpTimeList); k2 += 2 { + beginTime2 := validOpTimeList[k2] + endTime2 := validOpTimeList[k2+1] + if beginTime >= beginTime2 && beginTime <= endTime2 { + newOpTimeList = append(newOpTimeList, beginTime) + newOpTimeList = append(newOpTimeList, int16(math.Min(float64(endTime), float64(endTime2)))) + } else if beginTime2 >= beginTime && beginTime2 <= endTime { + newOpTimeList = append(newOpTimeList, beginTime2) + newOpTimeList = append(newOpTimeList, int16(math.Min(float64(endTime), float64(endTime2)))) + } + } + } + return newOpTimeList +} + +func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) { + shippingTime := openTimeJX2Mtwm(opTimeList) + if globals.EnableMtwmStoreWrite { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiShipTimeUpdate(vendorStoreID, shippingTime) + if err != nil { + shippingTime = "" + if validOpTimeList := getOpTimeListFromErr(err); len(validOpTimeList) > 0 { + shippingTime = openTimeJX2Mtwm(constrainOpTimeList(opTimeList, validOpTimeList)) + } + if shippingTime != "" { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiShipTimeUpdate(vendorStoreID, shippingTime) + } + } + } + return err +} + +func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) { + vendorStoreIDs, err = getAPIWithoutToken(vendorOrgCode).PoiGetIDs() + return vendorStoreIDs, err +} + +func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) { + return err +} + +func (c *PurchaseHandler) UpdateStoreBoxFee(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (err error) { + boxFee, err := dao.GetSysConfigAsInt64(dao.GetDB(), model.ConfigSysMtwmBoxFee) + if err == nil { + if globals.EnableMtwmStoreWrite && globals.IsProductEnv() { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PackagePriceUpdate(vendorStoreID, 1, int(boxFee)) + } + } + return err +} + +func (c *PurchaseHandler) UpdateStoreLineStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, lineStatus int) (err error) { + if lineStatus == model.StoreStatusOpened { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOnline(vendorStoreID) + } else { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOffline(vendorStoreID) + } + return err +} diff --git a/business/partner/purchase/tiktok_store/store_sku2.go b/business/partner/purchase/tiktok_store/store_sku2.go new file mode 100644 index 000000000..c83b00999 --- /dev/null +++ b/business/partner/purchase/tiktok_store/store_sku2.go @@ -0,0 +1,716 @@ +package tiktok_store + +import ( + "encoding/json" + "regexp" + "strings" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "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/model/dao" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/putils" + "git.rosy.net.cn/jx-callback/globals" +) + +const ( + updateTypeStock = iota + updateTypeStatus + updateTypePrice +) + +const ( + defVendorCatID = 200001903 // 生菜 + + specialStoreID = "8171010" + // specialStoreID = "2523687" +) + +var ( + sensitiveWordRegexp = regexp.MustCompile(`包含敏感词:(\[.*\])`) +) + +func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { + switch funcID { + case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice: + batchSize = mtwmapi.MaxStoreSkuBatchSize + case partner.FuncDeleteStoreSkus: + batchSize = mtwmapi.MaxBatchDeleteSize + case partner.FuncCreateStoreSkus: + batchSize = 1 // 可考虑用批量操作 + case partner.FuncUpdateStoreSkus: + batchSize = 1 // mtwmapi.MaxStoreSkuBatchSize + case partner.FuncGetStoreSkusFullInfo: + batchSize = 1 + case partner.FuncCreateActs: + batchSize = mtwmapi.MaxRetailDiscountCreateBatchSize + case partner.FuncCancelActs: + batchSize = mtwmapi.MaxRetailDiscountDeleteBatchSize + } + return batchSize +} + +func getStoreVendorOrgCode(storeID int) (vendorOrgCode string) { + if storeMap, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, ""); storeMap != nil { + return storeMap.VendorOrgCode + } + return vendorOrgCode +} + +// 门店分类 +func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) { + remoteCats, err := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatList(vendorStoreID) + if err == nil { + cats = convertVendorCatList(remoteCats) + } + return cats, err +} + +func convertVendorCatList(remoteCats []*mtwmapi.RetailCategoryInfo) (cats []*partner.BareCategoryInfo) { + for _, rCat := range remoteCats { + cat := &partner.BareCategoryInfo{ + VendorCatID: rCat.Code, + Name: rCat.Name, + Level: rCat.Level, + Seq: rCat.Sequence, + Children: convertVendorCatList(rCat.Children), + } + if cat.VendorCatID == "" { + cat.VendorCatID = rCat.Name + } + cats = append(cats, cat) + } + return cats +} + +func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) { + return mtwmapi.IsErrCategoryExist(err) +} + +func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { + return mtwmapi.IsErrCategoryNotExist(err) +} + +func catCode2Str(catCode int) (catCodeStr string) { + if catCode > 0 { + catCodeStr = utils.Int2Str(catCode) + } + return catCodeStr +} + +func tryCatName2Code(originName string) (catCodeStr string) { + if intValue := utils.Str2Int64WithDefault(originName, 0); intValue > 0 { + catCodeStr = utils.Int64ToStr(intValue) + if catCodeStr != originName { + catCodeStr = "" + } + } + return catCodeStr +} + +func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + level := 1 + if storeCat.ParentCatName != "" { + level = 2 + } + originName := "" + catName := storeCat.Name + catCode := storeCat.ID + + subCatName := "" + subCatCode := 0 + if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 { + // 修改一级分类 + originName = storeCat.VendorCatID + } + if level == 2 { // 二级分类 + // 创建二级分类 + originName = storeCat.ParentVendorCatID + catName = storeCat.ParentCatName + catCode = storeCat.ParentID + subCatName = storeCat.Name + subCatCode = storeCat.ID + if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 { + // 修改二级分类 + originName = storeCat.VendorCatID + catName = storeCat.Name + catCode = storeCat.ID + subCatName = "" + subCatCode = 0 + } + } + if catName == "" { + panic("catName is empty") + } + catName = utils.FilterEmoji(catName) + subCatName = utils.FilterEmoji(subCatName) + globals.SugarLogger.Debugf("mtwm CreateStoreCategory vendorStoreID:%s, originName:%s, catCode:%d, catName:%s, subCatCode:%d, subCatName:%s, seq:%d", + vendorStoreID, originName, catCode, catName, subCatCode, subCatName, storeCat.Seq) + if globals.EnableMtwmStoreWrite { + // err = api.MtwmAPI.RetailCatUpdate2(vendorStoreID, tryCatName2Code(originName), originName, catCode2Str(catCode), catName, catCode2Str(subCatCode), subCatName, storeCat.Seq) + param4Update := &mtwmapi.Param4UpdateCat{ + CategoryCodeOrigin: tryCatName2Code(originName), + CategoryNameOrigin: originName, + CategoryCode: catCode2Str(catCode), + SecondaryCategoryCode: catCode2Str(subCatCode), + SecondaryCategoryName: subCatName, + Sequence: storeCat.Seq, + } + err = getAPI(storeCat.VendorOrgCode, storeID, vendorStoreID).RetailCatUpdate(vendorStoreID, catName, param4Update) + if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 && p.IsErrCategoryNotExist(err) && originName != "" { // 修改分类名,但分类不存在 + storeCat.CatSyncStatus |= model.SyncFlagNewMask + err = p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat) + } + } + if err == nil { + // storeCat.VendorCatID = utils.FilterEmoji(storeCat.Name) + storeCat.VendorCatID = utils.Int2Str(storeCat.ID) + } + return err +} + +func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { + return p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat) +} + +func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { + if false { + if globals.EnableMtwmStoreWrite { + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID) + } + } else { + var catCodes []string + if catCode := tryCatName2Code(vendorCatID); catCode != "" { + catCodes = []string{catCode} + } + if globals.EnableMtwmStoreWrite { + if level == 1 { + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil) + } else { + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil) + } + } + } + return err +} + +// 门店商品 + +// 多门店平台不需要实现这个接口 + +func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) { + return false +} + +func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) { + return mtwmapi.IsErrSkuNotExist(err) +} + +// func duplicateStoreSkuList(storeSkuList []*dao.StoreSkuSyncInfo, index int) (newStoreSkuList []*dao.StoreSkuSyncInfo) { +// newStoreSkuList = make([]*dao.StoreSkuSyncInfo, len(storeSkuList)) +// for k, v := range storeSkuList { +// tmp := *v +// tmp.SkuName = fmt.Sprintf("%s.%d", tmp.SkuName, index) +// tmp.SkuID = index*1000000 + tmp.SkuID +// newStoreSkuList[k] = &tmp +// } +// return newStoreSkuList +// } + +func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false) + // if err == nil && vendorStoreID == specialStoreID { + // for i := 0; i < 2; i++ { + // p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true) + // } + // } + return failedList, err +} + +func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true) + // if err == nil && vendorStoreID == specialStoreID { + // for i := 0; i < 2; i++ { + // p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true) + // } + // } + return failedList, err +} + +// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义 +func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (failedList []*partner.StoreSkuInfoWithErr, err error) { + var syncType string + foodDataList := make([]map[string]interface{}, len(storeSkuList)) + if isCreate { + syncType = "创建商品" + } else { + syncType = "更新商品" + } + for i, storeSku := range storeSkuList { + isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 + foodData := make(map[string]interface{}) + foodDataList[i] = foodData + foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(storeSku.SkuID) + skus := []map[string]interface{}{ + map[string]interface{}{ + "sku_id": foodData[mtwmapi.KeyAppFoodCode], + }, + } + foodData["skus"] = skus + foodData["name"] = utils.LimitUTF8StringLen(storeSku.SkuName, mtwmapi.MaxSkuNameCharCount) + foodData["description"] = storeSku.Comment + if isNeedUpdatePrice { + foodData["price"] = jxutils.IntPrice2Standard(storeSku.VendorPrice) + } + if storeSku.MinOrderCount != 0 { + foodData["min_order_count"] = storeSku.MinOrderCount + } else { + foodData["min_order_count"] = 1 + } + foodData["unit"] = storeSku.Unit + attr := switchAttr(storeSku.VendorVendorCatID) + if attr != "" { + foodData["common_attr_value"] = attr + } + catCode := tryCatName2Code(storeSku.VendorCatID) + if catCode != "" { + foodData["category_code"] = catCode + } else { + foodData["category_name"] = storeSku.VendorCatID + } + foodData["is_sold_out"] = skuStatusJX2Mtwm(storeSku.MergedStatus) + if true { // vendorStoreID == specialStoreID { + img2 := storeSku.Img2 + img3 := storeSku.Img3 + img4 := storeSku.Img4 + img5 := storeSku.Img5 + if img2 == "" { + img2 = storeSku.Img + } + if img3 == "" { + img3 = storeSku.Img + } + if img4 == "" { + img4 = storeSku.Img + } + if img5 == "" { + img5 = storeSku.Img + } + if storeSku.ImgMix != "" && ((storeSku.BrandID == storeSku.ExBrandID && storeSku.ExBrandID != 0) || storeSku.ExBrandID == 0) { + foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.ImgMix, img2, img3, img4, img5), ",") + } else { + foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, img3, img4, img5), ",") + } + } else { + foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",") + } + if storeSku.DescImg != "" { + foodData["picture_contents"] = storeSku.DescImg + } + foodData["sequence"] = storeSku.GetSeq() + if storeSku.VendorVendorCatID != 0 { + foodData["tag_id"] = utils.Int64ToStr(storeSku.VendorVendorCatID) + } else { + // foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) + } + skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit) + if isNeedUpdatePrice { + skus[0]["price"] = foodData["price"] + } + skus[0]["stock"] = stockCount2Mtwm(model.MaxStoreSkuStockQty) + if storeSku.Upc != "" { + skus[0]["upc"] = storeSku.Upc + } + skus[0]["ladder_box_num"] = storeSku.LadderBoxNum + boxPirce := 0 + if storeSku.MtLadderBoxPrice != 0 { + boxPirce = storeSku.MtLadderBoxPrice + } else { + boxPirce = storeSku.LadderBoxPrice + } + skus[0]["ladder_box_price"] = jxutils.IntPrice2Standard(int64(boxPirce)) + if foodData["tag_id"] != nil { + skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 + } + + } + if globals.EnableMtwmStoreWrite { + if len(foodDataList) == 1 { + foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"])) + if err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]); err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType) + } + } else if len(foodDataList) > 0 { + failedFoodList, err2 := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) + if err = err2; err == nil { + if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType) + // successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } + } else if err2 != nil && len(failedFoodList) == 0 { + if errExt, ok := err2.(*utils.ErrorWithCode); ok { + err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType) + } + } + } + } + for _, storeSku := range storeSkuList { + storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID) + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) { + if len(l) > 0 { + vendorSkuIDs = make([]string, len(l)) + for k, v := range l { + vendorSkuIDs[k] = v.AppFoodCode + } + } + return vendorSkuIDs +} + +func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + if globals.EnableMtwmStoreWrite { + if len(storeSkuList) == 1 { + err = getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID) + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], "删除商品") + } else { + // todo 部分失败 + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) + if err != nil { + if errExt, ok := err.(*utils.ErrorWithCode); ok { + myMap := make(map[string][]*mtwmapi.AppFoodResult) + json.Unmarshal([]byte(errExt.ErrMsg()), &myMap) + failedList = SelectStoreSkuListByFoodList(storeSkuList, myMap["retail_error_list"], storeID, model.VendorChineseNames[model.VendorIDMTWM], "批量删除商品") + } + } + } + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func switchAttr(vendorCatID int64) (attrs string) { + switch vendorCatID { + case 200002727: + return mtwmapi.MtwmSkuAttr200002727 + case 200001555: + return mtwmapi.MtwmSkuAttr200001555 + case 200002728: + return mtwmapi.MtwmSkuAttr200002728 + case 200001519, 200000592: + return mtwmapi.MtwmSkuAttr200000592 + case 200002704, 200002731: + return mtwmapi.MtwmSkuAttr200002731 + case 200002716: + return mtwmapi.MtwmSkuAttr200002716 + case 200002667, 200002713, 200002670: + return mtwmapi.MtwmSkuAttr200002670 + case 200002680: + return mtwmapi.MtwmSkuAttr200002680 + default: + return "" + } + return attrs +} + +func stockCount2Mtwm(stock int) (mtwmStock string) { + return utils.Int2Str(stock) +} + +func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuList []*mtwmapi.BareStoreFoodInfo) { + for _, storeSku := range storeSkuList { + skuInfo := &mtwmapi.BareStoreFoodInfo{ + AppFoodCode: storeSku.VendorSkuID, + Skus: []*mtwmapi.BareStoreSkuInfo{ + &mtwmapi.BareStoreSkuInfo{ + SkuID: storeSku.VendorSkuID, + }, + }, + } + if updateType == updateTypeStock { + skuInfo.Skus[0].Stock = stockCount2Mtwm(storeSku.Stock) + } else if updateType == updateTypePrice { + skuInfo.Skus[0].Price = jxutils.IntPrice2StandardString(storeSku.VendorPrice) + } else { + skuInfo.Skus = nil + } + skuList = append(skuList, skuInfo) + } + return skuList +} + +func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) { + skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus) + mtwmStatus := skuStatusJX2Mtwm(status) + if globals.EnableMtwmStoreWrite { + failedFoodList, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).RetailSellStatus(ctx.GetTrackInfo(), vendorStoreID, skuList, mtwmStatus) + if err = err2; err == nil { + if len(failedFoodList) > 0 { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态") + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + } + } else if err2 != nil && len(failedFoodList) == 0 { + if errExt, ok := err2.(*utils.ErrorWithCode); ok { + err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态") + } + } + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + priceList := storeSku2Mtwm(storeSkuList, updateTypePrice) + if globals.EnableMtwmStoreWrite { + failedFoodList, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).RetailSkuPrice(ctx.GetTrackInfo(), vendorStoreID, priceList) + if err = err2; err == nil { + if len(failedFoodList) > 0 { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格") + } + } else if err2 != nil && len(failedFoodList) == 0 { + if errExt, ok := err2.(*utils.ErrorWithCode); ok { + err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格") + } + } + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + stockList := storeSku2Mtwm(storeSkuList, updateTypeStock) + if globals.EnableMtwmStoreWrite { + failedFoodList, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).RetailSkuStock(ctx.GetTrackInfo(), vendorStoreID, stockList) + if err = err2; err == nil { + if len(failedFoodList) > 0 { + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存") + } + //if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil { + // successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList)) + // } + } else if err2 != nil && len(failedFoodList) == 0 { + if errExt, ok := err2.(*utils.ErrorWithCode); ok { + err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList) + failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存") + } + } + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) { + if mtwmSkuStatus == mtwmapi.SellStatusOnline { + jxSkuStatus = model.SkuStatusNormal + } else { + jxSkuStatus = model.SkuStatusDontSale + } + return jxSkuStatus +} + +func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) { + if len(storeSkuList) == 1 { + skuInfo, err := getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).RetailGet(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID)) + if err != nil { + return nil, err + } + if skuName := vendorSku2Jx(skuInfo); skuName != nil { + skuNameList = append(skuNameList, skuName) + } + } else { + var storeSkuMap map[string]*partner.StoreSkuInfo + if storeSkuList != nil { + storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList) + } + mtapi := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID) + for { + // todo 待优化获取速度 + result, err := mtapi.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit) + if err != nil { + return nil, err + } + if storeSkuMap == nil { + skuNameList = append(skuNameList, vendorSkuList2Jx(result)...) + } else { + for _, v := range result { + if storeSkuMap[v.AppFoodCode] != nil { + if skuName := vendorSku2Jx(v); skuName != nil { + skuNameList = append(skuNameList, skuName) + } + } + } + } + if len(result) < mtwmapi.GeneralMaxLimit { + break + } + } + } + return skuNameList, err +} + +func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) { + if len(appFood.SkuList) == 0 { + globals.SugarLogger.Warnf("vendorSku2Jx, strange appFood:%s", utils.Format4Output(appFood, true)) + return nil + } + prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(appFood.Name) + vendorSku := appFood.SkuList[0] + weight := int(utils.Str2Int64WithDefault(vendorSku.Weight, 0)) + if weight <= 0 { + weight = jxutils.FormatSkuWeight(specQuality, specUnit) + } + skuID := int(utils.Str2Int64WithDefault(vendorSku.SkuID, 0)) + skuName = &partner.SkuNameInfo{ + NameID: int(utils.Str2Int64WithDefault(appFood.AppFoodCode, 0)), + VendorNameID: appFood.AppFoodCode, + UPC: appFood.SkuList[0].Upc, + Prefix: prefix, + Name: name, + Unit: unit, + Status: mtwmSkuStatus2Jx(appFood.IsSoldOut), //此处为之前一个bug 如果吧状态放到切片内层 对于内层函数中映射无法关联 永远获取到的初始值为0 + SkuList: []*partner.SkuInfo{ + &partner.SkuInfo{ + StoreSkuInfo: partner.StoreSkuInfo{ + VendorSkuID: vendorSku.SkuID, + SkuID: skuID, + IsSpecialty: appFood.IsSpecialty, + Stock: int(utils.Str2Int64WithDefault(vendorSku.Stock, partner.UnlimitedStoreSkuStock)), + VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64WithDefault(vendorSku.Price, 0)), + Status: mtwmSkuStatus2Jx(appFood.IsSoldOut), + }, + SkuName: appFood.Name, + Comment: comment, + SpecQuality: float64(specQuality), + SpecUnit: specUnit, + Weight: weight, + }, + }, + PictureList: appFood.PictureList, + } + if appFood.CategoryName != "" { + // todo, 因为当前我们用的是分类名操作这种方式,所以要返回分类名(而不是分类code) + skuName.VendorCatIDList = []string{appFood.CategoryName} + if appFood.SecondaryCategoryName != "" { + skuName.VendorCatIDList = append(skuName.VendorCatIDList, appFood.SecondaryCategoryName) + } + } + return skuName +} + +func vendorSkuList2Jx(appFoodList []*mtwmapi.AppFood) (skuNameList []*partner.SkuNameInfo) { + for _, appFood := range appFoodList { + if skuName := vendorSku2Jx(appFood); skuName != nil { + skuNameList = append(skuNameList, skuName) + } + } + return skuNameList +} + +func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { + return sensitiveWordRegexp +} + +//美团api返回 +func SelectStoreSkuListByFoodList(storeSkuList interface{}, foodList []*mtwmapi.AppFoodResult, storeID int, vendorName, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) { + foodMap := make(map[string]string) + if len(foodList) > 0 { + for _, v := range foodList { + foodMap[v.AppFoodCode] = v.ErrorMsg + } + if storeSkuLists, ok := storeSkuList.([]*partner.StoreSkuInfo); ok { + for _, v := range storeSkuLists { + if foodMap[v.VendorSkuID] != "" { + foodFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: v, + ErrMsg: foodMap[v.VendorSkuID], + StoreID: storeID, + VendoreName: vendorName, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, foodFailed) + } + } + } + if storeSkuLists, ok := storeSkuList.([]*dao.StoreSkuSyncInfo); ok { + for _, v := range storeSkuLists { + if foodMap[v.VendorSkuID] != "" { + storeSkuInfo := &partner.StoreSkuInfo{ + SkuID: v.SkuID, + VendorSkuID: v.VendorSkuID, + NameID: v.NameID, + VendorNameID: v.VendorNameID, + VendorPrice: v.VendorPrice, + Status: v.Status, + } + foodFailed := &partner.StoreSkuInfoWithErr{ + StoreSkuInfo: storeSkuInfo, + ErrMsg: foodMap[v.VendorSkuID], + StoreID: storeID, + VendoreName: vendorName, + SyncType: syncType, + } + selectedStoreSkuList = append(selectedStoreSkuList, foodFailed) + } + } + } + } + return selectedStoreSkuList +} + +func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + actStoreSkuList := putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, storeSkuList) + failedList, err = createOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, actStoreSkuList) + storeSkuMap := putils.StoreSkuList2MapBySkuID(storeSkuList) + for _, v := range actStoreSkuList { + storeSkuMap[v.SkuID].VendorActID = v.VendorActID + } + if len(failedList) > 0 { + err = nil + } + return failedList, err +} + +func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { + return cancelOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, putils.StoreSku2ActStoreSku(model.SyncFlagDeletedMask, vendorStoreID, storeSkuList)) +} + +func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) { + var foodDataList = []map[string]interface{}{} + for _, v := range storeSkuList { + var foodData = make(map[string]interface{}) + if v.IsSpecialty != 0 && v.IsSpecialty == -1 { + v.IsSpecialty = 0 + } + foodData["is_specialty"] = v.IsSpecialty + foodData["app_food_code"] = v.SkuID + foodDataList = append(foodDataList, foodData) + } + if globals.EnableMtwmStoreWrite { + if len(foodDataList) == 1 { + err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) + } else if len(foodDataList) > 0 { + _, err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) + } + } + return err +} diff --git a/business/partner/purchase/tiktok_store/store_sku2_test.go b/business/partner/purchase/tiktok_store/store_sku2_test.go new file mode 100644 index 000000000..e4037c14f --- /dev/null +++ b/business/partner/purchase/tiktok_store/store_sku2_test.go @@ -0,0 +1,64 @@ +package tiktok_store + +import ( + "testing" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/partner" + // _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" +) + +func TestGetStoreSkusFullInfo(t *testing.T) { + skuNameList, err := CurPurchaseHandler.GetStoreSkusFullInfo(jxcontext.AdminCtx, nil, 2, "8967897", nil) + if err != nil { + t.Fatal(err) + } + t.Log(utils.Format4Output(skuNameList, false)) + t.Log(len(skuNameList)) +} + +func TestGetStoreSkusBareInfo(t *testing.T) { + storeSkuList, err := CurPurchaseHandler.GetStoreSkusBareInfo(jxcontext.AdminCtx, "", nil, 2, "2523687", []*partner.StoreSkuInfo{ + &partner.StoreSkuInfo{ + SkuID: 16205, + }, + //&partner.StoreSkuInfo{ + // SkuID: 1306, + //}, + }) + if err != nil { + t.Fatal(err.Error()) + } + t.Log(utils.Format4Output(storeSkuList, false)) + t.Log(len(storeSkuList)) +} + +func TestDeleteStoreAllSkus(t *testing.T) { + err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, 2, "2523687", true) + if err != nil { + t.Fatal(err) + } +} + +func TestDeleteStoreAllCategories(t *testing.T) { + err := CurPurchaseHandler.DeleteStoreAllCategories(jxcontext.AdminCtx, nil, 2, "2523687", true) + if err != nil { + t.Fatal(err) + } +} + +func TestGetStoreCategory(t *testing.T) { + _, err := CurPurchaseHandler.GetStoreCategory(jxcontext.AdminCtx, 2, "2523687", "不存在的分类") + if err == nil { + t.Fatal("应该找不到这个分类") + } + catName := "小月饼" + cat, err := CurPurchaseHandler.GetStoreCategory(jxcontext.AdminCtx, 2, "2523687", catName) + if err != nil { + t.Fatal(err) + } else if cat.Name != catName { + t.Fatal("没有找到正确的商家分类") + } + t.Log(utils.Format4Output(cat, false)) +} diff --git a/business/partner/purchase/tiktok_store/store_sku_test.go b/business/partner/purchase/tiktok_store/store_sku_test.go new file mode 100644 index 000000000..ead1b02f6 --- /dev/null +++ b/business/partner/purchase/tiktok_store/store_sku_test.go @@ -0,0 +1,46 @@ +package tiktok_store + +import ( + "testing" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + // _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" +) + +// func TestSyncStoreCategory(t *testing.T) { +// hint, err := CurPurchaseHandler.SyncStoreCategory(jxcontext.AdminCtx, nil, testShopID, false) +// if err != nil { +// t.Fatal(err) +// } +// t.Log(hint) +// } + +// func TestSyncLocalStoreCategory(t *testing.T) { +// hint, err := CurPurchaseHandler.SyncLocalStoreCategory(jxcontext.AdminCtx, nil, testShopID, true, nil) +// if err != nil { +// t.Fatal(err) +// } +// t.Log(hint) +// } + +// func TestSyncStoreSkus(t *testing.T) { +// hint, err := CurPurchaseHandler.SyncStoreSkus(jxcontext.AdminCtx, nil, testShopID, nil, false, true) +// if err != nil { +// t.Fatal(err) +// } +// t.Log(hint) +// } + +func TestDeleteRemoteSkus(t *testing.T) { + err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, testShopID, testShopVendorID, true) + if err != nil { + t.Fatal(err) + } +} + +func TestDeleteRemoteCategories(t *testing.T) { + err := CurPurchaseHandler.DeleteStoreAllCategories(jxcontext.AdminCtx, nil, testShopID, testShopVendorID, true) + if err != nil { + t.Fatal(err) + } +} diff --git a/business/partner/purchase/tiktok_store/store_test.go b/business/partner/purchase/tiktok_store/store_test.go new file mode 100644 index 000000000..68defac00 --- /dev/null +++ b/business/partner/purchase/tiktok_store/store_test.go @@ -0,0 +1,43 @@ +package tiktok_store + +import ( + "testing" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "git.rosy.net.cn/baseapi/utils" + // _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" +) + +//func TestReadStore(t *testing.T) { +// store, err := CurPurchaseHandler.ReadStore(jxcontext.AdminCtx, "", "4351018") +// if err != nil { +// t.Fatal(err) +// } +// t.Log(utils.Format4Output(store, false)) +//} + +func TestUpdateStore(t *testing.T) { + err := CurPurchaseHandler.UpdateStore(nil, 100002, "test") + if err != nil { + t.Fatal(err) + } +} + +func TestConstrainOpTimeList(t *testing.T) { + timeList := constrainOpTimeList([]int16{830, 1800}, []int16{ + 0, + 200, + 930, + 1700, + }) + t.Log(utils.Format4Output(timeList, false)) + if timeList[0] != 930 || timeList[1] != 1700 { + t.Fatal("constrainOpTimeList failed") + } +} + +func TestGetOpTimeListFromErr(t *testing.T) { + err := utils.NewErrorIntCode("当前配送营业时间为:07:00~24:00", mtwmapi.ErrCodeOpFailed) + list := getOpTimeListFromErr(err) + t.Log(list) +} diff --git a/business/partner/purchase/tiktok_store/waybill.go b/business/partner/purchase/tiktok_store/waybill.go new file mode 100644 index 000000000..ac6a4cc98 --- /dev/null +++ b/business/partner/purchase/tiktok_store/waybill.go @@ -0,0 +1,59 @@ +package tiktok_store + +import ( + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" +) + +var ( + VendorWaybillStatus2StatusMap = map[string]int{ + mtwmapi.WaybillStatusWait4Delivery: model.WaybillStatusNew, + mtwmapi.WaybillStatusPending: model.WaybillStatusPending, + mtwmapi.WaybillStatusAccepted: model.WaybillStatusAccepted, + mtwmapi.WaybillStatusCourierArrived: model.WaybillStatusCourierArrived, + mtwmapi.WaybillStatusPickedup: model.WaybillStatusDelivering, + mtwmapi.WaybillStatusDelivered: model.WaybillStatusDelivered, + mtwmapi.WaybillStatusCanceled: model.WaybillStatusCanceled, + } +) + +func (p *PurchaseHandler) GetWaybillStatusFromVendorStatus(vendorStatus string) int { + if status, ok := VendorWaybillStatus2StatusMap[vendorStatus]; ok { + return status + } + return model.WaybillStatusUnknown +} + +func (c *PurchaseHandler) onWaybillMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) { + waybill := c.callbackMsg2Waybill(msg) + err := partner.CurOrderManager.OnWaybillStatusChanged(waybill) + if err == nil && waybill.Status == model.WaybillStatusDelivering { + c.postFakeMsg(waybill.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusDelivering) + } + return mtwmapi.Err2CallbackResponse(err, "") +} + +func (c *PurchaseHandler) callbackMsg2Waybill(msg *mtwmapi.CallbackMsg) (retVal *model.Waybill) { + orderID := GetOrderIDFromMsg(msg) + vendorStatus := msg.FormData.Get("logistics_status") + retVal = &model.Waybill{ + VendorOrderID: orderID, + OrderVendorID: model.VendorIDMTWM, + VendorWaybillID: orderID, + WaybillVendorID: model.VendorIDMTWM, + CourierName: msg.FormData.Get("dispatcher_name"), + CourierMobile: msg.FormData.Get("dispatcher_mobile"), + VendorStatus: vendorStatus, + Status: c.GetWaybillStatusFromVendorStatus(vendorStatus), + StatusTime: getTimeFromTimestamp(utils.Str2Int64(msg.FormData.Get("time"))), + Remark: "", + + VendorOrgCode: msg.AppID, + } + if retVal.StatusTime == utils.DefaultTimeValue { + retVal.StatusTime = getTimeFromTimestamp(utils.Str2Int64(msg.FormData.Get("timestamp"))) + } + return retVal +} diff --git a/conf/app.conf b/conf/app.conf index a5c49e6a3..44f31943f 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -213,9 +213,6 @@ tiktokAppSecret = "5c08a0465cf0f996af254a03b6c2548defef87ad" tiktokJXDJKey="ttaceeda5333d7a7ab01" #京西到家抖音小程序 TiktokJXDJApiID="ttaceeda5333d7a7ab01" tiktokJXDJSecret="5c8492ec2744fb72bb6cc356983f3cfc317f85d4" -#国美 -gomeiAppKey = "N0R033L2QQFR53" -gomeiAppSecret = "686ffc3e31c24594838baed045563790" [prod] EnableDocs = false @@ -339,9 +336,6 @@ tiktokAppSecret = "5c08a0465cf0f996af254a03b6c2548defef87ad" tiktokJXDJKey="ttaceeda5333d7a7ab01" #京西到家抖音小程序 TiktokJXDJApiID="ttaceeda5333d7a7ab01" tiktokJXDJSecret="5c8492ec2744fb72bb6cc356983f3cfc317f85d4" -#国美 -gomeiAppKey = "N0R033L2QQFR53" -gomeiAppSecret = "686ffc3e31c24594838baed045563790" [jxgy] httpport = 8088 EnableDocs = false @@ -445,9 +439,6 @@ tiktokAppSecret = "5c08a0465cf0f996af254a03b6c2548defef87ad" tiktokJXDJKey="ttaceeda5333d7a7ab01" #京西到家抖音小程序 TiktokJXDJApiID="ttaceeda5333d7a7ab01" tiktokJXDJSecret="5c8492ec2744fb72bb6cc356983f3cfc317f85d4" -#国美 -gomeiAppKey = "N0R033L2QQFR53" -gomeiAppSecret = "686ffc3e31c24594838baed045563790" [test] jdOrgCode = "82029" jdToken = "594ab45a-9a73-4a43-82b0-a64cbd55d883" @@ -634,6 +625,3 @@ tiktokAppSecret = "5c08a0465cf0f996af254a03b6c2548defef87ad" tiktokJXDJKey="ttaceeda5333d7a7ab01" #京西到家抖音小程序 TiktokJXDJApiID="ttaceeda5333d7a7ab01" tiktokJXDJSecret="5c8492ec2744fb72bb6cc356983f3cfc317f85d4" -#国美 -gomeiAppKey = "N0R033L2QQFR53" -gomeiAppSecret = "686ffc3e31c24594838baed045563790" \ No newline at end of file diff --git a/controllers/tiktok_store.go b/controllers/tiktok_store.go index a3e4a4b13..4eae45515 100644 --- a/controllers/tiktok_store.go +++ b/controllers/tiktok_store.go @@ -1,7 +1,9 @@ package controllers import ( + "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api" "git.rosy.net.cn/jx-callback/business/partner/purchase/tiktok_store" + "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego/server/web" ) @@ -10,13 +12,35 @@ type TiktokController struct { web.Controller } -// CallbackTiktok 抖店用户下单订单推送 (tiktokStore) -func (t *TiktokController) CallbackTiktok() { - data, resp := api.TiktokStore.CreateOrderCallback(t.Ctx.Request) - if resp.Code == 200 { - // 业务处理 - tiktok_store.OnCallbackMsg(data) +// CallbackTiktokOrderMsg 抖店用户下单订单推送 (tiktokStore) +func (t *TiktokController) CallbackTiktokOrderMsg() { + // 1.防伪校验 + resp := api.TiktokStore.EventSignChange(t.Ctx.Request) + if resp.Code != 0 { + t.Data["json"] = resp + t.ServeJSON() + return } - t.Data["json"] = resp + + // 2.参数解析 + orderStatus, resp := api.TiktokStore.CreateOrderCallback(t.Ctx.Request) + globals.SugarLogger.Debug("美团订单回调数据打印测试===========", orderStatus) + if resp.Code != 0 { + t.Data["json"] = resp + t.ServeJSON() + return + } + + for _, v := range orderStatus { + resp2 := tiktok_store.OnOrderMsg(v) + if resp2.Code != 0 { + t.Data["json"] = resp2 + t.ServeJSON() + return + } + } + + t.Data["json"] = tiktok_api.CallbackResponse{Code: tiktok_api.CallbackSuccessCode, Msg: tiktok_api.CallbackSuccess} t.ServeJSON() + } diff --git a/globals/api/api.go b/globals/api/api.go index fea5675c9..ab2c4c8e7 100644 --- a/globals/api/api.go +++ b/globals/api/api.go @@ -2,7 +2,6 @@ package api import ( enterprise "git.rosy.net.cn/baseapi/platformapi/enterprise_wechat" - gomei "git.rosy.net.cn/baseapi/platformapi/gome_live_show" "git.rosy.net.cn/baseapi/platformapi/jxprintapi" "git.rosy.net.cn/baseapi/platformapi/qywxapi" "git.rosy.net.cn/baseapi/platformapi/tiktok" @@ -117,8 +116,7 @@ var ( TiktokJXDJApi *tiktok.API //抖音京西到家api TiktokApiID string //抖音商城ID TiktokJXDJApiID string //抖音京西到家ID - GuoMeiApi *gomei.API // 国美api - TiktokStore *tiktokShop.Api + TiktokStore *tiktokShop.API EnterpriseChatHeadApi *enterprise.API // 企业微信api EnterpriseChatMin *enterprise.API // 企业微信小程序api ) @@ -309,9 +307,8 @@ func Init() { if TiktokJXDJApiID = beego.AppConfig.DefaultString("TiktokJXDJApiID", ""); TiktokJXDJApiID != "" { TiktokJXDJApi = tiktok.New(beego.AppConfig.DefaultString("tiktokJXDJSecret", ""), beego.AppConfig.DefaultString("TiktokJXDJApiID", "")) } + // 抖店 TiktokStore = tiktokShop.New(beego.AppConfig.DefaultString("key", ""), beego.AppConfig.DefaultString("sercret", ""), "") - // 国美aip - GuoMeiApi = gomei.New(beego.AppConfig.DefaultString("gomeiAppKey", ""), beego.AppConfig.DefaultString("gomeiAppSecret", ""), "") EnterpriseChatHeadApi = enterprise.New("ww9a156bfa070e1857", "0jBdCjSmoFiOoHIXyeCK9VbGQ82fVNJZ8uMl6JNN7X4") // 通讯录 EnterpriseChatMin = enterprise.NewMin("ww9a156bfa070e1857", "JQsEmSTltHhNgdPIT320YJFphiYmRs-YZa-rCBwplss") // 小程序 } diff --git a/globals/api/apimanager/apimanager.go b/globals/api/apimanager/apimanager.go index 9e89f2baf..f10e89f07 100644 --- a/globals/api/apimanager/apimanager.go +++ b/globals/api/apimanager/apimanager.go @@ -62,8 +62,6 @@ func (a *APIManager) GetAPI(vendorID int, appOrgCode string) (pfAPI interface{}) pfAPI = api.EbaiAPI case model.VendorIDJDShop: pfAPI = api.JdShopAPI - case model.VendorGoMei: - pfAPI = api.GuoMeiApi case model.VendorIDTT: pfAPI = api.TiktokApi } @@ -84,8 +82,6 @@ func (a *APIManager) GetAppOrgCodeList(vendorID int) (appOrgCodeList []string) { appOrgCodeList = []string{api.EbaiAPI.GetSource()} case model.VendorIDJDShop: appOrgCodeList = []string{"2"} - case model.VendorGoMei: - appOrgCodeList = []string{api.GuoMeiApi.GetAppKey()} } return appOrgCodeList }