diff --git a/business/auth2/auth2.go b/business/auth2/auth2.go index 9585578ea..617d6d6db 100644 --- a/business/auth2/auth2.go +++ b/business/auth2/auth2.go @@ -243,7 +243,6 @@ func LoginInternal(ctx *Context, authType, authID, authIDType, authSecret string realAuthID = user.GetID() } if authBindEx, err = handler.VerifySecret(realAuthID, authSecret); err == nil { - // globals.SugarLogger.Debugf("auth2 Login authBindEx:%s", utils.Format4Output(authBindEx, false)) if authBindEx == nil { // mobile, email会返回nil(表示不会新建AuthBind实体) user = userProvider.GetUser(authID, authIDType) authBindEx = &AuthBindEx{ @@ -275,9 +274,9 @@ func LoginInternal(ctx *Context, authType, authID, authIDType, authSecret string userProvider.UpdateLastLogin(user.GetID(), authType, ctx.GetRealRemoteIP()) } //如果是小程序 - if authType == "weixinmini" { + if authType == "weixinmini" || authType == "weixinapp" { appID := strings.Split(authSecret, ",")[0] - if appID == "wx08a5c2a8581414ff" || appID == "wx2d6949f724b2541d" { //菜市或者果园 + if appID == "wx08a5c2a8581414ff" || appID == "wx2d6949f724b2541d" || appID == "wx18111a41fd17f24f" { //菜市或者果园 if user != nil { binds, err := dao.GetUserBindAuthInfo(dao.GetDB(), user.GetID(), 0, nil, "", "", "wx2bb99eb5d2c9b82c") if err != nil { diff --git a/business/auth2/authprovider/weixin/weixin.go b/business/auth2/authprovider/weixin/weixin.go index ccb355a21..fd7df5196 100644 --- a/business/auth2/authprovider/weixin/weixin.go +++ b/business/auth2/authprovider/weixin/weixin.go @@ -15,6 +15,7 @@ const ( AuthTypeWeixin = "wxqrcode" // 微信扫码 AuthTypeMP = "weixinsns" // 公众号 AuthTypeWXNative = "wxnative" // 微信APP + AuthTypeWxApp = "weixinapp" //app微信登录 ) type Auther struct { @@ -26,6 +27,7 @@ var ( AutherObjWX *Auther AutherObjMP *Auther AutherObjNative *Auther + AutherObjApp *Auther ) var ( @@ -47,10 +49,15 @@ func init() { authType: AuthTypeWXNative, } auth2.RegisterAuther(AuthTypeWXNative, AutherObjNative) + + AutherObjApp = &Auther{ + authType: AuthTypeWxApp, + } + auth2.RegisterAuther(AuthTypeWxApp, AutherObjApp) } func (a *Auther) VerifySecret(id, secret string) (authBindEx *auth2.AuthBindEx, err error) { - globals.SugarLogger.Debugf("weixin VerifySecret id:%s secret:%s", secret, secret) + globals.SugarLogger.Debugf("weixin VerifySecret id:%s secret:%s", id, secret) var openID, accessToken string if a.authType != AuthTypeWXNative { state := id @@ -71,7 +78,7 @@ func (a *Auther) VerifySecret(id, secret string) (authBindEx *auth2.AuthBindEx, if err == nil { wxUserinfo, err2 := a.getAPI().SNSGetUserInfo(accessToken, openID) if err = err2; err == nil { - if authBindEx, err = a.UnionFindAuthBind(a.authType, a.getAPI().GetAppID(), []string{AuthTypeWeixin, AuthTypeMP, AuthTypeMini, AuthTypeWXNative}, wxUserinfo.OpenID, wxUserinfo.UnionID, wxUserinfo); err == nil { + if authBindEx, err = a.UnionFindAuthBind(a.authType, a.getAPI().GetAppID(), []string{AuthTypeWeixin, AuthTypeMP, AuthTypeMini, AuthTypeWXNative, AuthTypeWxApp}, wxUserinfo.OpenID, wxUserinfo.UnionID, wxUserinfo); err == nil { authBindEx.UserHint = &auth2.UserBasic{ Name: wxUserinfo.NickName, Avatar: wxUserinfo.HeadImgURL, @@ -86,6 +93,9 @@ func (a *Auther) getAPI() *weixinapi.API { if a.authType == AuthTypeWeixin { return api.WeixinPageAPI } + if a.authType == AuthTypeWxApp { + return api.WeixinApp + } return api.WeixinAPI } diff --git a/business/auth2/authprovider/weixin/weixin_mini.go b/business/auth2/authprovider/weixin/weixin_mini.go index 072ea9573..c8668948f 100644 --- a/business/auth2/authprovider/weixin/weixin_mini.go +++ b/business/auth2/authprovider/weixin/weixin_mini.go @@ -92,6 +92,9 @@ func getWxApp(appID string) (miniApi *weixinapi.API) { if len(appID) > 0 && appID == api.WeixinMiniAppID2 { miniApi = api.WeixinMiniAPI2 } + if len(appID) > 0 && appID == api.WeixinMiniAppIDsc { + miniApi = api.WeixinMiniAPIsc + } return miniApi } diff --git a/business/jxcallback/orderman/fake_jd_order.go b/business/jxcallback/orderman/fake_jd_order.go index f9923f511..2467d5ae1 100644 --- a/business/jxcallback/orderman/fake_jd_order.go +++ b/business/jxcallback/orderman/fake_jd_order.go @@ -33,7 +33,7 @@ func (c *OrderManager) OnNewFakeJdOrder(vendorOrderID string) (err error) { func (c *OrderManager) notifyNewFakeJdOrder(order *model.GoodsOrder) (err error) { db := dao.GetDB() - storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, model.VendorIDJD) + storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, model.VendorIDJD, "") if err != nil { return err } @@ -69,6 +69,6 @@ func notifyWxNewFakeJdOrder(order *model.GoodsOrder, storeID int) (err error) { title := fmt.Sprintf("你有到家菜市新订单%d", order.OrderSeq) content := sb.String() // globals.SugarLogger.Debugf("notifyWxNewFakeJdOrder, orderID:%s, content:%s", order.VendorOrderID, content) - _, err = weixinmsg.SendStoreMessage(jxcontext.AdminCtx, title, content, []int{storeID}, true, true) + _, err = weixinmsg.SendStoreMessage(jxcontext.AdminCtx, title, content, []int{storeID}, "", model.MessageTypeStore, true, true) return err } diff --git a/business/jxcallback/orderman/financial.go b/business/jxcallback/orderman/financial.go index e7e915a86..c9b9a3b61 100644 --- a/business/jxcallback/orderman/financial.go +++ b/business/jxcallback/orderman/financial.go @@ -258,3 +258,5 @@ func (c *OrderManager) UpdataOrderFinancialInfo(orderFinancial *model.OrderFinan // orderFinancial 和 OrderSkuFinancial 数据计算完毕,准备进行更新 return err } + + diff --git a/business/jxcallback/orderman/order.go b/business/jxcallback/orderman/order.go index 93a9c6705..91b42d4d1 100644 --- a/business/jxcallback/orderman/order.go +++ b/business/jxcallback/orderman/order.go @@ -1,15 +1,24 @@ package orderman import ( + "crypto/md5" "errors" "fmt" "math" "strings" "time" + "git.rosy.net.cn/baseapi/platformapi/jdeclpapi" + + "git.rosy.net.cn/jx-callback/business/jxstore/common" + "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jdshop" + "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/platformapi/dingdingapi" + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/jxutils" @@ -21,7 +30,12 @@ import ( "github.com/astaxie/beego/orm" ) +var ( + orderNoBeginTimestamp int64 +) + func init() { + orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() } type tSkuCountPrice struct { @@ -62,7 +76,7 @@ func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, orderStatus *model.Or if err == nil { dao.Commit(db) if !isDuplicated { - err = scheduler.CurrentScheduler.OnOrderNew(order, false) + err = scheduler.CurrentScheduler.OnOrderNew(order, false, false) } } else { dao.Rollback(db) @@ -123,13 +137,18 @@ func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, orderStatus *model // return err // }, "OnAdjustOrder delete order_sku, orderID:%s", order.VendorOrderID) order.AdjustCount = adjustCount + 1 + //扣点的订单需要修改订单的totalshopmoney + if err == nil && order.OrderPayPercentage < 100 { + order2, _ := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID) + order.TotalShopMoney = order2.TotalShopMoney + } isDuplicated, err = c.SaveOrder(order, true, db) } if err == nil { dao.Commit(db) if !isDuplicated { // 因为订单调度器需要的是真实状态,所以用order的状态 - _ = scheduler.CurrentScheduler.OnOrderNew(order, false) + _ = scheduler.CurrentScheduler.OnOrderNew(order, false, false) _ = scheduler.CurrentScheduler.OnOrderStatusChanged(order, orderStatus, false) } } else { @@ -141,9 +160,9 @@ func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, orderStatus *model func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *model.OrderStatus) (err error) { // 有些平台(比如美团外卖),在新订单事件没有成功返回,但在重发订单消息前,订单状态转换,则不会再重发新订单事件,特殊处理一下 if orderStatus.Status == model.OrderStatusAccepted { - if _, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == ErrCanNotFindOrder { + if ordermt, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == ErrCanNotFindOrder { if handler := partner.GetPurchaseOrderHandlerFromVendorID(orderStatus.VendorID); handler != nil { - if order, err2 := handler.GetOrder(vendorOrgCode, orderStatus.VendorOrderID); err2 == nil { + if order, err2 := handler.GetOrder(vendorOrgCode, orderStatus.VendorOrderID, ordermt.VendorStoreID); err2 == nil { c.OnOrderNew(order, orderStatus) } } @@ -186,6 +205,26 @@ func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *m } } } + //更新订单new_earning_price + if order.EarningType == model.EarningTypePoints { + waybill, _ := c.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) + // store, _ := c.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID) + if waybill == nil { + if (order.NewEarningPrice == 0 || order.NewEarningPrice != order.TotalShopMoney*int64(100-order.OrderPayPercentage/2)/int64(100)) && order.OrderPayPercentage <= 50 { + order.NewEarningPrice = order.TotalShopMoney * int64(100-order.OrderPayPercentage/2) / int64(100) + } + } else { + if (order.NewEarningPrice == 0 || order.NewEarningPrice != (order.TotalShopMoney-waybill.DesiredFee)*int64(100-order.OrderPayPercentage/2)/int64(100)) && order.OrderPayPercentage <= 50 { + order.NewEarningPrice = order.TotalShopMoney*int64(100-order.OrderPayPercentage/2)/int64(100) - waybill.DesiredFee + } + } + dao.UpdateEntity(db, order, "NewEarningPrice") + } + } + } else if orderStatus.Status == model.OrderStatusCanceled { + //如果取消订单则要把库存加回去 + if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil { + ModifyOrderSkusStock(db, order, true) } } if !isDuplicated { @@ -200,9 +239,9 @@ func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *m return err } -func (c *OrderManager) ChangeOrderInfo(order *model.GoodsOrder, valid map[string]interface{}) (err error) { +func (c *OrderManager) ChangeOrderInfo(order *model.GoodsOrder) (err error) { db := dao.GetDB() - dao.UpdateEntityLogically(db, order, valid, "jxadmin", nil) + _, err = dao.UpdateEntity(db, order, "ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeLat", "ConsigneeLng", "BuyerComment") return err } @@ -282,8 +321,7 @@ func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao } } - order.ConsigneeName = utils.LimitUTF8StringLen2(order.ConsigneeName, 32) - order.ConsigneeAddress = utils.LimitUTF8StringLen2(order.ConsigneeAddress, 255) + filterOrderInfo(order) created, _, err2 := db.Db.ReadOrCreate(order, "VendorOrderID", "VendorID") if err = err2; err == nil { originalOrder := &model.GoodsOrderOriginal{ @@ -310,9 +348,105 @@ func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao if err == nil { dao.Commit(db) } + //修改商品库存 + if err == nil { + utils.CallFuncAsync(func() { + err = ModifyOrderSkusStock(db, order, false) + }) + } return isDuplicated, err } +func ModifyOrderSkusStock(db *dao.DaoDB, order *model.GoodsOrder, isAdd bool) (err error) { + skus := order.Skus + for _, sku := range skus { + storeSkus, _ := dao.GetStoresSkusInfo(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, []int{sku.SkuID}) + if len(storeSkus) == 0 { + // if !isAdd { + // globals.SugarLogger.Warnf("此订单商品没得storsku,%v,%v", order.VendorOrderID, sku.SkuID) + // } + continue + } + storeSku, stock := storeSkus[0], 0 + if storeSku.Stock == 0 { + if !isAdd { + // globals.SugarLogger.Warnf("此订单商品库存为0,%v,%v", order.VendorOrderID, sku.SkuID) + } + continue + } + if isAdd { + stock = storeSku.Stock + sku.Count + } else { + stock = storeSku.Stock - sku.Count + //如果是进货的订单,进货方门店对应商品要加上这么多库存 + if order.OrderType == model.OrderTypeSupplyGoods { + storeSkus2, _ := dao.GetStoresSkusInfo(db, []int{order.FromStoreID}, []int{sku.SkuID}) + if len(storeSkus2) > 0 { + storeSku3 := storeSkus2[0] + storeSku3.Stock = storeSku3.Stock + sku.Count + dao.UpdateEntity(db, storeSku3, "Stock") + } + } + realStock := checkPriceDefendOrderByStock(db, jxutils.GetSaleStoreIDFromOrder(order), sku.SkuID, stock, storeSku.JxPrice) + if realStock != -1 { + stock = realStock + } + } + storeSku.Stock = stock + dao.UpdateEntity(db, storeSku, "Stock") + if order.VendorID != model.VendorIDJX { + dao.SetStoreSkuSyncStatus(db, order.VendorID, []int{jxutils.GetSaleStoreIDFromOrder(order)}, []int{sku.SkuID}, model.SyncFlagStockMask) + } + } + return err +} + +func filterOrderInfo(order *model.GoodsOrder) { + order.ConsigneeName = utils.LimitUTF8StringLen2(order.ConsigneeName, 32) + order.ConsigneeAddress = utils.LimitUTF8StringLen2(order.ConsigneeAddress, 255) + order.ConsigneeAddress = strings.ReplaceAll(order.ConsigneeAddress, "·", "") +} + +func checkPriceDefendOrderByStock(db *dao.DaoDB, storeID, skuID, stock, jxPrice int) (realStock int) { + var ( + sumStock = 0 + ) + priceDefends, _ := dao.GetPriceDefendOrder(db, "", []int{storeID}, []int{skuID}, []int{jxutils.GetDefendPriceIssue()}, 0, 1, 0, 1, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefends) == 0 { + return -1 + } + for _, v := range priceDefends { + sumStock += v.Count + } + //如果现库存小于等于用户守价的库存,就要开始了 + //如果小于,要按照守价时间的先后来决定 + //如果等于,就刚好全部成功,然后库存清0 + if stock < sumStock { + tStock := stock + for _, v := range priceDefends { + if tStock <= v.Count { + tStock -= v.Count + v.IsSuccess = model.YES + v.RealPrice = int64(jxPrice) + dao.UpdateEntity(db, v, "IsSuccess", "RealPrice") + } else { + continue + } + } + realStock = tStock + } else if stock == sumStock { + for _, v := range priceDefends { + v.IsSuccess = model.YES + v.RealPrice = int64(jxPrice) + dao.UpdateEntity(db, v, "IsSuccess", "RealPrice") + } + realStock = 0 //库存清0 + } else { + realStock = -1 + } + return realStock +} + func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.DaoDB, storePayPercentage, changePriceType int) (err error) { globals.SugarLogger.Debugf("updateOrderSkuOtherInfo orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID) jxStoreID := jxutils.GetShowStoreIDFromOrder(order) @@ -335,7 +469,13 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. } } if len(vendorSkuIDs) > 0 { - l, err := dao.GetStoreSkuPriceAndWeight(db, order.VendorStoreID, order.VendorID, vendorSkuIDs) + var vendorStoreID string + if order.VendorID == model.VendorIDJDShop && order.VendorOrgCode == "1" { + vendorStoreID = model.JdShopMainVendorStoreID + } else { + vendorStoreID = order.VendorStoreID + } + l, err := dao.GetStoreSkuPriceAndWeight(db, vendorStoreID, order.VendorID, vendorSkuIDs) if err != nil { globals.SugarLogger.Warnf("updateOrderSkuOtherInfo orderID:%s failed with err:%v", order.VendorOrderID, err) return err @@ -349,15 +489,42 @@ func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao. if intVendorSkuID != 0 && v.VendorSkuID != "-70000" { // todo hard code skuBindInfo := skumapper[v.VendorSkuID] if skuBindInfo == nil { + if v.ShopPrice == 0 { + v.ShopPrice = v.SalePrice * 70 / 100 + } globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku找不到门店价格(或商品映射),orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.VendorSkuID, v) } else { - v.JxSkuID = skuBindInfo.SkuID // TODO 客户端当前逻辑认为SkuID为0为赠品 if v.SkuID == 0 { v.SkuID = v.JxSkuID } - v.ShopPrice = int64(skuBindInfo.Price) + v.JxSkuID = skuBindInfo.SkuID + //京东商城的话,门店里可能取不到对应商品 + if order.VendorID == model.VendorIDJDShop { + if v.SkuID == 0 && v.JxSkuID != 0 { + v.SkuID = v.JxSkuID + } + // v.JxSkuID = v.SkuID + storeSkus, _ := dao.GetStoresSkusInfo(db, []int{order.StoreID}, []int{v.SkuID}) + if len(storeSkus) > 0 { + v.ShopPrice = int64(storeSkus[0].Price) + } else { + v.ShopPrice = v.SalePrice * 70 / 100 + } + } else { + v.ShopPrice = int64(skuBindInfo.Price) + if v.ShopPrice == 0 { + v.ShopPrice = v.SalePrice * 70 / 100 + } + } + v.SkuName = jxutils.ComposeSkuNameOriginal(skuBindInfo.Prefix, skuBindInfo.Name, skuBindInfo.Comment, skuBindInfo.Unit, skuBindInfo.SpecQuality, skuBindInfo.SpecUnit, 0) v.Weight = skuBindInfo.Weight // 以本地信息中的WEIGHT为准 + //饿鲜达的订单做一下处理 + if strings.Contains(order.StoreName, model.ExdStoreName) { + if v.SkuID == 0 && !strings.Contains(v.SkuName, "免费") { + v.SkuID = v.JxSkuID + } + } if skuBindInfo.Price == 0 { globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku门店价格为零(一般原因为没有门店价格信息),orderID:%s, StoreID:%d, SkuID:%d, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.JxSkuID, v) } @@ -428,9 +595,6 @@ func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) { } } if len(skuIDMap) > 0 { - if order.VendorOrderID == "5000356075877900459" { - fmt.Println("testupdateSingleOrderEarningPrice", order.VendorOrderID) - } actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, model.ActTypeAll, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt) if err != nil { globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err) @@ -455,7 +619,12 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao payPercentage := 0 changePriceType := model.StoreChangePriceTypeDirect - storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID) + var storeDetail *dao.StoreDetail + if order.VendorID == model.VendorIDJDShop { + storeDetail, err = dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID, order.VendorOrgCode) + } else { + storeDetail, err = dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID, "") + } if err != nil { if !dao.IsNoRowsError(err) { globals.SugarLogger.Warnf("updateOrderOtherInfo GetStoreDetailByVendorStoreID orderID:%s, VendorStoreID:%s, error:%v", order.VendorOrderID, order.VendorStoreID, err) @@ -467,8 +636,20 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao err = nil } else { order.JxStoreID = storeDetail.Store.ID - payPercentage = storeDetail.PayPercentage changePriceType = int(storeDetail.ChangePriceType) + //判断订单结算比例 + if storeDetail.VendorPayPercentage != 0 { + payPercentage = storeDetail.VendorPayPercentage + } else { + payPercentage = storeDetail.PayPercentage + } + if payPercentage < 50 { + order.EarningType = model.EarningTypePoints + } else { + order.EarningType = model.EarningTypeQuote + } + order.OrderPayPercentage = payPercentage + order.CreateDeliveryType = storeDetail.CreateDeliveryType } if err = c.updateOrderSkuOtherInfo(order, db, payPercentage, changePriceType); err == nil { jxutils.RefreshOrderSkuRelated(order) @@ -568,6 +749,14 @@ func (c *OrderManager) loadOrderSku(db *dao.DaoDB, vendorOrderID string, vendorI return orderSkus } +func (c *OrderManager) LoadStoreDetail(storeID, vendorID int) (storeDetail *dao.StoreDetail, err error) { + var ( + db = dao.GetDB() + ) + storeDetail, err = dao.GetStoreDetail(db, storeID, vendorID, "") + return storeDetail, err +} + func (c *OrderManager) loadOrder(vendorOrderID, vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) { db1 := dao.GetDB() db := db1.Db @@ -799,7 +988,7 @@ func (c *OrderManager) RefreshHistoryOrdersEarningPrice(ctx *jxcontext.Context, } else { storeID = order.StoreID } - store, _ := dao.GetStoreDetail(db, storeID, order.VendorID) + store, _ := dao.GetStoreDetail(db, storeID, order.VendorID, "") payPercentage := store.PayPercentage if payPercentage <= 50 { order.NewEarningPrice = order.TotalShopMoney * int64((100 - payPercentage/2)) / 100 @@ -985,9 +1174,14 @@ func GetOrderSimpleInfo(ctx *jxcontext.Context, vendorOrderID string) (getOrderS FROM goods_order a JOIN store b ON IF(a.store_id <> '', a.store_id, a.jx_store_id) = b.id LEFT JOIN waybill c ON c.vendor_order_id = a.vendor_order_id - WHERE a.vendor_order_id = ? + WHERE (a.vendor_order_id LIKE ? OR a.consignee_mobile LIKE ?) + ORDER BY a.order_created_at DESC + LIMIT 1 ` - sqlParams := []interface{}{vendorOrderID} + sqlParams := []interface{}{ + "%" + vendorOrderID + "%", + "%" + vendorOrderID + "%", + } err = dao.GetRow(db, &getOrderSimpleInfoResult, sql, sqlParams) if getOrderSimpleInfoResult == nil { return getOrderSimpleInfoResult, fmt.Errorf("未查询到该订单的信息!") @@ -995,3 +1189,801 @@ func GetOrderSimpleInfo(ctx *jxcontext.Context, vendorOrderID string) (getOrderS return getOrderSimpleInfoResult, err } + +func SaveJdsOrders(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd time.Time) (err error) { + var ( + pageSize = 20 + ) + orderResult, err := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), 1, pageSize) + if err != nil { + noticeMsg := fmt.Sprintf("京东商城保存订单出错!(多半是cookie过期了),err :[%v]", err) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "DDC5657B43EE11E9A9FF525400E86DC0", "cookie", noticeMsg) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "cookie", noticeMsg) + return err + } + orders, err := result2Orders(ctx, orderResult) + if orderResult.TotalCount > pageSize { + for pageNO := 2; pageNO < orderResult.TotalCount/pageSize+1; pageNO++ { + orderResult, _ := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), pageNO, pageSize) + orders2, _ := result2Orders(ctx, orderResult) + orders = append(orders, orders2...) + } + } + for _, order := range orders { + order.StoreID = 102919 + order.JxStoreID = 102919 + order.StoreName = "商城模板(成都发货)" + order.VendorStoreID = model.JdShopMainVendorStoreID + partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) + globals.SugarLogger.Debugf("SaveJdsOrders, order: [%v]", utils.Format4Output(order, false)) + noticeMsg := fmt.Sprintf("京东商城新订单,订单号:[%v] ,将要发到的门店id:[%v] , 门店名:[%v]", order.VendorOrderID, order.StoreID, order.StoreName) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "DDC5657B43EE11E9A9FF525400E86DC0", "京东商城来新订单了!", noticeMsg) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "京东商城来新订单了!", noticeMsg) + } + return err +} + +func result2Orders(ctx *jxcontext.Context, result *jdshopapi.AllOrdersResult) (orders []*model.GoodsOrder, err error) { + for _, jdsOrder := range result.OrderList { + //等待付款的排除 + if jdsOrder.OrderStatus != jdshopapi.JdsOrderStatusWaittingExport && jdsOrder.OrderStatus != jdshopapi.JdsOrderStatusPause { + continue + } + //有可能是库里已经有这个订单了 + orderE, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(jdsOrder.OrderID)+"000001", model.VendorIDJDShop) + if orderE != nil { + continue + } + orderDetail, err := api.JdShopAPI.OrderDetail(utils.Int64ToStr(jdsOrder.OrderID)) + if err != nil { + globals.SugarLogger.Debugf("jds OrderDetail error: %v", err.Error()) + continue + } + order := &model.GoodsOrder{ + VendorOrderID2: utils.Int64ToStr(jdsOrder.OrderID), + VendorOrderID: utils.Int64ToStr(jdsOrder.OrderID) + "000001", + 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)), + StoreName: jdsOrder.StoreName, + OrderCreatedAt: utils.Str2Time(jdsOrder.OrderCreateTime + ":00"), + ConsigneeAddress: orderDetail.ConsigneeAddress, + ConsigneeName: orderDetail.ConsigneeName, + ActualPayPrice: orderDetail.ActualPayPrice, + Status: model.OrderStatusNew, + TotalShopMoney: utils.Float64TwoInt64(math.Round(utils.Int64ToFloat64(orderDetail.ActualPayPrice) * jdshopapi.JdsPayPercentage)), + DeliveryFlag: model.OrderDeliveryFlagMaskScheduleDisabled, + DeliveryType: model.OrderDeliveryTypeStoreSelf, + StatusTime: utils.Str2Time(jdsOrder.OrderCreateTime + ":00"), + OrderSeq: 0, + VendorOrgCode: "1", + } + //获取真实手机号 + fakeMobile, err := api.JdShopAPI.PhoneSensltiveInfo(order.VendorOrderID2, orderDetail.MobileKey) + if err != nil { + globals.SugarLogger.Debugf("jds PhoneSensltiveInfo error: %v", err.Error()) + continue + } else { + order.ConsigneeMobile = jxutils.DecryptDESECB([]byte(fakeMobile), []byte(jdshopapi.JdsMobileKey)) + } + if order.TotalShopMoney < 100 { + order.TotalShopMoney = 100 + } + if order.ConsigneeAddress != "" { + lng, lat, _ := api.AutonaviAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "") + order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng) + order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat) + } + storeList, err := common.GetStoreListByLocation(ctx, jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), 5000, false, true, 0) + if err != nil { + globals.SugarLogger.Debugf("jds GetStoreListByLocation error: %v", err.Error()) + continue + } + order.StoreID = storeList[0].ID + order.StoreName = storeList[0].Name + storeMaps, _ := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDJDShop}, []int{order.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") + if len(storeMaps) > 0 { + order.VendorStoreID = storeMaps[0].VendorStoreID + } + //如果是暂停,表示是预订单 + if jdsOrder.OrderStatus == jdshopapi.JdsOrderStatusPause { + order.BusinessType = model.BusinessTypeDingshida + order.ExpectedDeliveredTime = utils.Str2Time(orderDetail.ExpectedDeliveredTime) + order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour) + } else if jdsOrder.OrderStatus == jdshopapi.JdsOrderStatusWaittingExport { + order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour) + order.BusinessType = model.BusinessTypeImmediate + } else { + globals.SugarLogger.Errorf("未知的京东商城订单状态!status : %v", jdsOrder.OrderStatus) + } + + //结算类型 + storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), order.StoreID, model.VendorIDJDShop, "") + if storeDetail != nil { + if storeDetail.PayPercentage < 50 { + order.EarningType = model.EarningTypePoints + } else { + order.EarningType = model.EarningTypeQuote + } + } + setJdsOrderSeq(order) + for _, v := range jdsOrder.OrderItems { + sku := &model.OrderSku{ + VendorID: model.VendorIDJDShop, + VendorOrderID: order.VendorOrderID, + Count: v.SkuNum, + VendorSkuID: utils.Int64ToStr(v.SkuID), + SkuName: v.SkuName, + VendorPrice: jxutils.StandardPrice2Int(v.JdPrice), + SalePrice: jxutils.StandardPrice2Int(v.JdPrice), + } + var storeSku *model.StoreSkuBind + sql := ` + SELECT * FROM store_sku_bind WHERE store_id = ? AND jds_id = ? AND deleted_at = ? + ` + sqlParams := []interface{}{model.JdShopMainStoreID, v.SkuID, utils.DefaultTimeValue} + err = dao.GetRow(dao.GetDB(), &storeSku, sql, sqlParams) + if storeSku != nil { + sku.SkuID = storeSku.SkuID + } + _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.SkuName) + sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit) + order.Skus = append(order.Skus, sku) + } + orders = append(orders, order) + } + return orders, err +} + +func setJdsOrderSeq(order *model.GoodsOrder) (err error) { + type tCount struct { + Count int `json:"count"` + } + var counts []*tCount + sql := ` + SELECT count(*) count FROM goods_order WHERE store_id = ? AND order_created_at >= ? AND order_created_at <= ? AND vendor_id = ? + ` + sqlParams := []interface{}{ + order.StoreID, utils.Time2Date(time.Now()), utils.Time2Date(time.Now().AddDate(0, 0, 1)), order.VendorID, + } + err = dao.GetRows(dao.GetDB(), &counts, sql, sqlParams) + order.OrderSeq = counts[0].Count + 1 + return err +} + +func MergeJdsOrders(ctx *jxcontext.Context, vendorOrderIDs []string) (vendorOrderIDJds string, err error) { + globals.SugarLogger.Debugf("jds MergeJdsOrders vendorOrderIDs: %v", vendorOrderIDs) + var ( + db = dao.GetDB() + orders []*model.GoodsOrder + orderSkus []*model.OrderSku + orderIDs []string + storeDuplicate = make(map[int]int) + storeID int + ) + for _, vendorOrderID := range vendorOrderIDs { + order, _ := dao.GetSimpleOrder(db, vendorOrderID) + if err != nil || order == nil { + return "", fmt.Errorf("未查询到该订单!订单号:[%v]", vendorOrderID) + } + if order.Status >= model.OrderStatusDelivering && order.Status != model.OrderStatusCanceled { + return "", fmt.Errorf("暂不支持此状态的订单进行转移!订单号:[%v]", vendorOrderID) + } + if order.VendorID != model.VendorIDJDShop { + return "", fmt.Errorf("暂不支持非京狗的订单进行转移!订单号:[%v]", vendorOrderID) + } + storeDuplicate[jxutils.GetSaleStoreIDFromOrder(order)] = jxutils.GetSaleStoreIDFromOrder(order) + orders = append(orders, order) + + //订单商品 + skus, _ := dao.GetSimpleOrderSkus(db, order.VendorOrderID, nil) + orderSkus = append(orderSkus, skus...) + + orderIDs = append(orderIDs, vendorOrderID) + } + if len(storeDuplicate) > 1 { + return "", fmt.Errorf("只能选择相同门店的订单进行合并!") + } else { + storeID = jxutils.GetSaleStoreIDFromOrder(orders[0]) + } + for _, order := range orders { + var waybill *model.Waybill + //将订单和运单取消 + waybills, err := dao.GetWaybills(db, order.VendorOrderID) + if err != nil { + return "", err + } + if len(waybills) > 0 { + for _, v := range waybills { + if v.Status != model.WaybillStatusCanceled { + waybill = v + } + } + if waybill != nil { + if waybill.WaybillVendorID != model.VendorIDJDWL { + if handler := partner.GetDeliveryPlatformFromVendorID(waybill.WaybillVendorID); handler != nil { + err = handler.Handler.CancelWaybill(waybill, 0, "订单合并被取消") + } + } + } + } + if err = jdshop.ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单合并被取消"); err != nil { + return "", err + } + } + //重新构建order的数据 + storeMaps, err := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") + if err != nil || len(storeMaps) == 0 { + return "", fmt.Errorf("该门店未绑定京狗平台,请先绑定后再转移!门店:[%v]", storeID) + } + stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") + var ( + newEarningPrice int64 + actualPrice int64 + shopPrice int64 + salePrice int64 + totalShop int64 + ) + for _, v := range orders { + newEarningPrice += v.NewEarningPrice + actualPrice += v.ActualPayPrice + shopPrice += v.ShopPrice + salePrice += v.SalePrice + totalShop += v.TotalShopMoney + } + store := stores[0] + order := orders[0] + order.ID = 0 + order.NewEarningPrice = newEarningPrice + order.ActualPayPrice = actualPrice + order.SalePrice = salePrice + order.ShopPrice = shopPrice + order.TotalShopMoney = totalShop + order.VendorOrderID = utils.Int64ToStr(utils.Str2Int64(orders[0].VendorOrderID2)*10000) + utils.Int2Str(time.Now().Second()) + if len(order.VendorOrderID) < 18 { + order.VendorOrderID = order.VendorOrderID + "0" + } + order.VendorOrderID2 = strings.Join(orderIDs, ",") + order.Status = model.OrderStatusNew + setJdsOrderSeq(order) + if order.BusinessType == model.BusinessTypeImmediate { + var ( + opentime1 = jxutils.JxOperationTime2TimeByDate(store.OpenTime1, order.CreatedAt) + opentime2 = jxutils.JxOperationTime2TimeByDate(store.OpenTime2, order.CreatedAt) + closetime1 = jxutils.JxOperationTime2TimeByDate(store.CloseTime1, order.CreatedAt) + closetime2 = jxutils.JxOperationTime2TimeByDate(store.CloseTime2, order.CreatedAt) + orderCreatedAt = order.CreatedAt + ) + if store.OpenTime1 == 0 || store.CloseTime1 == 0 { + return "", fmt.Errorf("该门店没有营业时间,不能接单!门店:[%v]", storeID) + } + if !(orderCreatedAt.Sub(opentime1) >= 0 && orderCreatedAt.Sub(closetime1) <= 0) { + if store.OpenTime2 != 0 && store.CloseTime2 != 0 { + if !(orderCreatedAt.Sub(opentime2) >= 0 && orderCreatedAt.Sub(closetime2) <= 0) { + if orderCreatedAt.Sub(opentime1) < 0 { + order.ExpectedDeliveredTime = opentime1 + order.BusinessType = model.BusinessTypeDingshida + } else { + if orderCreatedAt.Sub(opentime2) < 0 { + order.ExpectedDeliveredTime = opentime2 + } else { + order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1) + } + order.BusinessType = model.BusinessTypeDingshida + } + } + } else { + if orderCreatedAt.Sub(opentime1) < 0 { + order.ExpectedDeliveredTime = opentime1 + } else { + order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1) + } + order.BusinessType = model.BusinessTypeDingshida + } + } + } + //结算类型 + if store.PayPercentage < 50 { + order.EarningType = model.EarningTypePoints + } else { + order.EarningType = model.EarningTypeQuote + } + if storeID != model.JdShopMainStoreID { + order.DeliveryFlag = model.NO + } + //skus + for _, sku := range orderSkus { + sku.VendorOrderID = order.VendorOrderID + sku.ID = 0 + } + order.Skus = orderSkus + err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) + vendorOrderIDJds = order.VendorOrderID + return vendorOrderIDJds, err +} + +func TransferJdsOrder(ctx *jxcontext.Context, vendorOrderID string, storeID int) (vendorOrderIDJds string, err error) { + globals.SugarLogger.Debugf("jds TransferJdsOrder vendorOrderID: %v, storeID : %v", vendorOrderID, storeID) + var ( + db = dao.GetDB() + waybill *model.Waybill + ) + order, err := dao.GetSimpleOrder(db, vendorOrderID) + if err != nil || order == nil { + return "", fmt.Errorf("未查询到该订单!订单号:[%v]", vendorOrderID) + } + if order.Status >= model.OrderStatusDelivering && order.Status != model.OrderStatusCanceled { + return "", fmt.Errorf("暂不支持此状态的订单进行转移!") + } + if order.VendorID != model.VendorIDJDShop && order.VendorID != model.VendorIDJX { + return "", fmt.Errorf("暂不支持该平台的订单进行转移!") + } + skus, err := dao.GetSimpleOrderSkus(db, vendorOrderID, nil) + if err != nil || order == nil { + return "", fmt.Errorf("未查询到该订单商品!订单号:[%v]", vendorOrderID) + } + //将订单和运单取消 + waybills, err := dao.GetWaybills(db, vendorOrderID) + if err != nil { + return "", err + } + if len(waybills) > 0 { + for _, v := range waybills { + if v.Status != model.WaybillStatusCanceled { + waybill = v + } + } + if waybill != nil { + if handler := partner.GetDeliveryPlatformFromVendorID(waybill.WaybillVendorID); handler != nil { + err = handler.Handler.CancelWaybill(waybill, 0, "订单转移被取消") + } + } + } + //重新构建order的数据 + storeMaps, err := dao.GetStoresMapList(db, []int{order.VendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", order.VendorOrgCode) + if err != nil || len(storeMaps) == 0 { + return "", fmt.Errorf("该门店未绑定平台,请先绑定后再转移!门店:[%v]", storeID) + } + stores, err := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") + if len(storeMaps) > 0 && len(stores) > 0 { + if storeMaps[0].VendorStoreID == "" { + return "", fmt.Errorf("该门店未绑定平台,或绑定有误,请联系技术部!门店:[%v]", storeID) + } + order.StoreID = storeID + order.StoreName = stores[0].Name + order.VendorStoreID = storeMaps[0].VendorStoreID + //如果是立即达的订单,要判断一下下单时间是否在门店营业时间范围内 + //若没有,则要把这个订单变成定时达,预计送达时间改为门店的营业时间 + //如果门店没有营业时间,则直接报错 + if order.BusinessType == model.BusinessTypeImmediate { + store := stores[0] + var ( + opentime1 = jxutils.JxOperationTime2TimeByDate(store.OpenTime1, order.OrderCreatedAt) + opentime2 = jxutils.JxOperationTime2TimeByDate(store.OpenTime2, order.OrderCreatedAt) + closetime1 = jxutils.JxOperationTime2TimeByDate(store.CloseTime1, order.OrderCreatedAt) + closetime2 = jxutils.JxOperationTime2TimeByDate(store.CloseTime2, order.OrderCreatedAt) + orderCreatedAt = order.OrderCreatedAt + ) + if store.OpenTime1 == 0 || store.CloseTime1 == 0 { + return "", fmt.Errorf("该门店没有营业时间,不能接单!门店:[%v]", storeID) + } + if closetime1.Sub(opentime1) <= time.Hour { + return "", fmt.Errorf("该门店营业时间间隔过小,请确认!门店:[%v]", storeID) + } + if !(orderCreatedAt.Sub(opentime1) >= 0 && orderCreatedAt.Sub(closetime1) <= 0) { + if store.OpenTime2 != 0 && store.CloseTime2 != 0 { + if !(orderCreatedAt.Sub(opentime2) >= 0 && orderCreatedAt.Sub(closetime2) <= 0) { + if orderCreatedAt.Sub(opentime1) < 0 { + order.ExpectedDeliveredTime = opentime1 + order.BusinessType = model.BusinessTypeDingshida + } else { + if orderCreatedAt.Sub(opentime2) < 0 { + order.ExpectedDeliveredTime = opentime2 + } else { + order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1) + } + order.BusinessType = model.BusinessTypeDingshida + } + } + } else { + if orderCreatedAt.Sub(opentime1) < 0 { + order.ExpectedDeliveredTime = opentime1 + } else { + order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1) + } + order.BusinessType = model.BusinessTypeDingshida + } + } + } + //结算类型 + if stores[0].PayPercentage < 50 { + order.EarningType = model.EarningTypePoints + } else { + order.EarningType = model.EarningTypeQuote + } + } else { + return "", fmt.Errorf("未查询到该门店对应的平台信息!门店:[%v]", order.StoreID) + } + if order.VendorID == model.VendorIDJDShop { + if len(order.VendorOrderID) > 12 { + var goodsOrders []*model.GoodsOrder + sql := ` + SELECT * FROM goods_order WHERE vendor_order_id2 = ? ORDER BY vendor_order_id DESC + ` + sqlParams := []interface{}{order.VendorOrderID2} + err = dao.GetRows(db, &goodsOrders, sql, sqlParams) + for _, order := range goodsOrders { + if order.Status != model.OrderStatusCanceled { + err = jdshop.ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单转移被取消") + } + } + // suffix := utils.Str2Int(goodsOrders[0].VendorOrderID[12:len(goodsOrders[0].VendorOrderID)]) + // suffix++ + if len(order.VendorOrderID2) > 18 { + order.VendorOrderID2 = order.VendorOrderID2[0:12] + } + order.VendorOrderID = utils.Int64ToStr(utils.Str2Int64(order.VendorOrderID2)*10000) + utils.Int2Str(time.Now().Second()) + if len(order.VendorOrderID) < 18 { + order.VendorOrderID = order.VendorOrderID + "0" + } + } + if storeID != model.JdShopMainStoreID { + order.DeliveryFlag = model.NO + } + err = jdshop.ChangeOrderStatus(vendorOrderID, model.OrderStatusCanceled, "订单转移被取消") + if err != nil { + return "", err + } + order.Status = model.OrderStatusNew + if order.ActualPayPrice == 0 { + msg, err := jdshop.GetJdsOrder(order.VendorOrderID2, order.VendorOrgCode) + if err == nil { + 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) + } + } + } else { + order.VendorOrderID2 = order.VendorOrderID + order.VendorOrderID = utils.Int64ToStr(jxutils.GenOrderNo()) + order.DeliveryFlag = model.NO + orderStatus := &model.OrderStatus{ + VendorOrderID: vendorOrderID, + VendorID: model.VendorIDJX, + OrderType: model.OrderTypeOrder, + RefVendorOrderID: vendorOrderID, + RefVendorID: model.VendorIDJX, + VendorStatus: utils.Int2Str(model.OrderStatusCanceled), + Status: model.OrderStatusCanceled, + StatusTime: time.Now(), + Remark: "订单转移被取消", + } + jxutils.CallMsgHandlerAsync(func() { + err = partner.CurOrderManager.OnOrderStatusChanged(order.VendorOrgCode, orderStatus) + }, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJX)) + if err != nil { + return "", err + } + if order.VendorOrgCode == "1" { + order.Status = model.OrderStatusAccepted + } else { + order.Status = model.OrderStatusNew + } + } + for _, sku := range skus { + sku.VendorOrderID = order.VendorOrderID + sku.ID = 0 + order.Skus = append(order.Skus, sku) + } + setJdsOrderSeq(order) + err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order)) + vendorOrderIDJds = order.VendorOrderID + return vendorOrderIDJds, err +} + +func SendJdwlForJdsOrder(ctx *jxcontext.Context, vendorOrderID string) (err error) { + db := dao.GetDB() + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJDShop) + if order == nil || err != nil { + return fmt.Errorf("目前只支持京狗订单创建!") + } + if order.Status >= model.OrderStatusDelivering { + return fmt.Errorf("订单当前状态不支持创建!") + } + waybill := &model.Waybill{} + waybills, err := dao.GetWaybills(db, vendorOrderID) + if err != nil { + return err + } + if len(waybills) > 0 { + for _, v := range waybills { + if v.Status != model.WaybillStatusCanceled { + waybill = v + } + } + if handler := partner.GetDeliveryPlatformFromVendorID(model.VendorIDJDWL); handler != nil { + err = handler.Handler.CancelWaybill(waybill, 0, "订单已发送其他物流") + } + if err != nil { + return err + } + } + var vendorWaybillID string + if order.StoreID == model.JdShopMainStoreID { + var ( + goodsNos []string + prices []string + quantities []string + ) + for _, v := range order.Skus { + skus, err := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil) + if err != nil || len(skus) == 0 { + continue + } + goodsNos = append(goodsNos, skus[0].EclpID) + prices = append(prices, "0") + quantities = append(quantities, utils.Int2Str(v.Count)) + } + eclpSoNo, err := api.JdEclpAPI.AddOrder(&jdeclpapi.AddOrderParam{ + IsvUUID: order.VendorOrderID, + IsvSource: jdeclpapi.IsvSource, + ShopNo: jdeclpapi.ShopNo, + DepartmentNo: jdeclpapi.DepartmentNo, + WarehouseNo: jdeclpapi.WarehouseNo, + ShipperNo: jdeclpapi.ShipperNo, + SalesPlatformOrderNo: order.VendorOrderID, + SalePlatformSource: jdeclpapi.SalePlatformSource, + ConsigneeName: order.ConsigneeName, + ConsigneeMobile: order.ConsigneeMobile, + ConsigneeAddress: order.ConsigneeAddress, + OrderMark: jdeclpapi.OrderMark, + GoodsNo: strings.Join(goodsNos, ","), + Price: strings.Join(prices, ","), + Quantity: strings.Join(quantities, ","), + }) + waybill := &model.Waybill{ + VendorOrderID: order.VendorOrderID, + OrderVendorID: model.VendorIDJX, + VendorWaybillID: eclpSoNo, + WaybillVendorID: model.VendorIDJDWL, + Status: model.WaybillStatusDelivering, + WaybillCreatedAt: time.Now(), + StatusTime: time.Now(), + WaybillFinishedAt: utils.DefaultTimeValue, + DeliveryFlag: model.OrderDeliveryFlagMaskScheduleDisabled, + } + dao.CreateEntity(db, waybill) + if err != nil { + return err + } + order.EclpOutID = eclpSoNo + dao.UpdateEntity(db, order, "EclpOutID") + vendorWaybillID = eclpSoNo + } else { + // if handler := partner.GetDeliveryPlatformFromVendorID(model.VendorIDJDWL); handler != nil { + // waybill2, err := handler.Handler.CreateWaybill(order, 0) + // if err != nil { + // return err + // } + // vendorWaybillID = waybill2.VendorWaybillID + // } + } + jdshop.CurPurchaseHandler.OrderExport(ctx, vendorOrderID, vendorWaybillID, false) + return err +} + +func AdjustJdsOrderSimple(ctx *jxcontext.Context, vendorOrderID string, skuID int) (err error) { + var ( + db = dao.GetDB() + ) + orderSkus, err := dao.GetSimpleOrderSkus(db, vendorOrderID, []int{skuID}) + order, err := dao.GetSimpleOrder(db, vendorOrderID) + //如果不是商城模板店 + if jxutils.GetSaleStoreIDFromOrder(order) != model.JdShopMainStoreID { + return fmt.Errorf("目前只支持商城模板店的简单售前删除!") + } + orderSkus2, err := dao.GetSimpleOrderSkus(db, vendorOrderID, nil) + if len(orderSkus2) == 1 { + return fmt.Errorf("这一单只剩这最后一个商品了,不允许删除!") + } + if len(orderSkus) == 0 { + return fmt.Errorf("未查询到该订单商品!") + } + if order.Status > model.OrderStatusAccepted { + return fmt.Errorf("目前只支持待拣货状态前的订单售前调整!") + } + orderSku := orderSkus[0] + if orderSku.Count > 1 { + orderSku.Count-- + _, err = dao.UpdateEntity(db, orderSku, "Count") + } else { + _, err = dao.DeleteEntity(db, orderSku) + } + order.AdjustCount++ + order.ActualPayPrice = order.ActualPayPrice - orderSku.SalePrice + order.TotalShopMoney = int64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage) + dao.UpdateEntity(db, order, "AdjustCount", "TotalShopMoney") + return err +} + +func UpdateWaybillDesiredFee(ctx *jxcontext.Context, vendorOrderID string, desiredFee int) (err error) { + var ( + db = dao.GetDB() + ) + order, _ := dao.GetSimpleOrder(db, vendorOrderID) + if order == nil { + return fmt.Errorf("未找到该订单!orderID: %v", vendorOrderID) + } + bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) + if bill == nil { + waybill := &model.Waybill{ + VendorOrderID: order.VendorOrderID, + OrderVendorID: order.VendorID, + VendorWaybillID: utils.Int64ToStr(GenOrderNo(ctx)), + WaybillVendorID: -1, + Status: model.WaybillStatusDelivered, + WaybillCreatedAt: time.Now(), + StatusTime: time.Now(), + WaybillFinishedAt: utils.DefaultTimeValue, + DeliveryFlag: model.OrderDeliveryFlagMaskScheduleDisabled, + DesiredFee: int64(desiredFee), + } + dao.CreateEntity(db, waybill) + order.VendorWaybillID = waybill.VendorWaybillID + dao.UpdateEntity(db, order, "VendorWaybillID") + } else { + bill.DesiredFee = int64(desiredFee) + _, err = dao.UpdateEntity(db, bill, "DesiredFee") + if order.EarningType == model.EarningTypePoints { + order.NewEarningPrice = order.NewEarningPrice - int64(desiredFee) + _, err = dao.UpdateEntity(db, order, "NewEarningPrice") + } + } + return err +} + +func AcceptOrRefuseOrder(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isAccept bool) (err error) { + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) + handler := partner.GetPurchaseOrderHandlerFromVendorID(vendorID) + err = handler.AcceptOrRefuseOrder(order, isAccept, ctx.GetUserName()) + if err == nil && isAccept && vendorID == model.VendorIDEBAI { + // netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) + // smsmsg.NotifyNewOrder(order) + // smsmsg.NotifyNewUserOrder(order) + // weixinmsg.NotifyNewOrder(order) + // msghub.OnNewOrder(order) + } + return err +} + +func GenOrderNo(ctx *jxcontext.Context) (orderNo int64) { + const prefix = 88 + const randPartNum = 1000 + orderNo = time.Now().Unix() - orderNoBeginTimestamp + // fmt.Println(orderNo) + 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 RefreshJdsOrderConsigneeInfo(ctx *jxcontext.Context, vendorOrderID string) (err error) { + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJDShop) + if order == nil { + return fmt.Errorf("未查询到此京东商城订单!") + } + waybill, err := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) + if waybill != nil { + return fmt.Errorf("已经创建了三方运单不允许修改联系人信息!") + } + jdsOrder, err := jdshop.GetJdsOrder(order.VendorOrderID2, order.VendorOrgCode) + if err != nil { + return err + } + if jdsOrder == nil { + return fmt.Errorf("未查询到对应的京东商城订单!") + } + order.ConsigneeAddress = jdshop.Decrypt(jdsOrder.ConsigneeInfo.FullAddress, order.VendorOrgCode) + order.ConsigneeName = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Fullname, order.VendorOrgCode) + order.ConsigneeMobile = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Mobile, order.VendorOrgCode) + order.ConsigneeMobile2 = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Telephone, order.VendorOrgCode) + order.BuyerComment = jdsOrder.OrderRemark + if order.ConsigneeAddress != "" { + lng, lat, _ := api.AutonaviAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "") + order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng) + order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat) + } + partner.CurOrderManager.UpdateOrderFields(order, []string{"ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeMobile2", "BuyerComment", "ConsigneeLng", "ConsigneeLat"}) + return err +} + +func UpdateOrderInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, payload map[string]interface{}) (num int64, err error) { + var ( + db = dao.GetDB() + ) + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) + if payload["consigneeLng"] != nil || payload["consigneeLat"] != nil { + payload["consigneeLng"] = jxutils.StandardCoordinate2Int(utils.Interface2Float64WithDefault(payload["consigneeLng"], 0.0)) + payload["consigneeLat"] = jxutils.StandardCoordinate2Int(utils.Interface2Float64WithDefault(payload["consigneeLat"], 0.0)) + } + if payload["expectedDeliveredTime"] != nil { + payload["expectedDeliveredTime"] = utils.Str2Time(payload["expectedDeliveredTime"].(string)) + } + valid := dao.StrictMakeMapByStructObject(payload, order, ctx.GetUserName()) + if len(valid) > 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if num, err = dao.UpdateEntityByKV(db, order, valid, nil); err != nil { + dao.Rollback(db) + return 0, err + } + dao.Commit(db) + } + return num, err +} + +func RefreshOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID, skuID int) (num int64, err error) { + var ( + db = dao.GetDB() + shopPrice int64 + ) + order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) + if order.EarningType != model.EarningTypeQuote { + return 0, fmt.Errorf("目前只支持报价订单有此操作!") + } + updateOrderSku := func(v *model.OrderSku, skuID2 int) (err error) { + storeSkus, _ := dao.GetStoresSkusInfo(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, []int{skuID2}) + if len(storeSkus) == 0 { + return fmt.Errorf("未找到此门店商品!") + } + storeSku := storeSkus[0] + v.ShopPrice = int64(storeSku.Price) + dao.UpdateEntity(db, v, "ShopPrice") + return err + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + for _, v := range order.Skus { + if v.SkuID == 0 { + if v.SkuID == skuID { + err = updateOrderSku(v, skuID) + } + } else { + if v.JxSkuID == skuID { + err = updateOrderSku(v, skuID) + } + } + } + if err != nil { + return 0, err + } + for _, v := range order.Skus { + shopPrice += v.ShopPrice * int64(v.Count) + } + order.ShopPrice = shopPrice + num, err = dao.UpdateEntity(db, order, "ShopPrice") + dao.Commit(db) + return num, err +} diff --git a/business/jxcallback/orderman/order_afs.go b/business/jxcallback/orderman/order_afs.go index dbb58cae3..7a654c53a 100644 --- a/business/jxcallback/orderman/order_afs.go +++ b/business/jxcallback/orderman/order_afs.go @@ -54,7 +54,7 @@ func (c *OrderManager) onAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *mode if order, _ := c.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID); order != nil { if order.ConsigneeMobile2 == "" { if handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID); handler != nil { - if order2, _ := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID); order2 != nil && order.ConsigneeMobile != order2.ConsigneeMobile { + if order2, _ := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID); order2 != nil && order.ConsigneeMobile != order2.ConsigneeMobile { order.ConsigneeMobile = order2.ConsigneeMobile c.UpdateOrderFields(order, []string{"ConsigneeMobile"}) } @@ -100,6 +100,7 @@ func (c *OrderManager) onAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *mode return err } } + dao.Commit(db) scheduler.CurrentScheduler.OnAfsOrderNew(afsOrder, false) return err @@ -261,7 +262,13 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af } } if len(vendorSkuIDs) > 0 { - l, err := dao.GetStoreSkuPriceAndWeight(db, order.VendorStoreID, order.VendorID, vendorSkuIDs) + var vendorStoreID string + if order.VendorID == model.VendorIDJDShop { + vendorStoreID = model.JdShopMainVendorStoreID + } else { + vendorStoreID = order.VendorStoreID + } + l, err := dao.GetStoreSkuPriceAndWeight(db, vendorStoreID, order.VendorID, vendorSkuIDs) if err != nil { globals.SugarLogger.Warnf("updateAfsOrderSkuOtherInfo orderID:%s failed with err:%v", order.VendorOrderID, err) return err @@ -295,6 +302,7 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af globals.SugarLogger.Infof("updateAfsOrderSkuOtherInfo [运营%s]%s订单sku找不到门店价格(或商品映射),orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.VendorSkuID, v) } else { v.JxSkuID = skuBindInfo.SkuID + v.ShopPrice = int64(skuBindInfo.Price) } } if actStoreSkuMap != nil { @@ -312,7 +320,7 @@ func (c *OrderManager) updateAfsOrderSkuOtherInfo(db *dao.DaoDB, order *model.Af func (c *OrderManager) updateAfsOrderOtherInfo(db *dao.DaoDB, afsOrder *model.AfsOrder) (err error) { globals.SugarLogger.Debugf("updateAfsOrderOtherInfo orderID:%s, VendorStoreID:%s", afsOrder.VendorOrderID, afsOrder.VendorStoreID) if afsOrder.VendorStoreID != "" { - if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, afsOrder.VendorStoreID, 0); err == nil { + if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, afsOrder.VendorStoreID, 0, ""); err == nil { afsOrder.JxStoreID = storeDetail.Store.ID } } diff --git a/business/jxcallback/orderman/order_comment.go b/business/jxcallback/orderman/order_comment.go index 8a9e2c23a..178592fdc 100644 --- a/business/jxcallback/orderman/order_comment.go +++ b/business/jxcallback/orderman/order_comment.go @@ -85,7 +85,7 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) ( err = nil isNewComment = true if orderComment.IsReplied == 0 && time.Now().Sub(orderComment.CommentCreatedAt) < time.Duration(orderComment.ModifyDuration)*time.Hour { - if storeDetail, err2 := dao.GetStoreDetail(db, orderComment.StoreID, orderComment.VendorID); err2 == nil { + if storeDetail, err2 := dao.GetStoreDetail(db, orderComment.StoreID, orderComment.VendorID, ""); err2 == nil { if storeDetail.AutoReplyType == model.AutoReplyAll || orderComment.Score > JX_BAD_COMMENTS_MAX_LEVEL && storeDetail.AutoReplyType == model.AutoReplyGoodComment { c.replyOrderComment(storeDetail.VendorOrgCode, orderComment) @@ -112,7 +112,7 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) ( orderComment.ConsigneeMobile = order.ConsigneeMobile2 } else { if handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID); handler != nil { - if order2, _ := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID); order2 != nil && order.ConsigneeMobile != order2.ConsigneeMobile { + if order2, _ := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID); order2 != nil && order.ConsigneeMobile != order2.ConsigneeMobile { order.ConsigneeMobile = order2.ConsigneeMobile partner.CurOrderManager.UpdateOrderFields(order, []string{"ConsigneeMobile"}) } @@ -120,7 +120,7 @@ func (c *OrderManager) OnOrderComments(orderCommentList []*model.OrderComment) ( orderComment.ConsigneeMobile = order.ConsigneeMobile } } else { - if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, orderComment.VendorStoreID, orderComment.VendorID); err == nil { + if storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, orderComment.VendorStoreID, orderComment.VendorID, ""); err == nil { orderComment.StoreID = storeDetail.ID } } diff --git a/business/jxcallback/orderman/orderman.go b/business/jxcallback/orderman/orderman.go index e6c385406..b9233ee95 100644 --- a/business/jxcallback/orderman/orderman.go +++ b/business/jxcallback/orderman/orderman.go @@ -156,7 +156,7 @@ func LoadPendingOrders() { for _, item := range sortOrders { if order, ok := item.(*model.GoodsOrder); ok { jxutils.CallMsgHandlerAsync(func() { - scheduler.CurrentScheduler.OnOrderNew(order, true) + scheduler.CurrentScheduler.OnOrderNew(order, true, true) }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) } else if status, ok := item.(*model.OrderStatus); ok { jxutils.CallMsgHandlerAsync(func() { diff --git a/business/jxcallback/orderman/orderman_ext.go b/business/jxcallback/orderman/orderman_ext.go index 8eb0e4846..e099ee13c 100644 --- a/business/jxcallback/orderman/orderman_ext.go +++ b/business/jxcallback/orderman/orderman_ext.go @@ -1,12 +1,17 @@ package orderman import ( + "encoding/json" "fmt" "math" "strconv" "strings" "time" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" + + "github.com/astaxie/beego" + "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" @@ -62,11 +67,11 @@ type OrderCount struct { Flag bool `json:"flag"` //true表示可以买 } -func (c *OrderManager) GetStoreOrderCountInfo(ctx *jxcontext.Context, storeID, lastHours int, isIncludeFake bool) (countInfo []*model.GoodsOrderCountInfo, err error) { +func (c *OrderManager) GetStoreOrderCountInfo(ctx *jxcontext.Context, storeID, lastHours, lastMinutes int, isIncludeFake bool) (countInfo []*model.GoodsOrderCountInfo, err error) { globals.SugarLogger.Debugf("GetStoreOrderCountInfo storeID:%d", storeID) if lastHours > maxLastHours { lastHours = maxLastHours - } else if lastHours == 0 { + } else if lastHours == 0 && lastMinutes == 0 { lastHours = defLastHours } @@ -78,7 +83,12 @@ func (c *OrderManager) GetStoreOrderCountInfo(ctx *jxcontext.Context, storeID, l AND t1.order_created_at >= ?` sqlParams := []interface{}{ storeID, - time.Now().Add(-time.Duration(lastHours) * time.Hour), + // time.Now().Add(-time.Duration(lastHours) * time.Hour), + } + if lastMinutes != 0 { + sqlParams = append(sqlParams, time.Now().Add(-time.Duration(lastMinutes)*time.Minute)) + } else { + sqlParams = append(sqlParams, time.Now().Add(-time.Duration(lastHours)*time.Hour)) } if !isIncludeFake { sql += " AND (t1.flag & ?) = 0" @@ -102,6 +112,7 @@ func (c *OrderManager) GetOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID str if vendorID == model.VendorIDJD { fullSkuNameSQL = "CONCAT(t1.sku_name, IF(t3.is_spu = 1 AND LOCATE(';', t1.sku_name) = 0, CONCAT('[约', t2.spec_quality, t2.spec_unit, '/', t3.unit, ']'), ''))" } + // IF(t1.shop_price = 0, t1.sale_price, t1.shop_price) shop_price, sql := fmt.Sprintf(` SELECT t1.id, @@ -112,8 +123,8 @@ func (c *OrderManager) GetOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID str t1.sku_id, t1.jx_sku_id, t1.sku_name, - IF(t1.shop_price = 0, t1.sale_price, t1.shop_price) shop_price, t1.sale_price, + t1.shop_price, CAST(IF(t1.earning_price <> 0, t1.earning_price, IF(t1.shop_price <> 0 && t1.shop_price < t1.sale_price, t1.shop_price, t1.sale_price) * IF(t5.pay_percentage > 0, t5.pay_percentage, ?) / 100) AS SIGNED) earning_price, t1.weight, t1.sku_type, @@ -151,7 +162,9 @@ func (c *OrderManager) GetOrderInfo(ctx *jxcontext.Context, vendorOrderID string // 这里用QueryRows而不用QueryRow的原因是用QueryRow在这种情况下不能将数据读出,很奇怪。大概的原因是QueryRow对于GoodsOrderExt这种有嵌入的struct处理有问题 num, err := db.Raw(` - SELECT t3.*,ROUND(t3.shop_sum_price/t3.count) avg_price, t1.*, t2.status waybill_status, t2.courier_name, t2.courier_mobile + SELECT t3.*,ROUND(t3.shop_sum_price/t3.count) avg_price, t1.*, t2.status waybill_status, t2.courier_name, t2.courier_mobile, t2.desired_fee, + CAST(t1.consignee_lng AS DECIMAL(15,6))/1000000 float_lng, + CAST(t1.consignee_lat AS DECIMAL(15,6))/1000000 float_lat FROM goods_order t1 LEFT JOIN waybill t2 ON t1.vendor_waybill_id = t2.vendor_waybill_id AND t1.waybill_vendor_id = t2.waybill_vendor_id JOIN ( @@ -168,7 +181,7 @@ func (c *OrderManager) GetOrderInfo(ctx *jxcontext.Context, vendorOrderID string if err == nil && num > 0 { order = orders[0] if isRefresh && vendorID == model.VendorIDJD { - tmpOrder, err2 := partner.GetPurchaseOrderHandlerFromVendorID(vendorID).GetOrder(order.VendorOrgCode, vendorOrderID) + tmpOrder, err2 := partner.GetPurchaseOrderHandlerFromVendorID(vendorID).GetOrder(order.VendorOrgCode, vendorOrderID, order.VendorStoreID) if err = err2; err == nil { order.CurrentConsigneeMobile = tmpOrder.ConsigneeMobile } else { @@ -275,6 +288,29 @@ func (c *OrderManager) ExportMTWaybills(ctx *jxcontext.Context, fromDateStr, toD func (c *OrderManager) GetOrders(ctx *jxcontext.Context, isIncludeFake bool, fromDateStr, toDateStr string, isDateFinish bool, skuIDs []int, isJxFirst bool, params map[string]interface{}, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { globals.SugarLogger.Debugf("GetOrders from:%s to:%s", fromDateStr, toDateStr) + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if params["storeIDs"] != nil { + var storeIDs []int + if err = utils.UnmarshalUseNumber([]byte(params["storeIDs"].(string)), &storeIDs); err == nil { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + if data, err := json.Marshal(storeIDs2); err == nil { + params["storeIDs"] = string(data) + } + } + } orders, totalCount, err := dao.GetOrders(dao.GetDB(), nil, false, isIncludeFake, fromDateStr, toDateStr, isDateFinish, skuIDs, isJxFirst, "", params, offset, pageSize) if err == nil { pagedInfo = &model.PagedInfo{ @@ -296,6 +332,29 @@ func (c *OrderManager) ExportOrders(ctx *jxcontext.Context, fromDateStr, toDateS func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if mapParams["storeIDs"] != nil { + var storeIDs []int + if err = utils.UnmarshalUseNumber([]byte(mapParams["storeIDs"].(string)), &storeIDs); err == nil { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + if data, err := json.Marshal(storeIDs2); err == nil { + mapParams["storeIDs"] = string(data) + } + } + } orders, _, err = dao.GetOrders(dao.GetDB(), nil, true, true, fromDateStr, toDateStr, true, nil, false, "", mapParams, 0, model.UnlimitedPageSize) globals.SugarLogger.Debugf("orders:%d, er:%v", len(orders), err) case 1: @@ -314,111 +373,35 @@ func (c *OrderManager) ExportOrders(ctx *jxcontext.Context, fromDateStr, toDateS afsInfo[v.SkuID].Count -= minus } } - // if v.SkuCount2 == 1 { - // skuStr1 := strings.Join([]string{ - // utils.Int2Str(v.SkuID), - // utils.Int2Str(v.SkuCount2), - // utils.Int2Str(v.SkuShopPrice), - // utils.Int2Str(v.SkuSalePrice), - // utils.Int2Str(v.SkuEarningPrice), - // }, ",") - // if order == nil || v.ID != order.ID { - // order = v - // v.CourierVendorName = model.VendorChineseNames[v.WaybillVendorID] - // v.Status2 = model.OrderStatusName[v.Status] - // v.SkuInfo = skuStr1 - // v.SkuInfo2 = skuStr1 - // orders2 = append(orders2, v) - // } else { - // order.SkuInfo += ";" + skuStr1 - // order.SkuInfo2 += ";" + skuStr1 - // } - // } else if v.SkuCount2 > 1 { - // storeID := 0 - // if v.StoreID == 0 { - // storeID = v.JxStoreID - // } else { - // storeID = v.StoreID - // } - // result, _ := dao.GetEffectiveActStoreSkuInfo(dao.GetDB(), 0, nil, 0, []int{storeID}, []int{v.SkuID}, v.OrderCreatedAt, v.OrderCreatedAt) - // if len(result) > 0 { - // if result[0].EarningPrice != 0 { - // var ( - // storePayPercentage, price int - // ) - // stores, _ := dao.GetStoreList(dao.GetDB(), []int{v.StoreID}, nil, nil, nil, "") - // if len(stores) > 0 { - // storePayPercentage = stores[0].PayPercentage - // } else { - // storePayPercentage = 70 - // } - // skuStr1 := strings.Join([]string{ - // utils.Int2Str(v.SkuID), - // utils.Int2Str(v.SkuCount2), - // utils.Int2Str(v.SkuShopPrice), - // utils.Int2Str(v.SkuSalePrice), - // utils.Int2Str(v.SkuEarningPrice), - // }, ",") - // skuStr2 := strings.Join([]string{ - // utils.Int2Str(v.SkuID), - // utils.Int2Str(1), - // utils.Int2Str(v.SkuShopPrice), - // utils.Int2Str(v.SkuSalePrice), - // utils.Int2Str(v.SkuEarningPrice), - // }, ",") - // if v.SkuShopPrice < v.SkuSalePrice { - // price = v.SkuShopPrice * storePayPercentage - // } else { - // price = v.SkuSalePrice * storePayPercentage - // } - // skuStr3 := strings.Join([]string{ - // utils.Int2Str(v.SkuID), - // utils.Int2Str(v.SkuCount2 - 1), - // utils.Int2Str(v.SkuShopPrice), - // utils.Int2Str(v.SkuSalePrice), - // utils.Int2Str(price), - // }, ",") - // if order == nil || v.ID != order.ID { - // order = v - // v.CourierVendorName = model.VendorChineseNames[v.WaybillVendorID] - // v.Status2 = model.OrderStatusName[v.Status] - // v.SkuInfo2 = skuStr1 - // v.SkuInfo = skuStr2 + ";" + skuStr3 - // orders2 = append(orders2, v) - // } else { - // order.SkuInfo2 += ";" + skuStr1 - // order.SkuInfo += ";" + skuStr2 + ";" + skuStr3 - // } - // } - // } else { - // skuStr1 := strings.Join([]string{ - // utils.Int2Str(v.SkuID), - // utils.Int2Str(v.SkuCount2), - // utils.Int2Str(v.SkuShopPrice), - // utils.Int2Str(v.SkuSalePrice), - // utils.Int2Str(v.SkuEarningPrice), - // }, ",") - // if order == nil || v.ID != order.ID { - // order = v - // v.CourierVendorName = model.VendorChineseNames[v.WaybillVendorID] - // v.Status2 = model.OrderStatusName[v.Status] - // v.SkuInfo = skuStr1 - // v.SkuInfo2 = skuStr1 - // orders2 = append(orders2, v) - // } else { - // order.SkuInfo += ";" + skuStr1 - // order.SkuInfo2 += ";" + skuStr1 - // } - // } - // } if v.SkuCount2 > 0 { - skuStr := strings.Join([]string{ - utils.Int2Str(v.SkuID), - utils.Int2Str(v.SkuCount2), - utils.Int2Str(v.SkuShopPrice), - utils.Int2Str(v.SkuSalePrice), - utils.Int2Str(v.SkuEarningPrice), - }, ",") + var skuStr string + if beego.BConfig.RunMode == "jxgy" { + skuStr = strings.Join([]string{ + utils.Int2Str(v.SkuID), + utils.Int2Str(v.SkuCount2), + utils.Int2Str(v.SkuShopPrice), + utils.Int2Str(v.SkuSalePrice), + utils.Int2Str(v.SkuEarningPrice), + }, ",") + } else { + if v.EarningType == model.EarningTypeQuote { + skuStr = strings.Join([]string{ + utils.Int2Str(v.SkuID), + utils.Int2Str(v.SkuCount2), + utils.Int2Str(v.SkuEarningPrice), + utils.Int2Str(v.SkuSalePrice), + utils.Int2Str(v.SkuShopPrice), + }, ",") + } else { + skuStr = strings.Join([]string{ + utils.Int2Str(v.SkuID), + utils.Int2Str(v.SkuCount2), + utils.Int2Str(v.SkuShopPrice), + utils.Int2Str(v.SkuSalePrice), + utils.Int2Str(v.SkuEarningPrice), + }, ",") + } + } if order == nil || v.ID != order.ID { order = v v.CourierVendorName = model.VendorChineseNames[v.WaybillVendorID] @@ -728,10 +711,10 @@ func (c *OrderManager) GetStoresOrderSaleInfo(ctx *jxcontext.Context, storeIDLis func (c *OrderManager) GetStoresOrderSaleInfoNew(ctx *jxcontext.Context, storeIDList []int, fromTime time.Time, toTime time.Time, statusList []int) (saleInfoList []*dao.StoresOrderSaleInfo, err error) { db := dao.GetDB() - // var isFinish = true - // if toTime.Sub(fromTime).Hours() > 24 { - // isFinish = false - // } + var isLongTime = false + if toTime.Sub(fromTime).Hours() > 24 { + isLongTime = true + } orderSkuList, err := dao.GetStoreOrderSkuList(db, storeIDList, fromTime, toTime, statusList, true) if err != nil { return nil, err @@ -753,6 +736,7 @@ func (c *OrderManager) GetStoresOrderSaleInfoNew(ctx *jxcontext.Context, storeID flagVendorOrderID = skuList[0].VendorOrderID } for k, v := range skuList { + storeDetail, _ := dao.GetStoreDetail(db, v.StoreID, v.VendorID, "") if v.EarningPrice == 0 { v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, v.PayPercentage) } @@ -771,6 +755,16 @@ func (c *OrderManager) GetStoresOrderSaleInfoNew(ctx *jxcontext.Context, storeID } saleInfoMap[index] = saleInfo } + //成都菜市 + if beego.BConfig.RunMode == "prod" || beego.BConfig.RunMode == "beta" { + if v.EarningType == model.EarningTypeQuote { + saleInfo.RealEarningPrice += v.ShopPrice * int64(v.Count) + } + } else { + if v.OrderPayPercentage == 100 { + saleInfo.RealEarningPrice += v.ShopPrice * int64(v.Count) + } + } saleInfo.ShopPrice += v.ShopPrice * int64(v.Count) saleInfo.VendorPrice += v.VendorPrice * int64(v.Count) saleInfo.SalePrice += v.SalePrice * int64(v.Count) @@ -778,10 +772,37 @@ func (c *OrderManager) GetStoresOrderSaleInfoNew(ctx *jxcontext.Context, storeID if v.VendorOrderID == flagVendorOrderID { if k == 0 { saleInfo.EarningPrice = v.NewEarningPrice + if beego.BConfig.RunMode == "prod" || beego.BConfig.RunMode == "beta" { + if v.EarningType == model.EarningTypePoints { + if storeDetail.VendorPayPercentage != 0 && !isLongTime { + saleInfo.RealEarningPrice += 0 + } else { + saleInfo.RealEarningPrice += v.NewEarningPrice + } + } + } else { + if v.OrderPayPercentage < 100 { + saleInfo.RealEarningPrice += v.NewEarningPrice + } + } } } else { flagVendorOrderID = v.VendorOrderID saleInfo.EarningPrice += v.NewEarningPrice + if beego.BConfig.RunMode == "prod" || beego.BConfig.RunMode == "beta" { + if v.EarningType == model.EarningTypePoints { + if storeDetail.VendorPayPercentage != 0 && !isLongTime { + saleInfo.RealEarningPrice += 0 + } else { + // && v.VendorID != model.VendorIDJD && v.CityCode != 510100 + saleInfo.RealEarningPrice += v.NewEarningPrice + } + } + } else { + if v.OrderPayPercentage < 100 { + saleInfo.RealEarningPrice += v.NewEarningPrice + } + } } universalOrderID := jxutils.ComposeUniversalOrderID(v.VendorOrderID, v.VendorID) @@ -868,7 +889,25 @@ func (c *OrderManager) GetStoresOrderSaleInfoNew(ctx *jxcontext.Context, storeID func (c *OrderManager) GetAfsOrders(ctx *jxcontext.Context, keyword, afsOrderID, vendorOrderID string, vendorIDList, appealTypeList, storeIDList, statusList, skuIDs []int, fromTime, toTime time.Time, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { globals.SugarLogger.Debugf("GetAfsOrders") - + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDList) > 0 { + for _, v := range storeIDList { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDList = nil + storeIDList = storeIDs2 + } + } pageSize = jxutils.FormalizePageSize(pageSize) offset = jxutils.FormalizePageOffset(offset) sql := ` @@ -993,11 +1032,11 @@ func (c *OrderManager) getAfsOrderSkuInfo4ExportOrders(ctx *jxcontext.Context, f if err = err2; err != nil { return nil, err } - toDate = toDate.Add(7 * 24 * time.Hour) // todo 售后单最多只可能延后7天吧 + toDate = toDate.Add(30 * 24 * time.Hour) // todo 售后单最多只可能延后7天吧 sql := ` SELECT t2.* FROM afs_order t1 - JOIN order_sku_financial t2 ON t2.vendor_order_id = t1.vendor_order_id AND t2.vendor_id = t1.vendor_id AND t2.is_afs_order = 1 + JOIN order_sku_financial t2 ON t2.vendor_order_id = t1.vendor_order_id AND t2.vendor_id = t1.vendor_id AND t2.is_afs_order = 1 AND t1.afs_order_id = t2.afs_order_id WHERE t1.afs_finished_at >= ? AND t1.afs_finished_at <= ? AND t1.status = ? ` sqlParams := []interface{}{ @@ -1006,6 +1045,8 @@ func (c *OrderManager) getAfsOrderSkuInfo4ExportOrders(ctx *jxcontext.Context, f model.AfsOrderStatusFinished, } var skus []*model.OrderSkuFinancial + fmt.Println(sql) + fmt.Println(sqlParams) if err = dao.GetRows(dao.GetDB(), &skus, sql, sqlParams...); err == nil { skuMap = make(map[string]map[int]*model.OrderSkuFinancial) for _, v := range skus { @@ -1096,6 +1137,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in VendorOrderID string VendorID int VendorOrgCode string + VendorStoreID string } if len(dateVendorList) > 0 { var missingOrderList []*tOrderVendorPair @@ -1104,7 +1146,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in vendorStoreIDMap := make(map[int]string) if storeID > 0 { for _, vendorID := range vendorIDs { - storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID, "") if err = err2; err != nil { return "", err } @@ -1123,11 +1165,17 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in if err = err2; err == nil && len(orderIDs) > 0 { var orderList []*tOrderVendorPair for _, v := range orderIDs { + var vendorStoreID string + if orders, _ := dao.QueryOrders(db, v, 0, nil, 0, utils.ZeroTimeValue, utils.ZeroTimeValue); len(orders) > 0 { + vendorStoreID = orders[0].VendorStoreID + } orderList = append(orderList, &tOrderVendorPair{ VendorOrderID: v, VendorID: vendorDate.VendorID, VendorOrgCode: vendorDate.VendorOrgCode, + VendorStoreID: vendorStoreID, }) + } retVal = orderList } @@ -1172,7 +1220,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { pair := batchItemList[0].(*tOrderVendorPair) if handler := partner.GetPurchaseOrderHandlerFromVendorID(pair.VendorID); handler != nil { - order, err2 := handler.GetOrder(pair.VendorOrgCode, pair.VendorOrderID) + order, err2 := handler.GetOrder(pair.VendorOrgCode, pair.VendorOrderID, pair.VendorStoreID) if err = err2; err == nil { isDuplicated, err2 := c.SaveOrder(order, false, dao.GetDB()) if err2 == nil && !isDuplicated { @@ -1192,7 +1240,7 @@ func (c *OrderManager) AmendMissingOrders(ctx *jxcontext.Context, vendorIDs []in func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { goodsOrder := batchItemList[0].(*model.GoodsOrder) if handler := partner.GetPurchaseOrderHandlerFromVendorID(goodsOrder.VendorID); handler != nil { - order, err2 := handler.GetOrder(goodsOrder.VendorOrgCode, goodsOrder.VendorOrderID) + order, err2 := handler.GetOrder(goodsOrder.VendorOrgCode, goodsOrder.VendorOrderID, goodsOrder.VendorStoreID) if err = err2; err == nil { if model.IsOrderFinalStatus(order.Status) { goodsOrder.Status = order.Status @@ -1246,7 +1294,7 @@ func (c *OrderManager) RefreshOrderFinancial(ctx *jxcontext.Context, fromTime, t order := batchItemList[0].(*model.GoodsOrder) handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID) if handler != nil { - remoteOrder, err2 := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID) + remoteOrder, err2 := handler.GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID) if err = err2; err == nil { order.TotalShopMoney = remoteOrder.TotalShopMoney order.PmSubsidyMoney = remoteOrder.PmSubsidyMoney @@ -1310,7 +1358,7 @@ func GetMatterStoreOrderCount(ctx *jxcontext.Context, storeID int) (result *Orde err = dao.GetRows(db, &orderPays, sql, sqlParams) if len(orderPays) != 0 { orderPay := orderPays[0] - stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") if len(stores) > 0 { store := stores[0] if store.IsBoughtMatter == model.YES { @@ -1352,17 +1400,27 @@ func RefreshJdShopOrdersEarningPrice(ctx *jxcontext.Context, orderStartTime, ord var ( db = dao.GetDB() ) - results, err := api.JdAPI.GetJdShopOrders(orderStartTime, orderEndTime, globals.JdOrgCode, globals.JdLoginName) + results, err := api.JdAPI.GetJdShopOrders(utils.Str2Time(orderStartTime).Format("20060102"), utils.Str2Time(orderEndTime).Format("20060102"), globals.JdOrgCode, globals.JdLoginName) if err != nil { return err } for _, v := range results.BillList.Result { if v.DueAmount != 0 { - order := &model.GoodsOrder{} - order.VendorOrderID = utils.Int64ToStr(v.OrderID) - dao.GetEntity(db, order, "VendorOrderID") - order.TotalShopMoney = utils.Float64TwoInt64(v.DueAmount * 100) - dao.UpdateEntity(db, order, "TotalShopMoney") + order, _ := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(v.OrderID), model.VendorIDJD) + if order == nil { + continue + } + stores, _ := dao.GetStoreList(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, nil, nil, nil, nil, "") + if len(stores) > 0 { + store := stores[0] + if order.NewEarningPrice == 0 { + jxutils.RefreshOrderEarningPrice2(order, store.PayPercentage) + } + if order.TotalShopMoney == 0 { + order.TotalShopMoney = utils.Float64TwoInt64(v.DueAmount * 100) + } + dao.UpdateEntity(db, order, "TotalShopMoney", "NewEarningPrice") + } } } return err diff --git a/business/jxcallback/scheduler/basesch/basesch.go b/business/jxcallback/scheduler/basesch/basesch.go index 1f623cd4f..1fb05974b 100644 --- a/business/jxcallback/scheduler/basesch/basesch.go +++ b/business/jxcallback/scheduler/basesch/basesch.go @@ -20,7 +20,7 @@ type BaseScheduler struct { func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) - if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusNew { + if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusNew || order.Status == model.OrderStatusWaitAccepted { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).AcceptOrRefuseOrder(order, isAcceptIt, userName) @@ -34,7 +34,7 @@ func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt } func (c *BaseScheduler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { - globals.SugarLogger.Infof("PickupGoods orderID:%s", order.VendorOrderID) + globals.SugarLogger.Infof("PickupGoods orderID:%s,order :%v", order.VendorOrderID, utils.Format4Output(order, false)) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusAccepted { if c.IsReallyCallPlatformAPI { handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID) diff --git a/business/jxcallback/scheduler/basesch/basesch_ext.go b/business/jxcallback/scheduler/basesch/basesch_ext.go index 556879844..98d8ed087 100644 --- a/business/jxcallback/scheduler/basesch/basesch_ext.go +++ b/business/jxcallback/scheduler/basesch/basesch_ext.go @@ -5,6 +5,8 @@ import ( "strings" "time" + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" + "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils/errlist" @@ -27,7 +29,7 @@ const ( func (c *BaseScheduler) CreateWaybillOnProviders(ctx *jxcontext.Context, order *model.GoodsOrder, courierVendorIDs, excludeCourierVendorIDs []int, maxDeliveryFee int64, createOnlyOne bool) (bills []*model.Waybill, err error) { userName := ctx.GetUserName() globals.SugarLogger.Infof("CreateWaybillOnProviders orderID:%s userName:%s, courierVendorIDs:%v, excludeCourierVendorIDs:%v", order.VendorOrderID, userName, courierVendorIDs, excludeCourierVendorIDs) - storeCourierList, err := dao.GetStoreCourierList(dao.GetDB(), []int{jxutils.GetSaleStoreIDFromOrder(order)}, model.StoreStatusOpened, model.StoreAuditStatusOnline) + storeCourierList, err := dao.GetStoreCourierList2(dao.GetDB(), []int{jxutils.GetSaleStoreIDFromOrder(order)}, nil, model.StoreStatusOpened, []int{model.StoreAuditStatusOnline, model.StoreAuditStatusUpdated}) if err != nil { return nil, err } @@ -41,13 +43,6 @@ func (c *BaseScheduler) CreateWaybillOnProviders(ctx *jxcontext.Context, order * courierVendorID := storeCourier.VendorID bill, err2 := c.CreateWaybill(courierVendorID, order, maxDeliveryFee) if err = err2; err == nil { - stores, _ := dao.GetStoreList(dao.GetDB(), []int{order.StoreID}, nil, nil, nil, "") - if len(stores) > 0 { - if stores[0].PayPercentage <= 50 { - order.NewEarningPrice = (order.TotalShopMoney - bill.DesiredFee) * int64((100 - stores[0].PayPercentage/2)) / 100 - dao.UpdateEntity(dao.GetDB(), order, "NewEarningPrice") - } - } globals.SugarLogger.Debugf("CreateWaybillOnProviders orderID:%s userName:%s vendorID:%d bill:%v", order.VendorOrderID, userName, courierVendorID, bill) bills = append(bills, bill) if createOnlyOne { @@ -107,7 +102,8 @@ func (c *BaseScheduler) PickupGoodsAndUpdateStatus(ctx *jxcontext.Context, vendo globals.SugarLogger.Infof("PickupGoodsAndUpdateStatus orderID:%s userName:%s", vendorOrderID, userName) order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID) if err == nil { - err = c.PickupGoods(order, model.IsOrderDeliveryByStore(order), userName) + flag := model.IsOrderDeliveryByStore(order) || model.IsOrderDeliveryBySelf(order) + err = c.PickupGoods(order, flag, userName) if err == nil { order.Status = model.OrderStatusFinishedPickup if err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order); err == nil { @@ -147,7 +143,7 @@ func (c *BaseScheduler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOr if globals.IsAddEvent { err = cms.AddEventDetail(dao.GetDB(), ctx, model.OperateUpdate, order.StoreID, model.ThingTypeOrder, order.StoreID, order.VendorOrderID, order.StoreName) } - err = partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).CancelOrder(ctx, order, reason) + err = partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).CancelOrder(ctx, order, reason+","+ctx.GetUserName()) } return err } @@ -220,6 +216,37 @@ func (c *BaseScheduler) AgreeOrRefuseRefund(ctx *jxcontext.Context, afsOrderID s flag = model.AfsOrderFlagRefuseUserRefund afsOrder.RefuseReason = reason partner.CurOrderManager.UpdateAfsOrderFields(afsOrder, []string{"RefuseReason"}) + } else { + if order, _ := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID); order != nil { + if order.EarningType == model.EarningTypePoints { + var ( + skuMap = make(map[int]*model.OrderSku) + diff int64 + db = dao.GetDB() + ) + for _, sku := range order.Skus { + skuMap[sku.SkuID] = sku + } + storeDetail, _ := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + waybills, _ := dao.GetWaybills(db, order.VendorOrderID) + //京东商城和京西要重新算totalshopmoney等 + if order.VendorID == model.VendorIDJDShop || order.VendorID == model.VendorIDJX { + skus, _ := dao.GetAfsOrderSkuInfo(db, order.VendorOrderID, afsOrderID, order.VendorID, false) + for _, v := range skus { + if skuMap[v.SkuID] != nil { + diff += skuMap[v.SkuID].SalePrice * int64(v.Count) + } + } + order.TotalShopMoney = utils.Float64TwoInt64(float64(float64(order.TotalShopMoney)/jdshopapi.JdsPayPercentage-float64(diff)) * jdshopapi.JdsPayPercentage) + if len(waybills) > 0 { + jxutils.RefreshOrderEarningPrice3(order, storeDetail.PayPercentage, waybills[0]) + } else { + jxutils.RefreshOrderEarningPrice2(order, storeDetail.PayPercentage) + } + dao.UpdateEntity(db, order, "TotalShopMoney", "NewEarningPrice") + } + } + } } dao.SetAfsOrderFlag(dao.GetDB(), ctx.GetUserName(), afsOrderID, vendorID, flag) } @@ -285,7 +312,7 @@ func (c *BaseScheduler) SetOrderWaybillTipByOrder(ctx *jxcontext.Context, order } db := dao.GetDB() - storeDetail, err2 := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID) + storeDetail, err2 := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") if err = err2; err != nil { return err } diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index 1a3df3005..aac6f7401 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -6,6 +6,16 @@ import ( "sync" "time" + "git.rosy.net.cn/jx-callback/globals/api" + + push "git.rosy.net.cn/jx-callback/business/jxutils/unipush" + + "github.com/astaxie/beego" + + "git.rosy.net.cn/jx-callback/business/jxstore/cms" + + "git.rosy.net.cn/jx-callback/business/authz" + "git.rosy.net.cn/jx-callback/business/authz/autils" "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" @@ -34,9 +44,9 @@ const ( minute2Schedule3rdCarrier4Ebai = 30 // 饿百的最少转自配送需要的时间(分钟) minMinute2Schedule3rdCarrier = 5 // 转三方配送最少等待时间(分钟) - time2AutoPickupMin = 14 * time.Minute // 自动拣货等待时间,这个只有在没有PickDeadline信息才有用,否则会根据PickDeadline设置 - second2AutoPickupGap = 60 //随机60秒 - time2AutoPickupAhead = 20 * time.Second // 有最后拣货时间的提前值 + time2AutoPickupMin = 14 * time.Minute // 自动拣货等待时间,这个只有在没有PickDeadline信息才有用,否则会根据PickDeadline设置 + second2AutoPickupGap = 60 //随机60秒 + time2AutoPickupAhead = 120 * time.Second // 有最后拣货时间的提前值 switch2SelfDeliverRetryGap = 3 * time.Second // 转自送失败尝试的时间间隙 switch2SelfDeliverRetryCount = 2 // 转自送失败尝试次数 @@ -99,7 +109,8 @@ type WatchOrderInfo struct { timerList []*tTimerInfo - retryCount int // 失败后尝试的次数,调试阶段可能出现死循化,阻止这种情况发生 + retryCount int // 失败后尝试的次数,调试阶段可能出现死循化,阻止这种情况发生 + storeDetail *dao.StoreDetail } type StatusActionConfig struct { @@ -156,7 +167,7 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) if jxStoreID > 0 { db := dao.GetDB() - storeDetail, err2 := dao.GetStoreDetail(db, jxStoreID, order.VendorID) + storeDetail, err2 := dao.GetStoreDetail(db, jxStoreID, order.VendorID, "") if err = err2; err != nil { return err } @@ -218,53 +229,61 @@ func init() { FixedScheduler = sch sch.IsReallyCallPlatformAPI = globals.ReallyCallPlatformAPI scheduler.CurrentScheduler = sch + statusAccept := func(time time.Duration) *StatusActionConfig { + return &StatusActionConfig{ // 自动接单 + StatusActionParams: partner.StatusActionParams{ + TimerType: partner.TimerTypeBaseStatusTime, + Timeout: time, + }, + TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) { + order := savedOrderInfo.order + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil { + savedOrderInfo.storeDetail = storeDetail + } + mobile := order.ConsigneeMobile + if order.ConsigneeMobile2 != "" { + mobile = order.ConsigneeMobile2 + } + _ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, mobile, jxutils.GetSaleStoreIDFromOrder(order), nil, func(isAcceptIt bool) error { + if err = sch.AcceptOrRefuseOrder(order, isAcceptIt, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation { + partner.CurOrderManager.OnOrderMsg(order, "自动接单失败", err.Error()) + // 为了解决京东新消息与接单消息乱序的问题 + if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 && errWithCode.IntCode() == -1 { + if order2, err2 := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID); err2 == nil { + if order2.Status > order.Status { + order.Status = order2.Status + jxutils.CallMsgHandlerAsync(func() { + sch.OnOrderStatusChanged(order, model.Order2Status(order2), false) + }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) + err = nil + } + } else { + err = err2 + } + } + } + if isAcceptIt { + if err == nil { + sch.notifyNewOrder(order, false) + msghub.OnNewOrder(order) + } + } else { + partner.CurOrderManager.OnOrderMsg(order, "黑名单拒单", "") + } + return err + }) + return nil + }, + ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { + return savedOrderInfo.order.LockStatus == model.LockStatusUnlocked && (savedOrderInfo.order.Status == model.OrderStatusNew || savedOrderInfo.order.Status == model.OrderStatusWaitAccepted) + }, + } + } sch.defWorkflowConfig = []map[int]*StatusActionConfig{ map[int]*StatusActionConfig{ - model.OrderStatusNew: &StatusActionConfig{ // 自动接单 - StatusActionParams: partner.StatusActionParams{ - TimerType: partner.TimerTypeBaseStatusTime, - Timeout: 10 * time.Millisecond, - }, - TimeoutAction: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) { - order := savedOrderInfo.order - mobile := order.ConsigneeMobile - if order.ConsigneeMobile2 != "" { - mobile = order.ConsigneeMobile2 - } - _ = sch.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, mobile, jxutils.GetSaleStoreIDFromOrder(order), nil, func(isAcceptIt bool) error { - if err = sch.AcceptOrRefuseOrder(order, isAcceptIt, ""); err != nil && err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation { - partner.CurOrderManager.OnOrderMsg(order, "自动接单失败", err.Error()) - // 为了解决京东新消息与接单消息乱序的问题 - if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 && errWithCode.IntCode() == -1 { - if order2, err2 := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrgCode, order.VendorOrderID); err2 == nil { - if order2.Status > order.Status { - order.Status = order2.Status - jxutils.CallMsgHandlerAsync(func() { - sch.OnOrderStatusChanged(order, model.Order2Status(order2), false) - }, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) - err = nil - } - } else { - err = err2 - } - } - } - if isAcceptIt { - if err == nil { - sch.notifyNewOrder(order) - msghub.OnNewOrder(order) - } - } else { - partner.CurOrderManager.OnOrderMsg(order, "黑名单拒单", "") - } - return err - }) - return nil - }, - ShouldSetTimer: func(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) bool { - return savedOrderInfo.order.LockStatus == model.LockStatusUnlocked && savedOrderInfo.order.Status == model.OrderStatusNew - }, - }, + model.OrderStatusWaitAccepted: statusAccept(2 * time.Minute), //饿百假的自动接单 + model.OrderStatusNew: statusAccept(10 * time.Millisecond), model.OrderStatusAccepted: &StatusActionConfig{ // 自动拣货 StatusActionParams: partner.StatusActionParams{ TimerType: partner.TimerTypeBaseStatusTime, @@ -355,14 +374,38 @@ func Init() { } // 以下是订单 -func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder, isPending bool) (err error) { +func (s *DefScheduler) OnOrderNew(order *model.GoodsOrder, isPending bool, isAuto bool) (err error) { globals.SugarLogger.Debugf("OnOrderNew orderID:%s", order.VendorOrderID) savedOrderInfo := s.loadSavedOrderFromMap(model.Order2Status(order), false) savedOrderInfo.SetOrder(order) + if order.VendorID == model.VendorIDEBAI { //饿百订单待接单的时候就推所有东西 + if order.Status == model.OrderStatusWaitAccepted || order.Status == model.OrderStatusFinishedPickup { //错序 + s.resetTimer(savedOrderInfo, nil, isPending) + if order.Flag&model.OrderFlagMaskFake == 0 { + utils.CallFuncAsync(func() { + // order = setFakeActualPayPrice(order) + netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) + //目前暂且认为AdjustCount > 0 就是调整单 + if order.AdjustCount > 0 { + weixinmsg.NotifyAdjustOrder(order) + } else { + weixinmsg.NotifyNewOrder(order) + } + OrderProfitWarning(order) + if !isAuto { + smsmsg.NotifyNewOrder(order) + } + // smsmsg.NotifyNewUserOrder(order) + push.NotifyNewOrder(order) + }) + } + msghub.OnNewOrder(order) + } + } if order.Status >= model.OrderStatusNew { s.resetTimer(savedOrderInfo, nil, isPending) if !isPending && order.Status >= model.OrderStatusAccepted { // 有订单消息错序,先收到接单消息,再收到新订单消息,导致接单TIMER不动作,这里补一下 - s.notifyNewOrder(order) + s.notifyNewOrder(order, isAuto) msghub.OnNewOrder(order) } } @@ -403,7 +446,7 @@ func (s *DefScheduler) OnOrderStatusChanged(order *model.GoodsOrder, status *mod } } } - s.cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo, curWaybill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrOrderAlreadyFinished) + s.cancelOtherWaybills(savedOrderInfo, curWaybill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrOrderAlreadyFinished) if status.Status >= model.OrderStatusEndBegin { s.orderMap.Delete(jxutils.GetUniversalOrderIDFromOrderStatus(status)) } @@ -499,7 +542,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo } if needAddTip { if handler := partner.GetWaybillTipUpdater(bill.WaybillVendorID); handler != nil { - if storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID); err2 == nil { + if storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, ""); err2 == nil { handler.UpdateWaybillTip(jxcontext.AdminCtx, order.VendorOrgCode, order.VendorStoreID, order.VendorOrderID, bill.VendorWaybillID, bill.VendorWaybillID2, utils.Int2Str(storeDetail.CityCode), order.WaybillTipMoney) } } @@ -516,7 +559,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo s.resetTimer(savedOrderInfo, bill, isPending) s.saveDeliveryFeeFromAndStartWatch(savedOrderInfo, bill.StatusTime) } - s.sendCourierOrderSMS(bill) + // s.sendCourierOrderSMS(bill) } else { isBillExist := s.updateBillsInfo(savedOrderInfo, bill) if !isBillExist { @@ -537,7 +580,16 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo } s.updateOrderByBill(order, bill, false) s.cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) - + //若接单时间不在门店的营业时间范围内要取消运单 + s.cancelWaybillNotInStoreOpentime(savedOrderInfo, bill) + //京东商城的话,需要去把订单出库,如果是转移过的订单,则需要修改转移订单号 + if order.VendorID == model.VendorIDJDShop { + s.solutionJdsOrder(bill) + } + //订单已经是结束状态之后来的运单143945553920000001 + if order.Status > model.OrderStatusEndBegin { + s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime) + } if model.IsWaybillPlatformOwn(bill) { if bill.Status == model.WaybillStatusDelivering && order.Status < model.OrderStatusEndBegin { // 强制将订单状态置为配送中? @@ -655,6 +707,30 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo return err } +func (s *DefScheduler) cancelWaybillNotInStoreOpentime(savedOrderInfo *WatchOrderInfo, bill *model.Waybill) (err error) { + if savedOrderInfo != nil { + //TODO 2020-09-07 不在门店的营业时间内取消运单 + if savedOrderInfo.storeDetail != nil { + if savedOrderInfo.storeDetail.OpenTime1 != 0 && savedOrderInfo.storeDetail.CloseTime1 != 0 { + time1 := jxutils.JxOperationTime2TimeByDate(savedOrderInfo.storeDetail.OpenTime1, time.Now()) + time2 := jxutils.JxOperationTime2TimeByDate(savedOrderInfo.storeDetail.CloseTime1, time.Now()) + if time.Now().Sub(time1) < 0 || time.Now().Sub(time2.Add(time.Hour)) > 0 { + if savedOrderInfo.storeDetail.OpenTime2 != 0 && savedOrderInfo.storeDetail.CloseTime2 != 0 { + time3 := jxutils.JxOperationTime2TimeByDate(savedOrderInfo.storeDetail.OpenTime2, time.Now()) + time4 := jxutils.JxOperationTime2TimeByDate(savedOrderInfo.storeDetail.CloseTime2, time.Now()) + if time.Now().Sub(time3) < 0 || time.Now().Sub(time4.Add(time.Hour)) > 0 { + s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonNotInStoreOpenTime) + } + } else { + s.CancelWaybill(bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonNotInStoreOpenTime) + } + } + } + } + } + return err +} + func (s *DefScheduler) sendCourierOrderSMS(bill *model.Waybill) (err error) { err = smsmsg.NotifyNewCourierOrder(bill) return err @@ -712,16 +788,79 @@ func (s *DefScheduler) createWaybillOn3rdProviders(savedOrderInfo *WatchOrderInf globals.SugarLogger.Debugf("createWaybillOn3rdProviders orderID:%s门店没有设置配送竞争", order.VendorOrderID) } globals.SugarLogger.Debugf("createWaybillOn3rdProviders, orderID:%s, status:%d, maxDeliveryFee:%d, excludeBill:%v", order.VendorOrderID, order.Status, maxDeliveryFee, excludeBill) - if err = s.canOrderCreateWaybillNormally(order); err == nil { + if err = s.canOrderCreateWaybillNormally(order, savedOrderInfo); err == nil { if (order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { if savedOrderInfo.retryCount <= maxWaybillRetryCount { + var waybillVendorIDs = []int{model.VendorIDMTPS, model.VendorIDDada, model.VendorIDFengNiao} savedOrderInfo.isNeedCreate3rdWaybill = true excludeVendorIDs := savedOrderInfo.GetWaybillVendorIDs() - if order.VendorID == model.VendorIDJX { - excludeVendorIDs = append(excludeVendorIDs, model.VendorIDMTPS) + //TODO 取消京西不自动发美团 2020-06-02 + // if order.VendorID == model.VendorIDJX { + // excludeVendorIDs = append(excludeVendorIDs, model.VendorIDMTPS) + // } + //TODO 2020-08-18 饿百美团订单暂时不自动发送三方 + if order.VendorID == model.VendorIDMTWM || order.VendorID == model.VendorIDEBAI { + if order.DeliveryType != model.OrderDeliveryTypeStoreSelf { + excludeVendorIDs = append(excludeVendorIDs, waybillVendorIDs...) + } } - if _, err = s.CreateWaybillOnProviders4SavedOrder(jxcontext.AdminCtx, savedOrderInfo, nil, excludeVendorIDs, false, maxDeliveryFee); err == nil { - savedOrderInfo.retryCount++ + + var income int64 + if order.OrderPayPercentage < 50 { + income = order.TotalShopMoney * int64((order.OrderPayPercentage / 2)) + } else if order.OrderPayPercentage > 50 && order.OrderPayPercentage < 100 { + income = order.TotalShopMoney - order.NewEarningPrice + } else if order.OrderPayPercentage == 100 { + income = order.TotalShopMoney - order.ShopPrice + } + //2020-11-16 预计收益-配送费 > 0 再发 + for _, vendorID := range waybillVendorIDs { + var fee int64 + handler := partner.GetDeliveryPlatformFromVendorID(vendorID) + if deliveryFeeInfo, err := handler.Handler.GetWaybillFee(order); err == nil { + if deliveryFeeInfo != nil { + if income-deliveryFeeInfo.DeliveryFee <= 0 { + excludeVendorIDs = append(excludeVendorIDs, vendorID) + } + fee = deliveryFeeInfo.DeliveryFee + } + } + globals.SugarLogger.Debugf("count order income, vendorID: %v, income :%v , deliveryFee : %v", vendorID, income, fee) + } + + //TODO 2020-07-21 发单时间要在门店的营业时间内 + var storeDetail *dao.StoreDetail + if savedOrderInfo.storeDetail != nil { + storeDetail = savedOrderInfo.storeDetail + } else { + storeDetail, err = dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + } + if storeDetail != nil { + globals.SugarLogger.Debugf("三方运单门店营业时间范围 :time1 %v ,time2 %v", storeDetail.OpenTime1, storeDetail.CloseTime1) + if storeDetail.OpenTime1 != 0 && storeDetail.CloseTime1 != 0 { + time1 := jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime1, time.Now()) + time2 := jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime1, time.Now()) + if time.Now().Sub(time1) < 0 || time.Now().Sub(time2.Add(30*time.Minute)) > 0 { + if storeDetail.OpenTime2 != 0 && storeDetail.CloseTime2 != 0 { + time3 := jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime2, time.Now()) + time4 := jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime2, time.Now()) + if time.Now().Sub(time3) < 0 || time.Now().Sub(time4.Add(30*time.Minute)) > 0 { + err = fmt.Errorf("不在门店营业时间范围内!") + } + } else { + err = fmt.Errorf("不在门店营业时间范围内!") + } + } + } + } + //TODO 2021-02-19 增加品牌配送开关 + if storeDetail.BrandIsOpen == model.YES { + err = fmt.Errorf("此品牌已关闭配送! [%v]", storeDetail.BrandName) + } + if err == nil { + if _, err = s.CreateWaybillOnProviders4SavedOrder(jxcontext.AdminCtx, savedOrderInfo, nil, excludeVendorIDs, false, maxDeliveryFee); err == nil { + savedOrderInfo.retryCount++ + } } } else { errMsg := fmt.Sprintf("订单:%s已经自动创建过了%d次运单,仍然无法配送,请关注!", order.VendorOrderID, savedOrderInfo.retryCount) @@ -751,6 +890,21 @@ func (s *DefScheduler) cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo return err } +func (s *DefScheduler) solutionJdsOrder(bill *model.Waybill) (err error) { + if len(bill.VendorOrderID) > 12 { + //表示此订单是京东商城2次转移的订单,不用出库,但要去修改运单号 + // if utils.Str2Int(bill.VendorOrderID[12:len(bill.VendorOrderID)]) > 2 { + // err = jdshop.CurPurchaseHandler.OrderTransfer(jxcontext.AdminCtx, bill.VendorOrderID, bill.VendorWaybillID, true) + // if err != nil { + // globals.SugarLogger.Errorf("京东商城订单自动转移失败!", err) + // } + // } else { + // err = jdshop.CurPurchaseHandler.OrderExport(jxcontext.AdminCtx, bill.VendorOrderID, bill.VendorWaybillID, true) + // } + } + return err +} + func (s *DefScheduler) cancelOtherWaybills(savedOrderInfo *WatchOrderInfo, bill2Keep *model.Waybill, cancelReasonID int, cancelReason string) (err error) { globals.SugarLogger.Debugf("cancelOtherWaybills, orderID:%s, bill:%v", savedOrderInfo.order.VendorOrderID, bill2Keep) for _, v := range savedOrderInfo.waybills { @@ -1146,6 +1300,13 @@ func (s *DefScheduler) updateOrderByBill(order *model.GoodsOrder, bill *model.Wa } else { order.WaybillVendorID = bill.WaybillVendorID order.VendorWaybillID = bill.VendorWaybillID + if bill.Status == model.WaybillStatusDelivered { + storeDetail, _ := partner.CurOrderManager.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID) + if storeDetail != nil { + jxutils.RefreshOrderEarningPrice3(order, storeDetail.PayPercentage, bill) + updateFields = append(updateFields, "NewEarningPrice") + } + } } if revertStatus { order.Status = model.OrderStatusFinishedPickup @@ -1171,7 +1332,8 @@ func (s *DefScheduler) updateBillsInfo(savedOrderInfo *WatchOrderInfo, bill *mod func (s *DefScheduler) autoPickupGood(savedOrderInfo *WatchOrderInfo) (err error) { order := savedOrderInfo.order - if err = s.PickupGoods(order, model.IsOrderDeliveryByStore(order), ""); err == nil { + flag := model.IsOrderDeliveryByStore(order) || model.IsOrderDeliveryBySelf(order) + if err = s.PickupGoods(order, flag, ""); err == nil { order.DeliveryFlag |= model.OrderDeliveryFlagMaskAutoPickup partner.CurOrderManager.UpdateOrderFields(order, []string{"DeliveryFlag"}) } else if err == scheduler.ErrOrderStatusAlreadySatisfyCurOperation { @@ -1314,6 +1476,7 @@ func (s *DefScheduler) isBillCandidate(order *model.GoodsOrder, bill *model.Wayb func (s *DefScheduler) ProxyCancelWaybill(order *model.GoodsOrder, bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) { globals.SugarLogger.Debugf("ProxyCancelWaybill orderID:%s", order.VendorOrderID) + if (order.DeliveryFlag & model.OrderDeliveryFlagMaskScheduleDisabled) == 0 { if err = s.CancelWaybill(bill, cancelReasonID, cancelReason); err != nil { partner.CurOrderManager.OnOrderMsg(order, "取消三方运单失败", err.Error()) @@ -1341,7 +1504,7 @@ func OnDefSchConfChanged(key, value string) { func setFakeActualPayPrice(order *model.GoodsOrder) (newOrder *model.GoodsOrder) { orderCopy := *order - storeDetail, err := dao.GetStoreDetail(dao.GetDB(), order.JxStoreID, order.VendorID) + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), order.JxStoreID, order.VendorID, "") if err == nil { if storeDetail.PayPercentage < 50 { orderCopy.ActualPayPrice = order.TotalShopMoney * (100 - int64(storeDetail.PayPercentage/2)) / 100 @@ -1353,10 +1516,10 @@ func setFakeActualPayPrice(order *model.GoodsOrder) (newOrder *model.GoodsOrder) return newOrder } -func (s *DefScheduler) notifyNewOrder(order *model.GoodsOrder) { - if order.Flag&model.OrderFlagMaskFake == 0 { +func (s *DefScheduler) notifyNewOrder(order *model.GoodsOrder, isAuto bool) { + if order.Flag&model.OrderFlagMaskFake == 0 && order.VendorID != model.VendorIDEBAI { utils.CallFuncAsync(func() { - order = setFakeActualPayPrice(order) + // order = setFakeActualPayPrice(order) netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) //目前暂且认为AdjustCount > 0 就是调整单 if order.AdjustCount > 0 { @@ -1364,16 +1527,19 @@ func (s *DefScheduler) notifyNewOrder(order *model.GoodsOrder) { } else { weixinmsg.NotifyNewOrder(order) } - smsmsg.NotifyNewOrder(order) OrderProfitWarning(order) - smsmsg.NotifyNewUserOrder(order) + if !isAuto { + smsmsg.NotifyNewOrder(order) + } + // smsmsg.NotifyNewUserOrder(order) + push.NotifyNewOrder(order) }) } } func (s *DefScheduler) notifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) { utils.CallFuncAsync(func() { - order = setFakeActualPayPrice(order) + // order = setFakeActualPayPrice(order) weixinmsg.NotifyUserApplyCancel(order, cancelReason) }) } @@ -1381,9 +1547,10 @@ func (s *DefScheduler) notifyUserApplyCancel(order *model.GoodsOrder, cancelReas func (s *DefScheduler) notifyOrderCanceled(order *model.GoodsOrder) { if order.Flag&model.OrderFlagMaskFake == 0 { utils.CallFuncAsync(func() { - order = setFakeActualPayPrice(order) + // order = setFakeActualPayPrice(order) weixinmsg.NotifyOrderCanceled(order) smsmsg.NotifyOrderCanceled(order) + push.NotifyOrderCanceled(order) }) } } @@ -1417,21 +1584,66 @@ func OrderProfitWarning(order *model.GoodsOrder) { return } storeID := jxutils.GetShowStoreIDFromOrder(order) - storeDetail, err := dao.GetStoreDetail(db, storeID, order.VendorID) + storeDetail, err := dao.GetStoreDetail(db, storeID, order.VendorID, "") + payPercentage := 0 if storeDetail != nil && err == nil { - payPercentage := storeDetail.PayPercentage - if payPercentage >= 50 { - profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney-order.EarningPrice)) / 100 + if storeDetail.VendorPayPercentage != 0 { + payPercentage = storeDetail.VendorPayPercentage } else { - profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney*int64(payPercentage)/200)) / 100 + payPercentage = storeDetail.PayPercentage } + if beego.BConfig.RunMode == "jxgy" { + if payPercentage >= 50 { + profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney-order.EarningPrice)) / 100 + } else { + profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney*int64(payPercentage)/200)) / 100 + } + } else { + if payPercentage >= 50 { + profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney-order.ShopPrice)) / 100 + } else { + profit = utils.Str2Float64(utils.Int64ToStr(order.TotalShopMoney*int64(payPercentage)/200)) / 100 + } + } + globals.SugarLogger.Debugf("OrderProfitWarning profit : %v", profit) if profit < 0 { operatorPhone, operatorName := getOrderOperatorInfo(order, storeDetail) + operatorRole := getOrderOperatorRoleInfo(order, storeDetail) if operatorPhone != "" { - noticeMsg := fmt.Sprintf("利润 :[%v],运营负责人:[%v],门店ID:[%v],平台门店ID[%v],门店名:[%v],订单序号:[%v],订单号(点击进入详情):%v", profit, operatorName, order.StoreID, order.VendorStoreID, order.StoreName, order.OrderSeq, globals.BackstageHost+"/#/ordermanager/"+order.VendorOrderID) + var ( + roleList []*authz.RoleInfo + userIDs []string + flag = false + ) + if operatorRole != "" { + roleList = append(roleList, autils.NewRole(operatorRole, 0)) + if userIDMap, err := cms.GetRolesUserList(jxcontext.AdminCtx, roleList); err == nil { + for _, v := range userIDMap { + for _, vv := range v { + userIDs = append(userIDs, vv) + } + } + } + } + noticeMsg := fmt.Sprintf("利润 :[%v],运营负责人:[%v],商家负责人:[%v],门店ID:[%v],平台门店ID[%v],门店名:[%v],订单序号:[%v],订单号(点击进入详情):%v", profit, operatorName, storeDetail.MarketManName, order.StoreID, order.VendorStoreID, order.StoreName, order.OrderSeq, globals.BackstageHost+"/#/ordermanager/"+order.VendorOrderID) user, err := dao.GetUserByID(db, "mobile", operatorPhone) + user2, err := dao.GetUserByID(db, "mobile", storeDetail.MarketManPhone) if user != nil && err == nil { - ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "警告!此订单利润低于0", noticeMsg) + for _, v := range userIDs { + if v == user.UserID { + flag = true + break + } + } + if !flag { + userIDs = append(userIDs, user.UserID) + } + userIDs = append(userIDs, user2.UserID) + for _, v := range userIDs { + if api.DingDingAPI.GetToken() != "" { + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, v, "警告!此订单利润低于0", noticeMsg) + } + } } } } @@ -1443,7 +1655,7 @@ func (s *DefScheduler) notifyOrderStakeHolder(order *model.GoodsOrder, msgTitle, // "18180948107", } db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID) + storeDetail, err := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") if err == nil { operatorPhone, _ := getOrderOperatorInfo(order, storeDetail) if operatorPhone != "" { @@ -1480,3 +1692,15 @@ func getOrderOperatorInfo(order *model.GoodsOrder, storeDetail *dao.StoreDetail) } return operatorPhone, operatorName } + +func getOrderOperatorRoleInfo(order *model.GoodsOrder, storeDetail *dao.StoreDetail) (roleName string) { + switch order.VendorID { + case model.VendorIDJD: + roleName = storeDetail.OperatorRole + case model.VendorIDMTWM: + roleName = storeDetail.OperatorRole2 + case model.VendorIDEBAI: + roleName = storeDetail.OperatorRole3 + } + return roleName +} diff --git a/business/jxcallback/scheduler/defsch/defsch_afs.go b/business/jxcallback/scheduler/defsch/defsch_afs.go index f8a00c562..260aec703 100644 --- a/business/jxcallback/scheduler/defsch/defsch_afs.go +++ b/business/jxcallback/scheduler/defsch/defsch_afs.go @@ -3,6 +3,7 @@ package defsch import ( "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + push "git.rosy.net.cn/jx-callback/business/jxutils/unipush" "git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/msghub" @@ -31,6 +32,7 @@ func (s *DefScheduler) OnAfsOrderNew(order *model.AfsOrder, isPending bool) (err } msghub.OnNewWait4ApproveAfsOrder(order) weixinmsg.NotifyAfsOrderStatus(order) + push.NotifyAfsOrder(order) } } return err diff --git a/business/jxcallback/scheduler/defsch/defsch_ext.go b/business/jxcallback/scheduler/defsch/defsch_ext.go index 9acf53a29..802f4567d 100644 --- a/business/jxcallback/scheduler/defsch/defsch_ext.go +++ b/business/jxcallback/scheduler/defsch/defsch_ext.go @@ -5,6 +5,8 @@ import ( "math" "time" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" @@ -31,11 +33,12 @@ func (s *DefScheduler) SelfDeliveringAndUpdateStatus(ctx *jxcontext.Context, ven if savedOrderInfo != nil { order = savedOrderInfo.order if err = s.isPossibleSwitch2SelfDelivery(order); err == nil { + globals.SugarLogger.Infof("SelfDeliveringAndUpdateStatus ordersavedOrderInfoID:%s", utils.Format4Output(savedOrderInfo, false)) err = s.cancelOtherWaybillsCheckOrderDeliveryFlag(savedOrderInfo, nil, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) if err == nil { if model.IsOrderDeliveryByStore(order) { if order.Status < model.OrderStatusDelivering { - storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), order.StoreID, order.VendorID) + storeDetail, err2 := dao.GetStoreDetail(dao.GetDB(), order.StoreID, order.VendorID, "") phone := userName if err = err2; err == nil { phone = storeDetail.Tel1 @@ -81,7 +84,7 @@ func (s *DefScheduler) SelfDeliveringAndUpdateStatus(ctx *jxcontext.Context, ven return err } -func (s *DefScheduler) canOrderCreateWaybillNormally(order *model.GoodsOrder) (err error) { +func (s *DefScheduler) canOrderCreateWaybillNormally(order *model.GoodsOrder, savedOrderInfo *WatchOrderInfo) (err error) { if !(order.LockStatus != model.OrderStatusLocked && order.Status >= model.OrderStatusFinishedPickup && order.Status < model.OrderStatusEndBegin) { err = fmt.Errorf("当前订单%s没有处于拣货完成且没有结束没有锁定的订单才能进行召唤配送操作", order.VendorOrderID) } else if model.IsOrderHaveWaybill(order) { @@ -112,7 +115,7 @@ func (s *DefScheduler) isPossibleSwitch2SelfDelivery(order *model.GoodsOrder) (e func (s *DefScheduler) CreateWaybillOnProviders4SavedOrder(ctx *jxcontext.Context, savedOrderInfo *WatchOrderInfo, courierVendorIDs, excludeCourierVendorIDs []int, forceCreate bool, maxDeliveryFee int64) (bills []*model.Waybill, err error) { order := savedOrderInfo.order if !forceCreate { - err = s.canOrderCreateWaybillNormally(order) + err = s.canOrderCreateWaybillNormally(order, nil) } if err == nil { if forceCreate { @@ -152,10 +155,28 @@ func (s *DefScheduler) CreateWaybillOnProvidersEx(ctx *jxcontext.Context, vendor if order.DeliveryType == model.OrderDeliveryTypeSelfTake { return nil, fmt.Errorf("订单:%s是自提单", vendorOrderID) } + //1表示为门店发单,需要验证门店账户余额情况 + if order.CreateDeliveryType == model.YES { + //暂时这么认为,len courierVendorIDs 为1表示是老板或者运营从小程序上点的立即发单,因为小程序上是点哪个发哪个 + //京西后台则是点一下发3个,len courierVendorIDs 是0 + //如果是小程序上点哪个扣哪个平台的钱 + //如果是后台,则选最高的那个扣 + if len(courierVendorIDs) == 1 { + + } else if len(courierVendorIDs) == 0 { + + } + } if !forceCreate { err = s.isPossibleSwitch2SelfDelivery(order) } if err == nil { + if savedOrderInfo.order.VendorID == model.VendorIDEBAI { + courierVendorIDs = []int{model.VendorIDMTPS, model.VendorIDDada} + } + order := savedOrderInfo.order + order.DeliveryFlag = 0 + err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) if bills, err = s.CreateWaybillOnProviders4SavedOrder(ctx, savedOrderInfo, courierVendorIDs, nil, forceCreate, maxDeliveryFee); err == nil && len(bills) > 0 { partner.CurOrderManager.OnOrderMsg(order, "手动创建运单成功", fmt.Sprintf("%s创建%s平台运单,强发:%t,最高限价:%d", ctx.GetUserName(), model.VendorChineseNames[bills[0].WaybillVendorID], forceCreate, maxDeliveryFee)) } @@ -210,7 +231,7 @@ func (s *DefScheduler) QueryOrderWaybillFeeInfoEx(ctx *jxcontext.Context, vendor if order.DeliveryType == model.OrderDeliveryTypeSelfTake { return nil, fmt.Errorf("订单:%s是自提单", vendorOrderID) } - storeCourierList, err := dao.GetStoreCourierList(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, model.StoreStatusAll, model.StoreAuditStatusOnline) + storeCourierList, err := dao.GetStoreCourierList(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, nil, model.StoreStatusAll, model.StoreAuditStatusOnline) if err != nil { return nil, err } diff --git a/business/jxcallback/scheduler/scheduler.go b/business/jxcallback/scheduler/scheduler.go index e4a57e155..801f639f3 100644 --- a/business/jxcallback/scheduler/scheduler.go +++ b/business/jxcallback/scheduler/scheduler.go @@ -35,7 +35,7 @@ var ( type IScheduler interface { // 以下是订单 - OnOrderNew(order *model.GoodsOrder, isPending bool) (err error) + OnOrderNew(order *model.GoodsOrder, isPending bool, isAuto bool) (err error) OnOrderStatusChanged(order *model.GoodsOrder, status *model.OrderStatus, isPending bool) (err error) // 以下是运单 diff --git a/business/jxstore/act/act.go b/business/jxstore/act/act.go index 5cd8e4116..9466cc196 100644 --- a/business/jxstore/act/act.go +++ b/business/jxstore/act/act.go @@ -8,6 +8,7 @@ import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" @@ -137,6 +138,10 @@ var ( MinDiscount: 0, MaxDiscount: 80, }, + model.ActSkuDiscount: &tActRuleInfo{ + MinDiscount: 100, + MaxDiscount: 100, + }, }, } ) @@ -215,7 +220,7 @@ func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Ac validVendorMap := make(map[int]int) validSkuMap := make(map[int]int) for _, vendorID := range vendorIDs { - storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID, "") if err = err2; err == nil { if storeDetail.IsSync != 0 { if act.Type == model.ActSkuFake || @@ -456,6 +461,13 @@ func checkActValidation(act *model.Act, vendorIDs []int) (err error) { } } else if act.Type == model.ActSkuFake { + } else if act.Type == model.ActSkuDiscount { + if act.DiscountType == 0 { + errList.AddErr(fmt.Errorf("折扣活动必须选择折扣类型")) + } + if act.DiscountValue1 == 0 || act.DiscountValue2 == 0 { + errList.AddErr(fmt.Errorf("折扣活动必须填入两档")) + } } else { errList.AddErr(fmt.Errorf("当前只支持%s与%s活动", model.ActTypeName[model.ActSkuDirectDown], model.ActTypeName[model.ActSkuSecKill])) } @@ -515,6 +527,19 @@ func PreCreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRu } func CreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, vendorOrgCode string, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam, isAsync bool) (hint string, err error) { + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var actStoreSku2 []*ActStoreSkuParam + for _, v := range actStoreSku { + if storeIDsMap[v.StoreID] != 0 { + actStoreSku2 = append(actStoreSku2, v) + } + } + actStoreSku = nil + actStoreSku = actStoreSku2 + } + } if err = checkActValidation(act, vendorIDs); err != nil { return "", err } @@ -770,6 +795,16 @@ func CancelAct(ctx *jxcontext.Context, actID int) (err error) { return err } _, err = SyncAct(ctx, nil, actID, nil, false) + act := &model.Act{} + act.ID = actID + if err == nil { + if _, err = dao.UpdateEntityLogically(db, act, + map[string]interface{}{ + model.FieldStatus: model.ActStatusCanceled, + }, ctx.GetUserName(), nil); err != nil { + return err + } + } return err } @@ -872,14 +907,16 @@ func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, act } if isNeedCancelAct { - act := &model.Act{} - act.ID = actID - if _, err = dao.UpdateEntityLogically(db, act, - map[string]interface{}{ - model.FieldStatus: model.ActStatusCanceled, - }, ctx.GetUserName(), nil); err != nil { - return 0, err - } + // act := &model.Act{} + // act.ID = actID + // if err == nil { + // if _, err = dao.UpdateEntityLogically(db, act, + // map[string]interface{}{ + // model.FieldStatus: model.ActStatusCanceled, + // }, ctx.GetUserName(), nil); err != nil { + // return 0, err + // } + // } } dao.Commit(db) return originSyncStatus, err @@ -1057,6 +1094,46 @@ func RefreshPageActs(ctx *jxcontext.Context, vendorIDs []int, createdFrom time.T return hint, err } +func DeleteStoresFromAct(ctx *jxcontext.Context, vendorID int, actTypes, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { + db := dao.GetDB() + task := tasksch.NewParallelTask("将门店从所有活动中删除", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeID := batchItemList[0].(int) + acts, _ := dao.QueryActs(db, 0, 0, 50, -1, "", vendorID, []int{1}, actTypes, nil, storeID, nil, 0, utils.ZeroTimeValue, utils.ZeroTimeValue, time.Now().AddDate(0, -3, 0), time.Now()) + for _, v := range acts.Data { + var actStoreSkuParam []*ActStoreSkuParam + _, actStoreSkus, _ := dao.GetActStoreSkuVendorList(db, v.ID, []int{vendorID}, nil, nil, "", 0, 99999) + for _, actStoreSku := range actStoreSkus { + if actStoreSku.StoreID == storeID { + aa := &ActStoreSkuParam{ + ActStoreSku: model.ActStoreSku{ + StoreID: storeID, + SkuID: actStoreSku.SkuID, + ActID: v.ID, + }, + } + actStoreSkuParam = append(actStoreSkuParam, aa) + } + } + _, err = DeleteActStoreSkuBind(ctx, db, v.ID, actStoreSkuParam) + if err == nil { + _, err = SyncAct(ctx, nil, v.ID, nil, true) + } + } + return retVal, err + }, storeIDs) + tasksch.HandleTask(task, nil, true).Run() + if isAsync { + hint = task.GetID() + } else { + resultList, err2 := task.GetResult(0) + if err = err2; err == nil { + hint = utils.Int2Str(len(resultList)) + } + } + return hint, err +} + func DeleteSkusFromAct(ctx *jxcontext.Context, vendorID int, actTypes, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() actMap := make(map[int]*model.Act) @@ -1180,7 +1257,7 @@ func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, s for _, storeSkuBind := range storeSkuBindList { if _, err2 := dao.UpdateEntity(db, storeSkuBind); err2 == nil { if storeVendorIDMap[storeSkuBind.StoreID] == "" { - if storeDetail, err2 := dao.GetStoreDetail(db, storeSkuBind.StoreID, vendorID); err2 == nil { + if storeDetail, err2 := dao.GetStoreDetail(db, storeSkuBind.StoreID, vendorID, ""); err2 == nil { storeVendorIDMap[storeSkuBind.StoreID] = storeDetail.VendorStoreID } } @@ -1198,7 +1275,7 @@ func ForceUpdateVendorPrice(ctx *jxcontext.Context, vendorID int, actType int, s subTask := tasksch.NewParallelTask("同步平台价格", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeID := batchItemList[0].(int) - _, err = cms.SyncStoreSkuNew2(ctx, task, 0 /*model.SyncFlagPriceMask*/, vendorID, storeID, storeVendorIDMap[storeID], nil, storeSkuIDMap[storeID], nil, true, false, true) + _, err = cms.SyncStoreSkuNew2(ctx, task, 0 /*model.SyncFlagPriceMask*/, vendorID, storeID, storeVendorIDMap[storeID], "", nil, storeSkuIDMap[storeID], nil, true, false, true) return retVal, err }, storeIDs) tasksch.HandleTask(subTask, task, true).Run() @@ -1453,3 +1530,181 @@ func loadExcelForCreateAct(rowNum, mixType int, row []string, sheetParam *SheetP } actStoreSkuList = append(actStoreSkuList, actStoreSku) } + +func ChangeJxPriceByDiscountAct(ctx *jxcontext.Context) { + var ( + db = dao.GetDB() + pageSize = 9999 + ) + globals.SugarLogger.Debug("ChangeJxPriceByDiscountAct begin:") + page, err := dao.QueryActs(db, 0, 0, pageSize, -1, "", model.VendorIDJX, []int{model.YES}, []int{model.ActSkuDiscount}, nil, 0, nil, 0, utils.ZeroTimeValue, utils.ZeroTimeValue, time.Now().AddDate(0, -3, 0), time.Now()) + if err != nil { + return + } + if len(page.Data) == 0 { + return + } + for _, act := range page.Data { + _, actStoreSkus, _ := dao.GetActStoreSkuVendorList(db, act.ID, nil, nil, nil, "", 0, pageSize) + if len(actStoreSkus) == 0 { + continue + } + for _, actStoreSku2 := range actStoreSkus { + actStoreSkuMap := &model.ActStoreSkuMap{ + ModelIDCULD: model.ModelIDCULD{ + ID: actStoreSku2.MapID, + }, + ActID: actStoreSku2.ActID, + StoreID: actStoreSku2.StoreID, + SkuID: actStoreSku2.SkuID, + TrendPrice: actStoreSku2.TrendPrice, + TrendType: actStoreSku2.TrendType, + ActualActPrice: actStoreSku2.ActualActPrice, + VendorPrice: actStoreSku2.VendorPrice, + } + storeSkus, _ := dao.GetStoresSkusInfo(db, []int{actStoreSkuMap.StoreID}, []int{actStoreSkuMap.SkuID}) + if len(storeSkus) == 0 { + continue + } + var ( + storeSku = storeSkus[0] + shouldStockOut = utils.Float64TwoInt64(math.Ceil(float64(storeSku.Stock) / float64(60))) //每个时间点应出货 = 总库存/60 = N + actualStockOut int64 //每个时间点实际出货 = C + pricePercentage float64 //每次涨跌值为 原价的 2%,即原价100,每个时间点降价为2,涨价也为2 + actualPrice int64 + minJxPrice int64 + ) + if storeSku.Stock == 0 { + continue + } + actualStockOut, err = dao.GetOrderStoreSkusCount(db, actStoreSkuMap.StoreID, actStoreSkuMap.SkuID, time.Now().Add(-time.Minute*10), time.Now()) + dao.Begin(db) + defer func() { + if r := recover(); r != nil || err != nil { + dao.Rollback(db) + if r != nil { + panic(r) + } + } + }() + //第一档时间内 + if (time.Now().Hour() >= 10 && time.Now().Hour() < 20) || (time.Now().Hour() == 20 && time.Now().Minute() < 1) { + pricePercentage = 0.02 + actualPrice = utils.Float64TwoInt64(float64(actStoreSkuMap.VendorPrice) * pricePercentage) + if actStoreSkuMap.TrendType == model.TrendTypeUp { + actStoreSkuMap.ActualActPrice = actStoreSkuMap.ActualActPrice + actualPrice + // storeSku.JxPrice = storeSku.JxPrice + int(actualPrice) + } else if actStoreSkuMap.TrendType == model.TrendTypeDown { + actStoreSkuMap.ActualActPrice = actStoreSkuMap.ActualActPrice - actualPrice + //判断活动的折扣类型是最低价还是最低折扣(第一档) + if act.DiscountType == model.ActDiscountTypePrice { + minJxPrice = int64(act.DiscountValue1) + } else if act.DiscountType == model.ActDiscountTypePercentage { + minJxPrice = actStoreSkuMap.VendorPrice * int64(act.DiscountValue1) / 100 + } + if actStoreSkuMap.ActualActPrice <= minJxPrice { + actStoreSkuMap.ActualActPrice = minJxPrice + } + // storeSku.JxPrice = storeSku.JxPrice - int(actualPrice) + stock := checkPriceDefendOrderByPrice(db, storeSku.StoreID, storeSku.SkuID, storeSku.Stock, int(actStoreSkuMap.ActualActPrice)) + if stock != -1 { + storeSku.Stock = stock + if _, err = dao.UpdateEntity(db, storeSku, "Stock"); err != nil { + dao.Rollback(db) + } + } + } + if actStoreSkuMap.ActualActPrice >= actStoreSkuMap.VendorPrice { + actStoreSkuMap.ActualActPrice = actStoreSkuMap.VendorPrice + } + // if _, err = dao.UpdateEntity(db, actStoreSkuMap, "ActualActPrice"); err != nil { + // dao.Rollback(db) + // } + //C >= 2N 涨价趋势,最高涨价到无折扣 + if actualStockOut >= 2*shouldStockOut { + actStoreSkuMap.TrendType = model.TrendTypeUp + if actStoreSkuMap.ActualActPrice == actStoreSkuMap.VendorPrice { + actStoreSkuMap.TrendType = model.TrendTypeNothing + } + } else if actualStockOut < utils.Float64TwoInt64(math.Ceil(float64(shouldStockOut)/float64(2))) { //C <= N/2 降价趋势,最低降价到设置到最低折扣 + actStoreSkuMap.TrendType = model.TrendTypeDown + if actStoreSkuMap.ActualActPrice == minJxPrice { + actStoreSkuMap.TrendType = model.TrendTypeNothing + } + } else { + actStoreSkuMap.TrendType = model.TrendTypeNothing + } + actStoreSkuMap.TrendPrice = int(actualPrice) + if _, err = dao.UpdateEntity(db, actStoreSkuMap, "ActualActPrice", "TrendType", "TrendPrice"); err != nil { + dao.Rollback(db) + } + } else { //第二档时间内 + pricePercentage = 0.1 + actualPrice = utils.Float64TwoInt64(float64(actStoreSkuMap.VendorPrice) * pricePercentage) + //判断活动的折扣类型是最低价还是最低折扣(第二档) + if act.DiscountType == model.ActDiscountTypePrice { + minJxPrice = int64(act.DiscountValue2) + } else if act.DiscountType == model.ActDiscountTypePercentage { + minJxPrice = actStoreSkuMap.VendorPrice * int64(act.DiscountValue2) / 100 + } + if actStoreSkuMap.ActualActPrice == minJxPrice { + actStoreSkuMap.TrendType = model.TrendTypeNothing + } else { + actStoreSkuMap.TrendType = model.TrendTypeDown + } + actStoreSkuMap.TrendPrice = int(actualPrice) + // if _, err = dao.UpdateEntity(db, actStoreSkuMap, "TrendType", "TrendPrcie"); err != nil { + // dao.Rollback(db) + // } + actStoreSkuMap.ActualActPrice = actStoreSkuMap.ActualActPrice - actualPrice + if actStoreSkuMap.ActualActPrice <= minJxPrice { + actStoreSkuMap.ActualActPrice = minJxPrice + } + stock := checkPriceDefendOrderByPrice(db, storeSku.StoreID, storeSku.SkuID, storeSku.Stock, int(actStoreSkuMap.ActualActPrice)) + if stock != -1 { + storeSku.Stock = stock + if _, err = dao.UpdateEntity(db, storeSku, "Stock"); err != nil { + dao.Rollback(db) + } + } + //22:00 恢复库存为100,价格恢复原价 + if time.Now().Hour() == 22 && time.Now().Minute() < 1 { + storeSku.Stock = 100 + if _, err = dao.UpdateEntity(db, storeSku, "Stock"); err != nil { + dao.Rollback(db) + } + actStoreSkuMap.ActualActPrice = actStoreSkuMap.VendorPrice + actStoreSkuMap.TrendType = model.TrendTypeNothing + actStoreSkuMap.TrendPrice = 0 + } + if _, err = dao.UpdateEntity(db, actStoreSkuMap, "ActualActPrice", "TrendType", "TrendPrice"); err != nil { + dao.Rollback(db) + } + } + dao.Commit(db) + } + } +} + +func checkPriceDefendOrderByPrice(db *dao.DaoDB, storeID, skuID, stock, jxPrice int) (realStock int) { + priceDefends, _ := dao.GetPriceDefendOrder(db, "", []int{storeID}, []int{skuID}, []int{jxutils.GetDefendPriceIssue()}, 0, 0, 0, 1, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefends) == 0 { + return -1 + } + for _, v := range priceDefends { + //如果刚好守的价和降的价一样,再判断库存够不够 + if v.DefendPrice > int64(jxPrice) { + if v.Count <= stock { + stock -= v.Count + v.IsSuccess = model.YES + v.RealPrice = int64(jxPrice) + dao.UpdateEntity(db, v, "IsSuccess", "RealPrice") + } else { + continue + } + } else { + continue + } + } + return stock +} diff --git a/business/jxstore/cms/cms.go b/business/jxstore/cms/cms.go index 3a420aa95..3b5d5d5e0 100644 --- a/business/jxstore/cms/cms.go +++ b/business/jxstore/cms/cms.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" + "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/globals/api2" @@ -148,6 +150,10 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) { "operateType": model.OperateTypeName, "thingType": model.ThingTypeName, "apiFunctionName": model.ApiFunctionName, + "vendorStatus": model.VendorStatus, + "couponsStatus": model.CouponStatusName, + "ebaiSupplierID": ebai.EbaiSupplierIDMap, + "ebaiSupplierInfo": ebai.EbaiSupplierInfo, }, } } @@ -221,6 +227,11 @@ func GetCoordinateDistrictCode(ctx *jxcontext.Context, lng, lat float64) (code i return api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat), nil } +func GetCoordinateCityInfo(ctx *jxcontext.Context, lng, lat float64) (name string, err error) { + name, _ = api.AutonaviAPI.GetCoordinateCityInfo(lng, lat) + return name, err +} + func SendMsg2Somebody(ctx *jxcontext.Context, mobileNum, verifyCode, msgType, msgContent string) (err error) { if needConfirmRequestMap[msgType] == 1 { if _, err = mobile.AutherObj.VerifySecret(mobileNum, verifyCode); err != nil { @@ -380,6 +391,7 @@ func checkConfig(opFlag int, configType, key, value string) (err error) { } case model.ConfigTypeJxStore: case model.ConfigTypeCookie: + case model.ConfigTypeDiscountCard: default: err = fmt.Errorf("当前只支持配置:%s, 传入的配置类型:%s", utils.Format4Output(model.ConfigTypeName, true), configType) } @@ -412,7 +424,7 @@ func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { db := dao.GetDB() switch configType { case model.ConfigTypePricePack: - storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, key) + storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, key, "", "") if err = err2; err == nil { var storeInfo []string for _, v := range storeMapList { @@ -423,7 +435,7 @@ func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { } } case model.ConfigTypeFreightPack: - storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeMapList, err2 := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err = err2; err == nil { var storeInfo []string for _, v := range storeMapList { @@ -450,7 +462,7 @@ func DeleteConfig(ctx *jxcontext.Context, key, configType string) (err error) { } } errList.AddErr(err) - storeList, err2 := dao.GetStoreList(db, nil, nil, nil, nil, key) + storeList, err2 := dao.GetStoreList(db, nil, nil, nil, nil, nil, key) if err = err2; err == nil && len(storeList) > 0 { storeIDs := make([]int, len(storeList)) for k, v := range storeList { @@ -503,7 +515,7 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s } switch configType { case model.ConfigTypePricePack: - storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, key) + storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, key, "", "") if err != nil { dao.Rollback(db) return "", err @@ -522,7 +534,7 @@ func UpdateConfig(ctx *jxcontext.Context, key, configType, value string) (hint s } case model.ConfigTypeFreightPack: dao.Commit(db) - storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err != nil { return "", err } diff --git a/business/jxstore/cms/message.go b/business/jxstore/cms/message.go index 4ce418a22..6d04f3f72 100644 --- a/business/jxstore/cms/message.go +++ b/business/jxstore/cms/message.go @@ -78,7 +78,7 @@ func GetStoreMessages(ctx *jxcontext.Context, msgIDs, storeIDs, types []int, fro return pagedInfo, err } -func GetStoreMessageStatuses(ctx *jxcontext.Context, msgIDs, storeIDs []int, fromReadCount, toReadCount int, fromTime, toTime time.Time, keyword string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { +func GetStoreMessageStatuses(ctx *jxcontext.Context, msgIDs, storeIDs, confirmStatuss []int, fromReadCount, toReadCount int, fromTime, toTime time.Time, keyword string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { sql := ` SELECT SQL_CALC_FOUND_ROWS t1.*, @@ -92,6 +92,10 @@ func GetStoreMessageStatuses(ctx *jxcontext.Context, msgIDs, storeIDs []int, fro sql += " AND t1.store_id IN (" + dao.GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } + if len(confirmStatuss) > 0 { + sql += " AND t1.confirm_status IN (" + dao.GenQuestionMarks(len(confirmStatuss)) + ")" + sqlParams = append(sqlParams, confirmStatuss) + } if len(msgIDs) > 0 { sql += " AND t1.message_id IN (" + dao.GenQuestionMarks(len(msgIDs)) + ")" sqlParams = append(sqlParams, msgIDs) diff --git a/business/jxstore/cms/sku.go b/business/jxstore/cms/sku.go index 788bcd094..b3ee2f130 100644 --- a/business/jxstore/cms/sku.go +++ b/business/jxstore/cms/sku.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/astaxie/beego" + "git.rosy.net.cn/baseapi/platformapi/aliupcapi" "git.rosy.net.cn/baseapi/utils" @@ -112,8 +114,8 @@ func GetCategories(ctx *jxcontext.Context, parentID int, isExd bool) (catList [] func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string) (outCat *model.SkuCategory, err error) { db := dao.GetDB() - if cat.Level < 0 || cat.Level > 2 { - return nil, errors.New("Level必须为1或2") + if cat.Level < 0 || cat.Level > 3 { + return nil, errors.New("Level必须为1或2,3") } else if cat.Level == 1 && cat.ParentID != 0 { return nil, errors.New("Level1的分类其父分类必须为0") } else if cat.Level == 2 { @@ -128,8 +130,24 @@ func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string if parentCat.Level != 1 { return nil, errors.New("Level2的分类其父分类必须为Level1分类") } + } else if cat.Level == 3 { + if cat.ParentID == 0 { + return nil, errors.New("Level3的分类其父分类必须不为0") + } + parentCat := &model.SkuCategory{} + parentCat.ID = cat.ParentID + if err = dao.GetEntity(db, parentCat); err != nil { + return nil, err + } + if parentCat.Level != 2 { + return nil, errors.New("Level3的分类其父分类必须为Level2分类") + } + } + if catsByName, err := dao.GetCategoriesByName(db, cat.Name); err == nil && len(catsByName) > 0 { + return nil, fmt.Errorf("已有分类名:[%v],分类名不允许重复!", cat.Name) + } else if err != nil { + return nil, err } - dao.WrapAddIDCULDEntity(cat, userName) // cat.JdSyncStatus = model.SyncFlagNewMask // cat.JdID = 0 @@ -163,7 +181,7 @@ func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string return nil, err } if cat.IsExdSpec == model.NO { - if err = OnCreateThing(ctx, db, nil, int64(cat.ID), model.ThingTypeCategory); err != nil { + if err = OnCreateThing(ctx, db, nil, int64(cat.ID), model.ThingTypeCategory, model.SyncFlagNewMask, false); err != nil { dao.Rollback(db) return nil, err } @@ -588,6 +606,9 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric t1.price, t1.img, t1.img2, + t1.img3, + t1.img_watermark, + t1.img_mix, t1.status, t1.is_spu, t1.desc_img, @@ -595,7 +616,10 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric t1.ex_prefix, t1.ex_prefix_begin, t1.ex_prefix_end, - t1.yb_name_suffix + t1.yb_name_suffix, + t1.jds_stock_switch, + t1.preparation_time, + t1.best_seller ` if isQueryMidPrice { sql += `, @@ -623,6 +647,9 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric t1.price, t1.img, t1.img2, + t1.img3, + t1.img_watermark, + t1.img_mix, t1.status, t1.is_spu, t1.desc_img, @@ -635,6 +662,9 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric t1.ex_prefix_begin, t1.ex_prefix_end, t1.yb_name_suffix, + t1.jds_stock_switch, + t1.preparation_time, + t1.best_seller, ` if isQueryMidPrice { sqlData += " t4.mid_unit_price," @@ -648,6 +678,9 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric '","eclpID":"', t2.eclp_id, '","weight":', t2.weight, ',"categoryID":', t2.category_id, ',"nameID":', t2.name_id, ', "seq":', t2.seq, + ', "minOrderCount":', t2.min_order_count, + ', "ladderBoxNum":', t2.ladder_box_num, + ', "ladderBoxPrice":', t2.ladder_box_price, "}")), "]") skus_str, CONCAT("[", GROUP_CONCAT(DISTINCT t3.place_code), "]") places_str ` + sql + ` @@ -689,6 +722,23 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric return nil, err } } + skuVendorCats, _ := dao.GetSkuVendorCategoryMaps(db, []int{skuName.ID}, []int{model.VendorIDMTWM, model.VendorIDEBAI, model.VendorIDJDShop, model.VendorIDJD}, nil) + if len(skuVendorCats) > 0 { + for _, v := range skuVendorCats { + if v.VendorID == model.VendorIDJD { + skuName.JdCategoryID = v.VendorCategoryID + } + if v.VendorID == model.VendorIDEBAI { + skuName.EbaiCategoryID = v.VendorCategoryID + } + if v.VendorID == model.VendorIDMTWM { + skuName.MtwmCategoryID = v.VendorCategoryID + } + if v.VendorID == model.VendorIDJDShop { + skuName.JdsCategoryID = v.VendorCategoryID + } + } + } } if len(skuIDs) > 0 { thingMapMap, err2 := dao.GetThingMapMap(db, model.ThingTypeSku, nil, skuIDs) @@ -706,23 +756,37 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku, isQueryMidPric return skuNamesInfo, err } -func CheckHasSensitiveWord(word string) (bool, error) { +func CheckHasSensitiveWord(word string) (bool, string) { if hasSensitiveWord, sensitiveWord := IsSensitiveWordInList(word); hasSensitiveWord { - return true, errors.New(fmt.Sprintf("不能包含敏感词:[%s]", sensitiveWord)) + return true, sensitiveWord } - return false, nil + return false, "" } func IsSensitiveWordInList(str string) (bool, string) { - wordList, err := dao.GetSensitiveWordList() + wordList, err := dao.GetSensitiveWordList(-1) if err == nil { for _, value := range wordList { keyWord := value.Word - checkHas := strings.Contains(str, keyWord) - if checkHas { - return true, keyWord + if value.VendorID != -2 { + checkHas := strings.Contains(str, keyWord) + if checkHas { + return true, keyWord + } + } else { + var index int + for index > 0 { + index = strings.Index(keyWord, ",") + keyWord = keyWord[:index-1] + globals.SugarLogger.Debug("keyWord", keyWord) + checkHas := strings.Contains(str, keyWord) + if checkHas { + return true, keyWord + } + } } + } } @@ -742,8 +806,8 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s } skuNameExt.Name = utils.TrimBlankChar(skuNameExt.Name) - if hasSensitiveWord, err := CheckHasSensitiveWord(skuNameExt.Name); hasSensitiveWord { - return nil, err + if hasSensitiveWord, word := CheckHasSensitiveWord(skuNameExt.Name); hasSensitiveWord { + skuNameExt.Name = strings.ReplaceAll(skuNameExt.Name, word, "") } upc := utils.Pointer2String(skuNameExt.Upc) if upc == "" { @@ -824,7 +888,7 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s dao.Rollback(db) return nil, err } - if err = OnCreateThing(ctx, db, nil, int64(skuNameExt.SkuName.ID), model.ThingTypeSkuName); err != nil { + if err = OnCreateThing(ctx, db, nil, int64(skuNameExt.SkuName.ID), model.ThingTypeSkuName, model.SyncFlagNewMask, false); err != nil { dao.Rollback(db) return nil, err } @@ -832,14 +896,18 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s sku := v.Sku dao.WrapAddIDCULDEntity(sku, userName) sku.NameID = skuNameExt.ID - // sku.JdSyncStatus = model.SyncFlagNewMask - // sku.JdID = 0 + if beego.BConfig.RunMode == "jxgy" { + sku.LadderBoxPrice = 0 + } else if beego.BConfig.RunMode == "prod" { + sku.LadderBoxPrice = 10 + } + sku.LadderBoxNum = 1 if err = dao.CreateEntity(db, sku); err != nil { dao.Rollback(db) return nil, err } if sku.EclpID == "" { - if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil { + if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku, 0, false); err != nil { dao.Rollback(db) return nil, err } @@ -866,6 +934,8 @@ func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName s } outSkuNameExt = tmpInfo.SkuNames[0] _, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, -1, false, false, userName) + + updateOrCreateSkuVendorCategoryMap(db, ctx, outSkuNameExt.SkuName.ID, nil, skuNameExt, false) return outSkuNameExt, err } @@ -880,10 +950,11 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf var beforSkuName = *skuName if payload["name"] != nil { newSkuName := utils.TrimBlankChar(utils.Interface2String(payload["name"])) - if hasSensitiveWord, err := CheckHasSensitiveWord(newSkuName); hasSensitiveWord { - return 0, err + if hasSensitiveWord, word := CheckHasSensitiveWord(newSkuName); hasSensitiveWord { + payload["name"] = strings.ReplaceAll(payload["name"].(string), word, "") + } else { + payload["name"] = newSkuName } - payload["name"] = newSkuName } delete(payload, "isSpu") @@ -892,7 +963,8 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf valid := dao.StrictMakeMapByStructObject(payload, skuName, userName) valid = utils.RemoveGeneralMapKeys(valid, model.FieldSpecQuality, model.FieldSpecUnit) _, hasPlaces := payload["places"] - if len(valid) > 0 || hasPlaces { + flag := updateOrCreateSkuVendorCategoryMap(db, ctx, nameID, payload, nil, false) + if len(valid) > 0 || hasPlaces || flag { if valid["Upc"] != nil { if upc, _ := valid["Upc"].(string); upc == "" { valid["Upc"] = nil @@ -901,7 +973,7 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf } } globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false)) - for _, imgName := range []string{"img", "img2"} { + for _, imgName := range []string{"img", "img2", "img3"} { if valid[imgName] != nil { if imgStr := utils.Interface2String(valid[imgName]); imgStr != "" { _, err2 := datares.TryRegisterDataResource(ctx, skuName.Name, valid[imgName].(string), model.ImgTypeMain, true) @@ -992,6 +1064,12 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf dao.Rollback(db) return 0, err } + if valid["jdsStockSwitch"] != nil { + if _, err = SetStoreSkuSyncStatus2(db, []int{model.JdShopMainStoreID}, []int{model.VendorIDJDShop}, skuIDs, model.SyncFlagSaleMask); err != nil { + dao.Rollback(db) + return 0, err + } + } } dao.Commit(db) @@ -1008,6 +1086,70 @@ func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interf return num, err } +func updateOrCreateSkuVendorCategoryMap(db *dao.DaoDB, ctx *jxcontext.Context, nameID int, payload map[string]interface{}, skuNameExt *model.SkuNameExt, isDelete bool) (flag bool) { + if isDelete { + skuVendorCatMaps, _ := dao.GetSkuVendorCategoryMaps(db, []int{nameID}, nil, nil) + for _, v := range skuVendorCatMaps { + v.DeletedAt = time.Now() + v.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, v, "DeletedAt", "LastOperator") + } + flag = true + } else { + updateOrCreate := func(vendorID, nameID int, vendorCatID string) { + skuVendorCatMaps, _ := dao.GetSkuVendorCategoryMaps(db, []int{nameID}, []int{vendorID}, nil) + if len(skuVendorCatMaps) > 0 { + skuVendorCatMaps[0].VendorCategoryID = vendorCatID + dao.UpdateEntity(db, skuVendorCatMaps[0], "VendorCategoryID") + } else { + skuVendorCatMap := &model.SkuVendorCategoryMap{ + NameID: nameID, + VendorID: vendorID, + VendorCategoryID: vendorCatID, + } + dao.WrapAddIDCULDEntity(skuVendorCatMap, ctx.GetUserName()) + dao.CreateEntity(db, skuVendorCatMap) + } + } + if skuNameExt != nil { + if skuNameExt.JdCategoryID != "" { + updateOrCreate(model.VendorIDJD, nameID, skuNameExt.JdCategoryID) + flag = true + } + if skuNameExt.JdsCategoryID != "" { + updateOrCreate(model.VendorIDJDShop, nameID, skuNameExt.JdsCategoryID) + flag = true + } + if skuNameExt.EbaiCategoryID != "" { + updateOrCreate(model.VendorIDEBAI, nameID, skuNameExt.EbaiCategoryID) + flag = true + } + if skuNameExt.MtwmCategoryID != "" { + updateOrCreate(model.VendorIDMTWM, nameID, skuNameExt.MtwmCategoryID) + flag = true + } + } else { + if payload["jdCategoryID"] != nil { + updateOrCreate(model.VendorIDJD, nameID, payload["jdCategoryID"].(string)) + flag = true + } + if payload["jdsCategoryID"] != nil { + updateOrCreate(model.VendorIDJDShop, nameID, payload["jdsCategoryID"].(string)) + flag = true + } + if payload["ebaiCategoryID"] != nil { + updateOrCreate(model.VendorIDEBAI, nameID, payload["ebaiCategoryID"].(string)) + flag = true + } + if payload["mtwmCategoryID"] != nil { + updateOrCreate(model.VendorIDMTWM, nameID, payload["mtwmCategoryID"].(string)) + flag = true + } + } + } + return flag +} + func SetStoreSkuSyncStatus2(db *dao.DaoDB, storeIDs []int, vendorIDs, skuIDs []int, syncStatus int) (num int64, err error) { for _, vendorID := range vendorIDs { num2, err2 := dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, skuIDs, syncStatus) @@ -1075,6 +1217,7 @@ func DeleteSkuName(ctx *jxcontext.Context, nameID int, userName string) (num int if len(skuList) > 0 { _, err = CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, false, userName) } + updateOrCreateSkuVendorCategoryMap(db, ctx, nameID, nil, nil, true) return num, err } @@ -1093,7 +1236,12 @@ func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) // sku.JdSyncStatus = model.SyncFlagNewMask // sku.JdID = 0 sku.NameID = nameID - + if beego.BConfig.RunMode == "jxgy" { + sku.LadderBoxPrice = 0 + } else if beego.BConfig.RunMode == "prod" { + sku.LadderBoxPrice = 10 + } + sku.LadderBoxNum = 1 dao.Begin(db) defer func() { if r := recover(); r != nil { @@ -1105,7 +1253,7 @@ func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) dao.Rollback(db) return nil, err } - if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil { + if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku, 0, false); err != nil { dao.Rollback(db) return nil, err } @@ -1124,7 +1272,7 @@ func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) storeSkus, err := dao.GetStoreSkusByNameIDs(db, []int{model.JdShopMainStoreID}, nameID) if len(storeSkus) > 0 { storeIDs := make(map[int]int) - storeMaps, err2 := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMaps, err2 := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") err = err2 for _, v := range storeMaps { storeSkus2, err2 := dao.GetStoreSkusByNameIDs(db, []int{v.StoreID}, nameID) @@ -1207,6 +1355,9 @@ func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{} if maskValue&model.SyncFlagSpecMask != 0 { err = refreshStoreSkuPrice(ctx, db, skuID) } + if valid["status"] != nil { + SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), []int{skuID}, model.SyncFlagSaleMask) + } } errList := errlist.New() errList.AddErr(err) @@ -1227,7 +1378,7 @@ func refreshStoreSkuPrice(ctx *jxcontext.Context, db *dao.DaoDB, skuID int) (err func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*dao.StoreSkuAndName) storeID := v.StoreID - storeDetail, _ := dao.GetStoreDetail(db, storeID, model.VendorIDJX) + storeDetail, _ := dao.GetStoreDetail(db, storeID, model.VendorIDJX, "") if storeDetail == nil { return retVal, err } @@ -1509,7 +1660,7 @@ func GetJdUpcCodeByName(ctx *jxcontext.Context, name, upcCode string) (productIn return productInfos, err } -func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) { +func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, imgWaterMark string, vendorID int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) { var ( fromTimeP time.Time toTimeP time.Time @@ -1537,24 +1688,30 @@ func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fro "exPrefix": exPrefix, "exPrefixBegin": fromTimeP, "exPrefixEnd": toTimeP, + "imgWaterMark": imgWaterMark, + "exVendorID": vendorID, } - if now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0 { + if now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) <= 0 { _, err = UpdateSkuName(ctx, nameID, payload, false) } else if now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0 { payload["exPrefixBegin"] = nil payload["exPrefixEnd"] = nil + payload["imgWaterMark"] = nil + payload["exVendorID"] = nil _, err = UpdateSkuName(ctx, nameID, payload, false) } else { skuList, err := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) if err == nil && len(skuList) > 0 { if skuList[0].ExPrefixBegin != nil { _, err = UpdateSkuName(ctx, nameID, payload, false) - CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, []int{skuList[0].ID}, nil, model.SyncFlagModifiedMask, true, true) + CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, []int{vendorID}, nil, false, []int{skuList[0].ID}, nil, model.SyncFlagModifiedMask, true, true) } else { skuName := &model.SkuName{ ExPrefix: exPrefix, ExPrefixBegin: &fromTimeP, ExPrefixEnd: &toTimeP, + ImgWatermark: imgWaterMark, + ExVendorID: vendorID, } skuName.ID = nameID skuName.LastOperator = ctx.GetLoginID() @@ -1566,7 +1723,7 @@ func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fro panic(r) } }() - _, err = dao.UpdateEntity(db, skuName, "ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "LastOperator", "UpdatedAt") + _, err = dao.UpdateEntity(db, skuName, "ImgWatermark", "ExVendorID", "ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "LastOperator", "UpdatedAt") dao.Commit(db) } } @@ -1584,7 +1741,7 @@ func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fro for _, v := range skuList { skuIDs = append(skuIDs, v.ID) } - CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, skuIDs, nil, model.SyncFlagModifiedMask, true, true) + CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, []int{vendorID}, nil, false, skuIDs, nil, model.SyncFlagModifiedMask, true, true) } } } @@ -2507,8 +2664,318 @@ func getImgFromNet(db *dao.DaoDB, upc string) (img string) { func deleteJdsSku(db *dao.DaoDB, skuID int) (err error) { storeBinds, err := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, []int{skuID}) - if err == nil { + if err == nil && len(storeBinds) > 0 { err = api.JdShopAPI.DeleteSku(storeBinds[0].JdsID) } return err } + +func UpdateSkuExinfoMap(ctx *jxcontext.Context, nameIDs []int, imgWaterMark string, brandID, vendorID int, vendorOrgCode, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) { + var ( + fromTimeP time.Time + toTimeP time.Time + db = dao.GetDB() + // skuIDs []int + ) + if fromTime != "" { + fromTimeP = utils.Time2Date(utils.Str2Time(fromTime)) + } + if toTime != "" { + toTimeP = utils.Time2Date(utils.Str2Time(toTime)) + } + if toTimeP.Before(fromTimeP) { + return "", fmt.Errorf("结束时间不可以小于开始时间!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP) + } + task := tasksch.NewParallelTask("刷新商品前缀水印图", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + nameID := batchItemList[0].(int) + skuEx := &model.SkuExinfoMap{ + NameID: nameID, + ImgWatermark: imgWaterMark, + ExPrefix: exPrefix, + VendorID: vendorID, + BeginAt: fromTimeP, + EndAt: toTimeP, + BrandID: brandID, + } + dao.WrapAddIDCULDEntity(skuEx, ctx.GetUserName()) + if imgWaterMark != "" { + if skuNames, err := dao.GetSkuNames(db, []int{nameID}, nil, "", false); err == nil { + if ImgMix := jxutils.MixWatermarkImg(imgWaterMark, skuNames[0].Img, &fromTimeP, &toTimeP); ImgMix != "" { + skuEx.ImgWatermarkMix = ImgMix + } + } + } + skuExs, _ := dao.GetSkuExinfos(db, []int{nameID}, []int{vendorID}, "", utils.ZeroTimeValue, utils.ZeroTimeValue) + if len(skuExs) > 0 { + skuEx2 := skuExs[0] + skuEx2.DeletedAt = time.Now() + skuEx2.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, skuEx2, "DeletedAt", "LastOperator") + dao.CreateEntity(db, skuEx) + } else { + dao.CreateEntity(db, skuEx) + } + now := utils.Time2Date(time.Now()) + if now.Sub(fromTimeP) >= 0 && now.Sub(toTimeP) <= 0 { + var skuIDs []int + skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) + if err = err2; err == nil { + if len(skuList) > 0 { + for _, v := range skuList { + skuIDs = append(skuIDs, v.ID) + } + if partner.IsMultiStore(vendorID) { + for _, v := range skuIDs { + OnUpdateThing(ctx, db, nil, int64(v), model.ThingTypeSku) + } + } else { + var storeIDs []int + if brandID != 0 { + if stores, _ := dao.GetStoreList(db, nil, nil, nil, []int{brandID}, nil, ""); len(stores) > 0 { + for _, v := range stores { + storeIDs = append(storeIDs, v.ID) + } + } + } + SetStoreSkuSyncStatus2(db, storeIDs, []int{vendorID}, skuIDs, model.SyncFlagModifiedMask) + } + } + } + } + return retVal, err + }, nameIDs) + tasksch.HandleTask(task, nil, true).Run() + if isAsync { + hint = task.GetID() + } else { + _, err = task.GetResult(0) + hint = "1" + } + return hint, err +} + +func GetVendorCategoryMap(ctx *jxcontext.Context, parentID, level, vendorID int, vendorOrgCode string) (vendorMaps []*model.VendorCategoryMap, err error) { + db := dao.GetDB() + vendorMaps, err = dao.GetVendorCategoryMap(db, parentID, level, vendorID, vendorOrgCode, 0) + if err != nil { + return nil, err + } + return vendorMaps, err +} + +func AddVendorCategoryMap(ctx *jxcontext.Context, vendorCategoryMap *model.VendorCategoryMap) (result *model.VendorCategoryMap, err error) { + var ( + db = dao.GetDB() + ) + if vendorCategoryMap.Level != 1 { + storeCatMaps, _ := dao.GetVendorCategoryMap(db, -1, 0, vendorCategoryMap.VendorID, vendorCategoryMap.VendorOrgCode, vendorCategoryMap.CategoryID) + if len(storeCatMaps) > 0 { + return nil, fmt.Errorf("已存在绑定的京西分类,分类名:[%v]", storeCatMaps[0].VendorCategoryName) + } + } + vendorOrgCodes, _ := dao.GetVendorOrgCode(db, vendorCategoryMap.VendorID, vendorCategoryMap.VendorOrgCode, model.VendorOrgTypePlatform) + vendorCategoryMap.VendorCategoryName = strings.Trim(vendorCategoryMap.VendorCategoryName, " ") + dao.WrapAddIDCULDEntity(vendorCategoryMap, ctx.GetUserName()) + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if err = dao.CreateEntity(db, vendorCategoryMap); err != nil { + dao.Rollback(db) + return nil, err + } + //如果传了京西绑定,要去thingmap里改同步标志 + if vendorCategoryMap.CategoryID != 0 { + if err = OnCreateThing(ctx, db, vendorOrgCodes, int64(vendorCategoryMap.CategoryID), model.ThingTypeCategory, model.SyncFlagNewMask, true); err != nil { + dao.Rollback(db) + return nil, err + } + } + dao.Commit(db) + result = vendorCategoryMap + if vendorCategoryMap.CategoryID != 0 { + SyncCategories(ctx, nil, []int{vendorCategoryMap.VendorID}, []string{vendorCategoryMap.VendorOrgCode}, []int{vendorCategoryMap.CategoryID}, true) + // _, err = CurVendorSync.SyncCategory(ctx, nil, vendorCategoryMap.CategoryID, false, ctx.GetUserName()) + } + return result, err +} + +func UpdateVendorCategoryMap(ctx *jxcontext.Context, ID int, vendorCategoryMap *model.VendorCategoryMap, isDelete bool) (num int64, err error) { + var ( + db = dao.GetDB() + valid = make(map[string]interface{}) + vendorCategoryMap2 = &model.VendorCategoryMap{} + vendorCategoryID int + ) + vendorCategoryMap2.ID = ID + if err = dao.GetEntity(db, vendorCategoryMap2); err != nil { + return 0, err + } + if vendorCategoryMap.VendorCategoryName != "" { + valid["vendorCategoryName"] = vendorCategoryMap.VendorCategoryName + } + if vendorCategoryMap.CategoryID != 0 { + valid["categoryID"] = vendorCategoryMap.CategoryID + if !isDelete { + storeCatMaps, _ := dao.GetVendorCategoryMap(db, -1, 0, vendorCategoryMap2.VendorID, vendorCategoryMap2.VendorOrgCode, vendorCategoryMap.CategoryID) + if len(storeCatMaps) > 0 { + for _, v := range storeCatMaps { + if v.ID != ID { + return 0, fmt.Errorf("已存在绑定的京西分类,分类名:[%v]", storeCatMaps[0].VendorCategoryName) + } + } + } + } + vendorCategoryID = vendorCategoryMap.CategoryID + } else { + vendorCategoryID = vendorCategoryMap2.CategoryID + } + if vendorCategoryMap.Level != 0 { + valid["level"] = vendorCategoryMap.Level + if vendorCategoryMap.Level == 2 { + cat2, _ := dao.GetCategories(db, -1, 0, []int{vendorCategoryMap.CategoryID}, false) + if len(cat2) > 0 { + if cat2[0].ParentID != vendorCategoryMap.ParentID { + return 0, fmt.Errorf("此二级分类只能绑定到对应一级分类下!") + + } + } + } + } + if isDelete { + valid["deletedAt"] = time.Now() + valid["updatedAt"] = time.Now() + valid["lastOperator"] = ctx.GetUserName() + //如果是1级分类则删除下面的子分类 + var catIDs []int + if vendorCategoryMap2.Level == 1 { + storeCatMaps, _ := dao.GetVendorCategoryMap(db, vendorCategoryMap2.CategoryID, 2, vendorCategoryMap2.VendorID, vendorCategoryMap2.VendorOrgCode, 0) + if len(storeCatMaps) > 0 { + for _, v := range storeCatMaps { + catIDs = append(catIDs, v.CategoryID) + v.DeletedAt = time.Now() + v.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, v, "DeletedAt", "LastOperator") + } + } + } + } + vendorOrgCodes, err := dao.GetVendorOrgCode(db, vendorCategoryMap2.VendorID, vendorCategoryMap2.VendorOrgCode, model.VendorOrgTypePlatform) + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if num, err = dao.UpdateEntityLogically(db, vendorCategoryMap2, valid, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return 0, err + } + if err = OnUpdateThing(ctx, db, vendorOrgCodes, int64(vendorCategoryID), model.ThingTypeCategory); err != nil { + dao.Rollback(db) + return 0, err + } + dao.Commit(db) + SyncCategories(ctx, nil, []int{vendorCategoryMap.VendorID}, []string{vendorCategoryMap.VendorOrgCode}, []int{vendorCategoryID}, true) + return num, err +} + +func ReorderVendorCategories(ctx *jxcontext.Context, parentID, vendorID int, vendorOrgCode string, categoryIDs []int) (err error) { + var ( + vendorCatsMap []*model.VendorCategoryMap + ) + db := dao.GetDB() + vendorCatsMap, err = dao.GetVendorCategoryMap(db, parentID, 0, vendorID, vendorOrgCode, 0) + catsLen := len(vendorCatsMap) + if catsLen != len(categoryIDs) { + return ErrInputCatsDoesntMatch + } + catsMap := make(map[int]*model.VendorCategoryMap, catsLen) + for _, cat := range vendorCatsMap { + catsMap[cat.CategoryID] = cat + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + for k, v := range categoryIDs { + if catsMap[v] == nil { + dao.Rollback(db) + return fmt.Errorf("分类:%d不在%d分类下", v, parentID) + } + catsMap[v].VendorCategorySeq = k + catsMap[v].LastOperator = ctx.GetUserName() + if _, err = dao.UpdateEntity(db, catsMap[v]); err != nil { + dao.Rollback(db) + return err + } + } + dao.Commit(db) + err = SyncReorderCategories2(ctx, parentID, vendorID, vendorOrgCode) + return err +} + +func LoadStoreVendorCategories(ctx *jxcontext.Context, vendorOrgCode string, vendorID, storeID int) (err error) { + var ( + db = dao.GetDB() + ) + + storeCats, err := dao.GetStoreCategoryMap(db, -1, 0, storeID, 0) + if len(storeCats) == 0 { + return fmt.Errorf("未查询到该门店有门店分类,请重新选择! [%v]", storeID) + } + vendorOrgCodes, _ := dao.GetVendorOrgCode(db, vendorID, vendorOrgCode, model.VendorOrgTypePlatform) + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + sql := ` + DELETE FROM vendor_category_map WHERE vendor_id = ? AND vendor_org_code = ? + ` + sqlParams := []interface{}{ + vendorID, vendorOrgCode, + } + if _, err = dao.ExecuteSQL(db, sql, sqlParams); err != nil { + dao.Rollback(db) + return err + } + sql2 := ` + INSERT INTO vendor_category_map + (created_at, updated_at, last_operator, deleted_at, vendor_id, vendor_org_code, category_id, vendor_category_name, vendor_category_seq, level, parent_id) + SELECT ?, ?, ?, ?, ?, ?, category_id, store_category_name, store_category_seq, level, parent_id + FROM store_category_map + WHERE deleted_at = ? + AND store_id = ? + ` + sqlParams2 := []interface{}{ + time.Now(), time.Now(), ctx.GetUserName(), utils.DefaultTimeValue, + vendorID, vendorOrgCode, + utils.DefaultTimeValue, + storeID, + } + if _, err = dao.ExecuteSQL(db, sql2, sqlParams2); err != nil { + dao.Rollback(db) + return err + } + dao.Commit(db) + catList, _ := dao.GetSkuCategoryWithVendor(db, []int{vendorID}, []string{vendorOrgCode}, -1, nil, false) + for _, v := range storeCats { + if len(catList) > 0 { + OnUpdateThing(ctx, db, vendorOrgCodes, int64(v.CategoryID), model.ThingTypeCategory) + } else { + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.CategoryID), model.ThingTypeCategory, model.SyncFlagNewMask, true) + } + } + return err +} diff --git a/business/jxstore/cms/store.go b/business/jxstore/cms/store.go index b32cdd699..43af24d0c 100644 --- a/business/jxstore/cms/store.go +++ b/business/jxstore/cms/store.go @@ -2,6 +2,7 @@ package cms import ( "bytes" + "encoding/json" "errors" "fmt" "io" @@ -13,8 +14,14 @@ import ( "time" "unicode/utf8" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" + + "git.rosy.net.cn/jx-callback/business/authz" + + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/platformapi/yinbaoapi" + "git.rosy.net.cn/jx-callback/globals/api/apimanager" "git.rosy.net.cn/jx-callback/globals/refutil" "github.com/360EntSecGroup-Skylar/excelize" @@ -70,6 +77,8 @@ type StoreExt struct { CourierMapStr string `json:"-"` PayeeBankName string `json:"payeeBankName"` // 开户行名称 LinkStoreCount int `json:"linkStoreCount"` + BrandName string `json:"brandName"` + BrandLogo string `json:"brandLogo"` // StoreMaps []map[string]interface{} `orm:"-"` // CourierMaps []map[string]interface{} `orm:"-"` StoreMaps []*model.StoreMap `json:"StoreMaps"` @@ -78,55 +87,6 @@ type StoreExt struct { OrderCount int `json:"orderCount"` } -type Store4User struct { - model.ModelIDCULD - - OriginalName string `orm:"-" json:"originalName"` - Name string `orm:"size(255)" json:"name"` - OpenTime1 int16 `json:"openTime1"` // 930就表示9点半,用两个的原因是为了支持中午休息,1与2的时间段不能交叉,为0表示没有 - CloseTime1 int16 `json:"closeTime1"` // 格式同上 - OpenTime2 int16 `json:"openTime2"` // 格式同上 - CloseTime2 int16 `json:"closeTime2"` // 格式同上 - Status int `json:"status"` - CityCode int `orm:"default(0);null" json:"cityCode"` // todo ? - DistrictCode int `orm:"default(0);null" json:"districtCode"` // todo ? - Address string `orm:"size(255)" json:"address"` - Tel1 string `orm:"size(32);index" json:"tel1"` - Tel2 string `orm:"size(32);index" json:"tel2"` - Lng int `json:"-"` // 乘了10的6次方 - Lat int `json:"-"` // 乘了10的6次方 - DeliveryRangeType int8 `json:"-"` // 参见相关常量定义 - DeliveryRange string `orm:"type(text)" json:"-"` // 如果DeliveryRangeType为DeliveryRangeTypePolygon,则为逗号分隔坐标,分号分隔的坐标点(坐标与Lng和Lat一样,都是整数),比如 121361504,31189308;121420555,31150238。否则为半径,单位为米 - - FloatLng float64 `json:"lng"` - FloatLat float64 `json:"lat"` - CityName string `json:"cityName"` - DistrictName string `json:"districtName"` - - Distance int `json:"distance"` - WalkDistance int `json:"walkDistance"` -} - -type Store4UserList []*Store4User - -func (x Store4UserList) Len() int { - return len(x) -} - -func (x Store4UserList) Less(i, j int) bool { - if x[i].Status != x[j].Status { - return x[i].Status > x[j].Status - } - if x[i].WalkDistance != x[j].WalkDistance { - return x[i].WalkDistance < x[j].WalkDistance - } - return x[i].Distance < x[j].Distance -} - -func (x Store4UserList) Swap(i, j int) { - x[i], x[j] = x[j], x[i] -} - type StoresInfo struct { TotalCount int `json:"totalCount"` MapCenterLng float64 `json:"mapCenterLng"` @@ -230,6 +190,9 @@ var ( "15928865396": "15928865396", //何佳梦 "18048531223": "18048531223", //石老板 "18982250714": "18982250714", //赵敏夫 + "13708196093": "13708196093", //顾子航 + "15680070110": "15680070110", //李荣维 + "15208271238": "15208271238", } marketManPhoneRoleMap = map[string]string{ @@ -243,6 +206,9 @@ var ( "18328080405": "18328080405", "17380734342": "17380734342", "15208271238": "15208271238", + "18583684218": "18583684218", + "18982250714": "18982250714", + "13708196093": "13708196093", } ) @@ -261,6 +227,7 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte LEFT JOIN user om ON om.mobile <> '' AND om.mobile = t1.operator_phone AND om.deleted_at = ? LEFT JOIN user om2 ON om2.mobile <> '' AND om2.mobile = t1.operator_phone2 AND om2.deleted_at = ? LEFT JOIN user om3 ON om3.mobile <> '' AND om3.mobile = t1.operator_phone3 AND om3.deleted_at = ? + LEFT JOIN brand br ON br.id = t1.brand_id ` sqlFromParams = []interface{}{ utils.DefaultTimeValue, @@ -308,8 +275,9 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte } } sqlFrom += "\nLEFT JOIN " + tableName + " " + tableAlias + " ON " + tableAlias + ".vendor_id = ? AND " + - tableAlias + ".store_id = t1.id AND " + tableAlias + ".deleted_at = ? AND " + - tableAlias + ".is_sync <> 0 " + tableAlias + ".store_id = t1.id AND " + tableAlias + ".deleted_at = ?" + // AND " + // +tableAlias + ".is_sync <> 0 " sqlFromParams = append(sqlFromParams, vendor, utils.DefaultTimeValue) if cond == "1" { sqlVendorStoreCond += " " + mapCond + " " + tableAlias + ".id IS NOT NULL" @@ -331,9 +299,9 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte if keyword != "" { keywordLike := "%" + keyword + "%" sqlWhere += ` AND (t1.name LIKE ? OR t1.tel1 LIKE ? OR t1.tel2 LIKE ? OR t1.operator_phone LIKE ? OR t1.operator_phone2 LIKE ? OR t1.operator_phone3 LIKE ? OR t1.market_man_phone LIKE ? - OR t1.last_operator LIKE ? OR city.name LIKE ? OR t1.address LIKE ? OR t1.printer_sn LIKE ? OR t1.licence_code LIKE ? OR t1.id_code LIKE ?` + OR t1.last_operator LIKE ? OR city.name LIKE ? OR t1.address LIKE ? OR t1.printer_sn LIKE ? OR t1.licence_code LIKE ? OR t1.id_code LIKE ? OR t1.comment LIKE ?` sqlWhereParams = append(sqlWhereParams, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, - keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike) + keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike) if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil { if true { // jxutils.IsLegalMobileNumber(keywordInt64) { @@ -378,6 +346,12 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte sqlWhere += " AND t1.id >= ?" sqlWhereParams = append(sqlWhereParams, params["startStoreID"]) } + if params["brandID"] != nil { + if utils.MustInterface2Int64(params["brandID"]) != 0 { + sqlWhere += " AND t1.brand_id = ?" + sqlWhereParams = append(sqlWhereParams, params["brandID"]) + } + } if params["name"] != nil { sqlWhere += " AND t1.name LIKE ?" sqlWhereParams = append(sqlWhereParams, "%"+params["name"].(string)+"%") @@ -407,6 +381,15 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte sqlWhereParams = append(sqlWhereParams, "%"+params["tel"].(string)+"%") sqlWhereParams = append(sqlWhereParams, "%"+params["tel"].(string)+"%") } + if params["earningType"] != nil { + if params["earningType"].(int) != 0 { + if params["earningType"].(int) == 1 { + sqlWhere += " AND t1.pay_percentage = 100" + } else { + sqlWhere += " AND t1.pay_percentage < 50" + } + } + } if params["statuss"] != nil { var statuss []int @@ -418,6 +401,26 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte sqlWhereParams = append(sqlWhereParams, statuss) } } + if params["marketManPhones"] != nil { + var phones []string + if err = utils.UnmarshalUseNumber([]byte(params["marketManPhones"].(string)), &phones); err != nil { + return "", nil, "", nil, err + } + if len(phones) > 0 { + sqlWhere += " AND t1.market_man_phone IN (" + dao.GenQuestionMarks(len(phones)) + ")" + sqlWhereParams = append(sqlWhereParams, phones) + } + } + if params["storeLevels"] != nil { + var storeLevels []string + if err = jxutils.Strings2Objs(utils.Interface2String(params["storeLevels"]), &storeLevels); err != nil { + return "", nil, "", nil, err + } + if len(storeLevels) > 0 { + sqlWhere += " AND t1.store_level IN (" + dao.GenQuestionMarks(len(storeLevels)) + ")" + sqlWhereParams = append(sqlWhereParams, storeLevels) + } + } sql = sqlFrom + sqlWhere sqlParams = append(sqlParams, sqlFromParams...) @@ -426,11 +429,11 @@ func getStoresSql(ctx *jxcontext.Context, keyword string, params map[string]inte } func setStoreMapInfo(ctx *jxcontext.Context, db *dao.DaoDB, storesInfo *StoresInfo, storeIDs []int, briefLevel int) (err error) { - storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if err != nil { return err } - storeCourierList, err := dao.GetStoreCourierList(db, storeIDs, model.StoreStatusAll, model.StoreAuditStatusAll) + storeCourierList, err := dao.GetStoreCourierList(db, storeIDs, nil, model.StoreStatusAll, model.StoreAuditStatusAll) if err != nil { return err } @@ -479,6 +482,8 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa province.name province_name, city.name city_name, district.name district_name, + br.name brand_name, + br.logo brand_logo, (SELECT COUNT(*) FROM store t11 WHERE t11.link_store_id = t1.id) link_store_count ` + sql + ` ORDER BY t1.id DESC @@ -517,7 +522,19 @@ func GetStores(ctx *jxcontext.Context, keyword string, params map[string]interfa } else { retVal.Stores = storeList } - + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeList2 []*StoreExt + for _, v := range retVal.Stores { + if storeIDsMap[v.ID] != 0 { + storeList2 = append(storeList2, v) + } + } + retVal.Stores = nil + retVal.Stores = storeList2 + } + } // 订单情况过滤 storeList, err = filterStoreByOrderInfo(db, retVal.Stores, orderTimeFrom, orderTimeTo, orderCountFrom, orderCountTo) if err != nil { @@ -1086,6 +1103,13 @@ func CreateStore(ctx *jxcontext.Context, storeExt *StoreExt, userName string) (i } storeExt.LinkStoreID = realLinkStoreID + if storeExt.MarketManName == "" { + storeExt.MarketManName = ctx.GetUserName() + } + if storeExt.MarketManPhone == "" { + storeExt.MarketManPhone, _ = ctx.GetMobileAndUserID() + } + existingID := store.ID store.Lng = jxutils.StandardCoordinate2Int(storeExt.FloatLng) store.Lat = jxutils.StandardCoordinate2Int(storeExt.FloatLat) @@ -1111,6 +1135,9 @@ func CreateStore(ctx *jxcontext.Context, storeExt *StoreExt, userName string) (i store.PrinterKey = newID2 } } + if store.StoreLevel == "" { + store.StoreLevel = "C" + } dao.WrapAddIDCULDEntity(store, userName) store.ID = existingID if err = dao.CreateEntity(db, store); err == nil { @@ -1119,7 +1146,17 @@ func CreateStore(ctx *jxcontext.Context, storeExt *StoreExt, userName string) (i } UpdateOrCreateCourierStores(ctx, store.ID, false, false, false) TryAddStoreBossRole4StoreByMobile(ctx, storeExt.ID, []string{storeExt.Tel1, storeExt.Tel2}) - InsertStoreCategories(ctx, db, store.ID) + // InsertStoreCategories(ctx, db, store.ID) + AddStoreVendorMap(ctx, db, model.VendorIDJX, "", store.ID, &model.StoreMap{ + VendorStoreID: utils.Int2Str(store.ID), + AutoPickup: 1, + DeliveryCompetition: 1, + PricePercentage: 100, + IsSync: 1, + Status: model.StoreStatusOpened, + PricePercentagePack: "京西100-100", + VendorID: model.VendorIDJX, + }) return store.ID, err } return 0, err @@ -1155,18 +1192,31 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend return nil, fmt.Errorf("必须指定平台分账号信息") } if handler := CurVendorSync.GetStoreHandler(vendorID); handler != nil { - store, err2 := handler.ReadStore(ctx, vendorOrgCode, storeMap.VendorStoreID) - if err = err2; err == nil || storeMap.IsSync == 0 { - if store != nil { - storeMap.DeliveryType = store.DeliveryType - storeMap.Status = store.Status + if vendorOrgCode != globals.Mtwm2Code { + store, err2 := handler.ReadStore(ctx, vendorOrgCode, storeMap.VendorStoreID) + if err = err2; err == nil || storeMap.IsSync == 0 { + if store != nil { + storeMap.DeliveryType = store.DeliveryType + storeMap.Status = store.Status + } + err = nil + } + } else { + //美团商超获取token + mtapi := apimanager.CurAPIManager.GetAPI(model.VendorIDMTWM, outStoreMap.VendorOrgCode).(*mtwmapi.API) + if token, err := mtapi.GetAccessToken2(outStoreMap.VendorStoreID); err == nil && token != nil { + storeMap.MtwmToken = token.AccessToken + storeMap.MtwmToken = token.RefreshToken } - err = nil - storeMap.SyncStatus = model.SyncFlagModifiedMask | model.SyncFlagStoreName | model.SyncFlagStoreAddress // 新增绑定门店是修改的概念 } + storeMap.SyncStatus = model.SyncFlagModifiedMask | model.SyncFlagStoreName | model.SyncFlagStoreAddress // 新增绑定门店是修改的概念 } else { err = ErrCanNotFindVendor } + storeDetail, _ := dao.GetStoreDetailByVendorStoreID(db, storeMap.VendorStoreID, storeMap.VendorID, "") + if storeDetail != nil { + return nil, fmt.Errorf("此平台门店ID已在京西有绑定,请先解除绑定,平台门店ID :[%v]", storeMap.VendorStoreID) + } } else if vendorID == model.VendorIDJX { ReCalculateJxPriceLight(db, ctx, storeID) } else if vendorID == model.VendorIDYB { @@ -1175,6 +1225,7 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend return nil, err } } else if vendorID == model.VendorIDJDShop { + storeMap.VendorOrgCode = "1" if storeMap.VendorStoreID == "" { storeMap.SyncStatus = model.SyncFlagNewMask //京东商城要去建店 } else { @@ -1194,7 +1245,7 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend } } } - storeMapList, err := dao.GetStoresMapList2(db, []int{vendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", true) + storeMapList, err := dao.GetStoresMapList2(db, []int{vendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "", true) if len(storeMapList) > 0 { _, err = CurVendorSync.SyncStore(ctx, db, storeMap.VendorID, storeID, false, userName) } else { @@ -1211,9 +1262,13 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend } }() if err = dao.CreateEntity(db, storeMap); err == nil { + if vendorID == model.VendorIDJDShop { + storeMap2 := storeMap + storeMap2.VendorOrgCode = "2" + dao.CreateEntity(db, storeMap2) + } dao.Commit(db) outStoreMap = storeMap - _, err = CurVendorSync.SyncStore(ctx, db, storeMap.VendorID, storeID, false, userName) } else { dao.Rollback(db) } @@ -1232,6 +1287,8 @@ func AddStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, vendorID int, vend if globals.IsAddEvent { err = AddEventDetail(db, ctx, model.OperateAdd, vendorID, model.ThingTypeStore, storeID, "", `{"VendorID":`+utils.Int2Str(vendorID)+`}`) } + _, err = CurVendorSync.SyncStore(ctx, db, storeMap.VendorID, storeID, false, userName) + _, err = CurVendorSync.FullSyncStoresSkus(ctx, db, []int{vendorID}, []int{storeID}, true, nil, true, true) return outStoreMap, err } @@ -1305,6 +1362,10 @@ func UpdateStoreVendorMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendor if valid["status"] != nil { syncStatus |= model.SyncFlagStoreStatus } + //修改分类开关需要打同步标志 + if valid["isSysCat"] != nil { + SetStoreCategorySyncStatus2(db, []int{storeID}, nil, model.SyncFlagModifiedMask) + } if vendorStoreName, ok := valid["vendorStoreName"].(string); ok { if utf8.RuneCountInString(vendorStoreName) > jdapi.MaxStoreNameLen && vendorID == model.VendorIDJD { return 0, fmt.Errorf("门店名称不允许超过13位!") @@ -1468,6 +1529,25 @@ func TmpGetJxBadCommentsNo(ctx *jxcontext.Context, storeID int) (count int, err func TmpGetJxBadCommentsByStoreId(ctx *jxcontext.Context, keyword string, storeIDs []int, offset, pageSize, commentType int, fromTime, toTime time.Time) (retVal map[string]interface{}, err error) { db := dao.GetDB() + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } sql := ` SELECT SQL_CALC_FOUND_ROWS t1.*, t2.name store_name, t3.name city_name, @@ -1529,6 +1609,12 @@ func TmpGetJxBadCommentsByStoreId(ctx *jxcontext.Context, keyword string, storeI return retVal, err } +type GetStoreCourierMapsResult struct { + storeCourierMaps *model.StoreCourierMap + CourierAddress string `json:"courierAddress"` + CourierPhone string `json:"courierPhone"` +} + func GetStoreCourierMaps(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, vendorID int) (storeCourierMaps []*model.StoreCourierMap, err error) { cond := map[string]interface{}{ model.FieldStoreID: storeID, @@ -1536,7 +1622,30 @@ func GetStoreCourierMaps(ctx *jxcontext.Context, db *dao.DaoDB, storeID int, ven if vendorID != -1 { cond[model.FieldVendorID] = vendorID } - return storeCourierMaps, dao.GetEntitiesByKV(db, &storeCourierMaps, cond, false) + err = dao.GetEntitiesByKV(db, &storeCourierMaps, cond, false) + globals.SugarLogger.Debug("之前的storeCourierMaps") + globals.SugarLogger.Debug(utils.Format4Output(storeCourierMaps, false)) + if len(storeCourierMaps) != 0 { + //同步美团配送与否状态及美团门店是否存在 + for _, v := range storeCourierMaps { + if v.VendorID != model.VendorIDMTPS { + continue + } else { + SetMTPSStatus(jxcontext.AdminCtx, v.StoreID, v.Status) + globals.SugarLogger.Debug("之后的storeCourierMaps") + globals.SugarLogger.Debug(v) + break + } + } + } + handler := partner.GetDeliveryPlatformFromVendorID(vendorID).Handler + storeDetail, _ := handler.GetStore(ctx, storeID, utils.Int2Str(storeID)) + for _, v := range storeCourierMaps { + if v.VendorStoreName == "" { + v.VendorStoreName = storeDetail.Name + } + } + return storeCourierMaps, err } func AddStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID int, storeCourierMap *model.StoreCourierMap) (outStoreCourierMap *model.StoreCourierMap, err error) { @@ -1546,6 +1655,7 @@ func AddStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID func addStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID int, storeCourierMap *model.StoreCourierMap, isNeedUpdateRemote bool) (outStoreCourierMap *model.StoreCourierMap, err error) { storeCourierMap.StoreID = storeID storeCourierMap.VendorID = vendorID + storeCourierMap.VendorStatus = storeCourierMap.Status globals.SugarLogger.Debugf("addStoreCourierMap %s, storeCourierMap:%s, isNeedUpdateRemote:%t", model.VendorChineseNames[vendorID], utils.Format4Output(storeCourierMap, true), isNeedUpdateRemote) if handler := partner.GetDeliveryPlatformFromVendorID(vendorID); handler != nil { @@ -1582,6 +1692,10 @@ func addStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendorID } else { err = ErrCanNotFindVendor } + //同步美团配送与否状态及美团门店是否存在 + // if outStoreCourierMap.VendorID == model.VendorIDMTPS { + // SetMTPSStatus(jxcontext.AdminCtx, outStoreCourierMap.StoreID, outStoreCourierMap.Status) + // } return outStoreCourierMap, err } @@ -1591,7 +1705,8 @@ func DeleteStoreCourierMap(ctx *jxcontext.Context, db *dao.DaoDB, storeID, vendo } storeCourierMap := &model.StoreCourierMap{} num, err = dao.DeleteEntityLogically(db, storeCourierMap, map[string]interface{}{ - model.FieldStatus: model.StoreStatusDisabled, + model.FieldStatus: model.StoreStatusDisabled, + model.FieldVendorStatus: model.StoreStatusDisabled, }, userName, map[string]interface{}{ model.FieldStoreID: storeID, model.FieldVendorID: vendorID, @@ -1658,6 +1773,15 @@ func updateCourierStores(ctx *jxcontext.Context, storeID int) (err error) { if err = err2; err2 == nil { if storeDetail.VendorStoreID != "" && storeDetail.AuditStatus == model.StoreAuditStatusOnline { err = updateCourierStore(ctx, storeDetail) + if err == nil { + //美团配送修改门店信息后要待审核 + if k == model.VendorIDMTPS { + if couriers, err := dao.GetStoreCourierList(db, []int{storeID}, []int{model.VendorIDMTPS}, model.StoreStatusAll, model.StoreAuditStatusAll); len(couriers) > 0 && err == nil { + couriers[0].AuditStatus = model.StoreAuditStatusUpdated + dao.UpdateEntity(db, couriers[0], "AuditStatus") + } + } + } } } errList.AddErr(err) @@ -1745,9 +1869,10 @@ func UpdateOrCreateCourierStores(ctx *jxcontext.Context, storeID int, isForceUpd } if _, err = updateOrCreateCourierStore(ctx, storeDetail); err == nil && isNeedAdd { storeCourier := &model.StoreCourierMap{ - VendorStoreID: storeDetail.VendorStoreID, - Status: model.StoreStatusOpened, - AuditStatus: storeDetail.AuditStatus, + VendorStoreID: storeDetail.VendorStoreID, + Status: model.StoreStatusOpened, + AuditStatus: storeDetail.AuditStatus, + VendorStoreName: storeDetail.Name, } if storeDetail.AuditStatus != model.StoreAuditStatusOnline { storeCourier.Status = model.StoreStatusDisabled @@ -1806,7 +1931,7 @@ type EbaiStoreHealthy struct { func ExportShopsHealthInfo(ctx *jxcontext.Context, vendorIDs, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() vendorID := model.VendorIDEBAI - storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err != nil { return "", err } @@ -1924,7 +2049,7 @@ func GetCorporationInfo(ctx *jxcontext.Context, licenceCode string) (corporation func GetStoresVendorSnapshot(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs, storeIDs []int) (vendorStoreSnapshotList []*model.VendorStoreSnapshot, err error) { db := dao.GetDB() - storeMapList, err := dao.GetStoresMapList(db, vendorIDs, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeMapList, err := dao.GetStoresMapList(db, vendorIDs, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if err != nil { return nil, err } @@ -1971,7 +2096,7 @@ func getCurrentSnapshotAt(now time.Time) (snapshotAt time.Time) { } func updateVendorStoreStatusBySnapshot(db *dao.DaoDB, curSnapshotList []*model.VendorStoreSnapshot) (err error) { - storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if err != nil { return err } @@ -2176,7 +2301,7 @@ func SendAlarmVendorSnapshot(ctx *jxcontext.Context, parentTask tasksch.ITask, p userMap := make(map[string]map[int]int) userMapTxt := make(map[string][]*model.VendorStoreSnapshot) for storeID, list := range alarmSnapshotMap { - storeDetail, _ := dao.GetStoreDetail(db, storeID, list[0].VendorID) + storeDetail, _ := dao.GetStoreDetail(db, storeID, list[0].VendorID, "") if storeDetail != nil { storeDetailMap[storeID] = storeDetail userList := getAllUsers4Store(ctx, db, &storeDetail.Store) @@ -2199,7 +2324,7 @@ func SendAlarmVendorSnapshot(ctx *jxcontext.Context, parentTask tasksch.ITask, p } if len(userList) > 0 { - allStores, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + allStores, err := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") if err != nil { return err } @@ -2373,7 +2498,7 @@ func SaveAndSendAlarmVendorSnapshot(ctx *jxcontext.Context, vendorIDs, storeIDs func SyncStoresCourierInfo(ctx *jxcontext.Context, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() - storeList2, err := dao.GetStoreList(db, storeIDs, nil, nil, nil, "") + storeList2, err := dao.GetStoreList(db, storeIDs, nil, nil, nil, nil, "") var storeList []*model.Store for _, v := range storeList2 { if v.Status != model.StoreStatusDisabled { @@ -2398,7 +2523,7 @@ func SyncStoresCourierInfo(ctx *jxcontext.Context, storeIDs []int, isAsync, isCo storeCourier, err2 := handler.Handler.GetStore(ctx, store.ID, storeDetail2.VendorStoreID) if err = err2; err == nil { if storeDetail2.AuditStatus == model.StoreAuditStatusCreated { // 如果已经通过审核,更新本地状态 - partner.CurStoreManager.OnCourierStoreStatusChanged(ctx, storeCourier.VendorStoreID, vendorID, storeCourier.AuditStatus) + partner.CurStoreManager.OnCourierStoreStatusChanged(ctx, storeCourier.VendorStoreID, vendorID, storeCourier.AuditStatus, storeCourier.Comment) } distance := jxutils.EarthDistance(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat), jxutils.IntCoordinate2Standard(storeCourier.Lng), jxutils.IntCoordinate2Standard(storeCourier.Lat)) @@ -2450,15 +2575,14 @@ func SyncStoresCourierInfo(ctx *jxcontext.Context, storeIDs []int, isAsync, isCo return hint, err } -func SyncStoresQualify(ctx *jxcontext.Context, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +func SyncStoresQualify(ctx *jxcontext.Context, storeIDs []int, vendorID int, isAsync, isContinueWhenError bool) (hint string, err error) { if len(storeIDs) > 0 { db := dao.GetDB() task := tasksch.NewParallelTask(fmt.Sprintf("上传门店资质:%v", storeIDs), tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - vendorID := model.VendorIDJD if handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IStoreSyncQualifyHandler); handler != nil { storeID := batchItemList[0].(int) - storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID, "") if err = err2; err == nil { if err = handler.SyncQualify(ctx, storeDetail); err == nil { retVal = []int{1} @@ -2482,96 +2606,6 @@ func SyncStoresQualify(ctx *jxcontext.Context, storeIDs []int, isAsync, isContin return hint, err } -func GetStoreListByLocation(ctx *jxcontext.Context, lng, lat float64, needWalkDistance bool) (storeList []*Store4User, err error) { - const ( - maxRadius = 8000 - maxStoreCount4User = 5 - ) - - lng2, _ := jxutils.ConvertDistanceToLogLat(lng, lat, float64(maxRadius), 90) - _, lat2 := jxutils.ConvertDistanceToLogLat(lng, lat, float64(maxRadius), 0) - lng1 := lng - (lng2 - lng) - lat1 := lat - (lat2 - lat) - // globals.SugarLogger.Debugf("%f,%f,%f,%f\n", lng1, lng2, lat1, lat2) - sql := ` - SELECT t1.*, - city.name city_name - FROM store t1 - JOIN place city ON city.code = t1.city_code - JOIN store_map sm ON sm.store_id = t1.id AND sm.vendor_id = ? AND sm.deleted_at = ? AND sm.status <> ? - WHERE t1.deleted_at = ? AND t1.status <> ? AND t1.lng > ? AND t1.lng < ? AND t1.lat > ? AND t1.lat < ? - AND sm.is_order <> ? - ORDER BY t1.id - ` - sqlParams := []interface{}{ - model.VendorIDJX, utils.DefaultTimeValue, model.StoreStatusDisabled, - utils.DefaultTimeValue, model.StoreStatusDisabled, jxutils.StandardCoordinate2Int(lng1), jxutils.StandardCoordinate2Int(lng2), jxutils.StandardCoordinate2Int(lat1), jxutils.StandardCoordinate2Int(lat2), - model.YES, - } - var storeList1 []*Store4User - if err = dao.GetRows(dao.GetDB(), &storeList1, sql, sqlParams...); err == nil { - var storeList2 []*Store4User - for _, v := range storeList1 { - distance := jxutils.Point2StoreDistance(lng, lat, v.Lng, v.Lat, v.DeliveryRangeType, v.DeliveryRange) - if distance > 0 || (lng == jxutils.IntCoordinate2Standard(v.Lng) && lat == jxutils.IntCoordinate2Standard(v.Lat)) { - v.Distance = distance - storeList2 = append(storeList2, v) - } - } - - // 为了审核用 - if len(storeList2) == 0 { - sql2 := ` - SELECT t1.*, - city.name city_name - FROM store t1 - JOIN place city ON city.code = t1.city_code - WHERE t1.deleted_at = ? AND t1.status <> ? AND t1.id = ? - ` - sqlParams2 := []interface{}{ - // model.VendorIDJX, utils.DefaultTimeValue, model.StoreStatusDisabled, - utils.DefaultTimeValue, - model.StoreStatusDisabled, - // jxutils.StandardCoordinate2Int(0), - // jxutils.StandardCoordinate2Int(10000), - // jxutils.StandardCoordinate2Int(0), - // jxutils.StandardCoordinate2Int(10000), - // model.YES, - 102919, //商城模板店 - } - dao.GetRows(dao.GetDB(), &storeList2, sql2, sqlParams2...) - // if len(storeList2) > 1 { - // storeList2 = storeList2[:1] - // } - } - - // 如果要求以步行距离来算 - if needWalkDistance { - var coordList []*autonavi.Coordinate - for _, v := range storeList2 { - coordList = append(coordList, &autonavi.Coordinate{ - Lng: v.FloatLng, - Lat: v.FloatLat, - }) - } - if distanceList, err2 := api.AutonaviAPI.BatchWalkingDistance(lng, lat, coordList); err2 == nil { - for k, v := range storeList2 { - v.WalkDistance = int(distanceList[k]) - } - } else { - return nil, err2 - } - } - - sort.Sort(Store4UserList(storeList2)) - storeList = storeList2 - if len(storeList) > maxStoreCount4User { - storeList = storeList[:maxStoreCount4User] - } - } - return storeList, err -} - func JdStoreInfoCoordinateRecover(ctx *jxcontext.Context, vendorOrgCode string, files []*multipart.FileHeader) (err error) { if len(files) == 0 { return errors.New("没有文件上传!") @@ -2581,14 +2615,14 @@ func JdStoreInfoCoordinateRecover(ctx *jxcontext.Context, vendorOrgCode string, defer file1.Close() db := dao.GetDB() - storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err == nil { var validStoreList []*dao.StoreDetail for _, v := range storeList { if v.Status != model.StoreStatusDisabled && v.CreatedAt.Sub(utils.Str2Time("2019-10-01")) > 0 { storeInfo, err := jd.GetAPI(vendorOrgCode).GetStoreInfoByStationNo2(v.VendorStoreID) if err == nil && storeInfo.CreateTime.GoTime().Sub(utils.Str2Time("2019-10-25")) > 0 { - if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID); err == nil { + if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID, ""); err == nil { validStoreList = append(validStoreList, storeDetail) } } @@ -2690,7 +2724,7 @@ func GetVendorStoreInfo(ctx *jxcontext.Context, vendorIDList []int, isAsync, isC } } db := dao.GetDB() - storeDetail2, err := dao.GetStoreDetailByVendorStoreID(db, storeDetail.VendorStoreID, vendorID) + storeDetail2, err := dao.GetStoreDetailByVendorStoreID(db, storeDetail.VendorStoreID, vendorID, "") if err != nil { return "", err } @@ -2802,6 +2836,25 @@ func StoreStatus2Chinese(status int) (str string) { func GetStorePriceScore(ctx *jxcontext.Context, storeIDs, vendorIDs []int, fromScore, toScore, sort int, snapDate string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { var snapDateParam time.Time db := dao.GetDB() + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } if snapDate != "" { snapDateParam = utils.Str2Time(snapDate) } @@ -2847,7 +2900,7 @@ func CreateStorePriceScore(ctx *jxcontext.Context) (err error) { func RefreshJdLevel(ctx *jxcontext.Context) (err error) { db := dao.GetDB() - storeMapList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusOpened, -1, "") + storeMapList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusOpened, -1, "", "", "") if len(storeMapList) > 0 { dao.Begin(db) defer func() { @@ -2992,7 +3045,7 @@ func UpdateJdStoreNameAll(ctx *jxcontext.Context) (err error) { func DeletePrinterSeq(ctx *jxcontext.Context, storeIDs []int) (err error) { db := dao.GetDB() for _, v := range storeIDs { - stores, err := dao.GetStoreList(db, []int{v}, nil, nil, nil, "") + stores, err := dao.GetStoreList(db, []int{v}, nil, nil, nil, nil, "") if err != nil || len(stores) == 0 { return err } @@ -3034,7 +3087,7 @@ func checkYbParams(db *dao.DaoDB, storeMap *model.StoreMap, storeID int) (err er } } } - storeMaps, err := dao.GetStoresMapList2(db, []int{model.VendorIDYB}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", false) + storeMaps, err := dao.GetStoresMapList2(db, []int{model.VendorIDYB}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "", false) if len(storeMaps) > 0 { for _, v := range storeMaps { if v.YbAppID == appID { @@ -3045,7 +3098,7 @@ func checkYbParams(db *dao.DaoDB, storeMap *model.StoreMap, storeID int) (err er } } } - stores, err := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, "") + stores, err := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") if len(stores) > 0 { if configs, err := dao.QueryConfigs(dao.GetDB(), "yinbaoCookie", model.ConfigTypeCookie, ""); err == nil { yinbaoCookie = configs[0].Value @@ -3111,15 +3164,304 @@ func ChangeYbCookie() (err error) { return err } +func GetStoreCategoryMap(ctx *jxcontext.Context, parentID, level int, storeID int) (storeCatMaps []*model.StoreCategoryMap, err error) { + db := dao.GetDB() + storeCatMaps, err = dao.GetStoreCategoryMap(db, parentID, level, storeID, 0) + if err != nil { + return nil, err + } + return storeCatMaps, err +} + +func AddStoreCategoryMap(ctx *jxcontext.Context, storeCategoryMap *model.StoreCategoryMap) (result *model.StoreCategoryMap, err error) { + var ( + db = dao.GetDB() + ) + if storeCategoryMap.Level != 1 { + storeCatMaps, _ := dao.GetStoreCategoryMap(db, -1, 0, storeCategoryMap.StoreID, storeCategoryMap.CategoryID) + if len(storeCatMaps) > 0 { + return nil, fmt.Errorf("已存在绑定的京西分类,分类名:[%v]", storeCatMaps[0].StoreCategoryName) + } + } + storeCategoryMap.StoreCategoryName = strings.Trim(storeCategoryMap.StoreCategoryName, " ") + dao.WrapAddIDCULDEntity(storeCategoryMap, ctx.GetUserName()) + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if err = dao.CreateEntity(db, storeCategoryMap); err != nil { + dao.Rollback(db) + return nil, err + } + dao.Commit(db) + result = storeCategoryMap + if storeCategoryMap.CategoryID != 0 { + SetStoreCategorySyncStatus2(db, []int{storeCategoryMap.StoreID}, []int{storeCategoryMap.CategoryID}, model.SyncFlagModifiedMask) + } + // _, err = CurVendorSync.SyncCategory(ctx, nil, cat.ID, false, userName) + return result, err +} + +func UpdateStoreCategoryMap(ctx *jxcontext.Context, ID int, storeCategoryMap *model.StoreCategoryMap, isDelete bool) (num int64, err error) { + var ( + db = dao.GetDB() + valid = make(map[string]interface{}) + storeCategoryMap2 = &model.StoreCategoryMap{} + ) + storeCategoryMap2.ID = ID + if err = dao.GetEntity(db, storeCategoryMap2); err != nil { + return 0, err + } + if storeCategoryMap.StoreCategoryName != "" { + valid["storeCategoryName"] = storeCategoryMap.StoreCategoryName + } + if storeCategoryMap.CategoryID != 0 { + valid["categoryID"] = storeCategoryMap.CategoryID + if !isDelete { + storeCatMaps, _ := dao.GetStoreCategoryMap(db, -1, 0, storeCategoryMap2.StoreID, storeCategoryMap.CategoryID) + if len(storeCatMaps) > 0 { + for _, v := range storeCatMaps { + if v.ID != ID { + return 0, fmt.Errorf("已存在绑定的京西分类,分类名:[%v]", storeCatMaps[0].StoreCategoryName) + } + } + } + } + } + if storeCategoryMap.Level != 0 { + valid["level"] = storeCategoryMap.Level + if storeCategoryMap.Level == 2 { + cat2, _ := dao.GetCategories(db, -1, 0, []int{storeCategoryMap.CategoryID}, false) + if len(cat2) > 0 { + if cat2[0].ParentID != storeCategoryMap.ParentID { + return 0, fmt.Errorf("此二级分类只能绑定到对应一级分类下!") + + } + } + } + } + if isDelete { + valid["deletedAt"] = time.Now() + valid["updatedAt"] = time.Now() + valid["lastOperator"] = ctx.GetUserName() + //如果是1级分类则删除下面的子分类 + var catIDs []int + if storeCategoryMap2.Level == 1 { + storeCatMaps, _ := dao.GetStoreCategoryMap(db, storeCategoryMap2.CategoryID, 2, storeCategoryMap2.StoreID, 0) + if len(storeCatMaps) > 0 { + for _, v := range storeCatMaps { + catIDs = append(catIDs, v.CategoryID) + v.DeletedAt = time.Now() + v.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, v, "DeletedAt", "LastOperator") + } + } + } + // var storeSkus []*model.StoreSkuBind + // sql := ` + // SELECT a.* + // FROM store_sku_bind a + // JOIN sku b ON a.sku_id = b.id + // JOIN sku_name c ON c.id = b.name_id + // WHERE a.deleted_at = ? AND b.deleted_at = ? AND c.deleted_at = ? + // AND c.category_id = ? AND a.store_id = ? + // UNION ALL + // SELECT a.* + // FROM store_sku_bind a + // JOIN sku b ON a.sku_id = b.id + // JOIN sku_name c ON c.id = b.name_id + // JOIN sku_category d ON d.id = c.category_id + // JOIN sku_category e ON e.id = d.parent_id + // WHERE a.deleted_at = ? AND b.deleted_at = ? AND c.deleted_at = ? + // AND e.id = ? AND a.store_id = ? + // ` + // sqlParams := []interface{}{ + // utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, + // storeCategoryMap2.CategoryID, storeCategoryMap2.StoreID, + // utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, + // storeCategoryMap2.CategoryID, storeCategoryMap2.StoreID, + // } + // if err = dao.GetRows(db, &storeSkus, sql, sqlParams); err != nil { + // return 0, err + // } + // if len(storeSkus) > 0 { + // return 0, fmt.Errorf("该分类下或该分类的子分类下有关注的商品,不可删除!分类名:[%v]", storeCategoryMap2.StoreCategoryName) + // } + catIDs = append(catIDs, storeCategoryMap.CategoryID) + SetStoreCategorySyncStatus2(db, []int{storeCategoryMap2.StoreID}, catIDs, model.SyncFlagModifiedMask) + } else { + SetStoreCategorySyncStatus2(db, []int{storeCategoryMap2.StoreID}, []int{storeCategoryMap.CategoryID, storeCategoryMap2.CategoryID}, model.SyncFlagModifiedMask) + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if num, err = dao.UpdateEntityLogically(db, storeCategoryMap2, valid, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return 0, err + } + dao.Commit(db) + return num, err +} + +func ReorderStoreCategories(ctx *jxcontext.Context, parentID, storeID int, categoryIDs []int) (err error) { + var ( + storeCatsMap []*model.StoreCategoryMap + ) + db := dao.GetDB() + storeCatsMap, err = dao.GetStoreCategoryMap(db, parentID, 0, storeID, 0) + catsLen := len(storeCatsMap) + if catsLen != len(categoryIDs) { + return ErrInputCatsDoesntMatch + } + catsMap := make(map[int]*model.StoreCategoryMap, catsLen) + for _, cat := range storeCatsMap { + catsMap[cat.CategoryID] = cat + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + for k, v := range categoryIDs { + if catsMap[v] == nil { + dao.Rollback(db) + return fmt.Errorf("分类:%d不在%d分类下", v, parentID) + } + catsMap[v].StoreCategorySeq = k + catsMap[v].LastOperator = ctx.GetUserName() + if _, err = dao.UpdateEntity(db, catsMap[v]); err != nil { + dao.Rollback(db) + return err + } + } + dao.Commit(db) + SetStoreCategorySyncStatus2(db, nil, categoryIDs, model.SyncFlagModifiedMask) + if err == nil { + CurVendorSync.SyncStoresCategory(ctx, db, nil, nil, false, true, true) + } + return err +} + +func CopyStoreCategories(ctx *jxcontext.Context, fromStoreID int, toStoreIDs, categoryIDs []int, isContinueWhenError, isAsync bool) (hint string, err error) { + var ( + db = dao.GetDB() + ) + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + if storeIDsMap[fromStoreID] == 0 { + return "", fmt.Errorf("抱歉,您无权更改他人店铺分类 [%v]", fromStoreID) + } + for _, v := range toStoreIDs { + if storeIDsMap[v] == 0 { + return "", fmt.Errorf("抱歉,您无权更改他人店铺分类 [%v]", v) + } + } + } + } + storeCatList, err := dao.GetStoreCategoryMap(db, -1, 0, fromStoreID, 0) + if err != nil { + return "", err + } + if len(storeCatList) == 0 { + return "", fmt.Errorf("原门店无分类信息!storeID: %v", fromStoreID) + } + task := tasksch.NewParallelTask("CopyStoreCategories", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeID := batchItemList[0].(int) + //证明是要全复制 + if len(categoryIDs) == 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + sql := ` + DELETE FROM store_category_map WHERE store_id = ? + ` + sqlParams := []interface{}{storeID} + if _, err = dao.ExecuteSQL(db, sql, sqlParams); err != nil { + return retVal, err + } + sql2 := ` + INSERT INTO store_category_map(created_at,updated_at,last_operator,deleted_at,store_id,category_id,store_category_name,store_category_seq,level,parent_id) + SELECT ?, ?, ?, ?, ?, category_id, store_category_name, store_category_seq, level, parent_id + FROM store_category_map + WHERE store_id = ? AND deleted_at = ? + ` + sqlParams2 := []interface{}{ + time.Now(), time.Now(), ctx.GetUserName(), utils.DefaultTimeValue, storeID, + fromStoreID, utils.DefaultTimeValue, + } + if _, err = dao.ExecuteSQL(db, sql2, sqlParams2); err != nil { + return retVal, err + } + dao.Commit(db) + } else { + for _, v := range categoryIDs { + list, err := dao.GetStoreCategoryMap(db, -1, 0, storeID, v) + if err != nil { + return retVal, err + } + if len(list) > 0 { + return retVal, fmt.Errorf("该门店已有重复绑定的京西分类!storeID: %v,categroyID: %v", storeID, v) + } else { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + sql2 := ` + INSERT INTO store_category_map(created_at,updated_at,last_operator,deleted_at,store_id,category_id,store_category_name,store_category_seq,level,parent_id) + SELECT ?, ?, ?, ?, ?, category_id, store_category_name, store_category_seq, level, parent_id + FROM store_category_map + WHERE store_id = ? AND deleted_at = ? AND category_id = ? + ` + sqlParams2 := []interface{}{ + time.Now(), time.Now(), ctx.GetUserName(), utils.DefaultTimeValue, storeID, + fromStoreID, utils.DefaultTimeValue, v, + } + if _, err = dao.ExecuteSQL(db, sql2, sqlParams2); err != nil { + return retVal, err + } + dao.Commit(db) + } + } + } + return retVal, err + }, toStoreIDs) + tasksch.HandleTask(task, nil, true).Run() + if isAsync { + hint = task.GetID() + } else { + _, err = task.GetResult(0) + hint = "1" + } + return hint, err +} + func DisabledStoreWithoutVendor(ctx *jxcontext.Context, isContinueWhenError, isAsync bool) (hint string, err error) { var ( db = dao.GetDB() ) - stores, err := dao.GetStoreList(db, nil, nil, []int{model.StoreStatusClosed, model.StoreStatusHaveRest, model.StoreStatusOpened}, nil, "") + stores, err := dao.GetStoreList(db, nil, nil, []int{model.StoreStatusClosed, model.StoreStatusHaveRest, model.StoreStatusOpened}, nil, nil, "") task := tasksch.NewParallelTask("DisabledStoreWithoutVendor", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { store := batchItemList[0].(*model.Store) - storeMaps, err := dao.GetStoresMapList(db, []int{model.VendorIDYB, model.VendorIDJD, model.VendorIDJX, model.VendorIDEBAI, model.VendorIDMTWM}, []int{store.ID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMaps, err := dao.GetStoresMapList(db, []int{model.VendorIDYB, model.VendorIDJD, model.VendorIDJX, model.VendorIDEBAI, model.VendorIDMTWM}, []int{store.ID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if len(storeMaps) == 0 { store.Status = model.StoreStatusDisabled dao.UpdateEntity(db, store, "Status") @@ -3151,7 +3493,12 @@ func CleanStoreIsBoughtMatter(ctx *jxcontext.Context) (err error) { } func InsertStoreCategories(ctx *jxcontext.Context, db *dao.DaoDB, storeID int) (err error) { - err = dao.InsertStoreCategories(db, ctx.GetUserName(), storeID) + if db == nil { + db = dao.GetDB() + } + if err = dao.DeleteStoreCategroies2(db, storeID); err == nil { + err = dao.InsertStoreCategories(db, ctx.GetUserName(), storeID) + } return err } @@ -3176,3 +3523,544 @@ func findSkusBetweenJdsMainStore(db *dao.DaoDB, storeID int) (skus []int) { } return skus } + +func UpdateStorePricePack(ctx *jxcontext.Context, storeID, vendorID int, pricePack, value string) (err error) { + if err = checkConfig(model.SyncFlagModifiedMask, model.ConfigTypePricePack, pricePack, value); err != nil { + return err + } + db := dao.GetDB() + storeDetail, _ := dao.GetStoreDetail(db, storeID, vendorID, "") + if storeDetail.PayPercentage > 50 { + return fmt.Errorf("目前只允许扣点的门店修改调价包!") + } + + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + //证明是门店自己的调价包 + if strings.Contains(pricePack, utils.Int2Str(storeID)) { + obj := dao.PricePercentagePack2Obj(value) + realValue, _ := json.Marshal(obj) + // _, err = UpdateConfig(ctx, pricePack, model.ConfigTypePricePack, string(realValue)) + configList, err := dao.QueryConfigs(db, pricePack, model.ConfigTypePricePack, "") + if err != nil { + dao.Rollback(db) + return err + } + if _, err = dao.UpdateEntityLogically(db, configList[0], map[string]interface{}{ + "Value": string(realValue), + }, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return err + } + } else { + //表示门店要改他原有的调价包 + //1、调价包名字要加上门店编号门店名等 + //2、添加config + //3、更新storeVendorMap + //4、同步相关 + pricePack = pricePack + "_" + utils.Int2Str(storeID) + "_" + storeDetail.Name + if err = AddConfig(ctx, pricePack, model.ConfigTypePricePack, value); err != nil { + dao.Rollback(db) + return err + } + storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") + if err != nil { + dao.Rollback(db) + return err + } + if len(storeMapList) > 0 { + storeMapList[0].PricePercentagePack = pricePack + dao.UpdateEntity(db, storeMapList[0], "PricePercentagePack") + } + } + dao.Commit(db) + storeMapList, err := dao.GetStoresMapList(db, nil, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, pricePack, "", "") + if err != nil { + dao.Rollback(db) + return err + } + vendorStoreMap := make(map[int][]int) + for _, v := range storeMapList { + vendorStoreMap[v.VendorID] = append(vendorStoreMap[v.VendorID], v.StoreID) + } + for vendorID, storeIDs := range vendorStoreMap { + dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, nil, model.SyncFlagPriceMask) + } + return err +} + +func GetJdDeliveryArea(ctx *jxcontext.Context, storeIDs []int) (err error) { + type tmp struct { + JdID string `json:"jdID"` + S int `json:"s"` + } + type SpecialtyStoreSkus struct { + StoreID int `json:"门店ID"` + StoreName string `json:"门店名"` + City string `json:"城市"` + Area int `json:"面积"` + } + var ( + ss []*tmp + excelTitle = []string{ + "门店ID", + "门店名", + "城市", + "面积", + } + sheetList []*excel.Obj2ExcelSheetConfig + specialtyStoreSkus []*SpecialtyStoreSkus + downloadURL, fileName string + ) + storeMaps, _ := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDJD}, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") + for _, v := range storeMaps { + time.Sleep(time.Second / 3) + station, err := jd.GetAPI("320406").GetDeliveryRangeByStationNo2(v.VendorStoreID) + if err != nil { + continue + } + if station.DeliveryRangeType == 2 { + strs := strings.Split(station.DeliveryRange, ";") + ss = append(ss, &tmp{ + JdID: v.VendorStoreID, + S: utils.Float64TwoInt(math.Ceil((jxutils.ComputeSignedArea(strs[:len(strs)-1])))), + }) + } + } + for i := 0; i < len(ss)-1; i++ { + for j := 0; j < len(ss)-1-i; j++ { + if ss[j].S > ss[j+1].S { + temp := ss[j] + ss[j] = ss[j+1] + ss[j+1] = temp + } + } + } + for _, v := range ss { + storeDetail, _ := dao.GetStoreDetailByVendorStoreID(dao.GetDB(), v.JdID, model.VendorIDJD, "") + place, _ := dao.GetPlaceByCode(dao.GetDB(), storeDetail.CityCode) + specialtyStoreSku := &SpecialtyStoreSkus{ + StoreID: storeDetail.ID, + StoreName: storeDetail.Name, + City: place.Name, + Area: v.S, + } + specialtyStoreSkus = append(specialtyStoreSkus, specialtyStoreSku) + } + excelConf := &excel.Obj2ExcelSheetConfig{ + Title: "sheet1", + Data: specialtyStoreSkus, + CaptionList: excelTitle, + } + sheetList = append(sheetList, excelConf) + if excelConf != nil { + downloadURL, fileName, err = jxutils.UploadExeclAndPushMsg(sheetList, "面积") + } else { + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!") + } + if err != nil { + baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName, err) + } else { + noticeMsg := fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, ctx.GetUserID(), "异步任务完成", noticeMsg) + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess downloadURL: [%v]", downloadURL) + } + return err +} + +func UpdateStorePushClient(ctx *jxcontext.Context, storeID int, cID string) (err error) { + var ( + db = dao.GetDB() + ) + storePushClients, err := dao.GetStorePushClient(db, storeID, cID) + if err != nil { + return err + } + if len(storePushClients) == 0 { + storePushClient := &model.StorePushClient{ + StoreID: storeID, + ClientID: cID, + } + dao.WrapAddIDCULDEntity(storePushClient, ctx.GetUserName()) + dao.CreateEntity(db, storePushClient) + } + return err +} + +func CreateStoreAudit(ctx *jxcontext.Context, storeAudit *model.StoreAudit) (err error) { + var ( + db = dao.GetDB() + ) + storeAudits, err := dao.GetStoreAudit(db, []int{model.StoreAuditStatusOnline}, storeAudit.UserID, "") + if len(storeAudits) > 0 { + return fmt.Errorf("您已申请过入驻,请不要重复申请!") + } + if storeAudit.Address == "" { + return fmt.Errorf("门店地址必填!") + } + if storeAudit.Lng == 0 || storeAudit.Lat == 0 { + lng, lat, _ := api.AutonaviAPI.GetCoordinateFromAddress(storeAudit.Address, "") + if lng != 0 && lat != 0 { + storeAudit.Lng = jxutils.StandardCoordinate2Int(lng) + storeAudit.Lat = jxutils.StandardCoordinate2Int(lat) + } else { + return fmt.Errorf("请填写正确的门店地址!") + } + } + + if storeAudit.UserID == "" { + storeAudit.UserID = ctx.GetUserID() + } + dao.WrapAddIDCULDEntity(storeAudit, ctx.GetUserName()) + dao.CreateEntity(db, storeAudit) + return err +} + +func GetStoreAudit(ctx *jxcontext.Context, statuss []int, keyword, applyTimeStart, applyTimeEnd, auditTimeStart, auditTimeEnd string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) { + var ( + applyTimeStartp, applyTimeEndp, auditTimeStartp, auditTimeEndp time.Time + db = dao.GetDB() + ) + if applyTimeStart != "" { + applyTimeStartp = utils.Str2Time(applyTimeStart) + } + if applyTimeEnd != "" { + applyTimeEndp = utils.Str2Time(applyTimeEnd) + } + if auditTimeStart != "" { + auditTimeStartp = utils.Str2Time(auditTimeStart) + } + if auditTimeEnd != "" { + auditTimeEndp = utils.Str2Time(auditTimeEnd) + } + pagedInfo, err = dao.GetStoreAuditPage(db, statuss, keyword, applyTimeStartp, applyTimeEndp, auditTimeStartp, auditTimeEndp, pageSize, offset) + return pagedInfo, err +} + +func StoreAudit(ctx *jxcontext.Context, storeAudits []*model.StoreAudit, status int) (hint string, err error) { + db := dao.GetDB() + if status != model.StoreAuditStatusCreated && status != model.StoreAuditStatusRejected { + return "", fmt.Errorf("审核标志不正确!") + } + task := tasksch.NewParallelTask("StoreAudit", tasksch.NewParallelConfig().SetParallelCount(5).SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeAudit := batchItemList[0].(*model.StoreAudit) + storeAudits, err := dao.GetStoreAudit(db, []int{model.StoreAuditStatusOnline}, storeAudit.UserID, "") + if len(storeAudits) == 0 || err != nil { + return retVal, fmt.Errorf("未查询到待审核信息!") + } + if len(storeAudits) > 1 { + return retVal, fmt.Errorf("查询到该用户的待审核信息大于1条!userID: [%s]", storeAudit.UserID) + } + //审核通过 + if status == model.StoreAuditStatusCreated { + storeAudits[0].AuditStatus = model.StoreAuditStatusCreated + //添加门店 + storeExt := &StoreExt{} + if data, err := json.Marshal(&storeAudits[0]); err == nil { + utils.UnmarshalUseNumber(data, &storeExt) + } + storeExt.ID = 0 + storeExt.Store.StoreLevel = "C" + storeExt.FloatLng = jxutils.IntCoordinate2Standard(utils.Float64TwoInt(storeExt.FloatLng)) + storeExt.FloatLat = jxutils.IntCoordinate2Standard(utils.Float64TwoInt(storeExt.FloatLat)) + storeExt.Status = model.StoreStatusDisabled + storeExt.MarketManName = ctx.GetUserName() + storeExt.MarketManPhone, _ = ctx.GetMobileAndUserID() + storeID, err := CreateStore(ctx, storeExt, ctx.GetUserName()) + if err != nil { + return retVal, fmt.Errorf(err.Error()) + } + err = AddUsers4Role(ctx, autils.NewRole(authz.StoreRoleBoss, storeID), []string{storeAudit.UserID}) + if err != nil { + return retVal, fmt.Errorf(err.Error()) + } + } else if status == model.StoreAuditStatusRejected { + storeAudits[0].AuditStatus = model.StoreAuditStatusRejected + } else { + return retVal, fmt.Errorf("审核标志不正确!") + } + storeAudits[0].LastOperator = ctx.GetUserName() + storeAudits[0].Remark = storeAudit.Remark + _, err = dao.UpdateEntity(db, storeAudits[0], "LastOperator", "AuditStatus", "Remark") + //是否推送app消息 + if err == nil { + + } + return retVal, err + }, storeAudits) + tasksch.HandleTask(task, nil, true).Run() + hint = task.GetID() + return hint, err +} + +func GetDiffJxStoreAndMTWMStoreInfo(ctx *jxcontext.Context, storeIDs []int) (err error) { + type TmpDiffStore struct { + StoreID int `json:"门店ID"` + StoreName string `json:"门店名"` + City string `json:"城市"` + Coordinate string `json:"坐标"` + Address string `json:"地址"` + Phone string `json:"电话"` + CoordinateMT string `json:"坐标(美团)"` + AddressMT string `json:"地址(美团)"` + PhoneMT string `json:"电话(美团)"` + Comment string `json:"对比情况"` + } + var ( + excelTitle = []string{ + "门店ID", + "门店名", + "城市", + "坐标", + "地址", + "电话", + "坐标(美团)", + "地址(美团)", + "电话(美团)", + "对比情况", + } + sheetList []*excel.Obj2ExcelSheetConfig + tmpDiffStoreList []*TmpDiffStore + downloadURL, fileName string + db = dao.GetDB() + ) + courierStoreList, _ := dao.GetStoreCourierList(db, storeIDs, []int{model.VendorIDMTPS}, model.StoreStatusAll, model.StoreAuditStatusAll) + for _, v := range courierStoreList { + comment := "" + tmpDiffStore := &TmpDiffStore{ + StoreID: v.StoreID, + } + stores, err := dao.GetStoreList(db, []int{v.StoreID}, nil, nil, nil, nil, "") + store := stores[0] + place, _ := dao.GetPlaceByCode(db, store.CityCode) + tmpDiffStore.City = place.Name + tmpDiffStore.StoreName = store.Name + tmpDiffStore.Coordinate = utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)) + tmpDiffStore.Address = store.Address + tmpDiffStore.Phone = store.Tel1 + shopInfo, err := api.MtpsAPI.ShopQuery(v.VendorStoreID) + if err != nil { + tmpDiffStore.Comment += err.Error() + tmpDiffStoreList = append(tmpDiffStoreList, tmpDiffStore) + continue + } + tmpDiffStore.CoordinateMT = utils.Float64ToStr(jxutils.IntCoordinate2Standard(shopInfo.ShopLng)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(shopInfo.ShopLat)) + tmpDiffStore.AddressMT = shopInfo.ShopAddress + tmpDiffStore.PhoneMT = shopInfo.ContactPhone + if tmpDiffStore.Coordinate != tmpDiffStore.CoordinateMT { + comment += "坐标不同;" + } + if tmpDiffStore.Address != tmpDiffStore.AddressMT { + comment += "地址不同;" + } + if tmpDiffStore.Phone != tmpDiffStore.PhoneMT { + comment += "电话不同;" + } + tmpDiffStore.Comment = comment + if comment != "" { + tmpDiffStoreList = append(tmpDiffStoreList, tmpDiffStore) + } + } + + excelConf := &excel.Obj2ExcelSheetConfig{ + Title: "sheet1", + Data: tmpDiffStoreList, + CaptionList: excelTitle, + } + sheetList = append(sheetList, excelConf) + if excelConf != nil { + downloadURL, fileName, err = jxutils.UploadExeclAndPushMsg(sheetList, "美团配送信息对比") + } else { + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!") + } + if err != nil { + baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName, err) + } else { + noticeMsg := fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, ctx.GetUserID(), "异步任务完成", noticeMsg) + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess downloadURL: [%v]", downloadURL) + } + return err +} + +func GetBrands(ctx *jxcontext.Context, name string, brandID int) (brands []*model.Brand, err error) { + return dao.GetBrands(dao.GetDB(), name, brandID) +} + +func AddBrand(ctx *jxcontext.Context, brand *model.Brand) (err error) { + var ( + db = dao.GetDB() + ) + if brand.Name == "" { + return fmt.Errorf("请输入品牌名!") + } + brand.Name = utils.TrimBlankChar(brand.Name) + dao.WrapAddIDCULDEntity(brand, ctx.GetUserName()) + err = dao.CreateEntity(db, brand) + return err +} + +func UpdateBrand(ctx *jxcontext.Context, payload map[string]interface{}, isDel bool) (err error) { + var ( + db = dao.GetDB() + brand = &model.Brand{} + ) + brand.ID = int(utils.MustInterface2Int64(payload["id"])) + dao.GetEntity(db, brand) + if isDel { + brand.DeletedAt = time.Now() + brand.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, brand, "DeletedAt", "LastOperator") + } else { + valid := dao.StrictMakeMapByStructObject(payload, brand, ctx.GetUserName()) + if len(valid) > 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + if _, err = dao.UpdateEntityLogically(db, brand, valid, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return + } + dao.Commit(db) + }() + } + } + return err +} + +func CreateVendorStore(ctx *jxcontext.Context, storeID, vendorID int, payload map[string]interface{}) (err error) { + var ( + db = dao.GetDB() + storeDetail *dao.StoreDetail + ) + if storeDetail, err = dao.GetStoreDetail(db, storeID, vendorID, ""); err != nil { + return fmt.Errorf("获取门店信息失败,请联系技术部!") + } + if payload["vendorOrgCode"] == nil { + return fmt.Errorf("请选择平台账号!") + } + if vendorID == model.VendorIDMTWM { + if brands, err := dao.GetBrands(db, "", storeDetail.BrandID); err == nil { + if len(brands) > 0 { + if strings.Contains(brands[0].Name, "无品牌") { + return fmt.Errorf("无品牌店铺不允许创建美团门店!") + } + } + } + } + if payload["vendorStoreName"] == nil { + return fmt.Errorf("请输入平台名!") + } + handler := partner.GetPurchasePlatformFromVendorID(vendorID) + vendorStoreID, err := handler.CreateStore2(db, storeID, ctx.GetUserName(), payload, storeDetail) + if err != nil { + return err + } + if vendorStoreID != "" && vendorStoreID != "0" { + //AddStoreVendorMap 太复杂了并不满足,还是手动加吧 + storeMap := &model.StoreMap{ + VendorStoreID: vendorStoreID, + StoreID: storeID, + VendorID: vendorID, + VendorOrgCode: payload["vendorOrgCode"].(string), + Status: 0, //平台还未审核等 + DeliveryType: model.StoreDeliveryTypeByStore, + PricePercentage: int16(utils.MustInterface2Int64(payload["pricePercentage"])), + AutoPickup: 1, + DeliveryCompetition: 1, + IsSync: 1, + PricePercentagePack: payload["pricePercentagePack"].(string), + } + dao.WrapAddIDCULDEntity(storeMap, ctx.GetUserName()) + err = dao.CreateEntity(db, storeMap) + } + return err +} + +func GetBrandStore(ctx *jxcontext.Context, name string) (brands []*model.BrandStore, err error) { + var ( + db = dao.GetDB() + ) + sql := ` + SELECT * FROM brand_store WHERE deleted_at = ? AND name LIKE ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue, "%" + name + "%"} + err = dao.GetRows(db, &brands, sql, sqlParams) + return brands, err +} + +func RefreshMTWMToken(ctx *jxcontext.Context) (err error) { + var ( + db = dao.GetDB() + ) + if time.Now().YearDay()%20 != 0 { + return + } + //token是1个月过期,每20天刷一次吧 + storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDMTWM}, nil, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", globals.Mtwm2Code) + for _, v := range storeMaps { + if v.MtwmRefreshToken != "" { + if result, err := api.Mtwm2API.RefreshAccessToken(v.MtwmRefreshToken); err == nil { + v.MtwmToken = result.AccessToken + v.MtwmRefreshToken = result.RefreshToken + dao.UpdateEntity(db, v, "MtwmToken", "MtwmRefreshToken") + } + } + } + return err +} + +func StoreConfirmAct(ctx *jxcontext.Context, status, msgStatusID int) (err error) { + msgStatus := &model.MessageStatus{} + msgStatus.ID = msgStatusID + db := dao.GetDB() + if err = dao.GetEntity(db, msgStatus); err != nil { + return err + } + if status == model.YES { + msg := &model.Message{} + msg.ID = msgStatus.MessageID + if err = dao.GetEntity(db, msg); err != nil { + return err + } + actMap := &model.MessageActInfo{} + err = json.Unmarshal([]byte(msg.ActInfo), &actMap) + if time.Now().Sub(utils.Str2Time(actMap.BeginAt)) > 0 { + msgStatus.ConfirmStatus = -1 + dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName()) + _, err = dao.UpdateEntity(db, msgStatus, "ConfirmStatus") + return fmt.Errorf("参与活动时间已过期!") + } + } + msgStatus.ConfirmStatus = status + dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName()) + _, err = dao.UpdateEntity(db, msgStatus, "ConfirmStatus") + return err +} + +func GetStoreAcctBalance(ctx *jxcontext.Context, storeID int) (storeAcct *model.StoreAcct, err error) { + var ( + db = dao.GetDB() + ) + totalIncome, err := dao.GetStoreAcctIncomeTotal(db, storeID, 0, utils.ZeroTimeValue, utils.ZeroTimeValue) + if err != nil { + return nil, err + } + totalExpend, err := dao.GetStoreAcctExpendTotal(db, storeID, 0, utils.ZeroTimeValue, utils.ZeroTimeValue) + if err != nil { + return nil, err + } + return &model.StoreAcct{ + StoreID: storeID, + AccountBalance: totalIncome - totalExpend, + }, err +} diff --git a/business/jxstore/cms/store_acct.go b/business/jxstore/cms/store_acct.go new file mode 100644 index 000000000..fac82d992 --- /dev/null +++ b/business/jxstore/cms/store_acct.go @@ -0,0 +1,107 @@ +package cms + +import ( + "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" +) + +type StoreAcctManager struct { +} + +var ( + FixedStoreAcctManager *StoreAcctManager +) + +func init() { + FixedStoreAcctManager = &StoreAcctManager{} + partner.InitStoreAcctManager(FixedStoreAcctManager) +} + +func (s *StoreAcctManager) InsertStoreAcctIncome(ctx *jxcontext.Context, db *dao.DaoDB, storeID, price, acctType int) (err error) { + storeAcctIncome := &model.StoreAcctIncome{ + StoreID: storeID, + IncomePrice: price, + Type: acctType, + UserID: ctx.GetUserID(), + } + dao.WrapAddIDCULEntity(storeAcctIncome, ctx.GetUserName()) + err = dao.CreateEntity(db, storeAcctIncome) + return err +} + +func (s *StoreAcctManager) InsertStoreAcctExpend(ctx *jxcontext.Context, db *dao.DaoDB, storeID, price, acctType int, vendorOrderID string) (err error) { + storeAcctExpend := &model.StoreAcctExpend{ + StoreID: storeID, + ExpendPrice: price, + Type: acctType, + UserID: ctx.GetUserID(), + VendorOrderID: vendorOrderID, + } + dao.WrapAddIDCULEntity(storeAcctExpend, ctx.GetUserName()) + err = dao.CreateEntity(db, storeAcctExpend) + return err +} + +func (s *StoreAcctManager) UpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price int, isIncome bool) (err error) { + var ( + db = dao.GetDB() + ) + storeAcct := &model.StoreAcct{ + StoreID: storeID, + } + if isIncome { + storeAcct.AccountBalance += price + } else { + storeAcct.AccountBalance -= price + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil || err != nil { + dao.Rollback(db) + if r != nil { + panic(r) + } + } + }() + if err = dao.GetEntity(db, storeAcct, "StoreID"); err != nil && dao.IsNoRowsError(err) { + //新增门店账单 + dao.WrapAddIDCULEntity(storeAcct, ctx.GetUserName()) + if err = dao.CreateEntity(db, storeAcct); err != nil { + dao.Rollback(db) + return err + } + } else { + if _, err = dao.UpdateEntity(db, storeAcct, "AccountBalance"); err != nil { + dao.Rollback(db) + return err + } + } + dao.Commit(db) + return err +} + +func (s *StoreAcctManager) InsertStoreAcctExpendAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int, vendorOrderID string) (err error) { + var ( + db = dao.GetDB() + ) + if err = s.InsertStoreAcctExpend(ctx, db, storeID, price, acctType, vendorOrderID); err == nil { + s.UpdateStoreAcctBalance(ctx, storeID, price, false) + } + return err +} + +func (s *StoreAcctManager) InsertStoreAcctIncomeAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int) (err error) { + var ( + db = dao.GetDB() + ) + if err = s.InsertStoreAcctIncome(ctx, db, storeID, price, acctType); err == nil { + s.UpdateStoreAcctBalance(ctx, storeID, price, true) + } + return err +} + +func (s *StoreAcctManager) CheckStoreAcctExpendExist(storeID int, vendorOrderID string) (result bool, err error) { + return false, err +} diff --git a/business/jxstore/cms/store_sku.go b/business/jxstore/cms/store_sku.go index 93c513e16..0086a985d 100644 --- a/business/jxstore/cms/store_sku.go +++ b/business/jxstore/cms/store_sku.go @@ -13,6 +13,12 @@ import ( "time" "unicode" + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" + + "git.rosy.net.cn/jx-callback/business/auth2" + + "github.com/astaxie/beego" + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" "git.rosy.net.cn/jx-callback/globals/api" @@ -20,6 +26,7 @@ import ( "git.rosy.net.cn/jx-callback/globals/refutil" "git.rosy.net.cn/jx-callback/business/jxstore/event" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" "git.rosy.net.cn/baseapi" @@ -52,6 +59,8 @@ const ( CopyStoreSkuModeFresh = "fresh" // 全新复制 CopyStoreSkuModeUpdate = "update" // 增量复制 CopyStoreSkuModeUpdatePrice = "updatePrice" // 增量复制价格 + + upcSpecName1 = "(新老包装随机发货)" ) //通用写入Excel @@ -63,9 +72,9 @@ type ExcelParam struct { // UpdateStoreSku用,API调用时 type StoreSkuBindSkuInfo struct { - SkuID int `json:"skuID"` - IsSale int `json:"isSale,omitempty"` // -1:不可售,0:忽略,1:可售 - + SkuID int `json:"skuID"` + IsSale int `json:"isSale,omitempty"` // -1:不可售,0:忽略,1:可售 + Stock *int `json:"stock"` // ElmID int64 `json:"elmID,omitempty"` // EbaiID int64 `json:"ebaiID,omitempty"` } @@ -96,6 +105,7 @@ type tStoreSkuBindAndSpec struct { ExdSkuID string `orm:"column(exd_sku_id)"` StoreName string ChangePriceType int8 `json:"changePriceType"` // 修改价格类型,即是否需要审核 + NameID int `orm:"column(name_id)" json:"nameID"` } type SkuSaleInfo struct { @@ -128,6 +138,7 @@ type tGetStoresSkusInfo struct { dao.StoreSkuExt RealMidUnitPrice int `json:"realMidUnitPrice"` //真实的该商品的全国中位价 YbSkuName string + AuditUnitPrice int } type SheetParam struct { @@ -202,6 +213,14 @@ type MatterStock struct { Stock int `json:"stock"` } +type ActStoreSkuParam struct { + model.ActStoreSku + + ActualActPrice int64 `json:"actualActPrice,omitempty"` // 单品级活动用,创建活动时商品的活动价格 + VendorPrice int64 `json:"vendorPrice,omitempty"` // 创建活动时的平台价格 + ErrMsg string `json:"errMsg,omitempty"` +} + const ( maxStoreNameBind = 10000 // 最大门店SkuName bind个数 maxStoreNameBind2 = 10000 // 最大门店乘SkuName个数 @@ -312,11 +331,13 @@ func getGetStoresSkusBaseSQL(db *dao.DaoDB, storeIDs, skuIDs []int, isFocus bool JOIN store_sku_bind t4 ON t4.store_id = t3.id AND t4.sku_id = t2.id AND t4.deleted_at = ? LEFT JOIN sku_name_place_bind t5 ON t1.id = t5.name_id AND t3.city_code = t5.place_code LEFT JOIN price_refer_snapshot t6 ON t6.city_code = ? AND t6.sku_id = t2.id AND t6.snapshot_at = ? + LEFT JOIN store_sku_audit t7 ON t7.store_id = t3.id AND t7.name_id = t1.id AND t7.status = ? AND t7.deleted_at = ? WHERE t1.deleted_at = ? AND (t1.is_global = 1 OR t5.id IS NOT NULL OR 1 = ?)/* AND t1.status = ?*/ ` sqlParams = append(sqlParams, []interface{}{ utils.DefaultTimeValue, 0, utils.Time2Date(time.Now().AddDate(0, 0, -1)), + model.StoreAuditStatusOnline, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.Bool2Int(isFocus), }) @@ -449,10 +470,42 @@ func getGetStoresSkusBaseSQL(db *dao.DaoDB, storeIDs, skuIDs []int, isFocus bool sql += ")" } } + if isFocus { + /*前台传入的最大值和最小值设置*/ + if params["highestPrice"] != "" && params["highestPrice"] != nil { + //highestPrice := utils.Interface2Float64WithDefault(params["highestPrice"], 0) * 100 + sql += " AND t4.unit_price <= ? " + sqlParams = append(sqlParams, params["highestPrice"]) + } + if params["minimumPrice"] != "" && params["minimumPrice"] != nil { + //minimumPrice := utils.Interface2Float64WithDefault(params["minimumPrice"], 0) * 100 + sql += " AND t4.unit_price >= ? " + sqlParams = append(sqlParams, params["minimumPrice"]) + } + } return sql, sqlParams, err } func GetStoresSkus(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus, isHighPrice bool, priceType int, keyword string, isBySku, isAct bool, params map[string]interface{}, offset, pageSize int) (skuNamesInfo *dao.StoreSkuNamesInfo, err error) { + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } return GetStoresSkusNew(ctx, storeIDs, skuIDs, isFocus, isHighPrice, priceType, keyword, isBySku, isAct, params, offset, pageSize) } @@ -467,6 +520,27 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus, i if params["actVendorID"] != nil { actVendorID = int(utils.Interface2Int64WithDefault(params["actVendorID"], -1)) } + var highestPrice, minimumPrice float64 + if params["highestPrice"] != nil { + if highestPrice, err = strconv.ParseFloat(params["highestPrice"].(string), 64); err != nil { + delete(params, "highestPrice") + } else { + params["highestPrice"] = highestPrice * 100 + } + } + if params["minimumPrice"] != nil { + if minimumPrice, err = strconv.ParseFloat(params["minimumPrice"].(string), 64); err != nil { + delete(params, "minimumPrice") + } else { + params["minimumPrice"] = minimumPrice * 100 + } + } + if !(highestPrice > 0 && highestPrice > minimumPrice) || !(highestPrice > 0) { + delete(params, "highestPrice") + } + if !(minimumPrice >= 0 && highestPrice > 0 && highestPrice > minimumPrice) || !(minimumPrice >= 0) { + delete(params, "minimumPrice") + } db := dao.GetDB() sql, sqlParams, err := getGetStoresSkusBaseSQL(db, storeIDs, skuIDs, isFocus, keyword, isBySku, isAct, isHighPrice, priceType, actVendorID, params) if err != nil { @@ -543,8 +617,9 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus, i t4.jd_sync_status, t4.ebai_sync_status, t4.mtwm_sync_status, t4.yb_sync_status, t4.jds_sync_status, t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price, t4.yb_price, t4.jds_price, t4.jd_lock_time, t4.ebai_lock_time, t4.mtwm_lock_time, t4.jx_lock_time, t4.yb_lock_time, t4.jds_lock_time, - t4.status_sale_begin, t4.status_sale_end, - t6.mid_unit_price real_mid_unit_price + t4.status_sale_begin, t4.status_sale_end, t4.stock, + t6.mid_unit_price real_mid_unit_price, + t7.unit_price audit_unit_price ` + sql if isHighPrice || priceType != 0 { sql += " , t4.unit_price DESC LIMIT 99" @@ -573,6 +648,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus, i PayPercentage: v.PayPercentage, RealMidUnitPrice: v.RealMidUnitPrice, YbSkuName: v.YbSkuName, + AuditUnitPrice: v.AuditUnitPrice, } if !isBySku { storeNameMap[index] = storeName @@ -702,7 +778,7 @@ func updateSaleInfo4StoreSkuName(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs } func getValidStoreVendorMap(db *dao.DaoDB, storeIDs []int) (realVendorMap map[int]int, err error) { - storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeMapList, err := dao.GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err != nil { return nil, err } @@ -832,29 +908,60 @@ func UpdateStoreSku(ctx *jxcontext.Context, causeFlag, storeID int, skuBindInfo } func UpdateStoreSkus(ctx *jxcontext.Context, causeFlag, storeID int, skuBindInfos []*StoreSkuBindInfo, isAsync, isContinueWhenError bool) (hint string, err error) { - return UpdateStoresSkus(ctx, causeFlag, []int{storeID}, skuBindInfos, false, isAsync, isContinueWhenError) + return UpdateStoresSkus(ctx, causeFlag, []int{storeID}, skuBindInfos, false, false, isAsync, isContinueWhenError) } -func UpdateStoresSkus(ctx *jxcontext.Context, causeFlag int, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isScale, isAsync, isContinueWhenError bool) (hint string, err error) { +func UpdateStoresSkus(ctx *jxcontext.Context, causeFlag int, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isScale, isRefreshHigh, isAsync, isContinueWhenError bool) (hint string, err error) { globals.SugarLogger.Debugf("UpdateStoresSkus:%s, storeIDs:%v, skuBindInfos:%s", ctx.GetTrackInfo(), storeIDs, utils.Format4Output(skuBindInfos, true)) - - var num int64 - db := dao.GetDB() - skuIDs, err := updateStoresSkusWithoutSync(ctx, db, storeIDs, skuBindInfos, isScale) - if err != nil { - return "", err - } - isAsync = asyncStoreSkuOpFilter(ctx, isAsync) - num = int64(len(skuIDs)) - if num > 0 { - hint, err = CurVendorSync.SyncStoresSkus(ctx, nil, causeFlag, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError) - } - if num == 0 || !isAsync || hint == "" { - hint = utils.Int64ToStr(num) + if beego.BConfig.RunMode == "jxgy" { + var num int64 + db := dao.GetDB() + skuIDs, err := updateStoresSkusWithoutSync(ctx, db, storeIDs, skuBindInfos, isScale, isRefreshHigh) + if err != nil { + return "", err + } + isAsync = asyncStoreSkuOpFilter(ctx, isAsync) + num = int64(len(skuIDs)) + if num > 0 { + hint, err = CurVendorSync.SyncStoresSkus(ctx, nil, causeFlag, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError) + } + if num == 0 || !isAsync || hint == "" { + hint = utils.Int64ToStr(num) + } + } else { + flag, _ := doStoreSkuAudit(ctx, storeIDs, skuBindInfos) + if !flag { + var num int64 + db := dao.GetDB() + skuIDs, err := updateStoresSkusWithoutSync(ctx, db, storeIDs, skuBindInfos, isScale, isRefreshHigh) + if err != nil { + return "", err + } + isAsync = asyncStoreSkuOpFilter(ctx, isAsync) + num = int64(len(skuIDs)) + if num > 0 { + hint, err = CurVendorSync.SyncStoresSkus(ctx, nil, causeFlag, db, nil, storeIDs, skuIDs, false, isAsync, isContinueWhenError) + } + if num == 0 || !isAsync || hint == "" { + hint = utils.Int64ToStr(num) + } + } } return hint, err } +func UpdateStoresSkusWithoutSync(ctx *jxcontext.Context, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isRefreshHigh bool) (err error) { + db := dao.GetDB() + if len(storeIDs) == 0 { + stores, _ := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") + for _, v := range stores { + storeIDs = append(storeIDs, v.ID) + } + } + updateStoresSkusWithoutSync(ctx, db, storeIDs, skuBindInfos, false, isRefreshHigh) + return err +} + func UpdateStoresSkusByBind(ctx *jxcontext.Context, parentTask tasksch.ITask, skuBindInfos []*StoreSkuBindInfo, isAsync, isContinueWhenError, isFos bool) (hint string, err error) { // if len(skuBindInfos) > maxStoreNameBind { // return "", fmt.Errorf("门店商品信息大于%d", maxStoreNameBind) @@ -880,7 +987,7 @@ func UpdateStoresSkusByBind(ctx *jxcontext.Context, parentTask tasksch.ITask, sk // } // }() for _, storeID := range storeIDs { - skuIDs, err2 := updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosMap[storeID], false) + skuIDs, err2 := updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosMap[storeID], false, false) if err = err2; err != nil { // dao.Rollback(db) return "", err @@ -960,7 +1067,7 @@ func uniqueStoreNameBind(skuBindInfos []*StoreSkuBindInfo) (outSkuBindInfos []*S return outSkuBindInfos } -func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isScale bool) (needSyncSkus []int, err error) { +func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs []int, skuBindInfos []*StoreSkuBindInfo, isScale, isRefreshHigh bool) (needSyncSkus []int, err error) { // if len(storeIDs)*len(skuBindInfos) > maxStoreNameBind2 { // return nil, fmt.Errorf("门店商品信息大于%d", maxStoreNameBind2) // } @@ -976,17 +1083,15 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs // if err = checkStoresSkusSaleCity(ctx, db, storeIDs, skuBindInfos); err != nil { // return nil, err // } - // if storeIDs, skuBindInfos, err = filterStorePriceChange(ctx, storeIDs, skuBindInfos); err != nil { - // return nil, err - // } // globals.SugarLogger.Debugf("updateStoresSkusWithoutSync2, storeIDs:%v, skuBindInfos:%s", storeIDs, utils.Format4Output(skuBindInfos, false)) isUserCanDirectChangePrice := true if user := ctx.GetFullUser(); user != nil { isUserCanDirectChangePrice = user.Type&model.UserTypeOperator != 0 } - userName := ctx.GetUserName() needSyncIDMap := make(map[int]int) + isSyncSkus := false + var appCodeList []string dao.Begin(db) defer func() { if r := recover(); r != nil { @@ -996,10 +1101,16 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs }() for _, storeID := range storeIDs { // todo 可以考虑在需要更新价格再获取 - storeDetail, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDJX) - if err != nil { - dao.Rollback(db) - return nil, err + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDJX, "") + if err != nil || storeDetail == nil { + continue + } + if beego.BConfig.RunMode == "prod" || beego.BConfig.RunMode == "beta" { + if len(storeIDs) > 1 { + if storeDetail.StoreLevel == "D" || storeDetail.StoreLevel == "E" { + continue + } + } } scaleFactor := float64(1) if isScale { @@ -1018,7 +1129,7 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs sql += " IF(t5.unit_price > 0, t5.unit_price, t3.price) sku_name_price," } sql += ` - t3.unit sku_name_unit, t3.name, t3.status sku_name_status, + t3.unit sku_name_unit, t3.name, t3.status sku_name_status, t3.id name_id, ts.change_price_type, ts.name store_name FROM sku t1 JOIN store ts ON ts.id = ? AND ts.deleted_at = ? @@ -1060,6 +1171,11 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs return nil, fmt.Errorf("商品:%s价格:%s太夸张", allBinds[0].Name, jxutils.IntPrice2StandardCurrencyString(int64(skuBindInfo.UnitPrice))) } unitPrice = skuBindInfo.UnitPrice + if isRefreshHigh { + if allBinds[0].UnitPrice <= unitPrice { + continue + } + } } else { unitPrice = allBinds[0].UnitPrice if unitPrice == 0 { @@ -1088,9 +1204,26 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) if tmpStatus := getSkuSaleStatus(inSkuBind, skuBindInfo); tmpStatus != model.StoreSkuBindStatusNA { skuBind.Status = tmpStatus + if inSkuBind != nil { + if inSkuBind.Stock != nil { + skuBind.Stock = *inSkuBind.Stock + } else { + if tmpStatus == model.StoreSkuBindStatusNormal { + skuBind.Stock = model.MaxStoreSkuStockQty + } else { + skuBind.Stock = 0 + } + } + } else { + if tmpStatus == model.StoreSkuBindStatusNormal { + skuBind.Stock = model.MaxStoreSkuStockQty + } else { + skuBind.Stock = 0 + } + } } if globals.IsAddEvent { - err = AddEventDetail(db, ctx, model.OperateAdd, v.RealSkuID, model.ThingTypeSku, storeID, "", "") + err = AddEventDetail(db, ctx, model.OperateAdd, v.RealSkuID, model.ThingTypeSku, storeID, "", utils.Int2Str(skuBind.UnitPrice)) } setStoreSkuBindStatus(skuBind, model.SyncFlagNewMask) dao.WrapAddIDCULDEntity(skuBind, userName) @@ -1113,6 +1246,36 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs return nil, err } } + //下面这段很难受 + { + //可售了的才整 + if skuBind.Status == model.StoreSkuBindStatusNormal { + //如果是京东关注,要去建商品 + list1, _ := dao.GetStoresMapList(db, []int{model.VendorIDJD}, []int{storeID}, nil, model.StoreStatusAll, 1, "", "", "") + //表示这个门店绑定了京东 + if len(list1) > 0 { + vendorOrgCodes, _ := dao.GetVendorOrgCode(db, model.VendorIDJD, list1[0].VendorOrgCode, model.VendorOrgTypePlatform) + //thingmap里肯定存在,再判断有没有同步上去 + thingMaps, _ := dao.GetThingMapList(db, model.ThingTypeSku, []int{model.VendorIDJD}, []int{v.RealSkuID}, []string{list1[0].VendorOrgCode}) + if len(thingMaps) > 0 { + //如果平台ID为空(未创建到京东) + if thingMaps[0].VendorThingID == "" { + //并且同步标志还没有带待创建(因为addskuname现在建到thingmap上不会带待创建标志了) + if !model.IsSyncStatusNew(thingMaps[0].SyncStatus) { + isSyncSkus = true + appCodeList = append(appCodeList, list1[0].VendorOrgCode) + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.RealSkuID), model.ThingTypeSku, model.SyncFlagNewMask, false) + } + } + } else { + //万一不存在 + isSyncSkus = true + appCodeList = append(appCodeList, list1[0].VendorOrgCode) + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.RealSkuID), model.ThingTypeSku, model.SyncFlagNewMask, false) + } + } + } + } } } } else { @@ -1139,6 +1302,15 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs dao.Rollback(db) return nil, err } + //删除待审核商品信息 + storeAudits, err := dao.GetStoreSkuAuditLight(db, []int{storeID}, []int{v.NameID}, model.StoreAuditStatusOnline) + if len(storeAudits) > 0 { + storeAudits[0].DeletedAt = time.Now() + if _, err = dao.UpdateEntity(db, storeAudits[0], "DeletedAt"); err != nil { + dao.Rollback(db) + return nil, err + } + } } else { // 用了SELECT FOR UPDATE后,只更新修改字段是没有必要的,暂时保留 updateFieldMap := make(map[string]interface{}) @@ -1159,6 +1331,19 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs } skuBind.Status = tmpStatus setStoreSkuBindStatus(skuBind, model.SyncFlagSaleMask) + setStoreSkuBindStatus(skuBind, model.SyncFlagStockMask) + if tmpStatus == model.StoreSkuBindStatusNormal { + skuBind.Stock = model.MaxStoreSkuStockQty + } else { + skuBind.Stock = 0 + } + } + if inSkuBind != nil { + if inSkuBind.Stock != nil { + updateFieldMap["Stock"] = 1 + skuBind.Stock = *inSkuBind.Stock + setStoreSkuBindStatus(skuBind, model.SyncFlagStockMask) + } } if skuBindInfo.UnitPrice != 0 && isCanChangePrice { // 这里是否需要加此条件限制 price := jxutils.CaculateSkuPrice(unitPrice, v.SpecQuality, v.SpecUnit, v.SkuNameUnit) @@ -1173,6 +1358,9 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs skuBind.JxPrice = jxPrice updateFieldMap["UnitPrice"] = 1 updateFieldMap["JxPrice"] = 1 + + //TODO 2020-09-08 如果改价时商品在做直降,要取消这个商品的直降,再通过改价比例修改活动价,再上这个直降 + // checkActDirectDown(ctx, skuBind, beforeMsg) } } if skuBindInfo.StatusSaleBegin != 0 && skuBindInfo.StatusSaleEnd != 0 { @@ -1235,9 +1423,53 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs } dao.Commit(db) skuIDs := jxutils.IntMap2List(needSyncIDMap) + if isSyncSkus { + _, err = SyncSkus(ctx, nil, []int{model.VendorIDJD}, appCodeList, nil, skuIDs, true) + } return skuIDs, err } +// func checkActDirectDown(ctx *jxcontext.Context, skuBind *model.StoreSkuBind, beforeSkuBind tStoreSkuBindAndSpec) (err error) { +// var ( +// originPrice = beforeSkuBind.Price +// price = skuBind.Price +// db = dao.GetDB() +// pageSize = 9999 +// // percent = price / originPrice +// ) +// if paged, _ := dao.QueryActs(db, 0, 0, pageSize, -1, "", -1, []int{model.ActStatusCreated}, []int{model.ActSkuDirectDown}, nil, skuBind.StoreID, []int{skuBind.SkuID}, 0, utils.ZeroTimeValue, utils.ZeroTimeValue, time.Now().AddDate(0, -2, 0), time.Now()); len(paged.Data) > 0 { +// for _, act := range paged.Data { +// if _, actStoreSkus, err := dao.GetActStoreSkuVendorList(db, act.ID, nil, []int{skuBind.StoreID}, []int{skuBind.SkuID}, "", 0, pageSize); err == nil && len(actStoreSkus) > 0 { +// var ( +// handler = partner.GetPurchasePlatformFromVendorID(actStoreSkus[0].VendorID).(partner.IPurchasePlatformActHandler) +// actStoreSkuParam []*ActStoreSkuParam +// ) +// for _, actStoreSku := range actStoreSkus { +// aa := &ActStoreSkuParam{ +// ActStoreSku: model.ActStoreSku{ +// StoreID: skuBind.StoreID, +// SkuID: actStoreSku.SkuID, +// ActID: act.ID, +// }, +// } +// actStoreSkuParam = append(actStoreSkuParam, aa) +// } +// DeleteActStoreSkuBind(ctx, db, act.ID, actStoreSkuParam) +// actMap, err := dao.GetActVendorInfo(db, act.ID, []int{actStoreSkus[0].VendorID}) +// if err != nil { +// return err +// } +// actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, act.ID, nil, nil, nil) +// if err != nil { +// return err +// } +// handler.SyncAct(ctx, nil, actMap[actStoreSkus[0].VendorID], nil, actStoreSkuMap[actStoreSkus[0].VendorID]) +// } +// } +// } +// return err +// } + func getSkuSaleStatus(inSkuBind *StoreSkuBindSkuInfo, skuNameBindInfo *StoreSkuBindInfo) int { tempSale := 0 if inSkuBind != nil { @@ -1405,6 +1637,19 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co if copyMode != CopyStoreSkuModeFresh && copyMode != CopyStoreSkuModeUpdate && copyMode != CopyStoreSkuModeUpdatePrice { return 0, fmt.Errorf("不支持的拷贝模式:%s", copyMode) } + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + if storeIDsMap[fromStoreID] == 0 { + return 0, fmt.Errorf("抱歉,您无权更改他人店铺商品 [%v]", fromStoreID) + } + for _, v := range toStoreIDs { + if storeIDsMap[v] == 0 { + return 0, fmt.Errorf("抱歉,您无权更改他人店铺商品 [%v]", v) + } + } + } + } db := dao.GetDB() fromStore, err := checkStoreExisting(db, fromStoreID) if err != nil { @@ -1572,7 +1817,8 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co t1.status = IF(? = 0, t1.status, t0.status), t1.jd_sync_status = t1.jd_sync_status | ?, t1.mtwm_sync_status = t1.mtwm_sync_status | ?, - t1.ebai_sync_status = t1.ebai_sync_status | ? + t1.ebai_sync_status = t1.ebai_sync_status | ?, + t1.stock = t0.stock WHERE t1.store_id = ? AND t1.deleted_at = ? AND t0.id IS NOT NULL ` sqlParams := []interface{}{ @@ -1613,13 +1859,13 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co // 添加toStore中不存在,但fromStore存在的 sql = ` INSERT INTO store_sku_bind(created_at, updated_at, last_operator, deleted_at, store_id, sku_id, sub_store_id, price, jx_price, unit_price, status, - jd_sync_status, ebai_sync_status, mtwm_sync_status) + jd_sync_status, ebai_sync_status, mtwm_sync_status, stock) SELECT ?, ?, ?, ?, ?, t1.sku_id, 0, IF(t1.price * ? / 100 > 0, t1.price * ? / 100, 1) * ?, IF(t1.jx_price * ? / 100 > 0, t1.jx_price * ? / 100, 1) * ?, IF(t1.unit_price * ? / 100 > 0, t1.unit_price * ? / 100, 1) * ?, - IF(? = 0, ?, t1.status), ?, ?, ? + IF(? = 0, ?, t1.status), ?, ?, ?, t1.stock FROM store_sku_bind t1 JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? @@ -1684,6 +1930,41 @@ func CopyStoreSkus(ctx *jxcontext.Context, fromStoreID int, toStoreIDs []int, co } globals.SugarLogger.Debugf("CopyStoreSkus fromStoreID:%d, toStoreID:%d, trackInfo:%s num3:%d", fromStoreID, toStoreID, ctx.GetTrackInfo(), num2) dao.Commit(db) + + //同一商品若源门店的规格少于要复制到的门店,则在复制的门店里的其他规格的unitprice不会变, + //导致复制的门店的商品unitprice不尽相同,这里先处理一下 + type tStore struct { + NameID int `orm:"column(name_id)"` + StoreID int `orm:"column(store_id)"` + } + var resultList []*tStore + sql3 := ` + SELECT a.name_id, a.store_id FROM ( + SELECT DISTINCT a.unit_price, b.name_id, a.store_id FROM store_sku_bind a, sku b, store c + WHERE a.sku_id = b.id + AND c.id = a.store_id + AND c.deleted_at = ? + AND a.store_id = ? + AND a.deleted_at = ?)a + GROUP BY 1, 2 + HAVING COUNT(a.unit_price) > 1 + ` + sqlParams3 := []interface{}{utils.DefaultTimeValue, toStoreID, utils.DefaultTimeValue} + err = dao.GetRows(db, &resultList, sql3, sqlParams3) + if len(resultList) > 0 { + var skuBindInfos []*StoreSkuBindInfo + for _, v := range resultList { + storeSkus, _ := dao.GetStoreSkusByNameIDs(db, []int{v.StoreID}, v.NameID) + unitPirce := storeSkus[0].UnitPrice + skuBindInfo := &StoreSkuBindInfo{ + StoreID: v.StoreID, + NameID: v.NameID, + UnitPrice: int(unitPirce), + } + skuBindInfos = append(skuBindInfos, skuBindInfo) + } + _, err = updateStoresSkusWithoutSync(ctx, db, []int{toStoreID}, skuBindInfos, false, false) + } } if globals.IsAddEvent { mapAfter := make(map[string]interface{}) @@ -1851,7 +2132,7 @@ func AcceptStoreOpRequests(ctx *jxcontext.Context, reqIDs []int) (err error) { } } if err2 == nil { - _, err2 := UpdateStoresSkus(ctx, 0, []int{op.StoreID}, []*StoreSkuBindInfo{skuBindInfo}, false, false, false) + _, err2 := UpdateStoresSkus(ctx, 0, []int{op.StoreID}, []*StoreSkuBindInfo{skuBindInfo}, false, false, false, false) isLocalSucess := true if err2 != nil { subErrors[reqID] = err2 @@ -2067,7 +2348,7 @@ func RefreshStoresSkuByVendor(ctx *jxcontext.Context, storeIDs []int, vendorID i return "", fmt.Errorf("此功能当前只支持京东到家平台") } db := dao.GetDB() - storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMapList, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if err != nil { return "", err } @@ -2079,7 +2360,7 @@ func RefreshStoresSkuByVendor(ctx *jxcontext.Context, storeIDs []int, vendorID i if v.VendorID != vendorID { return "", fmt.Errorf("门店%d绑定的不(只)是京东", v.StoreID) } - storeMap[v.StoreID], err = dao.GetStoreDetail(db, v.StoreID, v.VendorID) + storeMap[v.StoreID], err = dao.GetStoreDetail(db, v.StoreID, v.VendorID, "") if err != nil { return "", err } @@ -2311,11 +2592,11 @@ func ReCalculateJxPrice(db *dao.DaoDB, ctx *jxcontext.Context, storeIDs []int) ( task := tasksch.NewParallelTask("刷新京西平台价格", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeID := batchItemList[0].(int) - if storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX); err == nil { + if storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX, ""); err == nil { if storeSkuList, err := dao.GetStoresSkusInfo(db, []int{storeID}, nil); err == nil { for _, skuBind := range storeSkuList { skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) - dao.UpdateEntity(db, skuBind) + dao.UpdateEntity(db, skuBind, "JxPrice") } } else { return nil, err @@ -2332,7 +2613,7 @@ func ReCalculateJxPrice(db *dao.DaoDB, ctx *jxcontext.Context, storeIDs []int) ( func ReCalculateJxPriceLight(db *dao.DaoDB, ctx *jxcontext.Context, storeID int) (err error) { if storeID != 0 { - if storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX); err == nil { + if storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX, ""); err == nil { if storeSkuList, err := dao.GetStoresSkusInfo(db, []int{storeID}, nil); err == nil { for _, skuBind := range storeSkuList { skuBind.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), skuBind.Price) @@ -2386,7 +2667,12 @@ func GetTopSkusByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (storeSkuNameE func GetTopSkusByCityCode(ctx *jxcontext.Context, cityCode, storeID int) (skuNameAndPlaceList []*dao.SkuNameAndPlace, err error) { db := dao.GetDB() orderCreate := time.Now().AddDate(0, -1, 0) - skuNameAndPlace, err := dao.GetTopSkusByCityCode(db, cityCode, orderCreate) + var skuNameAndPlace []*dao.SkuNameAndPlace + if cityCode > 0 { + skuNameAndPlace, err = dao.GetTopSkusByCityCode(db, cityCode, orderCreate) + } else { + skuNameAndPlace, err = dao.GetTopSkusByNoCityCode(db) + } if storeID > 0 { var skuNameList []*model.SkuName //不可售的商品nameID列表 @@ -2419,7 +2705,7 @@ func GetTopSkusByCityCode(ctx *jxcontext.Context, cityCode, storeID int) (skuNam for _, v := range skuNameList { skuNameMap[v.ID] = v } - store, err := dao.GetStoreDetail(db, storeID, -1) + store, err := dao.GetStoreDetail(db, storeID, -1, "") if err != nil { return nil, err } @@ -2536,7 +2822,7 @@ func RefershStoreSkusMidPrice(ctx *jxcontext.Context, storeIDs []int, isCountry } for _, v := range storeIDs { var skuBindInfos []*StoreSkuBindInfo - store, err := dao.GetStoreDetail(db, v, -1) + store, err := dao.GetStoreDetail(db, v, -1, "") if err != nil { return err } @@ -2570,7 +2856,7 @@ func RefershStoreSkusMidPrice(ctx *jxcontext.Context, storeIDs []int, isCountry } } } - updateStoresSkusWithoutSync(ctx, db, []int{v}, skuBindInfos, false) + updateStoresSkusWithoutSync(ctx, db, []int{v}, skuBindInfos, false, false) } if err == nil { CreateStorePriceScore(ctx) @@ -2712,7 +2998,7 @@ func RefreshJxPriceByExcelBin(ctx *jxcontext.Context, storeIDs []int, reader io. skuBindInfoList = append(skuBindInfoList, v.(*StoreSkuBindInfo)) } if isErr { - UpdateStoresSkus(ctx, 0, storeIDs, skuBindInfoList, false, isAsync, isContinueWhenError) + UpdateStoresSkus(ctx, 0, storeIDs, skuBindInfoList, false, false, isAsync, isContinueWhenError) } case 3: //写Excel @@ -2908,7 +3194,7 @@ func GetVendorStoreSkuPrice(ctx *jxcontext.Context, vendorIDs []int, skuID int, inStoreSku.SkuID = skuID } inStoreSkuList = append(inStoreSkuList, inStoreSku) - storeDetail2, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID) + storeDetail2, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID, "") if storeDetail2 != nil { outStoreSkuList, err = handler.GetStoreSkusBareInfo(ctx, v, task, storeDetail2.ID, vendorStoreID, inStoreSkuList) } else { @@ -3051,7 +3337,7 @@ func FocusStoreSkusByExcelBin(ctx *jxcontext.Context, reader io.Reader, isAsync, skuIDs = append(skuIDs, k) } skuList, err := dao.GetSkus(db, skuIDs, nil, nil, nil, nil) - storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") if err != nil && len(skuList) == 0 { return result, err } @@ -3159,7 +3445,12 @@ func FocusStoreSkusBySku(ctx *jxcontext.Context, skuBindInfos []*StoreSkuBindInf skuBindInfo := batchItemList[0].(*StoreSkuBindInfo) storeID := skuBindInfo.StoreID skuID := skuBindInfo.Skus[0].SkuID - store, err := dao.GetStoreDetail(db, storeID, -1) + store, err := dao.GetStoreDetail(db, storeID, -1, "") + if len(skuBindInfos) > 1 { + if store.StoreLevel == "D" || store.StoreLevel == "E" { + return retVal, err + } + } if err != nil { return retVal, err } @@ -3180,9 +3471,13 @@ func FocusStoreSkusBySku(ctx *jxcontext.Context, skuBindInfos []*StoreSkuBindInf } else { payPercentage = store.PayPercentage } - priceReferList, _ := dao.GetPriceReferSnapshotNoPage(db, []int{store.CityCode}, nil, []int{skuList[0].NameID}, utils.Time2Date(time.Now().AddDate(0, 0, -1))) + priceReferList, _ := dao.GetPriceReferSnapshotNoPage(db, []int{0}, nil, []int{skuList[0].NameID}, utils.Time2Date(time.Now().AddDate(0, 0, -1))) if len(priceReferList) > 0 { - price = priceReferList[0].MidUnitPrice / payPercentage * 100 + if payPercentage == 100 { + price = priceReferList[0].MidUnitPrice * payPercentage / 100 + } else { + price = priceReferList[0].MidUnitPrice / payPercentage * 100 + } } } skuBindSkuInfo := &StoreSkuBindSkuInfo{ @@ -3229,7 +3524,7 @@ func AutoFocusStoreSkusForTopSkus(ctx *jxcontext.Context, isAsync, isContinueWhe var ( result1 []interface{} ) - storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + storeList, err := dao.GetStoreList(db, nil, nil, nil, []int{1}, nil, "") taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: @@ -3265,7 +3560,8 @@ func AutoFocusStoreSkusForTopSkus(ctx *jxcontext.Context, isAsync, isContinueWhe for _, name := range skuName { skuNameMap[name.ID] = name.ID } - skuNameAndPlaceList, err2 := GetTopSkusByCityCode(ctx, v.CityCode, 0) + skuNameAndPlaceList, err2 := GetTopSkusByCityCode(ctx, 0, 0) + //skuNameAndPlaceList, err2 := GetTopSkusByCityCode(ctx, v.CityCode, 0) if err2 != nil { return retVal, err2 } @@ -3279,6 +3575,7 @@ func AutoFocusStoreSkusForTopSkus(ctx *jxcontext.Context, isAsync, isContinueWhe var skuBindInfoList []*StoreSkuBindInfo for _, vv := range skuNameAndPlaceList { if skuNameMap[vv.ID] != 0 { + globals.SugarLogger.Debugf("testAutoFocusStoreSkusForTopSkus,storeID:%v,nameID:%v", v.ID, vv.ID) storeSkuBindInfo := &StoreSkuBindInfo{ StoreID: v.ID, NameID: vv.ID, @@ -3325,7 +3622,7 @@ func AutoFocusStoreSkusWithoutFocus(ctx *jxcontext.Context, skuIDs []int, isSync nameMap = make(map[int]*StoreSkuBindInfo) ) db := dao.GetDB() - storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") for _, v := range storeList { storeSkuList, _ := dao.GetStoreSkusAndSkuName(db, []int{v.ID}, skuIDs, nil) for _, vv := range storeSkuList { @@ -3372,7 +3669,7 @@ func AutoFocusStoreSkusWithoutFocus(ctx *jxcontext.Context, skuIDs []int, isSync if isSync { UpdateStoreSkus(ctx, 0, v.StoreID, skuBindInfoList, true, true) } else { - updateStoresSkusWithoutSync(ctx, db, []int{v.StoreID}, skuBindInfoList, false) + updateStoresSkusWithoutSync(ctx, db, []int{v.StoreID}, skuBindInfoList, false, false) } } return err @@ -3437,23 +3734,32 @@ func UpdateStoreSkusSpecTagBin(ctx *jxcontext.Context, reader io.Reader, vendorI results[i] = results[len(results)-i-1] results[len(results)-i-1] = tmp } - for _, v := range results { - store, err := dao.GetStoreDetail(db, v.StoreID, model.VendorIDMTWM) - if err != nil || store == nil { - continue - } - food, err := api.MtwmAPI.RetailGet(store.VendorStoreID, utils.Int2Str(v.SkuID)) - if err != nil || food == nil { - continue - } - var foodData = make(map[string]interface{}) - if v.IsSpec != 0 && v.IsSpec == -1 { - v.IsSpec = 0 - } - foodData["is_specialty"] = v.IsSpec - foodData["price"] = food.Price - if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), store.VendorStoreID, utils.Int2Str(v.SkuID), foodData) + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + for _, v := range results { + if storeIDsMap[v.StoreID] == 0 { + continue + } + store, err := dao.GetStoreDetail(db, v.StoreID, model.VendorIDMTWM, "") + if err != nil || store == nil { + continue + } + mtapi := apimanager.CurAPIManager.GetAPI(model.VendorIDMTWM, store.VendorOrgCode).(*mtwmapi.API) + food, err := mtapi.RetailGet(store.VendorStoreID, utils.Int2Str(v.SkuID)) + if err != nil || food == nil { + continue + } + var foodData = make(map[string]interface{}) + if v.IsSpec != 0 && v.IsSpec == -1 { + v.IsSpec = 0 + } + foodData["is_specialty"] = v.IsSpec + foodData["price"] = food.Price + if globals.EnableMtwmStoreWrite { + err = mtapi.RetailInitData(ctx.GetTrackInfo(), store.VendorStoreID, utils.Int2Str(v.SkuID), foodData) + } + } } } } @@ -3479,7 +3785,7 @@ func SendSeckillSkusCountMsg(ctx *jxcontext.Context, vendorIDs []int, isAsync, i ddMsgresult []interface{} ) db := dao.GetDB() - storeList, err := dao.GetStoresMapList(db, vendorIDs, nil, []int{model.StoreStatusClosed, model.StoreStatusHaveRest, model.StoreStatusOpened}, model.StoreStatusOpened, model.StoreIsSyncAll, "") + storeList, err := dao.GetStoresMapList(db, vendorIDs, nil, []int{model.StoreStatusClosed, model.StoreStatusHaveRest, model.StoreStatusOpened}, model.StoreStatusOpened, model.StoreIsSyncAll, "", "", "") taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: @@ -3548,7 +3854,7 @@ func SendSeckillSkusCountMsg(ctx *jxcontext.Context, vendorIDs []int, isAsync, i } } if type1 < type1Count || type2 < type2Count { - storeDetail, _ := dao.GetStoreDetail(db, store.StoreID, store.VendorID) + storeDetail, _ := dao.GetStoreDetail(db, store.StoreID, store.VendorID, "") var ( type1Str = "爆品数量低于8个!" type2Str = "爆品价格小于1元的爆品数量低于5个!" @@ -3668,7 +3974,7 @@ func RefreshJxPriceByVendor(ctx *jxcontext.Context, jdStoreSkus []*JdStoreSkus, } else { return result, fmt.Errorf("没有找到该京东skuID对应的京西skuID!,京东skuID :[%v]", v.JdSkuID) } - store, err := dao.GetStoreDetailByVendorStoreID(db, utils.Int2Str(v.JdStoreID), vendorID) + store, err := dao.GetStoreDetailByVendorStoreID(db, utils.Int2Str(v.JdStoreID), vendorID, "") if err != nil || store == nil { return result, fmt.Errorf("没有找到该京东门店对应的京西门店!,京东门店ID :[%v]", v.JdStoreID) } @@ -3740,7 +4046,7 @@ func RefreshJxPriceByVendor(ctx *jxcontext.Context, jdStoreSkus []*JdStoreSkus, if len(skus) == 0 { continue } - store, _ := dao.GetStoreDetail(db, v.JdStoreID, vendorID) + store, _ := dao.GetStoreDetail(db, v.JdStoreID, vendorID, "") err = jxutils.Strings2Objs(store.PricePercentagePackStr, &pricePercentagePack) if skus[0].Unit == model.SpecialUnit { if skus[0].SpecUnit == model.SpecUnitNames[1] || skus[0].SpecUnit == model.SpecUnitNames[2] { @@ -3828,7 +4134,7 @@ func RefreshJxPriceByVendor2(ctx *jxcontext.Context, storeIDs []int, vendorID in pricePercentagePack []*model.PricePercentageItem skuNameMap = make(map[int]int64) ) - storeDetail, _ := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, _ := dao.GetStoreDetail(db, storeID, vendorID, "") err = jxutils.Strings2Objs(storeDetail.PricePercentagePackStr, &pricePercentagePack) if partner.IsMultiStore(vendorID) { mulitStoreSkuHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler) @@ -3925,14 +4231,10 @@ func BackUpStoreSkuBind(ctx *jxcontext.Context, isAsync, isContinueWhenError boo snapshotAt = utils.Time2Date(time.Now()) ) storeSkuBindHis := &model.StoreSkuBindHistory{ - SnapshotAt: snapshotAt.AddDate(0, 0, -2), - } - storeSkuBindHis2 := &model.StoreSkuBindHistory{ - SnapshotAt: snapshotAt, + SnapshotAt: snapshotAt.AddDate(0, 0, -5), } dao.DeleteEntity(db, storeSkuBindHis, "SnapshotAt") - dao.DeleteEntity(db, storeSkuBindHis2, "SnapshotAt") - storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") task := tasksch.NewParallelTask("BackUpStoreSkuBind", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { store := batchItemList[0].(*model.Store) @@ -4076,7 +4378,7 @@ func RefreshMatterStock(ctx *jxcontext.Context, skuID int) (err error) { } } //物料店666666 - updateStoresSkusWithoutSync(ctx, db, []int{666666}, skuBindInfos, false) + updateStoresSkusWithoutSync(ctx, db, []int{666666}, skuBindInfos, false, false) return err } @@ -4089,7 +4391,7 @@ func buildStoreSkuBindInfosAndFocus(ctx *jxcontext.Context, db *dao.DaoDB, store skus, _ := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil) err = jxutils.Strings2Objs(store.PricePercentagePackStr, &pricePercentagePack) price := jxutils.CaculateJxPriceByPricePack(pricePercentagePack, 0, int(v.SkuList[0].VendorPrice)) - store2, _ := dao.GetStoreDetail(db, store.ID, model.VendorIDJX) + store2, _ := dao.GetStoreDetail(db, store.ID, model.VendorIDJX, "") if store2 != nil { err = jxutils.Strings2Objs(store2.PricePercentagePackStr, &pricePercentagePack2) jxPrice = jxutils.CaculatePriceByPricePack(pricePercentagePack2, 0, price) @@ -4145,6 +4447,20 @@ func CreateSkusAndFocusFromWx(ctx *jxcontext.Context, productInfo *jdapi.Product return err } if len(skuNames) == 0 { + if productInfo.Name == "" { + var originName string + if strings.Contains(productInfo.OriginalName, upcSpecName1) { + originName = strings.ReplaceAll(productInfo.OriginalName, upcSpecName1, "") + } + if strings.Contains(productInfo.OriginalName, "*") { + originName = strings.ReplaceAll(productInfo.OriginalName, "*", "") + } + _, name, _, specUnit, unit, specQuality := jxutils.SplitSkuName(originName) + productInfo.Name = name + productInfo.SpecQuality = specQuality + productInfo.Unit = unit + productInfo.SpecUnit = specUnit + } skuNames2, err := dao.GetSkuNames(db, nil, nil, productInfo.Name, false) if err != nil { return err @@ -4247,7 +4563,6 @@ func SyncMatterC4ToGy(ctx *jxcontext.Context, isContinueWhenError, isAsync bool) updateMatters = append(updateMatters, skusMap[c4.EclpID]) } } - fmt.Println("updateMatters", utils.Format4Output(updateMatters, false)) case 1: if len(deleteMatters) > 0 { for _, v := range deleteMatters { @@ -4424,7 +4739,7 @@ func focusC4Matters(ctx *jxcontext.Context, db *dao.DaoDB, v *model.Sku) (err er } skuBindInfos = append(skuBindInfos, skuBindInfo) } - updateStoresSkusWithoutSync(ctx, db, []int{model.MatterStoreID}, skuBindInfos, false) + updateStoresSkusWithoutSync(ctx, db, []int{model.MatterStoreID}, skuBindInfos, false, false) } return err } @@ -4442,3 +4757,487 @@ func RefreshJdsSkusStatus(ctx *jxcontext.Context) (err error) { } return err } + +func GetStoreSkuAudit(ctx *jxcontext.Context, storeIDs, nameIDs, skuIDs, statuss, types []int, name, remark, keyword, cityName, marketManPhone, applyTimeStart, applyTimeEnd, auditTimeStart, auditTimeEnd string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) { + var ( + applyTimeStartp, applyTimeEndp, auditTimeStartp, auditTimeEndp time.Time + ) + if applyTimeStart != "" { + applyTimeStartp = utils.Str2Time(applyTimeStart) + } + if applyTimeEnd != "" { + applyTimeEndp = utils.Str2Time(applyTimeEnd) + } + if auditTimeStart != "" { + auditTimeStartp = utils.Str2Time(auditTimeStart) + } + if auditTimeEnd != "" { + auditTimeEndp = utils.Str2Time(auditTimeEnd) + } + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } + pagedInfo, err = dao.GetStoreSkuAudit(dao.GetDB(), storeIDs, nameIDs, skuIDs, statuss, types, name, remark, keyword, marketManPhone, cityName, applyTimeStartp, applyTimeEndp, auditTimeStartp, auditTimeEndp, pageSize, offset) + return pagedInfo, err +} + +func doStoreSkuAudit(ctx *jxcontext.Context, storeIDs []int, skuBindInfos []*StoreSkuBindInfo) (isAudit bool, err error) { + globals.SugarLogger.Debugf("doStoreSkuAudit storeIDs: %v", storeIDs) + time.Sleep(time.Second / 5) + db := dao.GetDB() + for _, storeID := range storeIDs { + stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") + //扣点的门店改价不进审核 + if len(stores) > 0 { + if stores[0].PayPercentage <= 50 || stores[0].StoreLevel == "E" || stores[0].StoreLevel == "D" { + globals.SugarLogger.Debugf("doStoreSkuAudit return0 storeID : %v", storeID) + return false, err + } + } + for _, skuBindInfo := range skuBindInfos { + globals.SugarLogger.Debugf("doStoreSkuAudit storeID: %v , nameID: %v", storeID, skuBindInfo.NameID) + storeAudits, err := dao.GetStoreSkuAuditLight(db, []int{storeID}, []int{skuBindInfo.NameID}, model.StoreAuditStatusOnline) + //取消关注,可售排除 + if skuBindInfo.IsFocus == -1 || skuBindInfo.IsSale != 0 || skuBindInfo.UnitPrice == 0 { + globals.SugarLogger.Debugf("doStoreSkuAudit return1 storeID : %v nameID: %v", storeID, skuBindInfo.NameID) + return false, err + } + + if ctx.GetLoginType() != weixin.AuthTypeMP && ctx.GetLoginType() != weixin.AuthTypeMini && ctx.GetLoginType() != weixin.AuthTypeWxApp && ctx.GetLoginType() != auth2.AuthTypeMobile { + globals.SugarLogger.Debugf("doStoreSkuAudit return3 storeID : %v loginType: %v", storeID, ctx.GetLoginType()) + authInfo, err := ctx.GetV2AuthInfo() + if err == nil && authInfo != nil && (ctx.GetFullUser().Type&model.UserTypeOperator) != 0 { + if len(storeAudits) > 0 { + storeAudits[0].DeletedAt = time.Now() + dao.UpdateEntity(db, storeAudits[0], "DeletedAt") + // if globals.IsProductEnv() { + // skuAndNames, err := dao.GetSkus(db, nil, []int{skuBindInfo.NameID}, nil, nil, nil) + // if len(skuAndNames) > 0 && err == nil { + // weixinmsg.NotifyStoreOpRequestStatus(true, storeID, skuBindInfo.NameID, jxutils.ComposeSpuName(skuAndNames[0].Prefix, skuAndNames[0].Name, 0), storeAudits[0].OriginUnitPrice, skuBindInfo.UnitPrice, "") + // } + // } + } + globals.SugarLogger.Debugf("doStoreSkuAudit return3 storeID : %v nameID: %v", storeID, skuBindInfo.NameID) + return false, err + } + } + storeSkuAudit := &model.StoreSkuAudit{ + StoreID: storeID, + NameID: skuBindInfo.NameID, + Status: model.StoreAuditStatusOnline, + UnitPrice: skuBindInfo.UnitPrice, + } + //如果是关注改价 + if skuBindInfo.IsFocus == 1 { + if len(storeAudits) > 0 { + storeAudits[0].DeletedAt = time.Now() + dao.UpdateEntity(db, storeAudits[0], "DeletedAt") + } + storeSkuAudit.Type = model.StoreSkuAuditTypeFocus + } else { + storeSkus, err := dao.GetStoreSkusByNameIDs(db, []int{storeID}, skuBindInfo.NameID) + if len(storeSkus) > 0 { + //如果改的价比原价低排除 + if skuBindInfo.UnitPrice <= int(storeSkus[0].UnitPrice) { + if len(storeAudits) > 0 { + storeAudits[0].DeletedAt = time.Now() + dao.UpdateEntity(db, storeAudits[0], "DeletedAt") + } + globals.SugarLogger.Debugf("doStoreSkuAudit return4 storeID : %v nameID: %v", storeID, skuBindInfo.NameID) + return false, err + } else { + if len(storeAudits) > 0 { + storeAudits[0].DeletedAt = time.Now() + dao.UpdateEntity(db, storeAudits[0], "DeletedAt") + } + globals.SugarLogger.Debugf("doStoreSkuAudit cover storeID : %v nameID: %v", storeID, skuBindInfo.NameID) + } + } else { + return false, fmt.Errorf("未查询到该门店商品价,storeID: %v, nameID: %V", storeID, skuBindInfo.NameID) + } + storeSkuAudit.Type = model.StoreSkuAuditTypePrice + storeSkuAudit.OriginUnitPrice = int(storeSkus[0].UnitPrice) + } + dao.WrapAddIDCULDEntity(storeSkuAudit, ctx.GetUserName()) + err = dao.CreateEntity(db, storeSkuAudit) + } + } + return true, err +} + +func StoreSkuPriceAudit(ctx *jxcontext.Context, storeSkuAudits []*model.StoreSkuAudit, status int, isAsync, isContinueWhenError bool) (storeSkuAudits2 []*model.StoreSkuAudit, hint string, err error) { + db := dao.GetDB() + if status == model.StoreAuditStatusOnline { + return nil, "", fmt.Errorf("审核标志不正确!") + } + //证明是预审核 + if status == 2 { + for _, v := range storeSkuAudits { + skuList, _ := dao.GetStoreSkusByNameIDs(db, []int{v.StoreID}, v.NameID) + if len(skuList) > 0 { + if int64(v.AuditPrice) > skuList[0].UnitPrice*2 { + storeSkuAudits2 = append(storeSkuAudits2, v) + } + } + } + return storeSkuAudits2, "", err + } + deletedDuplicateWaitAuditData(ctx, db) + task := tasksch.NewParallelTask("StoreSkuPriceAudit", tasksch.NewParallelConfig().SetParallelCount(5).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeAudit := batchItemList[0].(*model.StoreSkuAudit) + storeAudits, err := dao.GetStoreSkuAuditLight(db, []int{storeAudit.StoreID}, []int{storeAudit.NameID}, model.StoreAuditStatusOnline) + if len(storeAudits) == 0 || err != nil { + return retVal, err + } + if len(storeAudits) > 1 { + return retVal, fmt.Errorf("查询到该门店该商品的待审核信息大于1条!storeID: %v, nameID: %v", storeAudit.StoreID, storeAudit.NameID) + } + //审核通过 + if status == model.StoreAuditStatusCreated { + storeAudits[0].UserID = ctx.GetUserID() + storeAudits[0].Status = model.StoreAuditStatusCreated + storeAudits[0].Remark = storeAudit.Remark + storeAudits[0].AuditPrice = storeAudit.AuditPrice + _, err = dao.UpdateEntity(db, storeAudits[0], "UserID", "Status", "Remark", "AuditPrice") + var skuBindInfos = []*StoreSkuBindInfo{ + &StoreSkuBindInfo{ + NameID: storeAudit.NameID, + UnitPrice: storeAudits[0].UnitPrice, + }, + } + //证明填了额外的审核价格 + if storeAudit.AuditPrice != 0 { + skuBindInfos[0].UnitPrice = storeAudit.AuditPrice + } + //如果是关注改价 + if storeAudits[0].Type == model.StoreSkuAuditTypeFocus { + skuBindInfos[0].IsFocus = 1 + } + var num int64 + db := dao.GetDB() + skuIDs, err := updateStoresSkusWithoutSync(ctx, db, []int{storeAudit.StoreID}, skuBindInfos, false, false) + if err != nil { + return "", err + } + isAsync = asyncStoreSkuOpFilter(ctx, isAsync) + num = int64(len(skuIDs)) + if num > 0 { + hint, err = CurVendorSync.SyncStoresSkus(ctx, nil, 0, db, nil, []int{storeAudit.StoreID}, skuIDs, false, isAsync, isContinueWhenError) + } + if num == 0 || !isAsync || hint == "" { + hint = utils.Int64ToStr(num) + } + } else if status == model.StoreAuditStatusRejected { + storeAudits[0].UserID = ctx.GetUserID() + storeAudits[0].Status = model.StoreAuditStatusRejected + storeAudits[0].Remark = storeAudit.Remark + _, err = dao.UpdateEntity(db, storeAudits[0], "UserID", "Status", "Remark") + } else { + return retVal, fmt.Errorf("审核标志不正确!") + } + //TODO 暂时先不推消息了 + if err == nil { + // if globals.IsProductEnv() { + // skuAndNames, err := dao.GetSkus(db, nil, []int{storeAudit.NameID}, nil, nil, nil) + // if len(skuAndNames) > 0 && err == nil { + // price := 0 + // if storeAudit.AuditPrice != 0 { + // price = storeAudit.AuditPrice + // } else { + // price = storeAudits[0].UnitPrice + // } + // weixinmsg.NotifyStoreOpRequestStatus(flag, storeAudit.StoreID, storeAudit.NameID, jxutils.ComposeSpuName(skuAndNames[0].Prefix, skuAndNames[0].Name, 0), storeAudits[0].OriginUnitPrice, price, storeAudit.Remark) + // } + // } + } + return retVal, err + }, storeSkuAudits) + tasksch.HandleTask(task, nil, true).Run() + if isAsync { + hint = task.GetID() + } else { + _, err = task.GetResult(0) + hint = "1" + } + return nil, hint, err +} + +func deletedDuplicateWaitAuditData(ctx *jxcontext.Context, db *dao.DaoDB) { + var ( + duplicateDatas []*model.StoreSkuAudit + duplicateStore = make(map[int][]*model.StoreSkuAudit) + ) + sql := ` + SELECT a.* + FROM store_sku_audit a , + ( + SELECT count(*), store_id ,name_id ,status, deleted_at + FROM store_sku_audit + WHERE status = 0 + AND deleted_at = ? + GROUP BY 2,3,4,5 + HAVING count(*) > 1 + ) b + WHERE a.store_id = b.store_id + AND a.name_id = b.name_id + AND a.status= b.status + AND a.deleted_at = b.deleted_at + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + dao.GetRows(db, &duplicateDatas, sql, sqlParams) + for _, v := range duplicateDatas { + duplicateStore[v.StoreID] = append(duplicateStore[v.StoreID], v) + } + for _, v := range duplicateStore { + duplicateSkuName := make(map[int][]*model.StoreSkuAudit) + for _, vv := range v { + duplicateSkuName[vv.NameID] = append(duplicateSkuName[vv.NameID], vv) + } + for _, vv := range duplicateSkuName { + for i := 0; i < len(vv)-1; i++ { + dao.DeleteEntity(db, vv[i]) + } + } + } +} + +func GetSpecialtyStoreSkus(ctx *jxcontext.Context, storeIDs, vendorIDs []int) (err error) { + type SpecialtyStoreSkus struct { + StoreID int `json:"门店ID"` + StoreName string `json:"门店名"` + SkuID int `json:"SkuID"` + SkuName string `json:"商品名"` + Price float64 `json:"平台价"` + VendorName string `json:"平台名"` + } + var ( + db = dao.GetDB() + specialtyStoreSkus []*SpecialtyStoreSkus + excelTitle = []string{ + "门店ID", + "门店名", + "SkuID", + "商品名", + "平台价", + "平台名", + } + sheetList []*excel.Obj2ExcelSheetConfig + downloadURL, fileName string + ) + for _, v := range vendorIDs { + for _, vv := range storeIDs { + storeDetail, err := dao.GetStoreDetail(db, vv, v, "") + if err != nil || storeDetail == nil { + continue + } + if partner.IsMultiStore(v) { + var ( + page = 1 + vendorSkuIDs []string + ) + _, totalCount, _ := api.JdPageAPI.GetJdTopSkus(storeDetail.VendorStoreID, page) + for ; page < totalCount/10+1; page++ { + result, _, _ := api.JdPageAPI.GetJdTopSkus(storeDetail.VendorStoreID, page) + vendorSkuIDs = append(vendorSkuIDs, result...) + } + for _, vvv := range vendorSkuIDs { + thingMap := &model.ThingMap{} + sql := ` + SELECT * FROM thing_map WHERE thing_type = 3 AND vendor_thing_id = ? AND vendor_org_code = 320406 + AND deleted_at = ? + ` + sqlParams := []interface{}{ + vvv, utils.DefaultTimeValue, + } + dao.GetRow(db, &thingMap, sql, sqlParams) + skus, _ := dao.GetSkus(db, []int{int(thingMap.ThingID)}, nil, nil, nil, nil) + specialtyStoreSku := &SpecialtyStoreSkus{ + StoreID: vv, + StoreName: storeDetail.Name, + SkuID: int(thingMap.ThingID), + SkuName: skus[0].Name, + Price: 0, + VendorName: model.VendorNames[v], + } + specialtyStoreSkus = append(specialtyStoreSkus, specialtyStoreSku) + } + } else { + handler := partner.GetPurchasePlatformFromVendorID(v).(partner.ISingleStoreStoreSkuHandler) + skuList, _ := handler.GetStoreSkusFullInfo(ctx, nil, vv, storeDetail.VendorStoreID, nil) + for _, sku := range skuList { + if sku.SkuList[0].IsSpecialty == model.YES { + specialtyStoreSku := &SpecialtyStoreSkus{ + StoreID: vv, + StoreName: storeDetail.Name, + SkuID: sku.SkuList[0].SkuID, + SkuName: sku.Name, + Price: float64(sku.SkuList[0].VendorPrice) / 100, + VendorName: model.VendorNames[v], + } + specialtyStoreSkus = append(specialtyStoreSkus, specialtyStoreSku) + } + } + } + } + } + excelConf := &excel.Obj2ExcelSheetConfig{ + Title: "sheet1", + Data: specialtyStoreSkus, + CaptionList: excelTitle, + } + sheetList = append(sheetList, excelConf) + if excelConf != nil { + downloadURL, fileName, err = jxutils.UploadExeclAndPushMsg(sheetList, "力荐或置顶商品") + } else { + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess is nil!") + } + if err != nil { + baseapi.SugarLogger.Errorf("WriteToExcel:upload %s , %s failed error:%v", fileName, err) + } else { + noticeMsg := fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, ctx.GetUserID(), "异步任务完成", noticeMsg) + baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess downloadURL: [%v]", downloadURL) + } + return err +} + +func checkActUpdate(actID int, actMap map[int]*model.Act2) (err error) { + if len(actMap) == 0 { + return fmt.Errorf("活动%d不存在或已被取消", actID) + } + errList := errlist.New() + for vendorID, act := range actMap { + if vendorID == model.VendorIDEBAI && act.CreateType != model.ActCreateTypeAPI { + errList.AddErr(fmt.Errorf("饿百平台不支持修改或取消网页活动")) + } + } + return errList.GetErrListAsOne() +} + +func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSkuParam []*ActStoreSkuParam) (originSyncStatus int8, err error) { + actMap, err := dao.GetActVendorInfo(db, actID, nil) + if err != nil { + return 0, err + } + if err = checkActUpdate(actID, actMap); err != nil { + return 0, err + } + + actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil) + if err != nil { + return 0, err + } + act := actMap[partner.GetVendorIDsFromActMap(actMap)[0]] + if act.Status != model.ActStatusCreated || time.Now().Sub(act.EndAt) > 0 { + return 0, fmt.Errorf("当前活动状态:%s,不能进行此操作,或已过期", model.ActStatusName[act.Status]) + } + + dao.Begin(db) + defer func() { + if r := recover(); r != nil || err != nil { + dao.Rollback(db) + if r != nil { + panic(r) + } + } + }() + actStoreSkuParamMap := make(map[int64]*ActStoreSkuParam) + for _, v := range actStoreSkuParam { + actStoreSkuParamMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v + if _, err = dao.DeleteEntityLogically(db, &model.ActStoreSku{}, nil, ctx.GetUserName(), + map[string]interface{}{ + model.FieldActID: actID, + model.FieldStoreID: v.StoreID, + model.FieldSkuID: v.SkuID, + }); err != nil { + return 0, err + } + } + + isNeedCancelAct := true + for vendorID, act := range actMap { + originSyncStatus |= act.SyncStatus + isDeleteAll := true + isDeleteAtLeastOne := false + if true { //actStoreSkuParam != nil { + actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuMap[vendorID]) + for storeID := range actStoreSkuMap { + for _, actStoreSku := range actStoreSkuMap[storeID] { + if actStoreSkuParam == nil || actStoreSkuParamMap[jxutils.Combine2Int(actStoreSku.StoreID, actStoreSku.SkuID)] != nil { + if act.Type == model.ActSkuFake { + _, err = dao.DeleteEntityLogically(db, &model.ActStoreSkuMap{}, nil, ctx.GetUserName(), + map[string]interface{}{ + model.FieldActID: actID, + model.FieldStoreID: actStoreSku.StoreID, + model.FieldSkuID: actStoreSku.SkuID, + }) + } else { + _, err = dao.UpdateEntityLogically(db, partner.ActStoreSku2ActStoreSkuMap(actStoreSku), + map[string]interface{}{ + model.FieldSyncStatus: actStoreSku.SyncStatus | model.SyncFlagDeletedMask, + }, ctx.GetUserName(), nil) + } + if err != nil { + return 0, err + } + isDeleteAtLeastOne = true + } else { + isNeedCancelAct = false + isDeleteAll = false + } + } + } + } else { + isDeleteAll = true + isDeleteAtLeastOne = true + } + if isDeleteAll || isDeleteAtLeastOne { + syncStatus := int8(model.SyncFlagModifiedMask) + if isDeleteAll { + syncStatus = model.SyncFlagDeletedMask + } + syncStatus |= act.SyncStatus + if act.Type != model.ActSkuFake && vendorID != model.VendorIDJX { + if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act), + map[string]interface{}{ + model.FieldSyncStatus: syncStatus, + }, ctx.GetUserName(), nil); err != nil { + return 0, err + } + } + } + if isDeleteAll != isNeedCancelAct { + globals.SugarLogger.Warnf("deleteActStoreBind, actID:%d isDeleteAll:%t != isNeedCancelAct:%t", act.ID, isDeleteAll, isNeedCancelAct) + } + } + + if isNeedCancelAct { + act := &model.Act{} + act.ID = actID + if _, err = dao.UpdateEntityLogically(db, act, + map[string]interface{}{ + model.FieldStatus: model.ActStatusCanceled, + }, ctx.GetUserName(), nil); err != nil { + return 0, err + } + } + dao.Commit(db) + return originSyncStatus, err +} diff --git a/business/jxstore/cms/store_sku_check.go b/business/jxstore/cms/store_sku_check.go index af4fe0995..5156a193d 100644 --- a/business/jxstore/cms/store_sku_check.go +++ b/business/jxstore/cms/store_sku_check.go @@ -6,6 +6,10 @@ import ( "sync" "time" + "git.rosy.net.cn/baseapi/platformapi/dingdingapi" + "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" + "github.com/astaxie/beego" + "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/baseapi" @@ -22,7 +26,7 @@ import ( const ( canWriteTolocal = false - needStatistic = true + needStatistic = false isFilterToBeCreateAndNotSale = true parallelCount = 5 fileExt = ".xlsx" @@ -30,14 +34,16 @@ const ( //错误类型 const ( - DatAanalyse1 = "京西门店未关注,应删除对应的平台门店商品" - DatAanalyse2 = "平台商品库未创建成功(可能无经营许可等) " - DatAanalyse3 = "商品名不同 " - DatAanalyse4 = "商品可售状态不同 " - DatAanalyse5 = "京西商品库没有,平台商品库有 " - DatAanalyse6 = "京西商品库有,平台商品库没有" - DatAanalyse7 = "同步状态异常" - DatAanalyse8 = "平台门店未关注或平台门店商品库存为0,应添加对应的平台门店商品" + DatAanalyse1 = "京西门店未关注,应删除对应的平台门店商品" + DatAanalyse2 = "平台商品库未创建成功(可能无经营许可等) " + DatAanalyse3 = "商品名不同 " + DatAanalyse4 = "商品可售状态不同 " + DatAanalyse5 = "京西商品库没有,平台商品库有 " + DatAanalyse6 = "京西商品库有,平台商品库没有" + DatAanalyse7 = "同步状态异常" + DatAanalyse8 = "平台门店未关注或平台门店商品库存为0,应添加对应的平台门店商品" + DatAanalyse9 = "平台门店价格与京西商品库价格不一致" + DatAanalyse10 = "平台商品的VendorSkuID与京西的VendorSkuID不一致" ) var ( @@ -55,6 +61,8 @@ var ( "平台门店ID", "门店名", "SkuID", + "京西美团外卖ID", + "京西饿百ID", "同步状态", "待创建", "待删除", @@ -62,6 +70,8 @@ var ( "平台商品名", "京西可售状态", "平台可售状态", + "京西价格", + "平台价格", "数据分析", } @@ -129,6 +139,8 @@ type DiffData struct { VendorStoreID string `json:"平台门店ID"` VendorStoreName string `json:"门店名"` SkuID string `json:"SkuID"` + MtwmID string `json:"京西美团外卖ID"` + EbaiID string `json:"京西饿百ID"` SyncStatus string `json:"同步状态"` ToBeCreate string `json:"待创建"` ToBeDel string `json:"待删除"` @@ -136,6 +148,8 @@ type DiffData struct { VendorSkuName string `json:"平台商品名"` JxStatus string `json:"京西可售状态"` VendorStatus string `json:"平台可售状态"` + JxSkuPrice string `json:"京西价格"` /*哇,不能小写,不然会搞事情*/ + VendorPrice string `json:"平台价格"` DatAanalyse string `json:"数据分析"` } @@ -216,7 +230,13 @@ func GetMultiStoreAllSkuInfo(ctx *jxcontext.Context, vendorMap map[int]bool) { if err != nil { baseapi.SugarLogger.Errorf("GetMultiStoreAllSkuInfo error:%v", err) } else { - multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = StoreSkuFullList2BareFilter(allSkuNameInfoList) //map[平台ID:[]StoreSkuInfo1,StoreSkuInfo2...] + if multiStoreAllSkuInfoList[vendorID] != nil { + multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = StoreSkuFullList2BareFilter(allSkuNameInfoList) //map[平台ID:[]StoreSkuInfo1,StoreSkuInfo2...] + } else { + multiStoreAllSkuInfoList = make(map[int]map[string][]*partner.StoreSkuInfo) + multiStoreAllSkuInfoList[vendorID] = make(map[string][]*partner.StoreSkuInfo) + multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = StoreSkuFullList2BareFilter(allSkuNameInfoList) //map[平台ID:[]StoreSkuInfo1,StoreSkuInfo2...] + } tempMap := make(map[int]*partner.SkuNameInfo) for _, value := range allSkuNameInfoList { for _, skuInfo := range value.SkuList { @@ -332,24 +352,27 @@ func IsSkuCanSale(saleStatus int) bool { } //京西平台和其他平台商品的对比 -//storeIDStr 京西商家id ,vendorStoreID 平台商家id -func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName string, filterJxSkuInfoMap map[int]*dao.StoreSkuNameExt, filterVendorSkuInfoMap map[int]*partner.SkuNameInfo) { +//storeIDStr 京西商家id ,vendorStoreID 平台商家id ,isJd 京东比较的标记 0不是,1是 +func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName string, filterJxSkuInfoMap map[int]*dao.StoreSkuNameExt, filterVendorSkuInfoMap map[int]*partner.SkuNameInfo, isJd int) { + //utils.Writelog("进入 CompareJxAndVendor 方法") for skuID, jxSkuInfo := range filterJxSkuInfoMap { skuIDStr := utils.Int2Str(skuID) + /*写京西skuIDStr*/ + //utils.Writelog("skuIDStr" + skuIDStr) var jxSkuDetailName string - //多规格商品不用比较数量单位 - if jxSkuInfo.IsSpu == 0 { - //jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..) - jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, jxSkuInfo.SkuName.Unit, jxSkuInfo.Skus[0].SkuSpecQuality, jxSkuInfo.Skus[0].SkuSpecUnit, 0) - } else { - //jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..) - jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, "", jxSkuInfo.Skus[0].SkuSpecQuality, "", 0) - } - + //jxSkuDetailName : 前缀 ([荐]) + 分类名(xxx水饺) + 数量单位(约..g/份) + 注释 (补充..) + jxSkuDetailName = jxutils.ComposeSkuNameOriginal(jxSkuInfo.SkuName.Prefix, jxSkuInfo.SkuName.Name, jxSkuInfo.Skus[0].Comment, jxSkuInfo.SkuName.Unit, jxSkuInfo.Skus[0].SkuSpecQuality, jxSkuInfo.Skus[0].SkuSpecUnit, 0) + //utils.Writelog("jxSkuDetailName:" + jxSkuDetailName) //jxSkuSaleStatus : 商品状态 ,skustatus 优先级高于 StoreSkuStatus jxSkuSaleStatus := jxutils.MergeSkuStatus(jxSkuInfo.Skus[0].SkuStatus, jxSkuInfo.Skus[0].StoreSkuStatus) - jxSkuSaleStatusName := GetSkuSaleStatusName(jxSkuSaleStatus) - + jxSkuSaleStatusName := GetSkuSaleStatusName(jxSkuSaleStatus + 3) + /*京西价格*/ + jxSkuPrice := fmt.Sprintf("%.2f", float64(jxSkuInfo.Skus[0].JxPrice)/float64(100)) + /*饿了吗编码*/ + ebaiid := jxSkuInfo.Skus[0].EbaiID + /*美团编码*/ + mtwmid := jxSkuInfo.Skus[0].MtwmID + //jxSkuPrice := strconv.Itoa(jxSkuInfo.Skus[0].JxPrice) vendorSkuInfo := filterVendorSkuInfoMap[skuID] var status int8 if vendorID == model.VendorIDMTWM { @@ -365,14 +388,25 @@ func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName strin if vendorSkuInfo != nil { vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName - vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status) - + vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status + 3) + /* 供货商价格 */ + vendorPrice := fmt.Sprintf("%.2f", float64(vendorSkuInfo.SkuList[0].StoreSkuInfo.VendorPrice)/float64(100)) + var IdMark bool + if isJd == 0 { + IdMark = skuIDStr != ebaiid && skuIDStr != mtwmid + } else { + IdMark = false + } isSaleStatusDiff := jxSkuSaleStatusName != vendorSkuSaleStatusName isNameDiff := jxSkuDetailName != vendorSkuDetailName + /*比较价格*/ + isPriceDiff := vendorPrice != jxSkuPrice + //utils.Writelog("isSaleStatusDiff:" + strconv.FormatBool(isSaleStatusDiff)) + //utils.Writelog("isNameDiff:" + strconv.FormatBool(isNameDiff)) if jxSkuDetailName != "" && vendorSkuDetailName != "" && strings.Contains(jxSkuDetailName, vendorSkuDetailName) { isNameDiff = false } - if isSaleStatusDiff || isNameDiff { + if isSaleStatusDiff || isNameDiff || isPriceDiff { reason := "" if isNameDiff { reason += DatAanalyse3 @@ -380,15 +414,21 @@ func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName strin if isSaleStatusDiff { reason += DatAanalyse4 } + if isPriceDiff { + reason += DatAanalyse9 + } + if IdMark { + reason += DatAanalyse10 + } if status != model.SkuStatusDontSale { reason += DatAanalyse7 } - outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, reason} + outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, mtwmid, ebaiid, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, jxSkuPrice, vendorPrice, reason} diffData.AppendData(vendorID, outPutData) } if !isSaleStatusDiff && !isNameDiff { if status != model.SkuStatusDontSale { - outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, DatAanalyse7} + outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, mtwmid, ebaiid, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, vendorSkuDetailName, jxSkuSaleStatusName, vendorSkuSaleStatusName, jxSkuPrice, vendorPrice, DatAanalyse7} diffData.AppendData(vendorID, outPutData) } } @@ -405,7 +445,7 @@ func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName strin if status != model.SkuStatusDontSale { reason += DatAanalyse7 } - outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, "", jxSkuSaleStatusName, "", reason} + outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, mtwmid, ebaiid, syncStatus, toBeCreate, toBeDel, jxSkuDetailName, "", jxSkuSaleStatusName, "", jxSkuPrice, "", reason} diffData.AppendData(vendorID, outPutData) } } @@ -414,18 +454,21 @@ func CompareJxAndVendor(vendorID int, storeIDStr, vendorStoreID, storeName strin if len(vendorSkuInfo.SkuList) > 0 { skuIDStr := utils.Int2Str(skuID) vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName - vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status) - + vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status + 3) + /* 供货商价格 */ + vendorPrice := fmt.Sprintf("%.2f", float64(vendorSkuInfo.SkuList[0].StoreSkuInfo.VendorPrice)/float64(100)) + /* 供货商价格 */ jxSkuInfo := filterJxSkuInfoMap[skuID] + /*平台有,京西没有*/ if jxSkuInfo == nil { - outPutData := DiffData{storeIDStr, vendorStoreID, storeName, skuIDStr, "", "", "", "", vendorSkuDetailName, "", vendorSkuSaleStatusName, DatAanalyse1} + outPutData := DiffData{storeIDStr, vendorStoreID, "", "", storeName, skuIDStr, "", "", "", "", vendorSkuDetailName, "", vendorSkuSaleStatusName, "", vendorPrice, DatAanalyse1} diffData.AppendData(vendorID, outPutData) } } else { - globals.SugarLogger.Warnf("CompareJxAndVendor vendorSkuInfo.SkuList:%d is nil", skuID) + globals.SugarLogger.Debugf("CompareJxAndVendor vendorSkuInfo.SkuList:%d is nil", skuID) } } else { - globals.SugarLogger.Warnf("CompareJxAndVendor skuID:%d is nil", skuID) + globals.SugarLogger.Debugf("CompareJxAndVendor skuID:%d is nil", skuID) } } } @@ -497,7 +540,7 @@ func CompareJxAndMultiVenderDepot(ctx *jxcontext.Context, vendorMap map[int]bool if len(vendorSkuInfo.SkuList) > 0 { skuIDStr := utils.Int2Str(skuID) vendorSkuDetailName := vendorSkuInfo.SkuList[0].SkuName - vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status) + vendorSkuSaleStatusName := GetSkuSaleStatusName(vendorSkuInfo.SkuList[0].Status + 3) jxSkuInfo := filterJxSkuInfoMap2[skuID] if jxSkuInfo == nil { @@ -505,16 +548,575 @@ func CompareJxAndMultiVenderDepot(ctx *jxcontext.Context, vendorMap map[int]bool depotDiffData.AppendData2(vendorID, outPutData) } } else { - globals.SugarLogger.Warnf("CompareJxAndMultiVenderDepot vendorSkuInfo.SkuList:%d is nil", skuID) + globals.SugarLogger.Debugf("CompareJxAndMultiVenderDepot vendorSkuInfo.SkuList:%d is nil", skuID) } } else { - globals.SugarLogger.Warnf("CompareJxAndMultiVenderDepot skuID:%d is nil", skuID) + globals.SugarLogger.Debugf("CompareJxAndMultiVenderDepot skuID:%d is nil", skuID) } } } } } +func StoreOpenAll(ctx *jxcontext.Context) { + AutoFocusStoreSkusForTopSkus(ctx, true, true) + //globals.SugarLogger.Debug("StoreOpenAll skuID is start") + ///*获取美团门店信息*/ + //StoreInfoList, _ := api.MtpsAPI.GetStoreStatusAll() + //StoreInfoList2 := make(map[string]string) + //for _, store := range StoreInfoList { + // for _, data := range store.DataList { + // StoreInfoList2[data.OuterPoiID] = data.PoiName + // } + //} + //db := dao.GetDB() + ///*比较营业状态*/ + ///*把获取的京西状态和名称存一下*/ + //StoreCourierList, _ := dao.GetStoreCourierList(db, []int{}, model.StoreStatusAll, model.StoreStatusAll) + ///*循环美团*/ + //for _, StoreInfoList1 := range StoreInfoList { + // for _, StoreInfoList11 := range StoreInfoList1.DataList { + // /*循环京西*/ + // for _, StoreCourierList1 := range StoreCourierList { + // /*只比较美团*/ + // if StoreCourierList1.VendorID != model.VendorIDMTPS { + // continue + // } + // /*如果门店ID相同的时候进入判断,一个门店只用判断一次就行*/ + // if StoreCourierList1.VendorStoreID == StoreInfoList11.OuterPoiID { + // if StoreCourierList1.Status != StoreInfoList11.OpenType { + // sl := make(map[string]interface{}) + // sl["vendorStoreID"] = StoreInfoList11.OuterPoiID + // sl["status"] = StoreInfoList11.OpenType + // sl["vendorStatus"] = StoreInfoList11.OpenType + // globals.SugarLogger.Debugf("被修改配送状态的VendorStoreID是:%s,名称是:%s,美团状态是:%s,本地状态是:%s", + // StoreInfoList11.OuterPoiID, StoreInfoList11.PoiName, strconv.Itoa(StoreInfoList11.OpenType), strconv.Itoa(StoreCourierList1.Status)) + // UpdateStoreCourierMap(ctx, nil, StoreCourierList1.StoreID, StoreCourierList1.VendorID, sl, ctx.GetUserName()) + // break + // } + // } + // } + // } + //} + ///* 美团配送的门店是否存在,调用美团配送的api(有可能接了),查询京西门店对应的美团配送门店是否存在,若不存在则要在京西这边解绑美团配送门店 + // 怎么解绑可以在网页上门店管理那点一下看看调的什么接口,传的什么参数*/ + ///*获取所有门店信息*/ + ////test: + //for _, StoreCourierList1 := range StoreCourierList { + // diff := false + // StoreLists, _ := dao.GetStoreList(db, []int{StoreCourierList1.StoreID}, nil, nil, nil, "") + // if StoreLists == nil { + // globals.SugarLogger.Debugf("StoreID为:%s,在store表未找到", StoreCourierList1.StoreID) + // continue + // } + // if StoreCourierList1.VendorID != model.VendorIDMTPS || StoreCourierList1.VendorStoreID == "" { + // continue + // } + // if StoreCourierList1.Status == model.StoreStatusDisabled || StoreCourierList1.Status == model.StoreStatusClosed { + // continue + // } + // /*京西不为空,容错*/ + // //if { + // /*调用API获取美团的商店信息*/ + // MTPSInfo := new(mtpsapi.ShopInfo) + // MTPSInfo, _ = api.MtpsAPI.ShopQuery(StoreCourierList1.VendorStoreID) + // if MTPSInfo == nil { + // globals.SugarLogger.Debug("美团未找到该门店," + StoreLists[0].Name + strconv.Itoa(StoreCourierList1.StoreID) + " 被解绑,关联的ID为:" + StoreCourierList1.VendorStoreID) + // diff = true + // } + // if MTPSInfo != nil && MTPSInfo.ShopName == "" { + // MTPSInfo.ShopName = StoreInfoList2[MTPSInfo.ShopID] + // } + // if MTPSInfo != nil && MTPSInfo.ShopLng != StoreCourierList1.Lng && MTPSInfo.ShopLat == StoreCourierList1.Lat { + // /*平台上但是坐标不同,解绑*/ + // globals.SugarLogger.Debug("商店与美团配送上的坐标不同," + StoreLists[0].Name + strconv.Itoa(StoreCourierList1.StoreID) + " 被解绑,关联的ID为:" + StoreCourierList1.VendorStoreID) + // if _, err := DeleteStoreCourierMap(ctx, db, StoreCourierList1.StoreID, StoreCourierList1.VendorID, ctx.GetUserName()); err != nil { + // globals.SugarLogger.Debug(err.Error()) + // return + // } + // diff = true + // } + // if diff { + // if _, err := DeleteStoreCourierMap(ctx, db, StoreCourierList1.StoreID, StoreCourierList1.VendorID, ctx.GetUserName()); err != nil { + // globals.SugarLogger.Debug(err.Error()) + // return + // } + // //break test + // } + //} + //globals.SugarLogger.Debug("StoreOpenAll skuID is Complete") +} + +//func StoreOpenAll(ctx *jxcontext.Context) { +//db := dao.GetDB() +///*获取所有门店信息*/ +//StoreLists, err := dao.GetStoreList(db, nil, nil, []int{}, nil, "") +//if err != nil { +// globals.SugarLogger.Debugf("商店列表获取失败") +//} +///*距离结构体*/ +//type Distance struct { +// StoreID string `json:"门店ID"` +// StoreStatus string `json:"门店状态"` +// StoreName string `json:"门店名"` +// Tel string `json:"电话"` +// City string `json:"城市"` +// Address string `json:"地址"` +// DistanceId string `json:"附近门店ID"` +// DistanceStatus string `json:"附近门店状态"` +// DistanceName string `json:"附近门店名"` +// DistanceAddress string `json:"附近门店地址"` +// DistanceValue string `json:"距离附近门店距离(m)"` +//} +//distanceStore := make(map[int][]Distance) +//var isCloud []string +//var CloudBool bool +//for _, StoreList := range StoreLists { +// /*循环内部声明,1对多*/ +// var a []Distance +// lng := jxutils.IntCoordinate2Standard(StoreList.Lng) +// lat := jxutils.IntCoordinate2Standard(StoreList.Lat) +// for _, StoreList1 := range StoreLists { +// if StoreList1.ID == StoreList.ID { +// continue +// } +// /*把s与提前存好的字段对比,如果相同说明 A+B=B+A的情况,直接跳过*/ +// s := strconv.Itoa(StoreList1.ID) + strconv.Itoa(StoreList.ID) +// for _, x := range isCloud { +// if s == x { +// CloudBool = true +// break +// } +// } +// if CloudBool == true{ +// CloudBool = false +// continue +// } +// lng1 := jxutils.IntCoordinate2Standard(StoreList1.Lng) +// lat1 := jxutils.IntCoordinate2Standard(StoreList1.Lat) +// if jxutils.EarthDistance(lng, lat, lng1, lat1) < 0.5 { +// //门店ID,门店名,电话,城市,地址,附近门店ID,附近门店名,距离附近门店距离(m) +// b := &Distance{ +// strconv.Itoa(StoreList.ID), +// strconv.Itoa(StoreList.Status), +// StoreList.Name, +// StoreList.Tel1, +// strconv.Itoa(StoreList.CityCode), +// StoreList.Address, +// strconv.Itoa(StoreList1.ID), +// strconv.Itoa(StoreList1.Status), +// StoreList1.Name, +// StoreList1.Address, +// fmt.Sprintf("%.2f", jxutils.EarthDistance(lng, lat, lng1, lat1)*1000), +// } +// a = append(a, *b) +// distanceStore[StoreList.ID] = a +// isCloud = append(isCloud, strconv.Itoa(StoreList.ID)+strconv.Itoa(StoreList1.ID)) +// } +// } +//} +// +////DistanceTitle := []string{ +//// "门店ID", +//// "门店名", +//// "电话", +//// "城市", +//// "地址", +//// "附近门店ID", +//// "附近门店名", +//// "距离附近门店距离(m)", +////} +//fmt.Println(len(distanceStore)) +//xlsx := excelize.NewFile() +//index := xlsx.NewSheet("Sheet1") +//xlsx.SetCellValue("Sheet1", "A1", "门店ID") +//xlsx.SetCellValue("Sheet1", "B1", "门店状态") +//xlsx.SetCellValue("Sheet1", "C1", "门店名") +//xlsx.SetCellValue("Sheet1", "D1", "电话") +//xlsx.SetCellValue("Sheet1", "E1", "城市") +//xlsx.SetCellValue("Sheet1", "F1", "地址") +//xlsx.SetCellValue("Sheet1", "G1", "附近门店ID") +//xlsx.SetCellValue("Sheet1", "H1", "附近门店状态") +//xlsx.SetCellValue("Sheet1", "I1", "附近门店名") +//xlsx.SetCellValue("Sheet1", "J1", "附近门店地址") +//xlsx.SetCellValue("Sheet1", "K1", "距离附近门店距离(M)") +//i := 2 +//for _, value := range distanceStore { +// for _, value1 := range value { +// xlsx.SetCellValue("Sheet1", "A"+strconv.Itoa(i), value1.StoreID) +// xlsx.SetCellValue("Sheet1", "B"+strconv.Itoa(i), value1.StoreStatus) +// xlsx.SetCellValue("Sheet1", "C"+strconv.Itoa(i), value1.StoreName) +// xlsx.SetCellValue("Sheet1", "D"+strconv.Itoa(i), value1.Tel) +// xlsx.SetCellValue("Sheet1", "E"+strconv.Itoa(i), value1.City) +// xlsx.SetCellValue("Sheet1", "F"+strconv.Itoa(i), value1.Address) +// xlsx.SetCellValue("Sheet1", "G"+strconv.Itoa(i), value1.DistanceId) +// xlsx.SetCellValue("Sheet1", "H"+strconv.Itoa(i), value1.DistanceStatus) +// xlsx.SetCellValue("Sheet1", "I"+strconv.Itoa(i), value1.DistanceName) +// xlsx.SetCellValue("Sheet1", "J"+strconv.Itoa(i), value1.DistanceAddress) +// xlsx.SetCellValue("Sheet1", "K"+strconv.Itoa(i), value1.DistanceValue) +// i++ +// } +//} +//// Set active sheet of the workbook. +//xlsx.SetActiveSheet(index) +//// Save xlsx file by the given path. +//err = xlsx.SaveAs("C:\\Users\\86159\\Desktop\\WorkForTemp\\距离小于500米门店信息.xlsx") +//if err != nil { +// fmt.Println(err) +//} +//var sheetList []*excel.Obj2ExcelSheetConfig +//sheetName := "附近500米门店信息" +//for _, value := range distanceStore { +// excelConf := &excel.Obj2ExcelSheetConfig{ +// Title: sheetName, +// Data: value, +// CaptionList: DistanceTitle, +// } +// file,err := os.OpenFile("C:\\Users\\86159\\Desktop\\WorkForTemp\\haha.txt",os.O_APPEND|os.O_RDWR,6660) +// if err != nil{ +// fmt.Println(err.Error()) +// } +// file.WriteString(fmt.Sprintln(excelConf.Data)) +// sheetList = append(sheetList, excelConf) +// baseapi.SugarLogger.Debugf("WriteToExcel:append:%s count:%d", sheetName, len(value)) +//} +//if len(sheetList) > 0 { +// excelBin := excel.Obj2Excel(sheetList) +// sheetList = nil +// timeStr := utils.Int64ToStr(time.Now().Unix()) +// diffFullFileName := "附近500米门店信息数据" + timeStr + fileExt +// baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", diffFullFileName) +// //上传 +// downloadURL, err := jxutils.UploadExportContent(excelBin, diffFullFileName) +// if err != nil { +// baseapi.SugarLogger.Errorf("WriteToExcel:upload %s failed error:%v", diffFullFileName, err) +// } else { +// baseapi.SugarLogger.Debugf("WriteToExcel:upload %s success, downloadURL: %s", diffFullFileName, downloadURL) +// /*************发送钉钉消息**************/ +// //ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "", "异步任务完成", "附近500米门店信息数据上传成功:Excel下载地址是 "+downloadURL) +// } +//} else { +// baseapi.SugarLogger.Debug("WriteToExcel:No diff data!!!") +//} +//} + +//func StoreOpenAll(ctx *jxcontext.Context) { +// db := dao.GetDB() +// StoreLists, err := dao.GetStoreList(db, nil, nil, []int{1}, nil, "") +// if err != nil { +// globals.SugarLogger.Debugf("商店列表获取失败") +// } +// var StoreMapLists []*model.StoreMap +// for _, StoreList := range StoreLists { +// if StoreList.StoreLevel == "E" { +// continue +// } +// if StoreMapLists, err = dao.GetStoresMapList(db, []int{0, 1, 3}, []int{StoreList.ID}, nil, 1, -1, "", ""); err != nil { +// globals.SugarLogger.Debugf("商店列表获取失败") +// } +// if len(StoreMapLists) > 0 { +// /*将map查询的结果全部放进数组*/ +// for _, StoreMapList := range StoreMapLists { +// /*二元运算符*/ +// StoreMapList.SyncStatus = StoreMapList.SyncStatus | model.SyncFlagModifiedMask +// StoreMapList.UpdatedAt = time.Now() +// StoreMapList.LastOperator = ctx.GetUserName() +// dao.UpdateEntity(db, StoreMapList, "SyncStatus", "UpdatedAt", "LastOperator") +// //} +// /*同步*/ +// if _, err = CurVendorSync.SyncStore(ctx, db, StoreMapList.VendorID, StoreList.ID, false, ctx.GetUserName()); err != nil { +// globals.SugarLogger.Debugf("同步失败") +// } +// } +// } +// if StoreMapLists, err = dao.GetStoresMapList(db, []int{9}, []int{StoreList.ID}, nil, 1, -1, "", ""); err != nil { +// globals.SugarLogger.Debugf("商店列表获取失败") +// } +// if len(StoreMapLists) == 0 { +// /*遍历,绑定*/ +// Map := &model.StoreMap{} +// Map.VendorStoreID = strconv.Itoa(StoreList.ID) +// Map.AutoPickup = 1 +// Map.DeliveryCompetition = 1 +// Map.PricePercentage = 100 +// Map.IsSync = 1 +// Map.PricePercentagePack = "京西100-100" +// Map.DeliveryFeeDeductionSill = 0 +// Map.DeliveryFeeDeductionFee = 0 +// Map.IsOrder = 0 +// if _, err := AddStoreVendorMap(ctx, db, 9, "", StoreList.ID, Map); err != nil { +// globals.SugarLogger.Debugf("AddStoreVendorMap调用出错,StoreID是" + strconv.Itoa(StoreList.ID)) +// globals.SugarLogger.Debugf(err.Error()) +// } +// } +// /*改配送范围*/ +// //deliverrangetype 3 +// //deliverrange 3000 +// StoreList.DeliveryRange = "3000" +// StoreList.DeliveryRangeType = 3 +// StoreList.UpdatedAt = time.Now() +// StoreList.LastOperator = ctx.GetUserName() +// dao.UpdateEntity(db, StoreList, "DeliveryRange", "DeliveryRangeType", "LastOperator", "UpdatedAt") +// } +// globals.SugarLogger.Debug("StoreOpenAll skuID is Complete") +//} + +func TestDiff(ctx *jxcontext.Context, vendorIDList []int, storeIDList []int) { + baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor start time: %v", time.Now()) + startProcessTime := time.Now().Unix() + vendorMap := make(map[int]bool) + for _, vendorID := range vendorIDList { + vendorMap[vendorID] = true //map[平台ID:true] + } + storeIDMap := make(map[int]bool) + for _, storeID := range storeIDList { + storeIDMap[storeID] = true //map[门店ID:true] + } + /************************************************update**************************************************/ + //自己存值 + a := func() { + for vendorID, _ := range vendorNameList { + //filter for vendorID + if len(vendorMap) > 0 { + if _, ok := vendorMap[vendorID]; !ok { + continue + } + } + if partner.IsMultiStore(vendorID) { + multiHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IMultipleStoresHandler) + for _, vendorOrgCode := range apimanager.CurAPIManager.GetAppOrgCodeList(vendorID) { + allSkuNameInfoList, err := multiHandler.GetSkus(ctx, vendorOrgCode, 0, "") + //获取单个表格对比的物品信息列表 + skuNameInfoList = allSkuNameInfoList + if err != nil { + fmt.Println("allSkuNameInfoList赋值错误,error信息" + err.Error()) + continue + } + //*partner.StoreSkuInfo skuNameList []*SkuNameInfo + var bareStoreSkuList []*partner.StoreSkuInfo + for _, v := range allSkuNameInfoList { + for _, v2 := range v.SkuList { + if v2.Status > model.SkuStatusDontSale { + for _, v2 := range v.SkuList { + bareStoreSkuList = append(bareStoreSkuList, &v2.StoreSkuInfo) + } + } + } + } + //if multiStoreAllSkuInfoList[vendorID][vendorOrgCode] != nil && bareStoreSkuList != nil { + if multiStoreAllSkuInfoList[vendorID] != nil && bareStoreSkuList != nil { + multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = bareStoreSkuList + //}else if multiStoreAllSkuInfoList[vendorID][vendorOrgCode] == nil{ + } else if multiStoreAllSkuInfoList[vendorID] == nil { + multiStoreAllSkuInfoList = make(map[int]map[string][]*partner.StoreSkuInfo) + multiStoreAllSkuInfoList[vendorID] = make(map[string][]*partner.StoreSkuInfo) + multiStoreAllSkuInfoList[vendorID][vendorOrgCode] = bareStoreSkuList + } + tempMap := make(map[int]*partner.SkuNameInfo) + for _, value := range allSkuNameInfoList { + for _, skuInfo := range value.SkuList { + //表示平台商品库未下架的 + if skuInfo.Status > model.SkuStatusDontSale { + filterVendorDepotUnSaleSkuIds = append(filterVendorDepotUnSaleSkuIds, skuInfo.SkuID) + tempMap[skuInfo.SkuID] = value + } + } + } + //商品信息 + if multiStoreAllSkuInfoMap[vendorID] == nil { + multiStoreAllSkuInfoMap = make(map[int]map[string]map[int]*partner.SkuNameInfo) + multiStoreAllSkuInfoMap[vendorID] = make(map[string]map[int]*partner.SkuNameInfo) + //multiStoreAllSkuInfoMap[vendorID][vendorOrgCode] = make(map[int]*partner.SkuNameInfo) + multiStoreAllSkuInfoMap[vendorID][vendorOrgCode] = tempMap + } else { + multiStoreAllSkuInfoMap[vendorID][vendorOrgCode] = tempMap + } + } + } + } + } + + /************************************************update****************************************************/ + //1.获取京西本地所有门店信息 store、place、user表联查 jxStoreInfoList + //2.过滤所有门店信息,只留下传进来的vendorMap,storeIDMap中对应的平台和门台信息 filterStoreList + //3.判断是否多平台门店,两种情况两种处理 + b := func() { + jxStoreInfoList, err := GetStores(ctx, "", map[string]interface{}{}, 0, -1, utils.DefaultTimeValue, utils.DefaultTimeValue, 0, 0) + if err != nil { + baseapi.SugarLogger.Errorf("CheckSkuDiffBetweenJxAndVendor GetStores error:%v", err) + } else { + //获取总共几个门店任务 + filterStoreList := GetFilterStoreList(jxStoreInfoList.Stores, vendorMap, storeIDMap) + diffData.InitData() + for i := range filterStoreList { + jxStoreInfoListValue := filterStoreList[i] + storeID := jxStoreInfoListValue.ID + storeIDStr := utils.Int2Str(storeID) + storeName := jxStoreInfoListValue.Name + jxSkuInfoDataSingle := &dao.StoreSkuNamesInfo{} + jxSkuInfoDataMulti := &dao.StoreSkuNamesInfo{} + if jxStoreInfoListValue.StoreMaps != nil { + var multiFlag = false + var singleFlag = false + var filterJxSkuInfoMapSingle map[int]*dao.StoreSkuNameExt + var filterJxSkuInfoMapMulti map[int]*dao.StoreSkuNameExt + for _, vendorListValue := range jxStoreInfoListValue.StoreMaps { + vendorID := vendorListValue.VendorID + if partner.IsMultiStore(vendorID) { + if multiFlag == false { + jxSkuInfoDataMulti, _ = GetStoreSkus(ctx, storeID, filterJxDepotUnSaleSkuIds, true, "", true, false, map[string]interface{}{}, 0, -1) + /*重新计算价格*/ + SetJxPrice(jxSkuInfoDataMulti, storeID, vendorID) + filterJxSkuInfoMapMulti = GetFilterJxSkuInfoMap(jxSkuInfoDataMulti.SkuNames) //map[京西商品ID:StoreSkuNameExt] + multiFlag = true + } + } else { + if singleFlag == false { + jxSkuInfoDataSingle, _ = GetStoreSkus(ctx, storeID, nil, true, "", true, false, map[string]interface{}{}, 0, -1) + /*重新计算价格*/ + SetJxPrice(jxSkuInfoDataSingle, storeID, vendorID) + filterJxSkuInfoMapSingle = GetFilterJxSkuInfoMap(jxSkuInfoDataSingle.SkuNames) //map[京西商品ID:StoreSkuNameExt] + singleFlag = true + } + } + vendorStoreID := vendorListValue.VendorStoreID + baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor storeID:%d vendorID:%d vendorStoreID:%s vendorListValue:%v", storeID, vendorID, vendorStoreID, vendorListValue) + + if partner.IsMultiStore(vendorID) { + singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler) + allSkuInfoList := GetMultiStoreAllSkuInfoList(vendorID, vendorListValue.VendorOrgCode) + skuBareInfoList, err := singleStoreHandler.GetStoreSkusBareInfo(ctx, vendorListValue.VendorOrgCode, nil, storeID, vendorStoreID, allSkuInfoList) + if err != nil { + baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusBareInfo error:%v", err) + } else if len(skuBareInfoList) > 0 { + //获取京东的商品 + filterSkuInfoMap := GetFilterMultiStoreSkuInfoMap(vendorID, vendorListValue.VendorOrgCode, skuBareInfoList) //map[京东商品ID:SkuNameInfo] + CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapMulti, filterSkuInfoMap, 1) + } + } else { + singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) + vendorSkuInfoList, err := singleStoreHandler.GetStoreSkusFullInfo(ctx, nil, storeID, vendorStoreID, nil) + if err != nil { + baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusFullInfo error:%v", err) + } else if len(vendorSkuInfoList) > 0 { + //获取京东的商品 + filterVendorSkuInfoMap := GetFilterVendorSkuInfoMap(vendorSkuInfoList) //map[平台商品ID:SkuNameInfo] + CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapSingle, filterVendorSkuInfoMap, 0) + } + } + } + } + } + } + } + + /********************************第三步****************************/ + c := func(data map[int][]DiffData, depotData map[int][]DepotDiffData) { + var sheetList []*excel.Obj2ExcelSheetConfig + for key, value := range data { + sheetName := vendorNameList[key] + if partner.IsMultiStore(key) { + excelConfDepot := &excel.Obj2ExcelSheetConfig{ + Title: sheetName + "商品库与京西商品库对比", + Data: depotData[key], + CaptionList: deoptTitleList, + } + sheetList = append(sheetList, excelConfDepot) + } + excelConf := &excel.Obj2ExcelSheetConfig{ + Title: sheetName, + Data: value, + CaptionList: titleList, + } + sheetList = append(sheetList, excelConf) + if needStatistic { + statisticSheet := AddStatisticSheet(sheetName, value) + sheetList = append(sheetList, statisticSheet) + } + baseapi.SugarLogger.Debugf("WriteToExcel:append:%s count:%d", sheetName, len(value)) + } + + if len(sheetList) > 0 { + excelBin := excel.Obj2Excel(sheetList) + sheetList = nil + timeStr := utils.Int64ToStr(time.Now().Unix()) + diffFullFileName := diffFileName[IsJXCS()] + timeStr + fileExt + if canWriteTolocal { + jxutils.WriteFile(diffFullFileName, excelBin) + } + baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", diffFullFileName) + //上传 + downloadURL, err := jxutils.UploadExportContent(excelBin, diffFullFileName) + if err != nil { + baseapi.SugarLogger.Errorf("WriteToExcel:upload %s failed error:%v", diffFullFileName, err) + } else { + baseapi.SugarLogger.Debugf("WriteToExcel:upload %s success, downloadURL: %s", diffFullFileName, downloadURL) + /*************发送钉钉消息**************/ + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, ctx.GetUserID(), "异步任务完成", "京西平台对比数据上传成功:Excel下载地址是 "+downloadURL) + } + } else { + baseapi.SugarLogger.Debug("WriteToExcel:No diff data!!!") + } + //} + endProcessTime := time.Now().Unix() + diff := endProcessTime - startProcessTime + baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor end time: %v", time.Now()) + baseapi.SugarLogger.Debugf("CheckSkuDiffBetweenJxAndVendor cost time: %d sec", diff) + } + apiover := make(chan int, 1) + compover := make(chan int, 1) + over := false + /********************************第三步****************************/ + /*异步任务*/ + /************************************************************************************/ + go func() { + defer func() { + if recover() != nil { + beego.Info("执行任务失败") + panic("API调用失败") + } + }() + a() + depotDiffData.InitData2() + CompareJxAndMultiVenderDepot(ctx, vendorMap) + apiover <- 0 + }() + /*a等待a现成执行完*/ + go func() { + for !over { + select { + case <-apiover: + /*第二步 为了获取 filterJxDepotUnSaleSkuIds*/ + go func() { + defer func() { + if recover() != nil { + beego.Info("比较任务失败") + panic("比较任务失败") + } + }() + b() + compover <- 0 //比较任务完成 + }() + /*第二步*/ + case <-compover: + go func() { + defer func() { + if recover() != nil { + beego.Info("写入任务失败") + panic("写入任务失败") + } + }() + c(diffData.diffDataMap, depotDiffData.diffDataMap) + fmt.Println("任务执行完成") + over = true + }() + break + } + } + }() + /************************************************************************************/ +} + //入口函数,校验本地商品京西和其他平台的差异 func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, storeIDList []int) { startProcessTime := time.Now().Unix() @@ -588,7 +1190,7 @@ func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusBareInfo error:%v", err) } else if len(skuBareInfoList) > 0 { filterSkuInfoMap := GetFilterMultiStoreSkuInfoMap(vendorID, vendorListValue.VendorOrgCode, skuBareInfoList) //map[京东商品ID:SkuNameInfo] - CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapMulti, filterSkuInfoMap) + CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapMulti, filterSkuInfoMap, 1) } } else { singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) @@ -597,7 +1199,7 @@ func CheckSkuDiffBetweenJxAndVendor(ctx *jxcontext.Context, vendorIDList []int, baseapi.SugarLogger.Infof("CheckSkuDiffBetweenJxAndVendor GetStoreSkusFullInfo error:%v", err) } else if len(vendorSkuInfoList) > 0 { filterVendorSkuInfoMap := GetFilterVendorSkuInfoMap(vendorSkuInfoList) //map[平台商品ID:SkuNameInfo] - CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapSingle, filterVendorSkuInfoMap) + CompareJxAndVendor(vendorID, storeIDStr, vendorStoreID, storeName, filterJxSkuInfoMapSingle, filterVendorSkuInfoMap, 0) } } } @@ -719,6 +1321,7 @@ func WriteToExcel(task *tasksch.SeqTask, data map[int][]DiffData, depotData map[ jxutils.WriteFile(diffFullFileName, excelBin) } baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", diffFullFileName) + //上传 downloadURL, err := jxutils.UploadExportContent(excelBin, diffFullFileName) if err != nil { baseapi.SugarLogger.Errorf("WriteToExcel:upload %s failed error:%v", diffFullFileName, err) @@ -731,3 +1334,20 @@ func WriteToExcel(task *tasksch.SeqTask, data map[int][]DiffData, depotData map[ baseapi.SugarLogger.Debug("WriteToExcel:No diff data!!!") } } + +func SetJxPrice(jxSkuInfoDataMulti *dao.StoreSkuNamesInfo, storeId int, vendorid int) (err error) { + db := dao.GetDB() + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), storeId, vendorid, "") + if err != nil { + dao.Rollback(db) + return err + } + /*重新计算京西价格*/ + for _, values := range jxSkuInfoDataMulti.SkuNames { + for _, value := range values.Skus { + value.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), value.BindPrice) + } + } + /*重新计算京西价格*/ + return nil +} diff --git a/business/jxstore/cms/store_sku_check_test.go b/business/jxstore/cms/store_sku_check_test.go deleted file mode 100644 index 731575b51..000000000 --- a/business/jxstore/cms/store_sku_check_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package cms - -import ( - "testing" - - "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" -) - -func TestCheckSkuDiffBetweenJxAndVendor(t *testing.T) { - vendorIDList := []int{} - storeIDList := []int{} - CheckSkuDiffBetweenJxAndVendor(jxcontext.AdminCtx, vendorIDList, storeIDList) -} diff --git a/business/jxstore/cms/storeman.go b/business/jxstore/cms/storeman.go index d77e02159..ee78ab8de 100644 --- a/business/jxstore/cms/storeman.go +++ b/business/jxstore/cms/storeman.go @@ -25,7 +25,7 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int, return err globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeStatus:%d", vendorStoreID, storeStatus) db := dao.GetDB() - storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID) + storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, vendorStoreID, vendorID, "") if err == nil { var storeKV, storeMapKV map[string]interface{} if storeStatus == model.StoreStatusOpened { @@ -102,18 +102,23 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int, return err } -func (s *StoreManager) OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int) (err error) { +func (s *StoreManager) OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int, message string) (err error) { if vendorStoreID != "" { db := dao.GetDB() _, err2 := dao.GetStoreDetail2(db, 0, vendorStoreID, vendorID) if err = err2; err == nil { status := model.StoreStatusOpened - if auditStatus != model.StoreAuditStatusOnline { + if auditStatus != model.StoreAuditStatusOnline && auditStatus != model.StoreAuditStatusUpdated { status = model.StoreStatusDisabled } + comment := "" + if auditStatus == model.StoreAuditStatusRejected { + comment = message + } _, err = dao.UpdateEntityLogically(db, &model.StoreCourierMap{}, map[string]interface{}{ model.FieldStatus: status, "AuditStatus": auditStatus, + "Comment": comment, }, ctx.GetUserName(), map[string]interface{}{ model.FieldVendorStoreID: vendorStoreID, model.FieldVendorID: vendorID, diff --git a/business/jxstore/cms/sync.go b/business/jxstore/cms/sync.go index aba24309c..3277a6dde 100644 --- a/business/jxstore/cms/sync.go +++ b/business/jxstore/cms/sync.go @@ -3,10 +3,16 @@ package cms import ( "errors" "fmt" + "strconv" + "strings" "sync" "time" + "git.rosy.net.cn/baseapi/platformapi/mtpsapi" + + "git.rosy.net.cn/jx-callback/business/jxstore/permission" "git.rosy.net.cn/jx-callback/business/partner/putils" + "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/platformapi/dingdingapi" @@ -240,7 +246,7 @@ func (v *VendorSync) SyncStore2(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs db2 = dao.GetDB() } if model.IsSyncStatusNew(storeMap.SyncStatus) { - if vendorStoreID, err = handler.CreateStore2(db2, storeMap.StoreID, userName); err == nil { + if vendorStoreID, err = handler.CreateStore2(db2, storeMap.StoreID, userName, nil, nil); err == nil { resultList = append(resultList, 1) } else { failedList = putils.GetErrMsg2FailedSingleList(nil, err, storeMap.StoreID, model.VendorChineseNames[storeMap.VendorID], "创建门店") @@ -278,7 +284,7 @@ func (v *VendorSync) SyncStore2(ctx *jxcontext.Context, db *dao.DaoDB, vendorIDs var vendorStoreID string storeMap := loopMapInfo.StoreMapList[0] if model.IsSyncStatusNew(storeMap.SyncStatus) { - if vendorStoreID, err = handler.CreateStore2(db2, storeMap.StoreID, userName); err == nil { + if vendorStoreID, err = handler.CreateStore2(db2, storeMap.StoreID, userName, nil, nil); err == nil { resultList = append(resultList, 1) } else { failedList = putils.GetErrMsg2FailedSingleList(nil, err, storeMap.StoreID, model.VendorChineseNames[storeMap.VendorID], "创建门店") @@ -494,7 +500,7 @@ func (v *VendorSync) SyncStoresSkus2(ctx *jxcontext.Context, parentTask tasksch. if setSyncStatus != 0 { dao.SetStoreSkuSyncStatus(db, storeMap.VendorID, []int{storeMap.StoreID}, skuIDs, setSyncStatus) } - if _, err = SyncStoreSkuNew(ctx, task, causeFlag, storeMap.VendorID, storeMap.StoreID, storeMap.VendorStoreID, nil, skuIDs, excludeSkuIDs, false, isContinueWhenError); err != nil { + if _, err = SyncStoreSkuNew(ctx, task, causeFlag, storeMap.VendorID, storeMap.StoreID, storeMap.VendorStoreID, storeMap.VendorOrgCode, nil, skuIDs, excludeSkuIDs, false, isContinueWhenError); err != nil { globals.SugarLogger.Debugf("SyncStoresSkus2 failed2 store:%d failed with error:%v", storeMap.StoreID, err) } } @@ -516,6 +522,25 @@ func (v *VendorSync) SyncStoresSkus(ctx *jxcontext.Context, parentTask tasksch.I if isForce { setSyncStatus = model.SyncFlagStoreSkuModifiedMask } + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } return v.SyncStoresSkus2(ctx, parentTask, causeFlag, db, vendorIDs, storeIDs, true, skuIDs, nil, setSyncStatus, isAsync, isContinueWhenError) } @@ -645,7 +670,7 @@ func (v *VendorSync) AmendAndPruneStoreStuff(ctx *jxcontext.Context, vendorIDs [ func (v *VendorSync) LoopStoresMap2(ctx *jxcontext.Context, parentTask tasksch.ITask, db *dao.DaoDB, taskName string, isAsync, isManageIt bool, vendorIDs []int, storeIDs []int, mustDirty bool, handler tasksch.WorkFunc, isContinueWhenError bool) (task tasksch.ITask, hint string, err error) { var storeMapList []*model.StoreMap - if storeMapList, err = dao.GetStoresMapList2(db, vendorIDs, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", mustDirty); err != nil { + if storeMapList, err = dao.GetStoresMapList2(db, vendorIDs, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "", mustDirty); err != nil { return nil, "", err } if len(storeMapList) == 0 { @@ -677,6 +702,7 @@ func (v *VendorSync) LoopStoresMap2(ctx *jxcontext.Context, parentTask tasksch.I resultList, err2 := task.GetResult(0) if len(task.GetFailedList()) > 0 { err2 = buildErrMsg(task) + err = err2 } if err = err2; err == nil { if len(resultList) == 0 { @@ -711,12 +737,14 @@ func buildSetFinishHook(task tasksch.ITask, ctx *jxcontext.Context) { globals.SugarLogger.Debugf("同步错误发送钉钉消息失败, authinfo [%v] , [%v]", *authInfo, err) } } else { - if time.Now().Hour() >= 20 || time.Now().Hour() < 7 { - downloadURL, _, _ := WirteToExcelBySyncFailed(task) - user, err := dao.GetUserByID(dao.GetDB(), "mobile", "18160030913") - noticeMsg += fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) - if user != nil && err == nil { - ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "同步错误返回", noticeMsg) + if len(task.GetFailedList()) > 1 { + if time.Now().Hour() >= 20 || time.Now().Hour() < 7 { + downloadURL, _, _ := WirteToExcelBySyncFailed(task) + user, err := dao.GetUserByID(dao.GetDB(), "mobile", "18160030913") + noticeMsg += fmt.Sprintf("[详情点我]%s/billshow/?normal=true&path=%s \n", globals.BackstageHost, downloadURL) + if user != nil && err == nil { + ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "同步错误返回", noticeMsg) + } } } } @@ -949,14 +977,14 @@ func (v *VendorSync) SyncStoreSkusFromYb(ctx *jxcontext.Context, storeIDs []int, func syncStoreSkusFromYb(ctx *jxcontext.Context, storeID, vendorID int, vendorStoreID string, isAsync, isContinueWhenError bool) (hint string, err error) { var ( - db = dao.GetDB() - localSkuMap = make(map[string]*dao.StoreSkuSyncInfo) - vendorSkuMap = make(map[string]*partner.SkuNameInfo) - skuBindInfosDel []*StoreSkuBindInfo - skuBindInfosUpt []*StoreSkuBindInfo - addList []*partner.SkuNameInfo - updateList []*partner.SkuNameInfo - deleteList []*dao.StoreSkuSyncInfo + db = dao.GetDB() + localSkuMap = make(map[string]*dao.StoreSkuSyncInfo) + vendorSkuMap = make(map[string]*partner.SkuNameInfo) + // skuBindInfosDel []*StoreSkuBindInfo + // skuBindInfosUpt []*StoreSkuBindInfo + addList []*partner.SkuNameInfo + updateList []*partner.SkuNameInfo + deleteList []*dao.StoreSkuSyncInfo ) handler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) @@ -986,101 +1014,102 @@ func syncStoreSkusFromYb(ctx *jxcontext.Context, storeID, vendorID int, vendorSt deleteList = append(deleteList, v) } } - // fmt.Println("remoteSkuList", len(remoteSkuList)) - // fmt.Println("addList", len(addList)) - // fmt.Println("updateList", len(updateList)) - taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { - store, _ := dao.GetStoreDetail(db, storeID, vendorID) - switch step { - case 0: - if len(addList) > 0 { - taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - var ( - v = batchItemList[0].(*partner.SkuNameInfo) - upc = v.YbBarCode - ) - err = AddSkuNameByUpc(ctx, upc, store, v) - if err != nil { - task.AddFailedList(putils.GetErrMsg2FailedSingleList(nil, err, storeID, model.VendorChineseNames[vendorID], "根据upc创建京西商品")) - } - return retVal, err - } - taskParallel := tasksch.NewParallelTask("创建商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, addList) - tasksch.HandleTask(taskParallel, task, true).Run() - _, err = taskParallel.GetResult(0) - } - case 1: - if len(deleteList) > 0 { - taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - var ( - v = batchItemList[0].(*dao.StoreSkuSyncInfo) - ) - skuBindInfo := &StoreSkuBindInfo{ - NameID: v.NameID, - IsFocus: -1, - } - retVal = []*StoreSkuBindInfo{skuBindInfo} - return retVal, err - } - taskParallel := tasksch.NewParallelTask("删除商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, deleteList) - tasksch.HandleTask(taskParallel, task, true).Run() - resultDel, _ := taskParallel.GetResult(0) - for _, v := range resultDel { - skuBindInfosDel = append(skuBindInfosDel, v.(*StoreSkuBindInfo)) - } - _, err = updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosDel, false) - } - case 2: - if len(updateList) > 0 { - taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - var ( - v = batchItemList[0].(*partner.SkuNameInfo) - skuBindInfo = &StoreSkuBindInfo{} - storeSkus []*dao.StoreSkuExt - pricePercentagePack []*model.PricePercentageItem - ) - sql := ` - SELECT a.*, c.id name_id - FROM store_sku_bind a - JOIN sku b ON a.sku_id = b.id - JOIN sku_name c ON c.id = b.name_id - WHERE a.store_id = ? AND a.yb_id = ? AND a.deleted_at = ? - ` - sqlParams := []interface{}{storeID, v.SkuList[0].VendorSkuID, utils.DefaultTimeValue} - err = dao.GetRows(db, &storeSkus, sql, sqlParams) - if len(storeSkus) > 0 { - if storeSkus[0].YbPrice != int(v.SkuList[0].VendorPrice) { - err = jxutils.Strings2Objs(store.PricePercentagePackStr, &pricePercentagePack) - skuBindInfo.UnitPrice = jxutils.CaculateJxPriceByPricePack(pricePercentagePack, 0, int(v.SkuList[0].VendorPrice)) - } - } else { - return retVal, fmt.Errorf("未查询到门店商品,yb_id [%v]", v.SkuList[0].VendorSkuID) - } - if v.SkuList[0].Stock < 1 { - skuBindInfo.IsSale = model.StoreSkuBindStatusDontSale - } else { - skuBindInfo.IsSale = model.StoreSkuBindStatusNormal - } - skuBindInfo.NameID = storeSkus[0].NameID - retVal = []*StoreSkuBindInfo{skuBindInfo} - return retVal, err - } - taskParallel := tasksch.NewParallelTask("更新商品价格和库存", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, updateList) - tasksch.HandleTask(taskParallel, task, true).Run() - resultUpt, _ := taskParallel.GetResult(0) - for _, v := range resultUpt { - skuBindInfosUpt = append(skuBindInfosUpt, v.(*StoreSkuBindInfo)) - } - _, err = updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosUpt, false) - } - case 3: - _, err = CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{0, 1, 3}, nil, false, nil, nil, 0, true, true) - } - return result, err - } - taskSeq := tasksch.NewSeqTask2("同步银豹商品到京西", ctx, true, taskSeqFunc, 3) - tasksch.HandleTask(taskSeq, nil, true).Run() - hint = taskSeq.GetID() + fmt.Println("remoteSkuList", len(remoteSkuList)) + fmt.Println("addList", len(addList)) + fmt.Println("updateList", utils.Format4Output(updateList, false)) + fmt.Println("deleteList", utils.Format4Output(deleteList, false)) + // taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { + // store, _ := dao.GetStoreDetail(db, storeID, vendorID) + // switch step { + // case 0: + // if len(addList) > 0 { + // taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + // var ( + // v = batchItemList[0].(*partner.SkuNameInfo) + // upc = v.YbBarCode + // ) + // err = AddSkuNameByUpc(ctx, upc, store, v) + // if err != nil { + // task.AddFailedList(putils.GetErrMsg2FailedSingleList(nil, err, storeID, model.VendorChineseNames[vendorID], "根据upc创建京西商品")) + // } + // return retVal, err + // } + // taskParallel := tasksch.NewParallelTask("创建商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, addList) + // tasksch.HandleTask(taskParallel, task, true).Run() + // _, err = taskParallel.GetResult(0) + // } + // case 1: + // if len(deleteList) > 0 { + // taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + // var ( + // v = batchItemList[0].(*dao.StoreSkuSyncInfo) + // ) + // skuBindInfo := &StoreSkuBindInfo{ + // NameID: v.NameID, + // IsFocus: -1, + // } + // retVal = []*StoreSkuBindInfo{skuBindInfo} + // return retVal, err + // } + // taskParallel := tasksch.NewParallelTask("删除商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, deleteList) + // tasksch.HandleTask(taskParallel, task, true).Run() + // resultDel, _ := taskParallel.GetResult(0) + // for _, v := range resultDel { + // skuBindInfosDel = append(skuBindInfosDel, v.(*StoreSkuBindInfo)) + // } + // _, err = updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosDel, false, false) + // } + // case 2: + // if len(updateList) > 0 { + // taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + // var ( + // v = batchItemList[0].(*partner.SkuNameInfo) + // skuBindInfo = &StoreSkuBindInfo{} + // storeSkus []*dao.StoreSkuExt + // pricePercentagePack []*model.PricePercentageItem + // ) + // sql := ` + // SELECT a.*, c.id name_id + // FROM store_sku_bind a + // JOIN sku b ON a.sku_id = b.id + // JOIN sku_name c ON c.id = b.name_id + // WHERE a.store_id = ? AND a.yb_id = ? AND a.deleted_at = ? + // ` + // sqlParams := []interface{}{storeID, v.SkuList[0].VendorSkuID, utils.DefaultTimeValue} + // err = dao.GetRows(db, &storeSkus, sql, sqlParams) + // if len(storeSkus) > 0 { + // if storeSkus[0].YbPrice != int(v.SkuList[0].VendorPrice) { + // err = jxutils.Strings2Objs(store.PricePercentagePackStr, &pricePercentagePack) + // skuBindInfo.UnitPrice = jxutils.CaculateJxPriceByPricePack(pricePercentagePack, 0, int(v.SkuList[0].VendorPrice)) + // } + // } else { + // return retVal, fmt.Errorf("未查询到门店商品,yb_id [%v]", v.SkuList[0].VendorSkuID) + // } + // if v.SkuList[0].Stock < 1 { + // skuBindInfo.IsSale = model.StoreSkuBindStatusDontSale + // } else { + // skuBindInfo.IsSale = model.StoreSkuBindStatusNormal + // } + // skuBindInfo.NameID = storeSkus[0].NameID + // retVal = []*StoreSkuBindInfo{skuBindInfo} + // return retVal, err + // } + // taskParallel := tasksch.NewParallelTask("更新商品价格和库存", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, taskFunc, updateList) + // tasksch.HandleTask(taskParallel, task, true).Run() + // resultUpt, _ := taskParallel.GetResult(0) + // for _, v := range resultUpt { + // skuBindInfosUpt = append(skuBindInfosUpt, v.(*StoreSkuBindInfo)) + // } + // _, err = updateStoresSkusWithoutSync(ctx, db, []int{storeID}, skuBindInfosUpt, false, false) + // } + // case 3: + // _, err = CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{0, 1, 3}, nil, false, nil, nil, 0, true, true) + // } + // return result, err + // } + // taskSeq := tasksch.NewSeqTask2("同步银豹商品到京西", ctx, true, taskSeqFunc, 3) + // tasksch.HandleTask(taskSeq, nil, true).Run() + // hint = taskSeq.GetID() return hint, err } @@ -1088,114 +1117,162 @@ func (v *VendorSync) SyncJdsStoresSkus(ctx *jxcontext.Context, storeIDs []int, i var ( db = dao.GetDB() ) - _, hint, err = v.LoopStoresMap2(ctx, nil, db, fmt.Sprintf("同步京东商城库存商品信息:%v", storeIDs), isAsync, true, []int{model.VendorIDJDShop}, storeIDs, false, + // storeSkus, _ := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, nil) + _, hint, err = v.LoopStoresMap2(ctx, nil, db, fmt.Sprintf("同步京东商城门店的可售信息:%v", storeIDs), isAsync, true, []int{model.VendorIDJDShop}, storeIDs, false, func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) { loopMapInfo := batchItemList[0].(*LoopStoreMapInfo) if handler := v.GetStoreHandler(loopMapInfo.VendorID); handler != nil { - parallelCount := 5 - if model.MultiStoresVendorMap[loopMapInfo.VendorID] == 1 { - parallelCount = 2 + for _, storeMap := range loopMapInfo.StoreMapList { + if storeMap.Status > model.StoreStatusDisabled && storeMap.StoreID != model.JdShopMainStoreID && storeMap.SyncRule != 0 { + err = syncJdsStoresSkus(ctx, db, t, storeMap, isAsync, isContinueWhenError) + } + // err = syncJdsStoreStock(ctx, db, t, storeSkus, storeMap, isAsync, isContinueWhenError) } - loopStoreTask := tasksch.NewParallelTask(fmt.Sprintf("处理平台%s", model.VendorChineseNames[loopMapInfo.VendorID]), - tasksch.NewParallelConfig().SetParallelCount(parallelCount).SetIsContinueWhenError(isContinueWhenError), ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - storeMap := batchItemList[0].(*model.StoreMap) - if storeMap.Status > model.StoreStatusDisabled && storeMap.StoreID != model.JdShopMainStoreID && storeMap.SyncRule != 0 { - _, err = syncJdsStoresSkus(ctx, db, task, storeMap, isAsync, isContinueWhenError) - } - return nil, err - }, loopMapInfo.StoreMapList) - t.AddChild(loopStoreTask).Run() - _, err = loopStoreTask.GetResult(0) } return nil, partner.AddVendorInfo2Err(err, loopMapInfo.VendorID) }, isContinueWhenError) return hint, err } -func syncJdsStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.ITask, storeMap *model.StoreMap, isAsync, isContinueWhenError bool) (hint string, err error) { +func syncJdsStoreStock(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.ITask, storeSkus []*model.StoreSkuBind, storeMap *model.StoreMap, isAsync, isContinueWhenError bool) (err error) { + task := tasksch.NewParallelTask("syncJdsStoreStock", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeSku := batchItemList[0].(*model.StoreSkuBind) + stock := 0 + storeSku2, _ := dao.GetStoresSkusInfo(db, []int{storeMap.StoreID}, []int{storeSku.SkuID}) + if storeSku.JdsID != 0 { + if len(storeSku2) > 0 { + if storeSku2[0].Status == model.StoreSkuBindStatusNormal && storeSku.Status == model.StoreSkuBindStatusNormal { + stock = 9999 + } + if storeMap.VendorStoreID != "" { + err = api.JdShopAPI.UpdateSkuSiteStock(storeSku.JdsID, stock, utils.Str2Int(storeMap.VendorStoreID)) + } + } else { + err = api.JdShopAPI.UpdateSkuSiteStock(storeSku.JdsID, 0, utils.Str2Int(storeMap.VendorStoreID)) + } + } + return retVal, err + }, storeSkus) + tasksch.HandleTask(task, parentTask, true).Run() + _, err = task.GetResult(0) + return err +} + +func SyncJdsStoreStock(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (err error) { var ( - mainSkusMap = make(map[int]*model.StoreSkuBind) - skusMap = make(map[int]*model.StoreSkuBind) - updateList []*model.StoreSkuBind - addList []*model.StoreSkuBind - skuBindInfos1 []*StoreSkuBindInfo - skuBindInfos2 []*StoreSkuBindInfo - resultInterface1 []interface{} - resultInterface2 []interface{} + db = dao.GetDB() + storeMaps []*model.StoreMap ) - storeSkusMain, err := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, nil) - for _, v := range storeSkusMain { - mainSkusMap[v.SkuID] = v + sql := ` + SELECT * FROM store_map WHERE vendor_id = ? AND vendor_store_id <> '' AND store_id <> ? AND vendor_org_code = 1 + ` + sqlParams := []interface{}{ + model.VendorIDJDShop, model.JdShopMainStoreID, } - storeSkus, err := dao.GetStoresSkusInfo(db, []int{storeMap.StoreID}, nil) + err = dao.GetRows(db, &storeMaps, sql, sqlParams) + storeSkus, err := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, nil) + if err != nil { + return err + } + task1 := tasksch.NewParallelTask("syncJdsStoreStock1", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + func(task1 *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeMap := batchItemList[0].(*model.StoreMap) + task2 := tasksch.NewParallelTask("syncJdsStoreStock2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + func(task2 *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + storeSku := batchItemList[0].(*model.StoreSkuBind) + stock := 0 + storeSku2, _ := dao.GetStoresSkusInfo(db, []int{storeMap.StoreID}, []int{storeSku.SkuID}) + if storeSku.JdsID != 0 { + if len(storeSku2) > 0 { + if storeSku2[0].Status == model.StoreSkuBindStatusNormal && storeSku.Status == model.StoreSkuBindStatusNormal { + stock = 9999 + } + if storeMap.VendorStoreID != "" { + err = api.JdShopAPI.UpdateSkuSiteStock(storeSku.JdsID, stock, utils.Str2Int(storeMap.VendorStoreID)) + } + } else { + err = api.JdShopAPI.UpdateSkuSiteStock(storeSku.JdsID, 0, utils.Str2Int(storeMap.VendorStoreID)) + } + } + return retVal, err + }, storeSkus) + tasksch.HandleTask(task2, task1, true).Run() + _, err = task2.GetResult(0) + return retVal, err + }, storeMaps) + tasksch.HandleTask(task1, nil, true).Run() + _, err = task1.GetResult(0) + return err +} + +func syncJdsStoresSkus(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.ITask, storeMap *model.StoreMap, isAsync, isContinueWhenError bool) (err error) { + globals.SugarLogger.Debugf("syncJdsStoresSkus") + var ( + mainSkusMap = make(map[int][]*dao.StoreSkuSyncInfo) + skusMap = make(map[int][]*dao.StoreSkuSyncInfo) + updateList []*dao.StoreSkuSyncInfo + addList []*dao.StoreSkuSyncInfo + skuBindInfos1 []*StoreSkuBindInfo + skuBindInfos2 []*StoreSkuBindInfo + ) + storeSkusMain, err := dao.GetStoreSkusByNameIDs(db, []int{model.JdShopMainStoreID}, 0) + for _, v := range storeSkusMain { + mainSkusMap[v.NameID] = append(mainSkusMap[v.NameID], v) + } + storeSkus, err := dao.GetStoreSkusByNameIDs(db, []int{storeMap.StoreID}, 0) for _, v := range storeSkus { - skusMap[v.SkuID] = v - if mainSkusMap[v.SkuID] != nil && mainSkusMap[v.SkuID].Status != v.Status { - updateList = append(updateList, mainSkusMap[v.SkuID]) + skusMap[v.NameID] = append(skusMap[v.NameID], v) + } + for k, v := range skusMap { + if mainSkusMap[k] != nil { + flag := false + for _, storeSku := range v { + if storeSku.StoreSkuStatus == model.StoreSkuBindStatusNormal { + flag = true + } + } + if !flag { + continue + } + for _, storeSku := range v { + for _, storeSkuMain := range mainSkusMap[k] { + if storeSkuMain.StoreSkuStatus == model.StoreSkuBindStatusNormal && storeSku.StoreSkuStatus == model.StoreSkuBindStatusDontSale && + storeSkuMain.SkuID == storeSku.SkuID { + updateList = append(updateList, storeSkuMain) + } + } + } } } for k, v := range mainSkusMap { if skusMap[k] == nil { if storeMap.SyncRule == 2 { - addList = append(addList, v) + for _, storeSkuMain := range v { + addList = append(addList, storeSkuMain) + } } } } // fmt.Println("updateList", utils.Format4Output(updateList, false)) // fmt.Println("addList", utils.Format4Output(addList, false)) - task := tasksch.NewParallelTask("正在同步京东商城的库存商品", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, - func(ptTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - step := batchItemList[0].(int) - switch step { - case 0: - if len(updateList) > 0 { - task := tasksch.NewParallelTask("同步门店库存", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - storeBind := batchItemList[0].(*model.StoreSkuBind) - retVal = []*StoreSkuBindInfo{buildStoreSkuBindInfo(db, storeMap.StoreID, storeBind, false)} - return retVal, err - }, updateList) - tasksch.HandleTask(task, ptTask, false).Run() - resultInterface1, err = task.GetResult(0) - for _, v := range resultInterface1 { - skuBindInfos1 = append(skuBindInfos1, v.(*StoreSkuBindInfo)) - } - hint, err = UpdateStoresSkusByBind(ctx, ptTask, skuBindInfos1, isAsync, isContinueWhenError, false) - } - case 1: - if len(addList) > 0 { - task := tasksch.NewParallelTask("同步门店商品", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, - func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { - storeBind := batchItemList[0].(*model.StoreSkuBind) - retVal = []*StoreSkuBindInfo{buildStoreSkuBindInfo(db, storeMap.StoreID, storeBind, true)} - return retVal, err - }, addList) - tasksch.HandleTask(task, ptTask, false).Run() - resultInterface2, err = task.GetResult(0) - for _, v := range resultInterface2 { - skuBindInfos2 = append(skuBindInfos2, v.(*StoreSkuBindInfo)) - } - hint, err = UpdateStoresSkusByBind(ctx, ptTask, skuBindInfos2, isAsync, isContinueWhenError, false) - } - } - return retVal, err - }, []int{0, 1}) - tasksch.HandleTask(task, nil, true).Run() - if isAsync { - hint = task.GetID() - } else { - _, err = task.GetResult(0) - hint = "1" + if len(updateList) > 0 { + for _, v := range updateList { + skuBindInfos1 = append(skuBindInfos1, buildStoreSkuBindInfo(db, storeMap.StoreID, v, false)) + } + UpdateStoresSkusByBind(ctx, parentTask, skuBindInfos1, isAsync, isContinueWhenError, false) } - return hint, err + + if len(addList) > 0 { + for _, v := range addList { + skuBindInfos2 = append(skuBindInfos2, buildStoreSkuBindInfo(db, storeMap.StoreID, v, true)) + } + UpdateStoresSkusByBind(ctx, parentTask, skuBindInfos2, isAsync, isContinueWhenError, false) + } + return err } -func buildStoreSkuBindInfo(db *dao.DaoDB, storeID int, storeBind *model.StoreSkuBind, isFocus bool) (skuBindInfo *StoreSkuBindInfo) { - result, err := dao.GetSkus(db, []int{storeBind.SkuID}, nil, nil, nil, nil) - if err != nil || len(result) == 0 { - return nil - } +func buildStoreSkuBindInfo(db *dao.DaoDB, storeID int, storeBind *dao.StoreSkuSyncInfo, isFocus bool) (skuBindInfo *StoreSkuBindInfo) { skus := []*StoreSkuBindSkuInfo{ &StoreSkuBindSkuInfo{ SkuID: storeBind.SkuID, @@ -1203,12 +1280,12 @@ func buildStoreSkuBindInfo(db *dao.DaoDB, storeID int, storeBind *model.StoreSku } skuBindInfo = &StoreSkuBindInfo{ StoreID: storeID, - NameID: result[0].NameID, + NameID: storeBind.NameID, } if isFocus { skuBindInfo.IsFocus = 1 } - if storeBind.Status == model.SkuStatusNormal { + if storeBind.StoreSkuStatus == model.SkuStatusNormal { skus[0].IsSale = 1 } else { skus[0].IsSale = -1 @@ -1216,3 +1293,235 @@ func buildStoreSkuBindInfo(db *dao.DaoDB, storeID int, storeBind *model.StoreSku skuBindInfo.Skus = skus return skuBindInfo } + +func SyncSkuExperfixAndWatermark(ctx *jxcontext.Context) (err error) { + var ( + db = dao.GetDB() + ) + skuExinfos, err := dao.GetSkuExinfos(db, nil, []int{model.VendorIDMTWM, model.VendorIDEBAI, model.VendorIDJD, model.VendorIDJDShop}, "", utils.ZeroTimeValue, utils.ZeroTimeValue) + task := tasksch.NewParallelTask("SyncSkuExperfixAndWatermark", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + skuExinfo := batchItemList[0].(*model.SkuExinfoMap) + if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(skuExinfo.EndAt) > 0 { + skuExinfo.DeletedAt = time.Now() + dao.UpdateEntity(db, skuExinfo, "DeletedAt") + goto setModifiyFlag + } + if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(skuExinfo.BeginAt) == 0 { + goto setModifiyFlag + } + setModifiyFlag: + { + skus, _ := dao.GetSkus(db, nil, []int{skuExinfo.NameID}, nil, nil, nil) + var skuIDs []int + for _, v := range skus { + skuIDs = append(skuIDs, v.ID) + } + if partner.IsMultiStore(skuExinfo.VendorID) { + for _, v := range skuIDs { + OnUpdateThing(ctx, db, nil, int64(v), model.ThingTypeSku) + } + } else { + if len(skuIDs) > 0 { + SetStoreSkuSyncStatus2(db, nil, []int{skuExinfo.VendorID}, skuIDs, model.SyncFlagModifiedMask) + } + } + } + return retVal, err + }, skuExinfos) + tasksch.HandleTask(task, nil, true).Run() + _, err = task.GetResult(0) + return err +} + +func SetMTPSStatus(ctx *jxcontext.Context, storeId, courierStatus int) { + globals.SugarLogger.Debug("SetMTPSStatus is start ") + globals.SugarLogger.Debug("StoreId", "CourierStatus", storeId, courierStatus) + /*获取美团门店信息*/ + //&& CourierStatus != 0 + if storeId != 0 { + var ShopName string + StoreLists, _ := dao.GetStoreList(nil, []int{storeId}, nil, nil, nil, nil, "") + ShopName = StoreLists[0].Name + StoreInfoList := new(mtpsapi.GetStoreStatusResultAll) + StoreInfoList, _ = api.MtpsAPI.GetStoreStatus(ShopName) + /*通过名字找到了,正常情况*/ + if StoreInfoList != nil && StoreInfoList.DataList != nil { + goto ifExist + } else { + /*如果通过名字找不到,那就先通过ID去找名字*/ + ShopInfo, _ := api.MtpsAPI.GetStoreInfo(storeId) + if ShopInfo != nil { + ShopName = ShopInfo[0].PoiName + if ShopName == "" { + ShopName = StoreLists[0].Name[:len(StoreLists[0].Name)-3] + } + StoreInfoList, _ = api.MtpsAPI.GetStoreStatus(ShopName) + if StoreInfoList != nil && StoreInfoList.DataList != nil { + goto ifExist + } else { + /*如果通过API返回的名字也找不到*/ + goto ifNotExist + } + } else { + StoreCourierList, _ := dao.GetStoreCourierList(dao.GetDB(), []int{storeId}, []int{model.VendorIDMTPS}, model.StoreStatusAll, model.StoreAuditStatusAll) + if len(StoreCourierList) > 0 { + ShopInfo, _ := api.MtpsAPI.GetStoreInfo(utils.Str2Int(StoreCourierList[0].VendorStoreID)) + if ShopInfo != nil { + ShopName = ShopInfo[0].PoiName + StoreInfoList, _ = api.MtpsAPI.GetStoreStatus(ShopName) + if StoreInfoList != nil && StoreInfoList.DataList != nil { + goto ifExist + } else { + /*如果通过API返回的名字也找不到*/ + goto ifNotExist + } + } + } else { + /*如果通过ID找不到,那就直接去判断名字*/ + goto NameProblem + } + } + NameProblem: + { + var NotOpen int + if strings.Contains(StoreLists[0].Name, "不做") || strings.Contains(StoreLists[0].Name, "不想做") { + NotOpen = strings.Index(StoreLists[0].Name, "-") + if strings.Index(StoreLists[0].Name, "-") > 0 { + StoreLists[0].Name = StoreLists[0].Name[:NotOpen-1] + } + NotOpen = strings.Index(StoreLists[0].Name, "不") + if strings.Index(StoreLists[0].Name, "不") > 0 { + StoreLists[0].Name = StoreLists[0].Name[:NotOpen-1] + } + NotOpen = strings.Index(StoreLists[0].Name, "(") + if strings.Index(StoreLists[0].Name, "(") > 0 { + StoreLists[0].Name = StoreLists[0].Name[:NotOpen-1] + } + NotOpen = strings.Index(StoreLists[0].Name, "(") + if strings.Index(StoreLists[0].Name, "(") > 0 { + StoreLists[0].Name = StoreLists[0].Name[:NotOpen-1] + } + NotOpen = strings.Index(StoreLists[0].Name, " ") + if NotOpen > 0 { + StoreLists[0].Name = StoreLists[0].Name[:NotOpen-1] + } + ShopName = StoreLists[0].Name + StoreInfoList, _ = api.MtpsAPI.GetStoreStatus(ShopName) + if StoreInfoList != nil && StoreInfoList.DataList != nil { + goto ifExist + } else { + goto ifNotExist + } + } + } + } + ifNotExist: + { + sl := make(map[string]interface{}) + sl["vendorStatus"] = 0 + globals.SugarLogger.Debug("因为没找到被修改配送状态的VendorStoreID是", ShopName, storeId) + UpdateStoreCourierMap(ctx, nil, storeId, model.VendorIDMTPS, sl, ctx.GetUserName()) + return + } + ifExist: + { + if StoreInfoList.DataList[0].OuterPoiID != "" { + //若存在且名字不为空,就是找到了 + // if StoreInfoList.DataList[0].OpenType != courierStatus ||{ + sl := make(map[string]interface{}) + sl["vendorStoreID"] = StoreInfoList.DataList[0].OuterPoiID + sl["status"] = StoreInfoList.DataList[0].OpenType + sl["vendorStatus"] = StoreInfoList.DataList[0].OpenType + globals.SugarLogger.Debugf("被修改配送状态的VendorStoreID是:%s,名称是:%s,美团状态是:%s,本地状态是:%s", + StoreInfoList.DataList[0].OuterPoiID, StoreInfoList.DataList[0].PoiName, strconv.Itoa(StoreInfoList.DataList[0].OpenType), strconv.Itoa(StoreLists[0].Status)) + UpdateStoreCourierMap(ctx, nil, storeId, model.VendorIDMTPS, sl, ctx.GetUserName()) + // } + } + } + } else { + StoreInfoList, _ := api.MtpsAPI.GetStoreStatusAll() + StoreInfoList2 := make(map[string]string) + for _, store := range StoreInfoList { + for _, data := range store.DataList { + StoreInfoList2[data.OuterPoiID] = data.PoiName + } + } + db := dao.GetDB() + /*比较营业状态*/ + /*把获取的京西状态和名称存一下*/ + StoreCourierList, _ := dao.GetStoreCourierList(db, []int{}, nil, model.StoreStatusAll, model.StoreStatusAll) + /*循环美团*/ + for _, StoreInfoList1 := range StoreInfoList { + for _, StoreInfoList11 := range StoreInfoList1.DataList { + /*循环京西*/ + for _, StoreCourierList1 := range StoreCourierList { + /*只比较美团*/ + if StoreCourierList1.VendorID != model.VendorIDMTPS { + continue + } + /*如果门店ID相同的时候进入判断,一个门店只用判断一次就行*/ + if StoreCourierList1.VendorStoreID == StoreInfoList11.OuterPoiID { + if StoreCourierList1.Status != StoreInfoList11.OpenType { + sl := make(map[string]interface{}) + sl["vendorStoreID"] = StoreInfoList11.OuterPoiID + sl["status"] = StoreInfoList11.OpenType + sl["vendorStatus"] = StoreInfoList11.OpenType + globals.SugarLogger.Debugf("被修改配送状态的VendorStoreID是:%s,名称是:%s,美团状态是:%s,本地状态是:%s", + StoreInfoList11.OuterPoiID, StoreInfoList11.PoiName, strconv.Itoa(StoreInfoList11.OpenType), strconv.Itoa(StoreCourierList1.Status)) + UpdateStoreCourierMap(ctx, nil, StoreCourierList1.StoreID, StoreCourierList1.VendorID, sl, ctx.GetUserName()) + break + } + } + } + } + } + /* 美团配送的门店是否存在,调用美团配送的api(有可能接了),查询京西门店对应的美团配送门店是否存在,若不存在则要在京西这边解绑美团配送门店 + 怎么解绑可以在网页上门店管理那点一下看看调的什么接口,传的什么参数*/ + /*获取所有门店信息*/ + //test: + for _, StoreCourierList1 := range StoreCourierList { + diff := false + StoreLists, _ := dao.GetStoreList(db, []int{StoreCourierList1.StoreID}, nil, nil, nil, nil, "") + if StoreLists == nil { + globals.SugarLogger.Debugf("StoreID为:%s,在store表未找到", StoreCourierList1.StoreID) + continue + } + if StoreCourierList1.VendorID != model.VendorIDMTPS || StoreCourierList1.VendorStoreID == "" { + continue + } + if StoreCourierList1.Status == model.StoreStatusDisabled || StoreCourierList1.Status == model.StoreStatusClosed { + continue + } + /*京西不为空,容错*/ + //if { + /*调用API获取美团的商店信息*/ + MTPSInfo := new(mtpsapi.ShopInfo) + MTPSInfo, _ = api.MtpsAPI.ShopQuery(StoreCourierList1.VendorStoreID) + if MTPSInfo == nil { + globals.SugarLogger.Debug("美团未找到该门店," + StoreLists[0].Name + strconv.Itoa(StoreCourierList1.StoreID) + " 被解绑,关联的ID为:" + StoreCourierList1.VendorStoreID) + diff = true + } + if MTPSInfo != nil && MTPSInfo.ShopName == "" { + MTPSInfo.ShopName = StoreInfoList2[MTPSInfo.ShopID] + } + if MTPSInfo != nil && MTPSInfo.ShopLng != StoreCourierList1.Lng && MTPSInfo.ShopLat == StoreCourierList1.Lat { + /*平台上但是坐标不同,解绑*/ + globals.SugarLogger.Debug("商店与美团配送上的坐标不同," + StoreLists[0].Name + strconv.Itoa(StoreCourierList1.StoreID) + " 被解绑,关联的ID为:" + StoreCourierList1.VendorStoreID) + if _, err := DeleteStoreCourierMap(ctx, db, StoreCourierList1.StoreID, StoreCourierList1.VendorID, ctx.GetUserName()); err != nil { + globals.SugarLogger.Debug(err.Error()) + return + } + diff = true + } + if diff { + if _, err := DeleteStoreCourierMap(ctx, db, StoreCourierList1.StoreID, StoreCourierList1.VendorID, ctx.GetUserName()); err != nil { + globals.SugarLogger.Debug(err.Error()) + return + } + //break test + } + } + } + globals.SugarLogger.Debug("SetMTPSStatus is Complete") +} diff --git a/business/jxstore/cms/sync2.go b/business/jxstore/cms/sync2.go index 6316c4ce0..dde1eea01 100644 --- a/business/jxstore/cms/sync2.go +++ b/business/jxstore/cms/sync2.go @@ -2,6 +2,7 @@ package cms import ( "fmt" + "strings" "time" "git.rosy.net.cn/baseapi/utils" @@ -51,6 +52,13 @@ func syncCategories(ctx *jxcontext.Context, db *dao.DaoDB, parentTask tasksch.IT if catVendorInfo.MapID == 0 { return nil, fmt.Errorf("分类:%d的数据异常", catVendorInfo.ID) } + //表示是不用京西分类,要用平台分类 + if catVendorInfo.IsJxCat == model.YES { + if catVendorInfo.VendorCategoryID != 0 { + catVendorInfo.Seq = catVendorInfo.VendorCategorySeq + catVendorInfo.Name = catVendorInfo.VendorCategoryName + } + } if multiStoresHandler, ok := partner.GetPurchasePlatformFromVendorID(catVendorInfo.VendorID).(partner.IMultipleStoresHandler); ok { if model.IsSyncStatusDelete(catVendorInfo.CatSyncStatus) { //删除 if !dao.IsVendorThingIDEmpty(catVendorInfo.VendorCatID) && @@ -88,7 +96,7 @@ func SyncCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs db := dao.GetDB() catList, err := dao.GetSkuCategoryWithVendor(db, vendorIDs, appOrgCodes, -1, catIDs, true) if err == nil && len(catList) > 0 { - // TODO 同一平台不同账号会有影响needSyncParentIDs,暂不处理 + //TODO 同一平台不同账号会有影响needSyncParentIDs,暂不处理 var needSyncParentIDs []int for _, cat := range catList { if cat.Level == 2 && cat.ParentVendorCatID == "" && cat.IsExdSpec == model.NO { @@ -138,16 +146,24 @@ func SyncSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorIDs []int, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { skuVendorInfo := batchItemList[0].(*dao.StoreSkuSyncInfo) var failedList []*partner.StoreSkuInfoWithErr - if skuVendorInfo.VendorCatID == "" { - return nil, fmt.Errorf("商品:%d的商家分类没有同步", skuVendorInfo.SkuID) - } + // if skuVendorInfo.VendorCatID == "" { + // return nil, fmt.Errorf("商品:%d的商家分类没有同步", skuVendorInfo.SkuID) + // } if skuVendorInfo.BindID == 0 { return nil, fmt.Errorf("商品:%d的数据异常", skuVendorInfo.SkuID) } if skuVendorInfo.ExdSkuID != "" { return nil, err } - skuVendorInfo.SkuName = jxutils.ComposeSkuName(skuVendorInfo.Prefix, skuVendorInfo.Name, skuVendorInfo.Comment, skuVendorInfo.Unit, skuVendorInfo.SpecQuality, skuVendorInfo.SpecUnit, 0, skuVendorInfo.ExPrefix, skuVendorInfo.ExPrefixBegin, skuVendorInfo.ExPrefixEnd) + if skuVendorInfo.SkuVendorMapCatID != "" { + skuVendorInfo.VendorVendorCatID = utils.Str2Int64(skuVendorInfo.SkuVendorMapCatID) + } + skuVendorInfo.SkuName = jxutils.ComposeSkuNameSync(skuVendorInfo.Prefix, skuVendorInfo.Name, skuVendorInfo.Comment, skuVendorInfo.Unit, skuVendorInfo.SpecQuality, skuVendorInfo.SpecUnit, 0, skuVendorInfo.ExPrefix, skuVendorInfo.ExPrefixBegin, skuVendorInfo.ExPrefixEnd, true) + skuVendorInfo.SkuNameOrigin = jxutils.ComposeSkuNameOriginal(skuVendorInfo.Prefix, skuVendorInfo.Name, skuVendorInfo.Comment, skuVendorInfo.Unit, skuVendorInfo.SpecQuality, skuVendorInfo.SpecUnit, 0) + if skuVendorInfo.ImgWatermark != "" { + downLoad, _ := uploadImgStandard(skuVendorInfo.ImgWatermark) + skuVendorInfo.ImgMix = jxutils.MixWatermarkImg(downLoad, skuVendorInfo.Img, skuVendorInfo.ExPrefixBegin, skuVendorInfo.ExPrefixEnd) + } skuVendorInfo.MergedStatus = jxutils.MergeSkuStatus(skuVendorInfo.Status, skuVendorInfo.NameStatus) if multiStoresHandler, ok := partner.GetPurchasePlatformFromVendorID(skuVendorInfo.VendorID).(partner.IMultipleStoresHandler); ok { if model.IsSyncStatusDelete(skuVendorInfo.SkuSyncStatus) { //删除 @@ -207,20 +223,35 @@ func SyncReorderCategories(ctx *jxcontext.Context, parentCatID int, isAsync bool func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { vendorInfo := batchItemList[0].(*MultiStoreVendorInfo) multiStoresHandler := CurVendorSync.GetMultiStoreHandler(vendorInfo.VendorID) + vendorOrgCode, err := dao.GetVendorOrgCode(db, vendorInfo.VendorID, vendorInfo.OrgCode, "") if multiStoresHandler != nil { - catList, err2 := dao.GetSkuCategoryWithVendor(db, []int{vendorInfo.VendorID}, []string{vendorInfo.OrgCode}, parentCatID, nil, false) - if err = err2; err == nil { - var vendorCatIDList []string - for _, v := range catList { - if v.VendorCatID != "" { - vendorCatIDList = append(vendorCatIDList, v.VendorCatID) + var vendorCatIDList []string + var parentVendorCatID string + //如果用平台分类就走else,用京西分类就还是原来的if + if vendorOrgCode[0].IsJxCat == model.NO { + catList, err2 := dao.GetSkuCategoryWithVendor(db, []int{vendorInfo.VendorID}, []string{vendorInfo.OrgCode}, parentCatID, nil, false) + if err = err2; err == nil { + for _, v := range catList { + if v.VendorCatID != "" { + vendorCatIDList = append(vendorCatIDList, v.VendorCatID) + } } } - if len(vendorCatIDList) > 0 { - if err = multiStoresHandler.ReorderCategories2(ctx, vendorInfo.OrgCode, catList[0].ParentVendorCatID, vendorCatIDList); err == nil { - retVal = []int{len(vendorCatIDList)} + parentVendorCatID = catList[0].ParentVendorCatID + } else { + vendorCatList, _ := dao.GetVendorCategoryMapExt(db, parentCatID, 0, vendorInfo.VendorID, vendorInfo.OrgCode, 0) + for _, v := range vendorCatList { + if v.VendorThingID != "" { + vendorCatIDList = append(vendorCatIDList, v.VendorThingID) } } + thingMaps, _ := dao.GetThingMapList(db, model.ThingTypeCategory, []int{vendorInfo.VendorID}, []int{parentCatID}, []string{vendorInfo.OrgCode}) + parentVendorCatID = thingMaps[0].VendorThingID + } + if len(vendorCatIDList) > 0 { + if err = multiStoresHandler.ReorderCategories2(ctx, vendorInfo.OrgCode, parentVendorCatID, vendorCatIDList); err == nil { + retVal = []int{len(vendorCatIDList)} + } } } else { err = fmt.Errorf("非法平台:%d", vendorInfo.VendorID) @@ -230,16 +261,43 @@ func SyncReorderCategories(ctx *jxcontext.Context, parentCatID int, isAsync bool return hint, err } +func SyncReorderCategories2(ctx *jxcontext.Context, parentCatID, vendorID int, vendorOrgCode string) (err error) { + globals.SugarLogger.Debugf("SyncReorderCategories parentCatID:%d", parentCatID) + db := dao.GetDB() + multiStoresHandler := CurVendorSync.GetMultiStoreHandler(vendorID) + if multiStoresHandler != nil { + var vendorCatIDList []string + var parentVendorCatID string + vendorCatList, _ := dao.GetVendorCategoryMapExt(db, parentCatID, 0, vendorID, vendorOrgCode, 0) + for _, v := range vendorCatList { + if v.VendorThingID != "" { + vendorCatIDList = append(vendorCatIDList, v.VendorThingID) + } + } + thingMaps, _ := dao.GetThingMapList(db, model.ThingTypeCategory, []int{vendorID}, []int{parentCatID}, []string{vendorOrgCode}) + if len(thingMaps) > 0 { + parentVendorCatID = thingMaps[0].VendorThingID + } + + if len(vendorCatIDList) > 0 { + err = multiStoresHandler.ReorderCategories2(ctx, vendorOrgCode, parentVendorCatID, vendorCatIDList) + } + } else { + err = fmt.Errorf("非法平台:%d", vendorID) + } + return err +} + func getThingMap(db *dao.DaoDB, thingMap *model.ThingMap) (err error) { return dao.GetEntity(db, thingMap, "ThingID", "ThingType", "VendorID", "VendorOrgCode", model.FieldDeletedAt) } -func OnCreateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*MultiStoreVendorInfo, thingID int64, thingType int8) (err error) { +func OnCreateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*model.VendorOrgCode, thingID int64, thingType, syncFlag int8, vendorFlag bool) (err error) { if thingType == model.ThingTypeSkuName { return nil } if len(vendorInfoList) == 0 { - vendorInfoList = getMultiStoreVendorInfoList() + vendorInfoList, err = dao.GetVendorOrgCode(db, model.VendorIDJD, "", model.VendorOrgTypePlatform) } errList := errlist.New() for _, v := range vendorInfoList { @@ -247,13 +305,18 @@ func OnCreateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*Mult ThingID: thingID, ThingType: thingType, VendorID: v.VendorID, - VendorOrgCode: v.OrgCode, - SyncStatus: model.SyncFlagNewMask, + VendorOrgCode: v.VendorOrgCode, } + if thingType == model.ThingTypeCategory && !vendorFlag { + if v.IsJxCat == model.YES { + syncFlag = 0 + } + } + thingMap.SyncStatus = syncFlag dao.WrapAddIDCULDEntity(thingMap, ctx.GetUserName()) if err2 := dao.CreateEntity(db, thingMap); err2 != nil { if dao.IsDuplicateError(err2) { - errList.AddErr(onUpdateThing(ctx, db, vendorInfoList, thingID, thingType, model.SyncFlagNewMask)) + errList.AddErr(onUpdateThing(ctx, db, vendorInfoList, thingID, thingType, syncFlag)) } else { errList.AddErr(err2) } @@ -264,12 +327,12 @@ func OnCreateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*Mult return err } -func onUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*MultiStoreVendorInfo, thingID int64, thingType int8, syncStatus int8) (err error) { +func onUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*model.VendorOrgCode, thingID int64, thingType int8, syncStatus int8) (err error) { if thingType == model.ThingTypeSkuName { return nil } if len(vendorInfoList) == 0 { - vendorInfoList = getMultiStoreVendorInfoList() + vendorInfoList, err = dao.GetVendorOrgCode(db, model.VendorIDJD, "", model.VendorOrgTypePlatform) } errList := errlist.New() for _, v := range vendorInfoList { @@ -277,7 +340,7 @@ func onUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*Mult ThingID: thingID, ThingType: thingType, VendorID: v.VendorID, - VendorOrgCode: v.OrgCode, + VendorOrgCode: v.VendorOrgCode, } thingMap.DeletedAt = utils.DefaultTimeValue if err2 := getThingMap(db, thingMap); err2 == nil { @@ -288,14 +351,18 @@ func onUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*Mult updateThingMapEntity(db, thingMap) } else { - errList.AddErr(err2) + if dao.IsNoRowsError(err2) { + err2 = nil + } else { + errList.AddErr(err2) + } } } err = errList.GetErrListAsOne() return err } -func OnUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*MultiStoreVendorInfo, thingID int64, thingType int8) (err error) { +func OnUpdateThing(ctx *jxcontext.Context, db *dao.DaoDB, vendorInfoList []*model.VendorOrgCode, thingID int64, thingType int8) (err error) { return onUpdateThing(ctx, db, vendorInfoList, thingID, thingType, model.SyncFlagModifiedMask) } @@ -370,6 +437,12 @@ func OnThingSync(ctx *jxcontext.Context, db *dao.DaoDB, thingMap *model.ThingMap err = syncErr thingMap.Remark = utils.LimitUTF8StringLen(err.Error(), 255) dao.UpdateEntity(db, thingMap, "Remark") + + if thingMap.VendorOrgCode == globals.JdcsOrgCode { + if strings.Contains(err.Error(), "店内分类信息不存在") { + err = nil + } + } } else { updateFields := []string{ model.FieldSyncStatus, @@ -415,18 +488,13 @@ func updateThingMapEntity(db *dao.DaoDB, thingMap *model.ThingMap) { // } } -func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorID int, vendorOrgCode string, isAsync, isContinueWhenError bool, opType int, isForceUpdate bool) (hint string, err error) { +func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID, vendorID int, vendorOrgCode string, isAsync, isContinueWhenError bool, opType int, isForceUpdate bool) (hint string, err error) { handler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IMultipleStoresHandler) if handler == nil { return "", fmt.Errorf("平台:%s不支持此操作", model.VendorChineseNames[vendorID]) } db := dao.GetDB() - vendorInfo := []*MultiStoreVendorInfo{ - &MultiStoreVendorInfo{ - VendorID: vendorID, - OrgCode: vendorOrgCode, - }, - } + vendorOrgCodes, _ := dao.GetVendorOrgCode(db, vendorID, vendorOrgCode, model.VendorOrgTypePlatform) var sku2Delete []*partner.StoreSkuInfo var cat2Delete []*partner.BareCategoryInfo task := tasksch.NewParallelTask(fmt.Sprintf("平台:%s,账号:%s上的商品与商家分类", model.VendorChineseNames[vendorID], vendorOrgCode), @@ -466,7 +534,21 @@ func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, }) } } - + StoreSkuMap := make(map[int]*dao.StoreSkuSyncInfo) + if storeID != 0 { + skuList2, _ := dao.GetStoreSkuListWithVendor(db, storeID, vendorID, vendorOrgCode) + for _, v := range skuList2 { + if _, ok := StoreSkuMap[v.ID]; !ok { + StoreSkuMap[v.ID] = v + } + } + } + getSyncFlag := func(skuID int) int8 { + if StoreSkuMap[skuID] != nil { + return model.SyncFlagNewMask + } + return 0 + } if opType == AmendPruneOnlyAmend || opType == AmendPruneAll { for _, v := range localSkuList { if v.ExdSkuID == "" { @@ -474,14 +556,17 @@ func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, if !model.IsSyncStatusDelete(v.SkuSyncStatus) { if remoteSkuMap[v.VendorSkuID] == 0 { if !model.IsSyncStatusNew(v.SkuSyncStatus) { - OnCreateThing(ctx, db, vendorInfo, int64(v.SkuID), model.ThingTypeSku) + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.SkuID), model.ThingTypeSku, getSyncFlag(v.SkuID), false) } } else if isForceUpdate { - OnUpdateThing(ctx, db, vendorInfo, int64(v.SkuID), model.ThingTypeSku) + OnUpdateThing(ctx, db, vendorOrgCodes, int64(v.SkuID), model.ThingTypeSku) } } } else { - OnCreateThing(ctx, db, vendorInfo, int64(v.SkuID), model.ThingTypeSku) + //表示根据某门店的门店商品同步京东商品库中,这个门店关注并可售了这个商品,插到thingmap里同步标志是待创建(SyncFlagNewMask)才会创建 + //若该门店没关注可售,那插到thingmap里的话就该同步标志为0,就不会创建 + //getSyncFlag + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.SkuID), model.ThingTypeSku, getSyncFlag(v.SkuID), false) } } } @@ -509,6 +594,21 @@ func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, localCatMap[utils.Int2Str(v.ID)] = v } + vendorCatMap := make(map[int]*model.VendorCategoryMap) + if vendorOrgCodes[0].IsJxCat == model.YES { + vendorCats, _ := dao.GetVendorCategoryMap(db, -1, 0, vendorID, vendorOrgCode, 0) + for _, v := range vendorCats { + if _, ok := vendorCatMap[v.CategoryID]; !ok { + vendorCatMap[v.CategoryID] = v + } + } + } + getSyncFlagCat := func(categoryID int) int8 { + if vendorCatMap[categoryID] != nil { + return model.SyncFlagNewMask + } + return 0 + } remoteCatList, err2 := handler.GetAllCategories(ctx, vendorOrgCode) if err = err2; err == nil { remoteCatMap := make(map[string]int) @@ -520,14 +620,14 @@ func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, if !model.IsSyncStatusDelete(v.CatSyncStatus) { if remoteCatMap[v.VendorCatID] == 0 { if !model.IsSyncStatusNew(v.CatSyncStatus) { - OnCreateThing(ctx, db, vendorInfo, int64(v.ID), model.ThingTypeCategory) + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.ID), model.ThingTypeCategory, getSyncFlagCat(v.ID), true) } } else if isForceUpdate && !model.IsSyncStatusUpdate(v.CatSyncStatus) { - OnUpdateThing(ctx, db, vendorInfo, int64(v.ID), model.ThingTypeCategory) + OnUpdateThing(ctx, db, vendorOrgCodes, int64(v.ID), model.ThingTypeCategory) } } } else { - OnCreateThing(ctx, db, vendorInfo, int64(v.ID), model.ThingTypeCategory) + OnCreateThing(ctx, db, vendorOrgCodes, int64(v.ID), model.ThingTypeCategory, getSyncFlagCat(v.ID), true) } } } @@ -568,7 +668,7 @@ func amendAndPruneVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, return hint, err } -func FullSyncVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, vendorID int, vendorOrgCode string, isAsync, isContinueWhenError bool) (hint string, err error) { +func FullSyncVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID, vendorID int, vendorOrgCode string, isAsync, isContinueWhenError bool) (hint string, err error) { multiStoreHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IMultipleStoresHandler) if multiStoreHandler == nil { return "", fmt.Errorf("vendorID:%d不是多门店平台", vendorID) @@ -578,7 +678,7 @@ func FullSyncVendorStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo step := batchItemList[0].(int) switch step { case 0: - _, err = amendAndPruneVendorStuff(ctx, task, vendorID, vendorOrgCode, false, isContinueWhenError, AmendPruneAll, false) + _, err = amendAndPruneVendorStuff(ctx, task, storeID, vendorID, vendorOrgCode, false, isContinueWhenError, AmendPruneAll, false) case 1: _, err = SyncCategories(ctx, task, []int{vendorID}, []string{vendorOrgCode}, nil, false) case 2: diff --git a/business/jxstore/cms/sync_store.go b/business/jxstore/cms/sync_store.go index dcb95dc1d..d102c400e 100644 --- a/business/jxstore/cms/sync_store.go +++ b/business/jxstore/cms/sync_store.go @@ -16,7 +16,7 @@ func OpenRemoteStoreByJxStatus(ctx *jxcontext.Context, vendorIDs, storeIDs []int if !isForce { status = model.StoreStatusClosed } - storeMapList, err := dao.GetStoresMapList(db, vendorIDs, storeIDs, nil, status, model.StoreIsSyncYes, "") + storeMapList, err := dao.GetStoresMapList(db, vendorIDs, storeIDs, nil, status, model.StoreIsSyncYes, "", "", "") if err != nil { return "", err } @@ -34,7 +34,7 @@ func OpenRemoteStoreByJxStatus(ctx *jxcontext.Context, vendorIDs, storeIDs []int func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeMap := batchItemList[0].(*model.StoreMap) if handler, _ := partner.GetPurchasePlatformFromVendorID(storeMap.VendorID).(partner.IStoreHandler); handler != nil { - storeDetail, err := dao.GetStoreDetail(db, storeMap.StoreID, storeMap.VendorID) + storeDetail, err := dao.GetStoreDetail(db, storeMap.StoreID, storeMap.VendorID, "") if err == nil && storeDetail.Status == model.StoreStatusOpened { if err = handler.UpdateStoreStatus(ctx, storeMap.VendorOrgCode, storeMap.StoreID, storeMap.VendorStoreID, model.StoreStatusOpened); err == nil { storeMap.Status = model.StoreStatusOpened diff --git a/business/jxstore/cms/sync_store_sku.go b/business/jxstore/cms/sync_store_sku.go index 3c0d35393..991701466 100644 --- a/business/jxstore/cms/sync_store_sku.go +++ b/business/jxstore/cms/sync_store_sku.go @@ -71,6 +71,9 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) num := 0 db := dao.GetDB() + if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie2", model.ConfigTypeCookie, ""); err == nil { + api.JdShop2API.SetCookieWithStr(configs[0].Value) + } rootTask := tasksch.NewSeqTask(fmt.Sprintf("%s SyncStoreCategory step1", model.VendorChineseNames[vendorID]), ctx, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { level := step + 1 @@ -78,7 +81,7 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo if len(catList) > 0 { num += len(catList) task := tasksch.NewParallelTask(fmt.Sprintf("%s SyncStoreCategory step2, level=%d", model.VendorChineseNames[vendorID], level), - tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { updateFields := []string{dao.GetSyncStatusStructField(model.VendorNames[vendorID])} idFieldName := dao.GetVendorThingIDStructField(model.VendorNames[vendorID]) @@ -91,6 +94,16 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo return nil, err } } + if vendorID == model.VendorIDEBAI && catInfo.VendorOrgCode == "34665" && catInfo.CityCode == 510100 && catInfo.IsExdSync == 0 { + catInfo.Name = catInfo.ExdName + catInfo.Seq = catInfo.ExdSeq + } + if vendorID != model.VendorIDJD && vendorID != model.VendorIDJDShop { + if catInfo.IsSysCat == model.YES && catInfo.StoreCatID != 0 { + catInfo.Name = catInfo.StoreCatName + catInfo.Seq = catInfo.StoreCatSeq + } + } if model.IsSyncStatusDelete(catInfo.CatSyncStatus) { // 删除 if model.IsSyncStatusDelete(catInfo.CatSyncStatus) && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) { err = handler.DeleteStoreCategory(ctx, storeID, vendorStoreID, catInfo.VendorCatID, level) @@ -155,13 +168,13 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo return hint, err } -func SyncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, vendorID, storeID int, vendorStoreID string, nameIDs, skuIDs, excludeSkuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { - return SyncStoreSkuNew2(ctx, parentTask, causeFlag, vendorID, storeID, vendorStoreID, nameIDs, skuIDs, excludeSkuIDs, false, isAsync, isContinueWhenError) +func SyncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, vendorID, storeID int, vendorStoreID, vendorOrgCode string, nameIDs, skuIDs, excludeSkuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { + return SyncStoreSkuNew2(ctx, parentTask, causeFlag, vendorID, storeID, vendorStoreID, vendorOrgCode, nameIDs, skuIDs, excludeSkuIDs, false, isAsync, isContinueWhenError) } -func SyncStoreSkuNew2(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, vendorID, storeID int, vendorStoreID string, nameIDs, skuIDs, excludeSkuIDs []int, useVendorPriceDirectly, isAsync, isContinueWhenError bool) (hint string, err error) { +func SyncStoreSkuNew2(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, vendorID, storeID int, vendorStoreID, vendorOrgCode string, nameIDs, skuIDs, excludeSkuIDs []int, useVendorPriceDirectly, isAsync, isContinueWhenError bool) (hint string, err error) { singleStoreHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) - if singleStoreHandler != nil { + if singleStoreHandler != nil && vendorID != model.VendorIDJDShop { if err = CreateStoreCategoryByStoreSku(ctx, vendorID, storeID, vendorStoreID, nameIDs, skuIDs); err != nil { return "", err } @@ -170,11 +183,11 @@ func SyncStoreSkuNew2(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFla func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: - if singleStoreHandler != nil { + if singleStoreHandler != nil && vendorID != model.VendorIDJDShop { _, err = SyncStoreCategories(ctx, task, vendorID, storeID, vendorStoreID, nameIDs, skuIDs, false, isContinueWhenError) } case 1: - err = syncStoreSkuNew(ctx, task, causeFlag, false, vendorID, storeID, nameIDs, skuIDs, excludeSkuIDs, useVendorPriceDirectly, isContinueWhenError) + err = syncStoreSkuNew(ctx, task, causeFlag, false, vendorID, storeID, vendorOrgCode, nameIDs, skuIDs, excludeSkuIDs, useVendorPriceDirectly, isContinueWhenError) } return result, err }, 2) @@ -196,15 +209,15 @@ func FullSyncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo case 0: if singleStoreHandler != nil { // _, err = ClearRemoteStoreStuffAndSetNew(ctx, task, vendorID, storeID, vendorStoreID, false, isContinueWhenError) - _, err = amendAndPruneStoreStuff(ctx, parentTask, vendorID, storeID, vendorStoreID, false, isContinueWhenError, AmendPruneAll, true) + _, err = amendAndPruneStoreStuff(ctx, parentTask, vendorID, storeID, vendorStoreID, false, isContinueWhenError, AmendPruneAll, false) } else { _, err = dao.SetStoreSkuSyncStatus(dao.GetDB(), vendorID, []int{storeID}, nil, model.SyncFlagStoreSkuOnlyMask) } case 1: if singleStoreHandler != nil { - _, err = SyncStoreSkuNew(ctx, task, 0, vendorID, storeID, vendorStoreID, nil, nil, excludeSkuIDs, false, isContinueWhenError) + _, err = SyncStoreSkuNew(ctx, task, 0, vendorID, storeID, vendorStoreID, "", nil, nil, excludeSkuIDs, false, isContinueWhenError) } else { - err = syncStoreSkuNew(ctx, task, 0, true, vendorID, storeID, nil, nil, excludeSkuIDs, false, isContinueWhenError) + err = syncStoreSkuNew(ctx, task, 0, true, vendorID, storeID, "", nil, nil, excludeSkuIDs, false, isContinueWhenError) } } return retVal, err @@ -219,9 +232,16 @@ func FullSyncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo } func isStoreSkuSyncNeedDelete(storeSku *dao.StoreSkuSyncInfo) bool { - return model.IsSyncStatusDelete(storeSku.SkuSyncStatus) || + if model.IsSyncStatusDelete(storeSku.SkuSyncStatus) || storeSku.BindDeletedAt != utils.DefaultTimeValue || storeSku.BindID == 0 || - storeSku.NameID == 0 || storeSku.NameStatus != model.SkuStatusNormal || storeSku.Status != model.SkuStatusNormal + storeSku.NameID == 0 || storeSku.NameStatus != model.SkuStatusNormal { + return true + } + // if storeSku.Status != model.SkuStatusNormal { + // storeSku.IsDeletedBySku = true + // return true + // } + return false } func storeSkuSyncInfo2Bare(inSku *dao.StoreSkuSyncInfo) (outSku *partner.StoreSkuInfo) { @@ -231,16 +251,20 @@ func storeSkuSyncInfo2Bare(inSku *dao.StoreSkuSyncInfo) (outSku *partner.StoreSk NameID: inSku.NameID, VendorNameID: inSku.VendorNameID, - Status: inSku.MergedStatus, - VendorPrice: inSku.VendorPrice, - Seq: inSku.Seq, - JxPrice: inSku.Price, - JxUnitPrice: inSku.UnitPrice, - VendorSkuID2: utils.Int64ToStr(inSku.JdsWareID), - } - if !isStoreSkuSyncNeedDelete(inSku) { - outSku.Stock = model.MaxStoreSkuStockQty + Status: inSku.MergedStatus, + VendorPrice: inSku.VendorPrice, + Seq: inSku.Seq, + JxPrice: inSku.Price, + JxUnitPrice: inSku.UnitPrice, + VendorSkuID2: utils.Int64ToStr(inSku.JdsWareID), + JdsStockSwitch: inSku.JdsStockSwitch, + IsDeletedBySku: inSku.IsDeletedBySku, + Stock: inSku.Stock, + VendorOrgCode: inSku.VendorOrgCode, } + // if !isStoreSkuSyncNeedDelete(inSku) { + // outSku.Stock = model.MaxStoreSkuStockQty + // } return outSku } @@ -261,15 +285,6 @@ func getSkuBoxFee(vendorID int) (boxFee int64) { return boxFee } -func formalizeStoreSkuListForJds(inSkuList []*dao.StoreSkuSyncInfo) []*dao.StoreSkuSyncInfo { - if len(inSkuList) > 0 { - for _, skuItem := range inSkuList { - skuItem.SkuName = jxutils.ComposeSkuNameSync2(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0, skuItem.ExPrefix, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd) - } - } - return inSkuList -} - func formalizeStoreSkuList(inSkuList []*dao.StoreSkuSyncInfo) []*dao.StoreSkuSyncInfo { if len(inSkuList) > 0 { boxFee := getSkuBoxFee(inSkuList[0].VendorID) @@ -277,8 +292,31 @@ func formalizeStoreSkuList(inSkuList []*dao.StoreSkuSyncInfo) []*dao.StoreSkuSyn if skuItem.VendorPrice > skuItem.BoxFee { skuItem.BoxFee = boxFee } + //如果商品上绑定了映射,就用商品上的 + if skuItem.SkuVendorMapCatID != "" { + skuItem.VendorVendorCatID = utils.Str2Int64(skuItem.SkuVendorMapCatID) + } skuItem.MergedStatus = jxutils.MergeSkuStatus(jxutils.MergeSkuStatus(skuItem.NameStatus, skuItem.Status), skuItem.StoreSkuStatus) - skuItem.SkuName = jxutils.ComposeSkuNameSync(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0, skuItem.ExPrefix, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd) + //美团的商品名字非标品中间不能有 ‘约’ + if skuItem.VendorID == model.VendorIDMTWM { + skuItem.SkuName = jxutils.ComposeSkuNameSync2(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0, skuItem.ExPrefix, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd, (skuItem.BrandID == skuItem.ExBrandID && skuItem.ExBrandID != 0) || skuItem.ExBrandID == 0) + } else { + skuItem.SkuName = jxutils.ComposeSkuNameSync(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0, skuItem.ExPrefix, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd, (skuItem.BrandID == skuItem.ExBrandID && skuItem.ExBrandID != 0) || skuItem.ExBrandID == 0) + } + skuItem.SkuNameOrigin = jxutils.ComposeSkuNameOriginal(skuItem.Prefix, skuItem.Name, skuItem.Comment, skuItem.Unit, skuItem.SpecQuality, skuItem.SpecUnit, 0) + // if skuItem.ImgWatermark != "" && model.IsSyncStatusUpdate(skuItem.SkuSyncStatus) && skuItem.VendorID != model.VendorIDJD { + if skuItem.VendorID == model.VendorIDJD { + skuItem.ImgMix = "" + } + // if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*skuItem.ExPrefixBegin) == 0 { + // // if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*skuItem.ExPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*skuItem.ExPrefixEnd) <= 0 { + // downLoad, _ := uploadImgStandard(skuItem.ImgWatermark) + // skuItem.ImgMix = jxutils.MixWatermarkImg(skuItem.ImgWatermark, skuItem.ImgOrigin, skuItem.ExPrefixBegin, skuItem.ExPrefixEnd) + // } + // if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*skuItem.ExPrefixEnd) > 0 { + // skuItem.ImgMix = "" + // } + // } } } return inSkuList @@ -294,13 +332,13 @@ func sku2Update(vendorID int, sku *dao.StoreSkuSyncInfo, syncStatus int8) (item sku.SkuSyncStatus = 0 kvs[dao.GetVendorThingIDStructField(model.VendorNames[vendorID])] = utils.Str2Int64WithDefault(sku.VendorSkuID, 0) } else if model.IsSyncStatusDelete(syncStatus) { - sku.SkuSyncStatus = 0 if utils.IsTimeZero(sku.BindDeletedAt) && (sku.NameID == 0) { kvs[model.FieldDeletedAt] = time.Now() } if !dao.IsVendorThingIDEmpty(sku.VendorSkuID) && !partner.IsMultiStore(vendorID) { kvs[dao.GetVendorThingIDStructField(model.VendorNames[vendorID])] = 0 } + sku.SkuSyncStatus = sku.SkuSyncStatus & model.SyncFlagNewMask } else { sku.SkuSyncStatus = sku.SkuSyncStatus & model.SyncFlagPriceMask } @@ -380,10 +418,10 @@ func isSkuLockTimeValid(sku *dao.StoreSkuSyncInfo) bool { return sku.LockTime != nil && time.Now().Sub(*sku.LockTime) < 0 } -func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, isFull bool, vendorID, storeID int, nameIDs, skuIDs, excludeSkuIDs []int, useVendorPriceDirectly, isContinueWhenError bool) (err error) { - globals.SugarLogger.Debugf("syncStoreSkuNew causeFlag:%d", causeFlag) +func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag int, isFull bool, vendorID, storeID int, vendorOrgCode string, nameIDs, skuIDs, excludeSkuIDs []int, useVendorPriceDirectly, isContinueWhenError bool) (err error) { + globals.SugarLogger.Debugf("syncStoreSkuNew causeFlag:%d ,vendorOrgCode:%s", causeFlag, vendorOrgCode) db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID, vendorOrgCode) if err != nil { return err } @@ -397,6 +435,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag if err != nil || len(skus) == 0 { return err } + globals.SugarLogger.Debugf("syncStoreSkuNew len(skus):%v", len(skus)) if len(excludeSkuIDs) > 0 { excludeSkuMap := jxutils.IntList2Map(excludeSkuIDs) var skus2 []*dao.StoreSkuSyncInfo @@ -413,7 +452,6 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag // if vendorID == model.VendorIDJDShop { // formalizeStoreSkuListForJds(skus) // } - singleStoreHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler) storeSkuHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformStoreSkuHandler) reorderHandler, _ := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IStoreSkuSorter) @@ -431,11 +469,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag now := jxutils.OperationTime2HourMinuteFormat(time.Now()) var failedList []*partner.StoreSkuInfoWithErr for _, sku := range skus { - if vendorID == model.VendorIDJDShop && storeID != model.JdShopMainStoreID { - if sku.SkuSyncStatus != 0 { - sku.SkuSyncStatus = model.SyncFlagSaleMask - } - } + globals.SugarLogger.Debugf("syncStoreSkuNew sku sync:%v", sku.SkuSyncStatus) if !useVendorPriceDirectly && !isSkuLockTimeValid(sku) { sku.VendorPrice = 0 @@ -450,6 +484,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag if !dao.IsVendorThingIDEmpty(sku.VendorSkuID) { bareSku = storeSkuSyncInfo2Bare(sku) if singleStoreHandler == nil { + bareSku.Stock = 0 stockList = append(stockList, bareSku) } else { deleteList = append(deleteList, bareSku) @@ -476,9 +511,9 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag } else { if sku.MergedStatus == model.SkuStatusNormal { if dao.IsVendorThingIDEmpty(sku.VendorCatID) && !strings.Contains(sku.StoreName, model.ExdStoreName) && vendorID != model.VendorIDYB && vendorID != model.VendorIDJDShop { - globals.SugarLogger.Warnf("syncStoreSkuNew 创建门店:%d商品:%d,但没有平台分类ID", storeID, sku.SkuID) + // globals.SugarLogger.Warnf("syncStoreSkuNew 创建门店:%d商品:%d,但没有平台分类ID", storeID, sku.SkuID) } else if dao.IsVendorThingIDEmpty(utils.Int64ToStr(sku.VendorVendorCatID)) && vendorID == model.VendorIDJDShop { - globals.SugarLogger.Warnf("syncStoreSkuNew 创建门店:%d商品:%d,但没有映射的平台ID", storeID, sku.SkuID) + // globals.SugarLogger.Warnf("syncStoreSkuNew 创建门店:%d商品:%d,但没有映射的平台ID", storeID, sku.SkuID) } else { createList = append(createList, sku) } @@ -502,7 +537,7 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag // 修改商品信息时不改价(以免活动引起的失败),而用单独的改价来改 if (model.IsSyncStatusUpdate(sku.SkuSyncStatus) || (model.IsSyncStatusSeq(sku.SkuSyncStatus) && reorderHandler == nil)) && singleStoreHandler != nil { if dao.IsVendorThingIDEmpty(sku.VendorCatID) && !strings.Contains(sku.StoreName, model.ExdStoreName) && vendorID != model.VendorIDYB && vendorID != model.VendorIDJDShop { - globals.SugarLogger.Warnf("syncStoreSkuNew 修改门店:%d商品:%d,但没有平台分类ID", storeID, sku.SkuID) + // globals.SugarLogger.Warnf("syncStoreSkuNew 修改门店:%d商品:%d,但没有平台分类ID", storeID, sku.SkuID) } else { isAdded2Update = true updateList = append(updateList, calVendorPrice4StoreSku(sku, storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage))) @@ -514,10 +549,10 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag } if !isAdded2Update { if model.IsSyncStatusUpdate(sku.SkuSyncStatus) && singleStoreHandler == nil { // 正常就不应该进到这里 - if bareSku == nil { - bareSku = storeSkuSyncInfo2Bare(sku) - } - updateItems = append(updateItems, sku2Update(vendorID, sku, model.SyncFlagStockMask)) + // if bareSku == nil { + // bareSku = storeSkuSyncInfo2Bare(sku) + // } + // updateItems = append(updateItems, sku2Update(vendorID, sku, model.SyncFlagStockMask)) } if model.IsSyncStatusSale(sku.SkuSyncStatus) { if bareSku == nil { @@ -525,15 +560,23 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag } if sku.MergedStatus == model.SkuStatusNormal { onlineList = append(onlineList, bareSku) - stockList = append(stockList, bareSku) + // stockList = append(stockList, bareSku) } else { offlineList = append(offlineList, bareSku) // 因为京东平台以是否有库存表示是否关注,所以不论是否可售,都要设置库存 - if singleStoreHandler == nil { - stockList = append(stockList, bareSku) - } + // if singleStoreHandler == nil { + // stockList = append(stockList, bareSku) + // } } } + if model.IsSyncStatusStock(sku.SkuSyncStatus) { + if bareSku == nil { + bareSku = storeSkuSyncInfo2Bare(sku) + } + globals.SugarLogger.Debugf("syncStoreSkuNew sku stock sync:%v", sku.SkuSyncStatus) + stockList = append(stockList, bareSku) + globals.SugarLogger.Debugf("syncStoreSkuNew stock len:%v", len(stockList)) + } } isNeedReorder = model.IsSyncStatusSeq(sku.SkuSyncStatus) } @@ -607,7 +650,11 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag updateList = updateList[:] updateList = rList2 } + // if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie2", model.ConfigTypeCookie, ""); err == nil { + // api.JdShop2API.SetCookieWithStr(configs[0].Value) + // } } + task := tasksch.NewParallelTask("syncStoreSkuNew", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError2), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { step := batchItemList[0].(int) @@ -665,6 +712,10 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag //handle error for sensitive words, if find, then insert to table sensitive_words if sensitiveWord := GetSensitiveWord(singleStoreHandler, err.Error()); sensitiveWord != "" { dao.InsertSensitiveWord(sensitiveWord, vendorID, ctx.GetUserName()) + // words, _ := dao.GetSensitiveWordList(vendorID) + // word := words[0] + // word.Word = word.Word + "," + sensitiveWord + // dao.UpdateSensitiveWord(word, vendorID, 0, ctx.GetUserName()) } } successList := putils.UnselectStoreSkuSyncListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) @@ -691,23 +742,23 @@ func syncStoreSkuNew(ctx *jxcontext.Context, parentTask tasksch.ITask, causeFlag }, ctx, task, updateList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkus), isContinueWhenError2) } case 3: - for k, list := range [][]*partner.StoreSkuInfo{stockList /*, onlineList*/} { - if len(list) > 0 { - _, err = putils.FreeBatchStoreSkuInfo("更新门店商品库存", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { - var failedList []*partner.StoreSkuInfoWithErr - failedList, err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList) - failedList, err = buildFailedListAndErr(failedList, err, batchedStoreSkuList, nil, storeID, vendorID, "更新门店商品库存") - if len(failedList) > 0 { - task.AddFailedList(failedList) - } - successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) - if k == 0 && len(successList) > 0 { - updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagStockMask) - } - return nil, len(successList), err - }, ctx, task, list, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), isContinueWhenError2) - } + // for k, list := range [][]*partner.StoreSkuInfo{stockList /*, onlineList*/} { + if len(stockList) > 0 { + _, err = putils.FreeBatchStoreSkuInfo("更新门店商品库存", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + var failedList []*partner.StoreSkuInfoWithErr + failedList, err = storeSkuHandler.UpdateStoreSkusStock(ctx, storeDetail.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList) + failedList, err = buildFailedListAndErr(failedList, err, batchedStoreSkuList, nil, storeID, vendorID, "更新门店商品库存") + if len(failedList) > 0 { + task.AddFailedList(failedList) + } + successList := putils.UnselectStoreSkuListByVendorSkuIDs(batchedStoreSkuList, GetVendorSkuIDList(failedList)) + if len(successList) > 0 { + updateStoreSku(dao.GetDB(), vendorID, bareSku2Sync(successList), model.SyncFlagStockMask) + } + return nil, len(successList), err + }, ctx, task, stockList, storeSkuHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), isContinueWhenError2) } + // } case 4, 5: statusList := onlineList status := model.SkuStatusNormal @@ -865,7 +916,7 @@ func amendAndPruneStoreStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, v return "", fmt.Errorf("平台:%s不支持此操作", model.VendorChineseNames[vendorID]) } db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID, "") if err != nil { return "", err } @@ -908,7 +959,6 @@ func amendAndPruneStoreStuff(ctx *jxcontext.Context, parentTask tasksch.ITask, v }) } } - if opType == AmendPruneOnlyAmend || opType == AmendPruneAll { for _, v := range localSkuList { if !model.IsSyncStatusDelete(v.SkuSyncStatus) && v.BindID != 0 { @@ -1322,7 +1372,7 @@ func SyncStoreSkuBindAct(ctx *jxcontext.Context, parentTask tasksch.ITask, isCre subTask := tasksch.NewParallelTask(fmt.Sprintf("%s门店:%d", taskName, storeID), nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { vendorID := batchItemList[0].(int) - storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID, "") if err == nil { if isCreate { err = createStoreSkuActs2(ctx, task, vendorID, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, storeSkuMap[storeID][vendorID], storeSkuActMap[storeID][vendorID]) @@ -1400,6 +1450,7 @@ func changeList2Jds(list []*dao.StoreSkuSyncInfo) (rList []*dao.StoreSkuSyncInfo storeSku.DescImg = v[0].DescImg storeSku.JdsWareID = v[0].JdsWareID storeSku.CategoryName = v[0].CategoryName + storeSku.VendorOrgCode = v[0].VendorOrgCode rList = append(rList, storeSku) } return rList diff --git a/business/jxstore/cms/sync_store_sku_fakejd.go b/business/jxstore/cms/sync_store_sku_fakejd.go index 734be6322..9f0d8a863 100644 --- a/business/jxstore/cms/sync_store_sku_fakejd.go +++ b/business/jxstore/cms/sync_store_sku_fakejd.go @@ -58,7 +58,7 @@ func getStoreSkus(db *dao.DaoDB, storeID int, skuIDs []int) (skus []*dao.StoreSk func SyncStoreSku4FakeJD(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, inSkuMap map[int]string, isContinueWhenError bool) (err error) { vendorID := model.VendorIDJD db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID) + storeDetail, err := dao.GetStoreDetail(db, storeID, vendorID, "") if err != nil { return err } diff --git a/business/jxstore/cms/user2.go b/business/jxstore/cms/user2.go index 6fdc80348..f1ad66737 100644 --- a/business/jxstore/cms/user2.go +++ b/business/jxstore/cms/user2.go @@ -227,7 +227,7 @@ func TryAddStoreBossRole4User(ctx *jxcontext.Context, user *model.User) (err err if user.Type&model.UserTypeStoreBoss != 0 { userMobile := user.GetMobile() if userMobile != "" { - if storeList, err := dao.GetStoreList(dao.GetDB(), nil, nil, nil, []string{userMobile}, ""); err == nil && len(storeList) > 0 { + if storeList, err := dao.GetStoreList(dao.GetDB(), nil, nil, nil, nil, []string{userMobile}, ""); err == nil && len(storeList) > 0 { roleList := make([]*authz.RoleInfo, len(storeList)) for k, v := range storeList { roleList[k] = autils.NewStoreBossRole(v.ID) @@ -778,12 +778,18 @@ func LoadUserCart(ctx *jxcontext.Context, userID string, storeIDs []int) (cartIt return cartItems, err } -func GetSelfInfo(ctx *jxcontext.Context) (user *model.User, err error) { +func GetSelfInfo(ctx *jxcontext.Context) (getSelfInfoResult *dao.GetSelfInfoResult, err error) { tokenInfo, err := auth2.GetTokenInfo(ctx.GetToken()) if err == nil { - user, err = dao.GetUserByID(dao.GetDB(), "user_id", tokenInfo.GetID()) + if getSelfInfoResult, err = dao.GetUserByIDWithMembers(dao.GetDB(), "user_id", tokenInfo.GetID()); err == nil { + if userMembers, err3 := dao.GetUserMember(dao.GetDB(), getSelfInfoResult.UserID, "", 0, model.YES); err3 == nil { + getSelfInfoResult.UserMembers = userMembers + } else { + err = err3 + } + } } - return user, err + return getSelfInfoResult, err } func HandleUserWXRemark(db *dao.DaoDB, mobile string, mobileIsUerID bool) (err error) { @@ -1124,3 +1130,34 @@ func CleanUserOrderSMSMark(ctx *jxcontext.Context) (err error) { } return err } + +func RefreshUserMemberStatus(ctx *jxcontext.Context) (err error) { + var ( + db = dao.GetDB() + ) + userMembers, err := dao.GetUserMember(db, "", "", model.MemberTypeDiscountCard, -1) + for _, userMember := range userMembers { + if time.Now().Sub(userMember.EndAt) > 0 { + userMember.DeletedAt = time.Now() + dao.UpdateEntity(db, userMember, "DeletedAt") + } + } + return err +} + +func UpdateUserLastInfo(ctx *jxcontext.Context, storeID, brandID int) (err error) { + var ( + db = dao.GetDB() + ) + if user, err := dao.GetUserByID(db, "user_id", ctx.GetUserID()); err == nil { + if storeID != 0 { + user.LastStoreID = storeID + _, err = dao.UpdateEntity(db, user, "LastStoreID") + } + if brandID != 0 { + user.LastBrandID = brandID + _, err = dao.UpdateEntity(db, user, "LastBrandID") + } + } + return err +} diff --git a/business/jxstore/common/common.go b/business/jxstore/common/common.go new file mode 100644 index 000000000..52bc7a10d --- /dev/null +++ b/business/jxstore/common/common.go @@ -0,0 +1,261 @@ +package common + +import ( + "fmt" + "sort" + + "git.rosy.net.cn/baseapi/platformapi/autonavi" + "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/globals/api" +) + +type Store4User struct { + model.ModelIDCULD + + OriginalName string `orm:"-" json:"originalName"` + Name string `orm:"size(255)" json:"name"` + OpenTime1 int16 `json:"openTime1"` // 930就表示9点半,用两个的原因是为了支持中午休息,1与2的时间段不能交叉,为0表示没有 + CloseTime1 int16 `json:"closeTime1"` // 格式同上 + OpenTime2 int16 `json:"openTime2"` // 格式同上 + CloseTime2 int16 `json:"closeTime2"` // 格式同上 + Status int `json:"status"` + CityCode int `orm:"default(0);null" json:"cityCode"` // todo ? + DistrictCode int `orm:"default(0);null" json:"districtCode"` // todo ? + Address string `orm:"size(255)" json:"address"` + Tel1 string `orm:"size(32);index" json:"tel1"` + Tel2 string `orm:"size(32);index" json:"tel2"` + Lng int `json:"-"` // 乘了10的6次方 + Lat int `json:"-"` // 乘了10的6次方 + DeliveryRangeType int8 `json:"-"` // 参见相关常量定义 + DeliveryRange string `orm:"type(text)" json:"-"` // 如果DeliveryRangeType为DeliveryRangeTypePolygon,则为逗号分隔坐标,分号分隔的坐标点(坐标与Lng和Lat一样,都是整数),比如 121361504,31189308;121420555,31150238。否则为半径,单位为米 + + FloatLng float64 `json:"lng"` + FloatLat float64 `json:"lat"` + CityName string `json:"cityName"` + DistrictName string `json:"districtName"` + + Distance int `json:"distance"` + WalkDistance int `json:"walkDistance"` +} + +type Store4UserList []*Store4User + +func (x Store4UserList) Len() int { + return len(x) +} + +func (x Store4UserList) Less(i, j int) bool { + if x[i].Status != x[j].Status { + return x[i].Status > x[j].Status + } + if x[i].WalkDistance != x[j].WalkDistance { + return x[i].WalkDistance < x[j].WalkDistance + } + return x[i].Distance < x[j].Distance +} + +func (x Store4UserList) Swap(i, j int) { + x[i], x[j] = x[j], x[i] +} + +func GetNearSupplyGoodsStoreByStoreID(ctx *jxcontext.Context, storeID int) (store *model.Store, err error) { + var ( + stores []*model.Store + db = dao.GetDB() + ) + store2, _ := dao.GetStoreDetail(db, storeID, model.VendorIDJX, "") + if store2 == nil { + return nil, fmt.Errorf("该门店未绑定京西平台!storeID: %v", storeID) + } + if store2.IsSupplyGoods == model.YES { + return nil, fmt.Errorf("该门店已经是货源门店,无法从其他货源门店进货!storeID: %v", storeID) + } + sql := ` + SELECT a.* + FROM store a + JOIN store_map b ON b.store_id = a.id + JOIN store c ON c.city_code = a.city_code AND c.id = ? + WHERE a.deleted_at = ? + AND b.deleted_at = ? + AND b.vendor_id = ? + AND b.is_supply_goods = ? + AND a.status = ? + ` + sqlParams := []interface{}{ + storeID, + utils.DefaultTimeValue, utils.DefaultTimeValue, + model.VendorIDJX, model.YES, model.StoreStatusOpened, + } + err = dao.GetRows(db, &stores, sql, sqlParams) + if len(stores) > 0 { + realDistance := float64(0) + for _, v := range stores { + distance := jxutils.EarthDistance(jxutils.IntCoordinate2Standard(v.Lng), jxutils.IntCoordinate2Standard(v.Lat), jxutils.IntCoordinate2Standard(store2.Lng), jxutils.IntCoordinate2Standard(store2.Lat)) + if realDistance == 0 { + realDistance = distance + store = v + } else { + if realDistance > distance { + realDistance = distance + store = v + } + } + } + } + return store, err +} + +func GetStoreListByLocation(ctx *jxcontext.Context, lng, lat float64, maxRadius int, needWalkDistance, isJds bool, brandID int) (storeList []*Store4User, err error) { + const ( + maxStoreCount4User = 5 + ) + + var ( + sql string + sqlParams []interface{} + ) + + lng2, _ := jxutils.ConvertDistanceToLogLat(lng, lat, float64(maxRadius), 90) + _, lat2 := jxutils.ConvertDistanceToLogLat(lng, lat, float64(maxRadius), 0) + lng1 := lng - (lng2 - lng) + lat1 := lat - (lat2 - lat) + // globals.SugarLogger.Debugf("%f,%f,%f,%f\n", lng1, lng2, lat1, lat2) + if !isJds { + sql = ` + SELECT t1.*, + city.name city_name + FROM store t1 + JOIN place city ON city.code = t1.city_code + JOIN store_map sm ON sm.store_id = t1.id AND sm.vendor_id = ? AND sm.deleted_at = ? AND sm.status <> ? + WHERE t1.deleted_at = ? AND t1.status <> ? AND t1.lng > ? AND t1.lng < ? AND t1.lat > ? AND t1.lat < ? + AND sm.is_order <> ? + AND t1.id <> ? + ` + sqlParams = append(sqlParams, + model.VendorIDJX, utils.DefaultTimeValue, model.StoreStatusDisabled, + utils.DefaultTimeValue, model.StoreStatusDisabled, jxutils.StandardCoordinate2Int(lng1), jxutils.StandardCoordinate2Int(lng2), jxutils.StandardCoordinate2Int(lat1), jxutils.StandardCoordinate2Int(lat2), + model.YES, + model.MatterStoreID, + ) + if brandID != 0 { + sql += " AND t1.brand_id = ?" + sqlParams = append(sqlParams, brandID) + } + sql += ` + ORDER BY t1.id + ` + } else { + sql = ` + SELECT t1.*, + city.name city_name + FROM store t1 + JOIN place city ON city.code = t1.city_code + JOIN store_map sm ON sm.store_id = t1.id AND sm.vendor_id = ? AND sm.deleted_at = ? AND sm.status = ? + WHERE t1.deleted_at = ? AND t1.status = ? AND t1.lng > ? AND t1.lng < ? AND t1.lat > ? AND t1.lat < ? + AND sm.is_order <> ? + AND t1.id <> ? + ORDER BY t1.id + ` + sqlParams = []interface{}{ + model.VendorIDJDShop, utils.DefaultTimeValue, model.StoreStatusOpened, + utils.DefaultTimeValue, model.StoreStatusOpened, jxutils.StandardCoordinate2Int(lng1), jxutils.StandardCoordinate2Int(lng2), jxutils.StandardCoordinate2Int(lat1), jxutils.StandardCoordinate2Int(lat2), + model.YES, + model.MatterStoreID, + } + } + var storeList1 []*Store4User + if err = dao.GetRows(dao.GetDB(), &storeList1, sql, sqlParams...); err == nil { + var storeList2 []*Store4User + for _, v := range storeList1 { + distance := jxutils.Point2StoreDistance(lng, lat, v.Lng, v.Lat, v.DeliveryRangeType, v.DeliveryRange) + if distance > 0 || (lng == jxutils.IntCoordinate2Standard(v.Lng) && lat == jxutils.IntCoordinate2Standard(v.Lat)) { + v.Distance = distance + storeList2 = append(storeList2, v) + } + } + + // 为了审核用 + if len(storeList2) == 0 { + sql2 := ` + SELECT t1.*, + city.name city_name + FROM store t1 + JOIN place city ON city.code = t1.city_code + WHERE t1.deleted_at = ? AND t1.id = ? + ` + sqlParams2 := []interface{}{ + // model.VendorIDJX, utils.DefaultTimeValue, model.StoreStatusDisabled, + utils.DefaultTimeValue, + // model.StoreStatusDisabled, + // jxutils.StandardCoordinate2Int(0), + // jxutils.StandardCoordinate2Int(10000), + // jxutils.StandardCoordinate2Int(0), + // jxutils.StandardCoordinate2Int(10000), + // model.YES, + 102919, //商城模板店 + } + dao.GetRows(dao.GetDB(), &storeList2, sql2, sqlParams2...) + // if len(storeList2) > 1 { + // storeList2 = storeList2[:1] + // } + } + + // 如果要求以步行距离来算 + if needWalkDistance { + var coordList []*autonavi.Coordinate + for _, v := range storeList2 { + coordList = append(coordList, &autonavi.Coordinate{ + Lng: v.FloatLng, + Lat: v.FloatLat, + }) + } + if distanceList, err2 := api.AutonaviAPI.BatchWalkingDistance(lng, lat, coordList); err2 == nil { + for k, v := range storeList2 { + v.WalkDistance = int(distanceList[k]) + } + } else { + return nil, err2 + } + } + + sort.Sort(Store4UserList(storeList2)) + storeList = storeList2 + if len(storeList) > maxStoreCount4User { + storeList = storeList[:maxStoreCount4User] + } + } + return storeList, err +} + +func GetVendorOrgCode(ctx *jxcontext.Context, vendorID int, vendorOrgCode, vendorType string) (vendorOrgs []*model.VendorOrgCode, err error) { + return dao.GetVendorOrgCode(dao.GetDB(), vendorID, vendorOrgCode, vendorType) +} + +func UpdateVendorOrgCode(ctx *jxcontext.Context, ID int, payload map[string]interface{}) (err error) { + var ( + db = dao.GetDB() + vendorOrgCode = &model.VendorOrgCode{} + ) + vendorOrgCode.ID = ID + err = dao.GetEntity(db, vendorOrgCode) + valid := dao.StrictMakeMapByStructObject(payload, vendorOrgCode, ctx.GetUserName()) + if len(valid) > 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if _, err = dao.UpdateEntityLogically(db, vendorOrgCode, valid, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return err + } + dao.Commit(db) + } + return err +} diff --git a/business/jxstore/event/event.go b/business/jxstore/event/event.go index 7dc392dde..fa2557df5 100644 --- a/business/jxstore/event/event.go +++ b/business/jxstore/event/event.go @@ -11,10 +11,8 @@ import ( "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/purchase/jd" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" - "git.rosy.net.cn/jx-callback/globals/api/apimanager" ) var ( @@ -149,78 +147,52 @@ func GetCheckVendorCookie(ctx *jxcontext.Context, vendorIDs []int, isAuto bool) errMsg = "" ) for _, v := range vendorIDs { - appOrgCodeList := apimanager.CurAPIManager.GetAppOrgCodeList(v) - if len(appOrgCodeList) > 0 { - for _, vv := range appOrgCodeList { - cc := &CheckCookie{} - var flag = false - switch v { - case model.VendorIDEBAI: - resultMap, err := api.EbaiAPI.GetStoreOrderInfo(ebaiOrderID) - if len(resultMap) < 1 && err != nil { - if strings.Contains(err.Error(), ebaiErr) || strings.Contains(err.Error(), ebaiErr2) { - errMsg += fmt.Sprintf(" 饿百账号:[%v]的Cookie无效了!", vv) - flag = true - } - } - // result, err := api.Ebai2API.GetEbaiDepotSku(ebaiapi.EbaiWholeCountryStore, "190700570") - // if err != nil || len(result) < 1 { - // cc := &CheckCookie{} - // cc.VendorID = v - // cc.VendorOrgCode = "饿百后台饿鲜达全国账号" - // cc.Status = "无效" - // ccList = append(ccList, cc) - // errMsg += fmt.Sprintf(" 饿百账号:[饿百后台饿鲜达全国账号]的Cookie无效了!", vv) - // flag = true - // } - // result2, err2 := api.EbaiAPI.GetExianDaSkuDepot("190600741") - // if err2 != nil || result2 == nil { - // cc := &CheckCookie{} - // cc.VendorID = v - // cc.VendorOrgCode = "饿鲜达供应链系统" - // cc.Status = "无效" - // ccList = append(ccList, cc) - // errMsg += fmt.Sprintf(" 饿百账号:[饿鲜达供应链系统]的Cookie无效了!", vv) - // flag = true - // } - case model.VendorIDMTWM: - _, err := api.MtwmAPI.PackagePriceGet(mtStoreID) - if err != nil { - if strings.Contains(err.Error(), mtErr) { - errMsg += fmt.Sprintf(" 美团账号:[%v]的Cookie无效了!", vv) - flag = true - } - globals.SugarLogger.Debugf("cookieCheck", err) - } - case model.VendorIDJD: - result, err := jd.GetAPI(vv).GetJdUpcCodeByName("", jdUpcCode, 1, 5) - if len(result) < 1 && err != nil { - if strings.Contains(err.Error(), jdErr) { - errMsg += fmt.Sprintf(" 京东账号:[%v]的Cookie无效了!", vv) - flag = true - } - } - result2, err2 := api.JdPageAPI.GetCorporationInfo("11926674", "92510108MA68KK3M8P") - if err2 != nil || result2 == nil { - cc := &CheckCookie{} - cc.VendorID = v - cc.VendorOrgCode = "京东page账号" - cc.Status = "无效" - ccList = append(ccList, cc) - errMsg += fmt.Sprintf(" 京东page账号:的Cookie无效了!", vv) - flag = true - } + cc := &CheckCookie{} + var flag = false + switch v { + case model.VendorIDEBAI: + resultMap, err := api.EbaiAPI.GetStoreOrderInfo(ebaiOrderID) + if len(resultMap) < 1 && err != nil { + if strings.Contains(err.Error(), ebaiErr) || strings.Contains(err.Error(), ebaiErr2) { + errMsg += fmt.Sprintf(" 饿百账号:[%v]的Cookie无效了!") + flag = true } - cc.VendorID = v - cc.VendorOrgCode = vv - if flag { - cc.Status = "无效" - } else { - cc.Status = "有效" + } + case model.VendorIDMTWM: + _, err := api.MtwmAPI.PackagePriceGet(mtStoreID) + if err != nil { + if strings.Contains(err.Error(), mtErr) { + errMsg += fmt.Sprintf(" 美团账号:[%v]的Cookie无效了!") + flag = true } - ccList = append(ccList, cc) + globals.SugarLogger.Debugf("cookieCheck", err) + } + case model.VendorIDJD: + result, err := api.JdAPI.GetJdUpcCodeByName("", jdUpcCode, 1, 5) + if len(result) < 1 && err != nil { + if strings.Contains(err.Error(), jdErr) { + errMsg += fmt.Sprintf(" 京东账号:[%v]的Cookie无效了!") + flag = true + } + } + case model.VendorIDJDShop: + _, err := api.JdShopAPI.OrderDetail("124350112427") + if err != nil { + if strings.Contains(err.Error(), "登录") { + errMsg += fmt.Sprintf("京东商城:[%v]的Cookie无效了!") + flag = true + } + globals.SugarLogger.Debugf("cookieCheck", err) } } + cc.VendorID = v + cc.VendorOrgCode = "" + if flag { + cc.Status = "无效" + } else { + cc.Status = "有效" + } + ccList = append(ccList, cc) } if isAuto && errMsg != "" { globals.SugarLogger.Warnf("GetCheckVendorCookie:[%v]", errMsg) diff --git a/business/jxstore/misc/misc.go b/business/jxstore/misc/misc.go index 226797d12..edc36d2c6 100644 --- a/business/jxstore/misc/misc.go +++ b/business/jxstore/misc/misc.go @@ -6,6 +6,8 @@ import ( "sync" "time" + "git.rosy.net.cn/jx-callback/business/partner/purchase/jdshop" + "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx" @@ -43,10 +45,13 @@ var ( "09:00:00", } dailyWorkTimeList = []string{ - "22:00:00", + "20:30:00", + } + dailyWorkTimeList2 = []string{ + "02:00:00", } priceReferTimeList = []string{ - "01:00:00", + "03:00:00", } checkCookieList = []string{ "08:00:00", @@ -54,7 +59,7 @@ var ( "18:00:00", } createStorePriceTimeList = []string{ - "02:00:00", + "04:00:00", } refreshPageActTimeList = []string{ "7:00:00", @@ -117,6 +122,7 @@ var ( importantTaskMap = &sync.Map{} cancelPayTimeOutOrderList = localjx.GetHalfHoursList() + discountActJxList = localjx.GetDiscountActHoursList() ebaiStorePageCookieExdTOKEN string ebaiStorePageCookieWMUSS2 string @@ -131,6 +137,7 @@ var ( feiePageCookie string jdStorePageEarning string jdsCookie string + // jdsCookie2 string ) func GetImportantTaskID(taskName string) string { @@ -158,6 +165,17 @@ func Init() { if globals.IsProductEnv() { ScheduleTimerFunc("doDailyWork", doDailyWork, dailyWorkTimeList) + ScheduleTimerFunc("doDailyWork2", doDailyWork2, dailyWorkTimeList2) + + // ScheduleTimerFuncByInterval(func() { + // orderman.SaveJdsOrders(jxcontext.AdminCtx, time.Now().Add(-20*time.Minute), time.Now()) + // }, 10*time.Second, 10*time.Minute) + + //京东的订单信息解密密钥获取 + ScheduleTimerFuncByInterval(func() { + jdshop.InitKey() + }, 10*time.Second, 8*time.Hour) + ScheduleTimerFuncByInterval(func() { RefreshRealMobile(jxcontext.AdminCtx, model.VendorIDEBAI, time.Now().Add(-24*time.Hour), utils.DefaultTimeValue, false, true) }, 5*time.Second, 1*time.Hour) @@ -168,12 +186,12 @@ func Init() { ScheduleTimerFunc("auto enable remote store", func() { cms.EnableHaveRestStores(jxcontext.AdminCtx, false, true) - cms.OpenRemoteStoreByJxStatus(jxcontext.AdminCtx, nil, nil, false, false, true) + // cms.OpenRemoteStoreByJxStatus(jxcontext.AdminCtx, nil, nil, false, false, true) }, openRemoteStoreTimeList) - ScheduleTimerFunc("SaveAndSendAlarmVendorSnapshot", func() { - cms.SaveAndSendAlarmVendorSnapshot(jxcontext.AdminCtx, nil, nil, false) - }, cms.WatchVendorStoreTimeList) + // ScheduleTimerFunc("SaveAndSendAlarmVendorSnapshot", func() { + // cms.SaveAndSendAlarmVendorSnapshot(jxcontext.AdminCtx, nil, nil, false) + // }, cms.WatchVendorStoreTimeList) ScheduleTimerFunc("RefreshPageActs", func() { act.RefreshPageActs(jxcontext.AdminCtx, []int{model.VendorIDEBAI}, time.Now().Add(-30*24*time.Hour), false) @@ -196,7 +214,7 @@ func Init() { cms.AutoFocusStoreSkusForTopSkus(jxcontext.AdminCtx, true, true) }, createStorePriceTimeList) ScheduleTimerFunc("GetCheckVendorCookie", func() { - event.GetCheckVendorCookie(jxcontext.AdminCtx, []int{model.VendorIDEBAI, model.VendorIDJD, model.VendorIDMTWM, model.VendorIDMTPS}, true) + event.GetCheckVendorCookie(jxcontext.AdminCtx, []int{model.VendorIDEBAI, model.VendorIDJD, model.VendorIDMTWM, model.VendorIDMTPS, model.VendorIDJDShop}, true) }, checkCookieList) ScheduleTimerFunc("SendSeckillSkusCountMsg", func() { cms.SendSeckillSkusCountMsg(jxcontext.AdminCtx, []int{model.VendorIDEBAI, model.VendorIDJD, model.VendorIDMTWM}, false, true) @@ -222,26 +240,45 @@ func Init() { ScheduleTimerFunc("CleanUserOrderSMSMark", func() { cms.CleanUserOrderSMSMark(jxcontext.AdminCtx) }, priceReferTimeList) - ScheduleTimerFunc("exSync", func() { - var ( - db = dao.GetDB() - storeList []int - exSyncStoreIDList string - syncFlag = 0 - ) - syncFlag = model.SyncFlagPriceMask - if (time.Now().Unix()/24*3600)%10 == 0 { - syncFlag |= model.SyncFlagSaleMask - } - if configs, err := dao.QueryConfigs(dao.GetDB(), "exSyncStoreIDList", model.ConfigTypeSys, ""); err == nil { - exSyncStoreIDList = configs[0].Value - } - storeIDList := strings.Split(exSyncStoreIDList, ",") - for _, v := range storeIDList { - storeList = append(storeList, int(utils.Str2Int64(v))) - } - cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetMultiStoreVendorIDs(), storeList, false, nil, []int{27379}, syncFlag, true, true) - }, exSyncList) + // ScheduleTimerFunc("exSync", func() { + // var ( + // db = dao.GetDB() + // storeList []int + // exSyncStoreIDList string + // syncFlag = 0 + // ) + // syncFlag = model.SyncFlagPriceMask + // if (time.Now().Unix()/24*3600)%10 == 0 { + // syncFlag |= model.SyncFlagSaleMask + // } + // if configs, err := dao.QueryConfigs(dao.GetDB(), "exSyncStoreIDList", model.ConfigTypeSys, ""); err == nil { + // exSyncStoreIDList = configs[0].Value + // } + // storeIDList := strings.Split(exSyncStoreIDList, ",") + // for _, v := range storeIDList { + // storeList = append(storeList, int(utils.Str2Int64(v))) + // } + // cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetMultiStoreVendorIDs(), storeList, false, nil, []int{27379}, syncFlag, true, true) + // }, exSyncList) + ScheduleTimerFunc("CreateOrderByPriceDefend", func() { + localjx.CreateOrderByPriceDefend(jxcontext.AdminCtx) + }, []string{ + "22:00:00", + }) + ScheduleTimerFunc("ChangeJxPriceByDiscountAct", func() { + act.ChangeJxPriceByDiscountAct(jxcontext.AdminCtx) + }, discountActJxList) + ScheduleTimerFunc("RefreshUserMemberStatus", func() { + cms.RefreshUserMemberStatus(jxcontext.AdminCtx) + }, updateActStatusTimeList) + //刷优惠券状态 + ScheduleTimerFunc("RefreshCouponsStatus", func() { + localjx.RefreshCouponsStatus(jxcontext.AdminCtx) + }, updateActStatusTimeList) + //刷新美团商超门店Token + ScheduleTimerFunc("RefreshMTWMToken", func() { + cms.RefreshMTWMToken(jxcontext.AdminCtx) + }, updateActStatusTimeList) } ScheduleTimerFunc("AutoSaleStoreSku", func() { cms.AutoSaleStoreSku(jxcontext.AdminCtx, nil, false) @@ -261,6 +298,18 @@ func Init() { }, []string{ "04:05:06", }) + //京东的订单信息解密密钥获取 + ScheduleTimerFuncByInterval(func() { + jdshop.InitKey() + }, 10*time.Second, 8*time.Hour) + ScheduleTimerFunc("ChangeJxPriceByDiscountAct", func() { + act.ChangeJxPriceByDiscountAct(jxcontext.AdminCtx) + }, discountActJxList) + ScheduleTimerFunc("CreateOrderByPriceDefend", func() { + localjx.CreateOrderByPriceDefend(jxcontext.AdminCtx) + }, []string{ + "22:00:00", + }) } if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieExdTOKEN", model.ConfigTypeCookie, ""); err == nil { ebaiStorePageCookieExdTOKEN = configs[0].Value @@ -299,6 +348,9 @@ func Init() { jdsCookie = configs[0].Value api.JdShopAPI.SetCookieWithStr(jdsCookie) } + if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie2", model.ConfigTypeCookie, ""); err == nil { + api.JdShop2API.SetCookieWithStr(configs[0].Value) + } if configs, err := dao.QueryConfigs(dao.GetDB(), "yinbaoCookie", model.ConfigTypeCookie, ""); err == nil { yinbaoCookie := configs[0].Value api.YinBaoAPI.SetCookie(".POSPALAUTH30220", yinbaoCookie) @@ -340,12 +392,12 @@ func syncStoreSku() { _, err = cms.CurVendorSync.LoopMultiStoresVendors(jxcontext.AdminCtx, db, "同步多门店平台商品库", false, true, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { vendorInfo := batchItemList[0].(*cms.MultiStoreVendorInfo) - _, err = cms.FullSyncVendorStuff(jxcontext.AdminCtx, task, vendorInfo.VendorID, vendorInfo.OrgCode, false, true) + _, err = cms.FullSyncVendorStuff(jxcontext.AdminCtx, task, 0, vendorInfo.VendorID, vendorInfo.OrgCode, false, true) return retVal, err }) errList.AddErr(err) - _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetMultiStoreVendorIDs(), nil, false, nil, []int{27379}, syncFlag, true, true) + _, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{0}, nil, false, nil, []int{27379}, syncFlag, true, true) // _, err = cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, db, partner.GetMultiStoreVendorIDs(), nil, false, []int{27379}, true, true) errList.AddErr(err) case 1: @@ -353,13 +405,13 @@ func syncStoreSku() { errList.AddErr(cms.SetSingleStoreSkuSyncModifyStatus(db, []int{1, 3})) // errList.AddErr(cms.SetSingleStoreSkuSyncModifyStatus(db, partner.GetSingleStoreVendorIDs())) - _, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, []int{1, 3}, nil, false, true, cms.AmendPruneAll, false) + // _, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, []int{1, 3}, nil, false, true, cms.AmendPruneAll, false) // _, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, partner.GetSingleStoreVendorIDs(), nil, false, true, cms.AmendPruneAll, false) errList.AddErr(err) SaveImportantTaskID(TaskNameSyncStoreSku, SpecialTaskID) - taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{1, 3}, nil, false, nil, nil, syncFlag, true, true) + taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{1, 3, 5}, nil, false, nil, nil, syncFlag, true, true) // taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, nil, nil, syncFlag, true, true) errList.AddErr(err2) @@ -371,9 +423,23 @@ func syncStoreSku() { tasksch.HandleTask(task, nil, true).Run() } +func doDailyWork2() { + globals.SugarLogger.Debug("doDailyWork2") + + //同步京东商城门店的商品 + cms.CurVendorSync.SyncJdsStoresSkus(jxcontext.AdminCtx, nil, true, true) + //刷新京东商城的门店库存 + cms.SyncJdsStoreStock(jxcontext.AdminCtx, true, true) + //刷新京东商城订单结算价 + orderman.RefreshJdShopOrdersEarningPrice(jxcontext.AdminCtx, utils.Time2Str(time.Now().AddDate(0, 0, -2)), utils.Time2Str(time.Now())) +} + func doDailyWork() { globals.SugarLogger.Debug("doDailyWork") + //同步商品额外前缀和水印图(打标记) + cms.SyncSkuExperfixAndWatermark(jxcontext.AdminCtx) + dao.SetStoresMapSyncStatus(dao.GetDB(), nil, nil, model.SyncFlagStoreStatus) cms.CurVendorSync.SyncStore2(jxcontext.AdminCtx, dao.GetDB(), nil, nil, true, true) @@ -392,19 +458,36 @@ func doDailyWork() { //刷新京东门店的等级 cms.RefreshJdLevel(jxcontext.AdminCtx) //删除操作日志 - event.DeleteOperateEventAndDetail(jxcontext.AdminCtx, time.Now().AddDate(0, -3, 0)) + // event.DeleteOperateEventAndDetail(jxcontext.AdminCtx, time.Now().AddDate(0, -3, 0)) //禁用没有绑定的门店 cms.DisabledStoreWithoutVendor(jxcontext.AdminCtx, true, true) //刷新物料订单状态 localjx.RefreshAllMatterOrderStatus(jxcontext.AdminCtx) //同步银豹到京西 - cms.CurVendorSync.SyncStoreSkusFromYb(jxcontext.AdminCtx, nil, true, true) - //刷新京东商城订单结算价 - orderman.RefreshJdShopOrdersEarningPrice(jxcontext.AdminCtx, time.Now().AddDate(0, 0, -3).Format("20060102"), time.Now().Format("20060102")) - //同步京东商城门店库存和商品 - cms.CurVendorSync.SyncJdsStoresSkus(jxcontext.AdminCtx, nil, true, true) + // cms.CurVendorSync.SyncStoreSkusFromYb(jxcontext.AdminCtx, nil, true, true) //同步上架京东商城待售商品 cms.RefreshJdsSkusStatus(jxcontext.AdminCtx) + //同步美团配送与否状态及美团门店是否存在 + cms.SetMTPSStatus(jxcontext.AdminCtx, 0, 0) + //售后单如果超过12小时没有审核,就自动通过 + RefreshAfsOrderStatusAccess(jxcontext.AdminCtx) +} + +func RefreshAfsOrderStatusAccess(ctx *jxcontext.Context) { + var ( + offset = 0 + pageSize = 9999 + db = dao.GetDB() + ) + afsOrderList, _, err := dao.GetAfsOrdersByPage(db, "", "", "", time.Now().AddDate(0, 0, -7), time.Now(), offset, pageSize) + if err != nil { + return + } + for _, v := range afsOrderList { + if v.Status == model.AfsOrderStatusWait4Approve && time.Now().Sub(v.AfsCreatedAt).Hours() > 12 { + defsch.FixedScheduler.AgreeOrRefuseRefund(ctx, v.AfsOrderID, v.VendorID, model.AfsTypePartRefund, "超时系统同意") + } + } } func RefreshRealMobile(ctx *jxcontext.Context, vendorID int, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) { diff --git a/business/jxstore/misc/store_score.go b/business/jxstore/misc/store_score.go index 269467ba8..0340dc879 100644 --- a/business/jxstore/misc/store_score.go +++ b/business/jxstore/misc/store_score.go @@ -11,6 +11,7 @@ import ( "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" "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" @@ -804,6 +805,7 @@ func GetWeeklyStoreScore(storeID, weekIndexParam int) (outWeeklyStoreScoreDataLi if weekIndexParam == -1 { outWeeklyStoreScoreDataList = weeklyStoreScoreDataList } else { + fmt.Println("testss", utils.Format4Output(weeklyStoreScoreDataList, false)) outWeeklyStoreScoreDataList = []*model.WeeklyStoreScore{weeklyStoreScoreDataList[weekIndexParam]} } } @@ -811,8 +813,27 @@ func GetWeeklyStoreScore(storeID, weekIndexParam int) (outWeeklyStoreScoreDataLi return outWeeklyStoreScoreDataList, err } -func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beginTime, endTime time.Time, isDesc bool, checkScoreLow, checkScoreHigh, offset, pageSize int) (storeTotalScoreEx model.StoreTotalScoreEx, err error) { +func GetStoreTotalScoreList(ctx *jxcontext.Context, storeIDList []int, cityCode int, keyWord string, beginTime, endTime time.Time, isDesc bool, checkScoreLow, checkScoreHigh, offset, pageSize int) (storeTotalScoreEx model.StoreTotalScoreEx, err error) { db := dao.GetDB() + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDList) > 0 { + for _, v := range storeIDList { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDList = nil + storeIDList = storeIDs2 + } + } storeTotalScoreMapData := make(map[int]*model.StoreTotalScore) storeTotalScoreList, err := dao.GetStoreTotalScoreList(db, storeIDList, cityCode, keyWord, beginTime, endTime) var filterStoreTotalScoreList []*model.StoreTotalScore diff --git a/business/jxstore/permission/permission.go b/business/jxstore/permission/permission.go new file mode 100644 index 000000000..ad3e16ac0 --- /dev/null +++ b/business/jxstore/permission/permission.go @@ -0,0 +1,415 @@ +package permission + +import ( + "fmt" + "strings" + "time" + + "git.rosy.net.cn/jx-callback/business/jxutils" + + "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" +) + +func GetMenu(ctx *jxcontext.Context, userID string) (menus []*model.Menu, err error) { + if userID == "" { + return dao.GetMenu(dao.GetDB(), "", 0, userID) + } else { + if user, err := dao.GetUserByID(dao.GetDB(), "user_id", userID); err == nil { + if user.Type&model.UserTypeRole != 0 { + return dao.GetMenuWithUser(dao.GetDB(), "", 0, userID) + } else { + return dao.GetMenu(dao.GetDB(), "", 0, "") + } + } + } + return dao.GetMenu(dao.GetDB(), "", 0, userID) +} + +func AddMenu(ctx *jxcontext.Context, menu *model.Menu) (err error) { + var ( + db = dao.GetDB() + ) + if menu == nil { + return fmt.Errorf("添加失败!menu nil") + } + if menu.Name == "" || menu.Level == 0 { + return fmt.Errorf("添加失败!menu 名称和等级必须有值!") + } + menus, err := dao.GetMenu(db, menu.Name, menu.Level, "") + if len(menus) > 0 { + return fmt.Errorf("添加失败!已存在相同名称的 menu name : %v", menu.Name) + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + dao.WrapAddIDCULDEntity(menu, ctx.GetUserName()) + err = dao.CreateEntity(db, menu) + dao.Commit(db) + return err +} + +func UpdateMenu(ctx *jxcontext.Context, menuID int, payload map[string]interface{}, isDelete bool) (num int64, err error) { + var ( + db = dao.GetDB() + ) + menu := &model.Menu{} + menu.ID = menuID + err = dao.GetEntity(db, menu) + if err != nil { + return 0, err + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if !isDelete { + valid := dao.StrictMakeMapByStructObject(payload, menu, ctx.GetUserName()) + if len(valid) > 0 { + if num, err = dao.UpdateEntityLogically(db, menu, valid, ctx.GetUserName(), nil); err != nil { + dao.Rollback(db) + return 0, err + } + } + } else { + menu.DeletedAt = time.Now() + num, err = dao.UpdateEntity(db, menu, "DeletedAt") + } + dao.Commit(db) + return num, err +} + +func GetRole(ctx *jxcontext.Context, name string) (roles []*model.Role, err error) { + var ( + db = dao.GetDB() + ) + roles, err = dao.GetRole(db, name, "") + for _, v := range roles { + if v.CityCodes != "" { + if cityInfos, err := dao.GetPlaces(db, jxutils.StrListToIntList(strings.Split(v.CityCodes, ","))); err == nil { + v.CityInfo = cityInfos + } + } + if v.StoreIDs != "" { + if stores, err := dao.GetStoreList(db, jxutils.StrListToIntList(strings.Split(v.StoreIDs, ",")), nil, nil, nil, nil, ""); err == nil { + v.Stores = stores + } + } + } + return roles, err +} + +func AddRole(ctx *jxcontext.Context, name string) (err error) { + var ( + db = dao.GetDB() + ) + roles, err := dao.GetRole(db, "", name) + if len(roles) > 0 { + return fmt.Errorf("添加失败!已存在相同名称的 role name : %v", name) + } + role := &model.Role{ + Name: name, + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + dao.WrapAddIDCULDEntity(role, ctx.GetUserName()) + err = dao.CreateEntity(db, role) + dao.Commit(db) + return err +} + +func UpdateRole(ctx *jxcontext.Context, roleID int, name string, isDelete bool, brandID int, cityCodes, storeIDs []int) (num int64, err error) { + var ( + db = dao.GetDB() + cityCodesStr []string + storeIDsStr []string + ) + for _, v := range cityCodes { + cityCodesStr = append(cityCodesStr, utils.Int2Str(v)) + } + for _, v := range storeIDs { + storeIDsStr = append(storeIDsStr, utils.Int2Str(v)) + } + if roleID == 1 { + return 0, fmt.Errorf("管理员不允许修改!") + } + role := &model.Role{} + role.ID = roleID + err = dao.GetEntity(db, role) + if err != nil { + return 0, err + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if !isDelete { + role.Name = name + role.UpdatedAt = time.Now() + role.LastOperator = ctx.GetUserName() + role.BrandID = brandID + role.CityCodes = strings.Join(cityCodesStr, ",") + role.StoreIDs = strings.Join(storeIDsStr, ",") + num, err = dao.UpdateEntity(db, role, "Name", "UpdatedAt", "LastOperator", "BrandID", "CityCodes", "StoreIDs") + } else { + role.DeletedAt = time.Now() + num, err = dao.UpdateEntity(db, role, "DeletedAt") + } + dao.Commit(db) + return num, err +} + +func GetUserRole(ctx *jxcontext.Context, userID string) (userRoles []*model.UserRole, err error) { + return dao.GetUserRole(dao.GetDB(), []string{userID}, nil) +} + +func UpdateUserRole(ctx *jxcontext.Context, userIDs []string, roleIDs []int) (err error) { + var ( + db = dao.GetDB() + roleIDMap = make(map[int]int) + nowRoleIDMap = make(map[int]int) + userRoleMap = make(map[string][]int) + addUserRoleMap = make(map[string][]int) + deleteUserRoleMap = make(map[string][]int) + ) + for _, v := range roleIDs { + roleIDMap[v] = 1 + } + userRoles, err := dao.GetUserRole(db, userIDs, nil) + if err != nil { + return err + } + if len(userRoles) > 0 { + for _, v := range userRoles { + userRoleMap[v.UserID] = append(userRoleMap[v.UserID], v.RoleID) + } + } + for _, userID := range userIDs { + nowRoleIDs := userRoleMap[userID] + for _, nowRoleID := range nowRoleIDs { + if roleIDMap[nowRoleID] == 0 { + deleteUserRoleMap[userID] = append(deleteUserRoleMap[userID], nowRoleID) + } + nowRoleIDMap[nowRoleID] = 1 + } + for roleID, _ := range roleIDMap { + if nowRoleIDMap[roleID] == 0 { + addUserRoleMap[userID] = append(addUserRoleMap[userID], roleID) + } + } + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if len(addUserRoleMap) > 0 { + for userID, roleIDs := range addUserRoleMap { + for _, roleID := range roleIDs { + userRole := &model.UserRole{ + UserID: userID, + RoleID: roleID, + } + dao.WrapAddIDCULDEntity(userRole, ctx.GetUserName()) + err = dao.CreateEntity(db, userRole) + } + } + } + if len(deleteUserRoleMap) > 0 { + for userID, roleIDs := range deleteUserRoleMap { + for _, roleID := range roleIDs { + userRoles, _ := dao.GetUserRole(db, []string{userID}, []int{roleID}) + if len(userRoles) > 0 { + userRoles[0].DeletedAt = time.Now() + userRoles[0].LastOperator = ctx.GetUserName() + _, err = dao.UpdateEntity(db, userRoles[0], "DeletedAt", "LastOperator") + } + } + } + } + for _, v := range userIDs { + if user, err := dao.GetUserByID(db, "user_id", v); err == nil { + user.Type = user.Type | model.UserTypeRole + dao.UpdateEntity(db, user, "Type") + } + } + dao.Commit(db) + return err +} + +func GetRoleMenu(ctx *jxcontext.Context, roleID int) (roleMenus []*model.RoleMenu, err error) { + return dao.GetRoleMenu(dao.GetDB(), []int{roleID}, nil) +} + +func UpdateRoleMenu(ctx *jxcontext.Context, roleIDs, menuIDs []int) (err error) { + var ( + db = dao.GetDB() + menuIDMap = make(map[int]int) + nowMenuIDMap = make(map[int]int) + roleMenuMap = make(map[int][]int) + addRoleMenuMap = make(map[int][]int) + deleteRoleMenuMap = make(map[int][]int) + ) + for _, v := range menuIDs { + menuIDMap[v] = 1 + } + roleMenus, err := dao.GetRoleMenu(db, roleIDs, nil) + if err != nil { + return err + } + if len(roleMenus) > 0 { + for _, v := range roleMenus { + roleMenuMap[v.RoleID] = append(roleMenuMap[v.RoleID], v.MenuID) + } + } + for _, roleID := range roleIDs { + nowMenuIDs := roleMenuMap[roleID] + for _, nowMenuID := range nowMenuIDs { + if menuIDMap[nowMenuID] == 0 { + deleteRoleMenuMap[roleID] = append(deleteRoleMenuMap[roleID], nowMenuID) + } + nowMenuIDMap[nowMenuID] = 1 + } + for menuID, _ := range menuIDMap { + if nowMenuIDMap[menuID] == 0 { + addRoleMenuMap[roleID] = append(addRoleMenuMap[roleID], menuID) + } + } + } + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if len(addRoleMenuMap) > 0 { + for roleID, menuIDs := range addRoleMenuMap { + for _, menuID := range menuIDs { + roleMenu := &model.RoleMenu{ + RoleID: roleID, + MenuID: menuID, + } + dao.WrapAddIDCULDEntity(roleMenu, ctx.GetUserName()) + err = dao.CreateEntity(db, roleMenu) + } + } + } + if len(deleteRoleMenuMap) > 0 { + for roleID, menuIDs := range deleteRoleMenuMap { + for _, menuID := range menuIDs { + roleMenus, _ := dao.GetRoleMenu(db, []int{roleID}, []int{menuID}) + if len(roleMenus) > 0 { + roleMenus[0].DeletedAt = time.Now() + roleMenus[0].LastOperator = ctx.GetUserName() + _, err = dao.UpdateEntity(db, roleMenus[0], "DeletedAt", "LastOperator") + } + } + } + } + dao.Commit(db) + return err +} + +func GetUserStoresResultMap(userID string) (resultMap map[int]int, err error) { + var ( + db = dao.GetDB() + // brandIDMap = make(map[int]int) + // cityCodeMap = make(map[int]int) + // storeIDMap = make(map[int]int) + ) + resultMap = make(map[int]int) + userRoles, err := dao.GetUserRole2(db, []string{userID}, nil) + for _, v := range userRoles { + var ( + brandIDs, cityCodes, storeIDs []int + ) + // if _, ok := brandIDMap[v.BrandID]; !ok { + // brandIDMap[v.BrandID] = 1 + // } + // if v.CityCodes != "" { + // for _, cityCode := range jxutils.StrListToIntList(strings.Split(v.CityCodes, ",")) { + // if _, ok := cityCodeMap[cityCode]; !ok { + // cityCodeMap[cityCode] = 1 + // } + // } + // } + // if v.StoreIDs != "" { + // for _, storeID := range jxutils.StrListToIntList(strings.Split(v.StoreIDs, ",")) { + // if _, ok := storeIDMap[storeID]; !ok { + // storeIDMap[storeID] = 1 + // } + // } + // } + if v.CityCodes == "" && v.StoreIDs == "" { + continue + } + if v.BrandID != 0 { + brandIDs = append(brandIDs, v.BrandID) + } + if v.CityCodes != "0" && v.CityCodes != "" { + cityCodes = append(cityCodes, jxutils.StrListToIntList(strings.Split(v.CityCodes, ","))...) + } + if v.StoreIDs != "" { + storeIDs = append(storeIDs, jxutils.StrListToIntList(strings.Split(v.StoreIDs, ","))...) + } + if stores, err := dao.GetStoreList(db, storeIDs, cityCodes, nil, brandIDs, nil, ""); len(stores) > 0 && err == nil { + for _, v := range stores { + if _, ok := resultMap[v.ID]; !ok { + resultMap[v.ID] = v.ID + } + } + } + } + // for k, _ := range brandIDMap { + // brandIDs = append(brandIDs, k) + // } + // for k, _ := range cityCodeMap { + // cityCodes = append(cityCodes, k) + // } + // for k, _ := range storeIDMap { + // storeIDs = append(storeIDs, k) + // } + // if stores1, err := dao.GetStoreList(db, nil, nil, brandIDs, nil, nil, ""); len(stores1) > 0 && err == nil { + // stores = append(stores, stores1...) + // } + // if stores2, err := dao.GetStoreList(db, nil, cityCodes, nil, nil, nil, ""); len(stores2) > 0 && err == nil { + // stores = append(stores, stores2...) + // } + // if stores3, err := dao.GetStoreList(db, storeIDs, nil, nil, nil, nil, ""); len(stores3) > 0 && err == nil { + // stores = append(stores, stores3...) + // } + + return resultMap, err +} + +func IsRoled(ctx *jxcontext.Context) bool { + if ctx.GetUserName() != "jxadmin" { + if user, err := dao.GetUserByID(dao.GetDB(), "user_id", ctx.GetUserID()); err == nil { + if user.Type&model.UserTypeRole != 0 { + return true + } + } + } + return false +} diff --git a/business/jxstore/report/report.go b/business/jxstore/report/report.go index 6fadcdcfe..ecd472c31 100644 --- a/business/jxstore/report/report.go +++ b/business/jxstore/report/report.go @@ -97,7 +97,7 @@ func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int, isAsyn resultMap = make(map[int]map[int]*model.PriceReferSnapshot) resultCountryMap = make(map[int]*model.PriceReferSnapshot) ) - storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") + storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, nil, "") if err != nil { return result, err } @@ -283,3 +283,103 @@ func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int, isAsyn } return hint, err } + +type GetManageStateResult struct { + OpenStoreCount int `json:"openStoreCount"` //营业店铺数 + HaveRestStoreCount int `json:"haveRestStoreCount"` //临时休息店铺数 + RestStoreCount int `json:"restStoreCount"` //休息店铺数 + FinishOrderState *GetManageStateOrderInfo //完成订单情况 + IngOrderState *GetManageStateOrderInfo //进行中订单情况 + CancelOrderState *GetManageStateOrderInfo //取消订单情况 +} + +type GetManageStateOrderInfo struct { + ActualPayPrice int `json:"actualPayPrice"` //支付总额 + TotalShopMoney int `json:"totalShopMoney"` //平台结算 + DesiredFee int `json:"desiredFee"` //配送费 + Yhld string `json:"yhld"` //优惠力度(支付总额-平台结算-配送支出)/支付总额*100% +} + +func getStoreStatusCount(db *dao.DaoDB, cityCodes []int, vendorID, status int) (count int, err error) { + countType := &struct{ Count int }{} + sqlParams := []interface{}{} + sql := ` + SELECT COUNT(DISTINCT a.id) count + FROM store a + LEFT JOIN store_map b ON a.id = b.store_id AND b.deleted_at = ? + WHERE a.deleted_at = ? + ` + sqlParams = append(sqlParams, utils.DefaultTimeValue, utils.DefaultTimeValue) + if len(cityCodes) > 0 { + sql += " AND a.city_code IN (" + dao.GenQuestionMarks(len(cityCodes)) + ")" + sqlParams = append(sqlParams, cityCodes) + } + if vendorID != -1 { + sql += " AND b.vendor_id = ? AND b.status = ?" + sqlParams = append(sqlParams, vendorID, status) + } else { + sql += " AND a.status = ?" + sqlParams = append(sqlParams, status) + } + err = dao.GetRow(db, &countType, sql, sqlParams) + return countType.Count, err +} + +func getOrderStateCount(db *dao.DaoDB, cityCodes []int, vendorID, status int) (getManageStateOrderInfo *GetManageStateOrderInfo, err error) { + sqlParams := []interface{}{} + getManageStateOrderInfo = &GetManageStateOrderInfo{} + endTime := time.Now().AddDate(0, -3, 0) + sql := ` + SELECT SUM(b.actual_pay_price) actual_pay_price, SUM(b.total_shop_money) total_shop_money, SUM(IFNULL(c.desired_fee, 0)) desired_fee + FROM store a + LEFT JOIN goods_order b ON a.id = IF(b.jx_store_id = 0, b.store_id, b.jx_store_id) + LEFT JOIN waybill c ON IF(b.waybill_vendor_id = -1,b.vendor_order_id,b.vendor_waybill_id) = c.vendor_waybill_id + WHERE a.deleted_at = ? AND a.status <> ? + AND b.order_created_at < ? AND b.order_created_at > ? + ` + sqlParams = append(sqlParams, utils.DefaultTimeValue, model.StoreStatusDisabled, time.Now(), endTime) + if len(cityCodes) > 0 { + sql += " AND a.city_code IN (" + dao.GenQuestionMarks(len(cityCodes)) + ")" + sqlParams = append(sqlParams, cityCodes) + } + if vendorID != -1 { + sql += " AND b.vendor_id = ?" + sqlParams = append(sqlParams, vendorID) + } + if status != model.OrderStatusDelivering { + sql += " AND b.status = ?" + sqlParams = append(sqlParams, status) + } else { + sql += " AND b.status < ? AND b.status >= ?" + sqlParams = append(sqlParams, model.OrderStatusEndBegin, model.OrderStatusWait4Pay) + } + err = dao.GetRow(db, &getManageStateOrderInfo, sql, sqlParams) + getManageStateOrderInfo.Yhld = utils.Float64ToStr(math.Round((float64(getManageStateOrderInfo.ActualPayPrice-getManageStateOrderInfo.TotalShopMoney-getManageStateOrderInfo.DesiredFee) / float64(getManageStateOrderInfo.ActualPayPrice) * 100))) + "%" + return getManageStateOrderInfo, err +} + +func GetManageState(ctx *jxcontext.Context, cityCodes []int, vendorID int) (getManageStateResult *GetManageStateResult, err error) { + var ( + db = dao.GetDB() + ) + getManageStateResult = &GetManageStateResult{} + if openCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusOpened); err == nil { + getManageStateResult.OpenStoreCount = openCount + } + if haveRestCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusHaveRest); err == nil { + getManageStateResult.HaveRestStoreCount = haveRestCount + } + if restCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusClosed); err == nil { + getManageStateResult.RestStoreCount = restCount + } + if finishCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusFinished); err == nil { + getManageStateResult.FinishOrderState = finishCount + } + if ingCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusDelivering); err == nil { + getManageStateResult.IngOrderState = ingCount + } + if cancelCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusCanceled); err == nil { + getManageStateResult.CancelOrderState = cancelCount + } + return getManageStateResult, err +} diff --git a/business/jxstore/tempop/tempop.go b/business/jxstore/tempop/tempop.go index 9257cd023..a629969db 100644 --- a/business/jxstore/tempop/tempop.go +++ b/business/jxstore/tempop/tempop.go @@ -8,8 +8,6 @@ import ( "strings" "time" - "git.rosy.net.cn/baseapi/platformapi/jdshopapi" - "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/partner/delivery" "github.com/360EntSecGroup-Skylar/excelize" @@ -1006,7 +1004,7 @@ func CreateConsumerFromOrders(ctx *jxcontext.Context, vendorIDs []int, fromDate, } } if order2 == nil && order.VendorID == model.VendorIDMTWM && time.Now().Sub(curDate) < 60*24*time.Hour { - order2, err = handler.GetOrder(order.VendorOrgCode, order.VendorOrderID) + order2, err = handler.GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID) } if order2 != nil { if order2.VendorUserID != "" && order.VendorUserID != order2.VendorUserID { @@ -1236,14 +1234,14 @@ func FixMtwmCategory(ctx *jxcontext.Context, mtwmStoreIDs []int, isAsync, isCont func JdStoreInfo1125() (hint string, err error) { fileName := "老格恢复拓店进度.xlsx" db := dao.GetDB() - storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "") + storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err == nil { var validStoreList []*dao.StoreDetail for _, v := range storeList { if v.Status != model.StoreStatusDisabled && v.CreatedAt.Sub(utils.Str2Time("2019-10-01")) > 0 { storeInfo, err := api.JdAPI.GetStoreInfoByStationNo2(v.VendorStoreID) if err == nil && storeInfo.CreateTime.GoTime().Sub(utils.Str2Time("2019-10-25")) > 0 { - if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID); err == nil { + if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID, ""); err == nil { validStoreList = append(validStoreList, storeDetail) } } @@ -1500,120 +1498,512 @@ func addSku(outSkuId string, cagtegoryId int, shopCategories []int64, brandId in } func UploadJdsImage(ctx *jxcontext.Context) (err error) { - // db := dao.GetDB() - // result1, _ := api.JdShopAPI.GetProvince() - // for _, v := range result1 { - // place1, _ := dao.GetPlaceByName(db, v.AreaName, 1, 0) - // place1.JdsCode = v.AreaID - // dao.UpdateEntity(db, place1, "JdsCode") - // result2, _ := api.JdShopAPI.GetCity(v.AreaID) - // for _, vv := range result2 { - // place2, _ := dao.GetPlaceByName(db, vv.AreaName, 2, 0) - // place2.JdsCode = vv.AreaID - // dao.UpdateEntity(db, place2, "JdsCode") - // place22, _ := dao.GetPlaceByName(db, vv.AreaName, 3, 0) - // if place22 != nil { - // place22.JdsCode = vv.AreaID - // dao.UpdateEntity(db, place22, "JdsCode") - // } - // result3, _ := api.JdShopAPI.GetCounty(vv.AreaID) - // for _, vvv := range result3 { - // place3, _ := dao.GetPlaceByName(db, vvv.AreaName, 3, 0) - // place3.JdsCode = vvv.AreaID - // dao.UpdateEntity(db, place3, "JdsCode") - // } + // var ( + // jdStoreIDs = []string{"12007046"} + // jdStoreIDxipu = "12005417" + // skuMap = make(map[string]partner.StoreSkuInfo) + // priceList = make(map[string][]*partner.StoreSkuInfo) + // statusList1 = make(map[string][]*partner.StoreSkuInfo) + // statusList2 = make(map[string][]*partner.StoreSkuInfo) + // stockList = make(map[string][]*partner.StoreSkuInfo) + // vendorOrgCode = "320406" + // vendorOrgCode = "82029" + // ) + + // handler := partner.GetPurchasePlatformFromVendorID(model.VendorIDJD).(partner.IPurchasePlatformStoreSkuHandler) + // multiHandler := partner.GetPurchasePlatformFromVendorID(model.VendorIDJD).(partner.IMultipleStoresHandler) + // allSkuNameInfoList, err := multiHandler.GetSkus(ctx, vendorOrgCode, 0, "") + // skuInfos := storeSkuFullList2BareFilter(allSkuNameInfoList) + // outStoreSkuList, err := handler.GetStoreSkusBareInfo(ctx, vendorOrgCode, nil, 0, jdStoreIDxipu, skuInfos) + // for _, vv := range outStoreSkuList { + // skuMap[vv.VendorSkuID] = *vv + // } + // for _, jdStoreID := range jdStoreIDs { + // skuInfos2 := storeSkuFullList2BareFilter(allSkuNameInfoList) + // outStoreSkuList2, _ := handler.GetStoreSkusBareInfo(ctx, vendorOrgCode, nil, 0, jdStoreID, skuInfos2) + // for _, v := range outStoreSkuList2 { + // v.VendorPrice = utils.Float64TwoInt64(float64(v.VendorPrice) * 1.05) + // priceList[jdStoreID] = append(priceList[jdStoreID], v) + // a := skuMap[v.VendorSkuID] + // if &a == nil { + // continue + // } + // if a.VendorPrice != v.VendorPrice { + // v.VendorPrice = a.VendorPrice + // priceList[jdStoreID] = append(priceList[jdStoreID], v) + // } + // if a.Status != v.Status { + // v.Status = a.Status + // if v.Status == model.SkuStatusNormal { + // statusList1[jdStoreID] = append(statusList1[jdStoreID], v) + // } else { + // statusList2[jdStoreID] = append(statusList2[jdStoreID], v) // } // } - - ///建店 - // beginTime := utils.Str2Time("2020-05-18") - // endTime := utils.Str2Time("2020-05-24") - // result, _ := misc.GetStoreTotalScoreList(nil, 0, "", beginTime, endTime, true, 50, 100, 1, 700) - // for _, v := range result.StoreTotalScoreList { - // storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDJX}, []int{v.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") - // if len(storeMaps) == 0 { - // stores, _ := dao.GetStoreList(db, []int{v.StoreID}, nil, nil, nil, "") - // store := stores[0] - // if store.Status != model.StoreStatusDisabled && !strings.Contains(store.Name, "不做") { - // pricePercentagePack := "" - // if store.PayPercentage >= 90 { - // pricePercentagePack = "京西100" - // } else if store.PayPercentage >= 80 { - // pricePercentagePack = "京西80" - // } else { - // pricePercentagePack = "京西70" - // } - // storeMap := &model.StoreMap{ - // Status: 1, - // VendorID: model.VendorIDJX, - // AutoPickup: 1, - // DeliveryCompetition: 1, - // PricePercentage: 100, - // IsSync: 1, - // VendorStoreID: utils.Int2Str(v.StoreID), - // PricePercentagePack: pricePercentagePack, - // } - // _, err = cms.AddStoreVendorMap(ctx, db, model.VendorIDJX, "", v.StoreID, storeMap) - // if err != nil { - // continue - // } - // } + // if a.Stock != v.Stock { + // v.Stock = a.Stock + // stockList[jdStoreID] = append(stockList[jdStoreID], v) + // } // } // } - - //京东商城街道name - // var stores []*model.Store + // task := tasksch.NewParallelTask("syncStoreSkuNew", 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: + // if len(priceList) > 0 { + // for k, v := range priceList { + // _, err = putils.FreeBatchStoreSkuInfo("更新门店商品价格", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + // failedList, err := handler.UpdateStoreSkusPrice(ctx, vendorOrgCode, 0, k, batchedStoreSkuList) + // if len(failedList) > 0 { + // task.AddFailedList(failedList) + // } + // return nil, 1, err + // }, ctx, task, v, 50, true) + // } + // } + // case 1: + // if len(statusList1) > 0 { + // for k, v := range statusList1 { + // _, err = putils.FreeBatchStoreSkuInfo("更新门店商品状态", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + // failedList, err := handler.UpdateStoreSkusStatus(ctx, vendorOrgCode, 0, k, batchedStoreSkuList, batchedStoreSkuList[0].Status) + // if len(failedList) > 0 { + // task.AddFailedList(failedList) + // } + // return nil, 1, err + // }, ctx, task, v, 50, true) + // } + // } + // case 2: + // case 3: + // if len(stockList) > 0 { + // for k, v := range stockList { + // _, err = putils.FreeBatchStoreSkuInfo("更新门店商品库存", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) { + // failedList, err := handler.UpdateStoreSkusStock(ctx, vendorOrgCode, 0, k, batchedStoreSkuList) + // if len(failedList) > 0 { + // task.AddFailedList(failedList) + // } + // return nil, 1, err + // }, ctx, task, v, 50, true) + // } + // } + // } + // return retVal, err + // }, []int{0}) + // tasksch.HandleTask(task, nil, true).Run() + // _, err = task.GetResult(0) + //建店 + // var ( + // storeMaps []*model.StoreMap + // db = dao.GetDB() + // ) + // if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie2", model.ConfigTypeCookie, ""); err == nil { + // api.JdShop2API.SetCookieWithStr(configs[0].Value) + // } // sql := ` - // SELECT b.* - // FROM store_map a, store b - // WHERE a.store_id = b.id - // AND a.vendor_store_id = '' AND a.vendor_id = 5 AND a.deleted_at = ? - // AND b.deleted_at = ? + // SELECT * from store_map where vendor_id = 5 and deleted_at = '1970-01-01 00:00:00' and vendor_org_code = 2 and store_id <> 667281 + // AND store_id <> 100000 + // AND store_id <> 102919 + // AND LENGTH(vendor_store_id) < 9 // ` - // sqlParams := []interface{}{utils.DefaultTimeValue, utils.DefaultTimeValue} - // err = dao.GetRows(db, &stores, sql, sqlParams) - // for _, v := range stores { - // result, _ := api.AutonaviAPI.GetCoordinateAreaInfo(jxutils.IntCoordinate2Standard(v.Lng), jxutils.IntCoordinate2Standard(v.Lat)) - // if result["regeocode"] != nil { - // street := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})["township"].(string) - // if street != "" { - // storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, []int{v.ID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") - // storeMap := storeMaps[0] - // storeMap.JdsStreetName = street - // dao.UpdateEntity(db, storeMap, "JdsStreetName") + // err = dao.GetRows(db, &storeMaps, sql, nil) + // for _, v := range storeMaps { + // store, _ := dao.GetStoreDetail(db, v.StoreID, model.VendorIDJDShop, "2") + // err = api.JdShop2API.DeleteStoresByID(utils.Str2Int64(store.VendorStoreID)) + // time.Sleep(time.Second) + // data, _, _ := jxutils.DownloadFileByURL(jdshopapi.JdsStoreImg) + // url, _ := api.JdShop2API.UploadImageNew(data, "2659335b16e3880e367759b8fc675933.tem.png") + // ex := store.LicenceExpire + // if ex == "" { + // ex = utils.Time2Str(utils.Str2Time(store.LicenceValid).AddDate(0, 6, 0)) + // } + // if !strings.Contains(ex, "00:00:00") { + // ex += " 00:00:00" + // } + // var url2 string + // if store.Licence != "" { + // data2, _, _ := jxutils.DownloadFileByURL(store.Licence) + // fileName := store.Licence[strings.LastIndex(store.Licence, "/")+1 : len(store.Licence)] + // url2, _ = api.JdShop2API.UploadImageNew(data2, fileName) + // } + // storeName := store.Name + // if strings.Contains(storeName, "(") { + // storeName = storeName[0:strings.Index(storeName, "(")] + storeName[strings.Index(storeName, ")")+3:len(storeName)] + // } + // if strings.Contains(storeName, "(") { + // storeName = storeName[0:strings.Index(storeName, "(")] + storeName[strings.Index(storeName, ")")+3:len(storeName)] + // } + // if strings.Contains(storeName, ".") { + // storeName = strings.ReplaceAll(storeName, ".", "") + // } + // if strings.Contains(storeName, "-") { + // storeName = strings.ReplaceAll(storeName, "-", "") + // } + // if strings.Contains(storeName, " ") { + // storeName = strings.ReplaceAll(storeName, " ", "") + // } + // storeName = "京西菜市" + strings.ReplaceAll(storeName, "店", "") + "生鲜店" + // if len(storeName) > 30 { + // storeName = utils.LimitUTF8StringLen2(storeName, 30) + // } + // param := &jdshopapi.UpdateBasicParam{ + // StoreName: storeName, + // CategoryID2: 4, + // Coordinate: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)), + // BussinessBeginTime: int2TimeStr(int(store.OpenTime1)), + // BussinessEndTime: int2TimeStr(int(store.CloseTime1)), + // ImgURL: url, + // StorePhone: store.Tel1, + // AddName: store.Address, + // AddCode3: store.JdsCode, + // CategoryID1: 3, + // } + // if url2 != "" { + // param.CategoryID1 = 34 + // param.CategoryID2 = 62 + // param.QualificationRequests = []*jdshopapi.QualificationRequests{ + // &jdshopapi.QualificationRequests{ + // QualificationID: 41, + // QualificationName: "营业执照", + // QualificationNo: store.LicenceCode, + // QualificationURL: url2, + // StartTime: utils.Time2Str(utils.Str2Time(store.LicenceValid)), + // EndingTime: ex, + // Time: []string{utils.Time2Str(utils.Str2Time(store.LicenceValid)), ex}, + // }, + // } + // } + // if store.JdsStreetCode != 0 { + // param.AddCode3 = store.JdsStreetCode + // } + // if param.AddCode3 == 0 { + // param.AddCode3 = store.JdCode + // } + // //证明这个店可能隶属直辖市或者东莞 + // if model.ZXCityCodeMap[store.CityCode] != "" { + // result, _ := api.AutonaviAPI.GetCoordinateAreaInfo(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat)) + // if result["regeocode"] != nil { + // street := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})["township"].(string) + // if street != "" { + // result1, _ := api.JdShopAPI.GetProvince() + // for _, v := range result1 { + // if strings.Contains(store.CityName, v.AreaName) { + // result2, _ := api.JdShopAPI.GetCity(v.AreaID) + // for _, vv := range result2 { + // if strings.Contains(store.DistrictName, vv.AreaName) { + // result3, _ := api.JdShopAPI.GetCounty(vv.AreaID) + // for _, vvv := range result3 { + // if street == vvv.AreaName { + // param.AddCode3 = vvv.AreaID + // break + // } + // } + // } + // } + // } + // } + // } + // } + // } + // if vendorStroeID, err := api.JdShop2API.SubmitBasic(param); err == nil { + // v.VendorStoreID = utils.Int64ToStr(vendorStroeID) + // dao.UpdateEntity(db, v, "VendorStoreID") + // time.Sleep(time.Second) + // err = api.JdShop2API.UpdateExpand(int(vendorStroeID)) + // } + // } + //分类 + // var ( + // db = dao.GetDB() + // ) + // catResult, _ := api.JdShop2API.FindShopCategories() + // for _, v := range catResult { + // var skuCat *model.SkuCategory + // sql := ` + // SELECT * + // FROM sku_category + // WHERE deleted_at = ? + // AND name = ? + // AND is_exd_spec = 0 + // ` + // sqlParams := []interface{}{utils.DefaultTimeValue, v.Name} + // err = dao.GetRow(db, &skuCat, sql, sqlParams) + // if skuCat != nil { + // var storeSkuCat *model.StoreSkuCategoryMap + // sql2 := ` + // SELECT * + // FROM store_sku_category_map + // WHERE store_id = ? + // AND deleted_at = ? + // AND category_id = ? + // ` + // sqlParams2 := []interface{}{100000, utils.DefaultTimeValue, skuCat.ID} + // err = dao.GetRow(db, &storeSkuCat, sql2, sqlParams2) + // if storeSkuCat != nil { + // storeSkuCat.JdsID = v.CID + // dao.UpdateEntity(db, storeSkuCat, "JdsID") // } // } // } - - // var stores []*model.Store + //京东商城补身份证 + // var ( + // storeMaps []*model.StoreMap + // db = dao.GetDB() + // ) // sql := ` - // SELECT a.* - // FROM store a - // LEFT JOIN store_map b ON a.id = b.store_id AND b.vendor_id = 5 AND b.deleted_at = '1970-01-01 00:00:00' - // WHERE 1=1 - // AND (a.status = 1 OR a.status = 0) - // AND b.id IS NULL - // AND a.deleted_at = '1970-01-01 00:00:00' + // SELECT * from store_map where vendor_id = 5 and deleted_at = '1970-01-01 00:00:00' and vendor_org_code = 2 + // and store_id <> 100206 // ` - // err = dao.GetRows(db, &stores, sql, nil) - // for _, v := range stores { - // storeMap := &model.StoreMap{ - // Status: 1, - // VendorID: model.VendorIDJDShop, - // AutoPickup: 1, - // DeliveryCompetition: 1, - // PricePercentage: 100, - // IsSync: 1, - // SyncRule: 1, + // dao.GetRows(db, &storeMaps, sql, nil) + // for _, v := range storeMaps { + // detail, _ := api.JdShop2API.ShopDetail(utils.Str2Int(v.VendorStoreID)) + // storeDetail, _ := dao.GetStoreDetail(db, v.StoreID, model.VendorIDJDShop, "2") + + // var ( + // url2 string + // idCode string + // startTime string + // ) + // if storeDetail.IDCardFront != "" { + // data2, _, _ := jxutils.DownloadFileByURL(storeDetail.IDCardFront) + // fileName := storeDetail.IDCardFront[strings.LastIndex(storeDetail.IDCardFront, "/")+1 : len(storeDetail.IDCardFront)] + // url2, _ = api.JdShop2API.UploadImageNew(data2, fileName) + // } else { + // data2, _, _ := jxutils.DownloadFileByURL("http://image.jxc4.com/image/a9bfc170a950ab9a4c76bd10b48b222b.tem.jpg") + // fileName := "a9bfc170a950ab9a4c76bd10b48b222b.tem.jpg" + // url2, _ = api.JdShop2API.UploadImageNew(data2, fileName) // } - // _, err = cms.AddStoreVendorMap(ctx, db, model.VendorIDJDShop, "", v.ID, storeMap) - // if err != nil { - // continue + // if storeDetail.IDCode == "" { + // idCode = "610126198012230014" + // } else { + // idCode = storeDetail.IDCode + // } + // if storeDetail.IDValid == "" { + // startTime = "2013-01-25 00:00:00" + // } else { + // startTime = utils.Time2Str(utils.Str2Time(storeDetail.IDValid)) + // } + // ex := storeDetail.IDExpire + // if ex == "" { + // ex = utils.Time2Str(utils.Str2Time(storeDetail.IDValid).AddDate(20, 0, 0)) + // } + // if !strings.Contains(ex, "00:00:00") { + // ex += " 00:00:00" + // } + // api.JdShop2API.UpdateBasic(&jdshopapi.UpdateBasicParam{ + // StoreID: detail.StoreID, + // StoreName: detail.StoreName, + // CategoryID2: detail.CategoryID2, + // Coordinate: detail.Coordinate, + // BussinessBeginTime: detail.BussinessBeginTime, + // BussinessEndTime: detail.BussinessEndTime, + // ImgURL: detail.ImgURL, + // StorePhone: detail.StorePhone, + // AddName: storeDetail.Address, + // AddCode1: detail.AddCode1, + // AddCode2: detail.AddCode2, + // AddCode3: detail.AddCode3, + // CategoryID1: detail.CategoryID1, + // QualificationRequests: []*jdshopapi.QualificationRequests{ + // &jdshopapi.QualificationRequests{ + // QualificationID: 41, + // QualificationName: "营业执照", + // QualificationNo: detail.QualificationInfoTOList[0].QualificationNo, + // QualificationURL: detail.QualificationInfoTOList[0].QualificationURL, + // StartTime: detail.QualificationInfoTOList[0].StartTime, + // EndingTime: detail.QualificationInfoTOList[0].EndingTime, + // Time: []string{detail.QualificationInfoTOList[0].StartTime, detail.QualificationInfoTOList[0].EndingTime}, + // }, + // &jdshopapi.QualificationRequests{ + // QualificationID: 42, + // QualificationName: "身份证件", + // QualificationNo: idCode, + // QualificationURL: url2, + // StartTime: startTime, + // EndingTime: ex, + // Time: []string{startTime, ex}, + // }, + // }, + // }) + // } + // var ( + // db = dao.GetDB() + // vendorThingIDs []int64 + // ) + // storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, []int{model.StoreStatusOpened, model.StoreStatusHaveRest, model.StoreStatusClosed}, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "320406") + // things, _ := dao.GetThingMapList(db, model.ThingTypeSku, []int{model.VendorIDJD}, nil, []string{"320406"}) + // thingIDmap := make(map[int64]string) + + // for _, v := range things { + // if v.VendorThingID != "" { + // // lists = append(lists, &jdapi.SkuIdEntity{ + // // OutSkuId: utils.Int64ToStr(v.ThingID), + // // }) + // vendorThingIDs = append(vendorThingIDs, utils.Str2Int64(v.VendorThingID)) + // thingIDmap[utils.Str2Int64(v.VendorThingID)] = utils.Int64ToStr(v.ThingID) // } // } - _, err = api.JdShopAPI.AllOrders(&jdshopapi.AllOrdersParam{ - Current: 1, - PageSize: 10, - }) + + // task := tasksch.NewParallelTask("uuuuu", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, + // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + // storeMap := batchItemList[0].(*model.StoreMap) + // FreeBatchInfo("uuuuu2", func(task tasksch.ITask, batchedStoreSkuList []int64) (result interface{}, successCount int, err error) { + // priceInfo, _ := api.JdAPI.GetStationInfoList(storeMap.VendorStoreID, batchedStoreSkuList) + // var list []*jdapi.SkuIdEntity + // for _, vv := range priceInfo { + // if vv.VipPrice != 0 { + // fmt.Println("vipPrice uuu", vv.SkuID) + // list = append(list, &jdapi.SkuIdEntity{ + // OutSkuId: thingIDmap[vv.SkuID], + // }) + // } + // } + // err = api.JdAPI.DelVipPrice(utils.Int2Str(storeMap.StoreID), list) + // return result, 0, err + // }, ctx, task, vendorThingIDs, 50, true) + // return retVal, err + // }, storeMaps) + // tasksch.HandleTask(task, nil, true).Run() + // _, err = task.GetResult(0) + stores := []int{} + for i := 1; i < 26; i++ { + result, _ := api.JdShop2API.ShopList(i) + for _, v := range result.List { + if v.Kilometres == "" { + if err = api.JdShop2API.CreateGisFence(v.StoreID, "1"); err != nil { + stores = append(stores, v.StoreID) + } + } + } + } + fmt.Println("resultstores112", stores) return err } + +func FreeBatchInfo2(name string, handler func(tasksch.ITask, []*jdapi.SkuIdEntity) (interface{}, int, error), ctx *jxcontext.Context, parentTask tasksch.ITask, storeSkuList []*jdapi.SkuIdEntity, batchSize int, isContinueWhenError bool) (resultList []interface{}, err error) { + task := tasksch.NewParallelTask2(fmt.Sprintf("FreeBatchInfo:%s", name), tasksch.NewParallelConfig().SetParallelCount(1).SetBatchSize(batchSize).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, successCount int, err error) { + batchStoreSkuList := make([]*jdapi.SkuIdEntity, len(batchItemList)) + for k, v := range batchItemList { + batchStoreSkuList[k] = v.(*jdapi.SkuIdEntity) + } + retVal, successCount, err = handler(task, batchStoreSkuList) + if err != nil { + retVal = nil + } + return retVal, successCount, err + }, storeSkuList) + tasksch.HandleTask(task, parentTask, false).Run() + resultList, err = task.GetResult(0) + return resultList, err +} + +func FreeBatchInfo(name string, handler func(tasksch.ITask, []int64) (interface{}, int, error), ctx *jxcontext.Context, parentTask tasksch.ITask, storeSkuList []int64, batchSize int, isContinueWhenError bool) (resultList []interface{}, err error) { + task := tasksch.NewParallelTask2(fmt.Sprintf("FreeBatchInfo:%s", name), tasksch.NewParallelConfig().SetParallelCount(1).SetBatchSize(batchSize).SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, successCount int, err error) { + batchStoreSkuList := make([]int64, len(batchItemList)) + for k, v := range batchItemList { + batchStoreSkuList[k] = v.(int64) + } + retVal, successCount, err = handler(task, batchStoreSkuList) + if err != nil { + retVal = nil + } + return retVal, successCount, err + }, storeSkuList) + tasksch.HandleTask(task, parentTask, false).Run() + resultList, err = task.GetResult(0) + return resultList, err +} + +func int2TimeStr(time int) (str string) { + str += utils.Int2Str(time / 1000) + str += utils.Int2Str(time % 1000 / 100) + str += ":" + str += utils.Int2Str(time % 100 / 10) + str += utils.Int2Str(time % 10) + return str +} + +func storeSkuFullList2BareFilter(storeSkuFull []*partner.SkuNameInfo) (bareStoreSkuList []*partner.StoreSkuInfo) { + for _, v := range storeSkuFull { + for _, v2 := range v.SkuList { + // if v2.Status > model.SkuStatusDontSale { + bareStoreSkuList = append(bareStoreSkuList, &v2.StoreSkuInfo) + // } + } + } + return bareStoreSkuList +} + +func RefreshJXPriceChange(ctx *jxcontext.Context, storeID int) (hint string, err error) { + db := dao.GetDB() + var ( + stores []*model.Store + vendorIDs = []int{0, 1, 3, 5, 9} + isAsync = true + isContinueWhenError = true + ) + sql := ` + SELECT * + FROM store + WHERE deleted_at = ? AND pay_percentage > 50 + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if storeID != 0 { + sql += " AND id = ?" + sqlParams = append(sqlParams, storeID) + } + err = dao.GetRows(db, &stores, sql, sqlParams) + task := tasksch.NewParallelTask("刷新门店价格", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + store := batchItemList[0].(*model.Store) + var skuBindInfos []*cms.StoreSkuBindInfo + for _, v := range vendorIDs { + storeMaps, _ := dao.GetStoresMapList(db, []int{v}, []int{store.ID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") + if len(storeMaps) > 0 { + storeMap := storeMaps[0] + switch v { + case model.VendorIDJD: + storeMap.PricePercentagePack = "京东测试报价=结算价" + dao.UpdateEntity(db, storeMap, "PricePercentagePack") + case model.VendorIDEBAI: + storeMap.PricePercentagePack = "美团测试报价=结算价" + dao.UpdateEntity(db, storeMap, "PricePercentagePack") + case model.VendorIDMTWM: + storeMap.PricePercentagePack = "饿百测试报价=结算价" + dao.UpdateEntity(db, storeMap, "PricePercentagePack") + case model.VendorIDJDShop: + storeMap.PricePercentagePack = "京西100-100" + dao.UpdateEntity(db, storeMap, "PricePercentagePack") + case model.VendorIDJX: + storeMap.PricePercentagePack = "京西100-100" + dao.UpdateEntity(db, storeMap, "PricePercentagePack") + } + } + } + storeSkus, err := dao.GetStoresSkusInfo(db, []int{store.ID}, nil) + for _, v := range storeSkus { + skuAndName, _ := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil) + skuBindInfo := &cms.StoreSkuBindInfo{ + // StoreID: store.ID, + NameID: skuAndName[0].NameID, + UnitPrice: v.UnitPrice * store.PayPercentage / 100, + } + skuBindInfos = append(skuBindInfos, skuBindInfo) + } + // cms.UpdateStoresSkusByBind(ctx, task, skuBindInfos, isAsync, isContinueWhenError, false) + cms.UpdateStoresSkusWithoutSync(ctx, []int{store.ID}, skuBindInfos, false) + store.PayPercentage = 100 + dao.UpdateEntity(db, store, "PayPercentage") + return retVal, err + }, stores) + tasksch.HandleTask(task, nil, true).Run() + if isAsync { + hint = task.GetID() + } else { + _, err = task.GetResult(0) + hint = "1" + } + return hint, err +} diff --git a/business/jxstore/yonghui/yonghui.go b/business/jxstore/yonghui/yonghui.go index a56207879..38cbb183d 100644 --- a/business/jxstore/yonghui/yonghui.go +++ b/business/jxstore/yonghui/yonghui.go @@ -851,7 +851,7 @@ func UpdateJxPriceByWeimob(ctx *jxcontext.Context, storeIDs []int, isAsync, isCo for _, v := range storeSkuBindInfoList { skuBindInfos = append(skuBindInfos, v.(*cms.StoreSkuBindInfo)) } - cms.UpdateStoresSkus(ctx, 0, storeIDs, skuBindInfos, false, isAsync, isContinueWhenError) + cms.UpdateStoresSkus(ctx, 0, storeIDs, skuBindInfos, false, false, isAsync, isContinueWhenError) case 2: WriteToExcel3(task, dataStoreSkusSuccess.dataStoreSkusSuccessList, dataFailed.dataFailedList) } diff --git a/business/jxutils/datares/datares.go b/business/jxutils/datares/datares.go index 1d6630372..0e6fca441 100644 --- a/business/jxutils/datares/datares.go +++ b/business/jxutils/datares/datares.go @@ -23,8 +23,10 @@ import ( const ( qiniuTokenExpires = 300 // 七牛TOKEN有效时间,5分钟 - MainImgWidth = 800 - MainImgHeight = 800 + MainImgWidth = 800 + MainImgHeight = 800 + MainImgWidth2 = 500 + MainImgHeight2 = 500 ) type UploadResTokenInfo struct { @@ -81,7 +83,7 @@ func RegisterDataResource(ctx *jxcontext.Context, name, resourceURL, mimeType, h return nil, err } if imgType == model.ImgTypeMain { - if img.Bounds().Dx() != MainImgWidth || img.Bounds().Dy() != MainImgHeight { + if (img.Bounds().Dx() != MainImgWidth || img.Bounds().Dy() != MainImgHeight) && (img.Bounds().Dx() != MainImgWidth2 || img.Bounds().Dy() != MainImgHeight2) { return nil, fmt.Errorf("图片大小:%dx%d非法,要求必须:%dx%d", img.Bounds().Dx(), img.Bounds().Dy(), MainImgWidth, MainImgHeight) } } diff --git a/business/jxutils/eventhub/syseventhub/syseventhub.go b/business/jxutils/eventhub/syseventhub/syseventhub.go index a99d35e02..1c2f75635 100644 --- a/business/jxutils/eventhub/syseventhub/syseventhub.go +++ b/business/jxutils/eventhub/syseventhub/syseventhub.go @@ -13,9 +13,10 @@ import ( const ( EventCategory = "sys" - EventTypeWXToken = "wxToken" - EventTypeWX2Token = "wx2Token" - + EventTypeWXToken = "wxToken" + EventTypeWX2Token = "wx2Token" + EventTypeWX3Token = "wx3Token" + EventTypePushToken = "pushToken" EventTypeYLYToken = "ylyToken" EventTypeWeimobToken = "weimobToken" ) @@ -66,6 +67,20 @@ func (h *Hub) OnNewWX2Token(token string) { }) } +func (h *Hub) OnNewPushToken(token string) { + h.eventHub.PostNewEvent(EventCategory, &eventhub.EventInfo{ + Type: EventTypePushToken, + Data: token, + }) +} + +func (h *Hub) OnNewWX3Token(token string) { + h.eventHub.PostNewEvent(EventCategory, &eventhub.EventInfo{ + Type: EventTypeWX3Token, + Data: token, + }) +} + func (h *Hub) OnNewYLYToken(token string) { h.eventHub.PostNewEvent(EventCategory, &eventhub.EventInfo{ Type: EventTypeYLYToken, @@ -91,6 +106,8 @@ func (h *Hub) GetToken(tokenType, oldToken string, waitTime time.Duration) (toke if weimobToken := api.WeimobAPI.GetToken(); weimobToken != nil { token = string(utils.MustMarshal(weimobToken)) } + case EventTypePushToken: + token = api.PushAPI.CBGetToken() case EventTypeWX2Token: token = api.WeixinMiniAPI2.CBGetToken() } @@ -128,3 +145,7 @@ func (h *Hub) GetYLYToken(oldToken string, waitTime time.Duration) (tokenInfo *T func (h *Hub) GetWeimobToken(oldToken string, waitTime time.Duration) (tokenInfo *TokenInfo) { return h.GetToken(EventTypeWeimobToken, oldToken, waitTime) } + +func (h *Hub) GetPushToken(oldToken string, waitTime time.Duration) (tokenInfo *TokenInfo) { + return h.GetToken(EventTypePushToken, oldToken, waitTime) +} diff --git a/business/jxutils/excel/excel.go b/business/jxutils/excel/excel.go index ff991a88d..23d3d45e0 100644 --- a/business/jxutils/excel/excel.go +++ b/business/jxutils/excel/excel.go @@ -3,12 +3,11 @@ package excel import ( "bytes" "fmt" - "io" - "reflect" - "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" "github.com/360EntSecGroup-Skylar/excelize" + "io" + "reflect" ) type Obj2ExcelSheetConfig struct { @@ -20,7 +19,8 @@ type Obj2ExcelSheetConfig struct { func Obj2Excel(sheetList []*Obj2ExcelSheetConfig) []byte { globals.SugarLogger.Debug("Obj2Excel") excelFile := excelize.NewFile() - for sheetIndex, sheetConfig := range sheetList { + //for sheetIndex, sheetConfig := range sheetList { + for _, sheetConfig := range sheetList { obj := sheetConfig.Data typeInfo := reflect.TypeOf(obj) @@ -39,12 +39,14 @@ func Obj2Excel(sheetList []*Obj2ExcelSheetConfig) []byte { } valueInfo := reflect.Indirect(reflect.ValueOf(obj)) - if sheetIndex == 0 { - sheetName := excelFile.GetSheetName(1) - excelFile.SetSheetName(sheetName, sheetConfig.Title) - } else { - excelFile.NewSheet(sheetConfig.Title) - } + /*因爲默認是Sheet1,所以直接賦值就叫sheet1,然後再改名字就行了,不然會默認多一頁空白頁為sheet1*/ + //if sheetIndex == 0 { + index := excelFile.NewSheet("Sheet1") + // sheetName := excelFile.GetSheetName(1) + excelFile.SetSheetName("Sheet1", sheetConfig.Title) + //} else { + // excelFile.NewSheet(sheetConfig.Title) + //} isMemberStruct := typeInfo.Kind() == reflect.Struct colWithList := make([]float64, len(sheetConfig.CaptionList)) if isMemberStruct { @@ -63,9 +65,9 @@ func Obj2Excel(sheetList []*Obj2ExcelSheetConfig) []byte { for i := 0; i < valueInfo.Len(); i++ { for col, index := range indexSlice { str := fmt.Sprint(reflect.Indirect(valueInfo.Index(i)).FieldByIndex(index).Interface()) - // if colWith := float64(len(str)); colWith > colWithList[col] { - // colWithList[col] = colWith - // } + //// if colWith := float64(len(str)); colWith > colWithList[col] { + //// colWithList[col] = colWith + //// } excelFile.SetCellStr(sheetConfig.Title, genAxis(i+1, col), str) } } @@ -104,6 +106,7 @@ func Obj2Excel(sheetList []*Obj2ExcelSheetConfig) []byte { // colName, _ := excelize.ColumnNumberToName(col + 1) // excelFile.SetColWidth(sheetConfig.Title, colName, colName, colWithList[col]) // } + excelFile.SetActiveSheet(index) } buf := &bytes.Buffer{} excelFile.Write(buf) diff --git a/business/jxutils/jxcontext/jxcontext.go b/business/jxutils/jxcontext/jxcontext.go index b7a46648e..69ad6985a 100644 --- a/business/jxutils/jxcontext/jxcontext.go +++ b/business/jxutils/jxcontext/jxcontext.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/auth2" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" @@ -56,7 +57,7 @@ func New(notUsed interface{}, token string, w http.ResponseWriter, r *http.Reque authInfo, err2 := auth2.GetTokenInfo(token) if err = err2; err == nil { ctx.userInfo = authInfo - // globals.SugarLogger.Debugf("jxcontext New, V2 authInfo:%s", utils.Format4Output(authInfo, true)) + globals.SugarLogger.Debugf("jxcontext New, V2 authInfo:%s", utils.Format4Output(authInfo, true)) if authInfo.TokenType != auth2.TokenTypeNormal { err = errors.New("需要正式TOKEN") } diff --git a/business/jxutils/jxutils.go b/business/jxutils/jxutils.go index 723130186..d1c34a7ba 100644 --- a/business/jxutils/jxutils.go +++ b/business/jxutils/jxutils.go @@ -3,6 +3,9 @@ package jxutils import ( "bytes" "context" + "crypto/aes" + "crypto/md5" + "encoding/base64" "fmt" "io/ioutil" "math" @@ -24,9 +27,10 @@ import ( ) var ( - routinePool *routinepool.Pool - skuNamePat *regexp.Regexp - emailPat *regexp.Regexp + routinePool *routinepool.Pool + skuNamePat *regexp.Regexp + emailPat *regexp.Regexp + orderNoBeginTimestamp int64 resourceTypeMap = map[int][]string{ model.VendorIDQiNiuCloud: []string{ @@ -73,6 +77,7 @@ func init() { // https://stackoverflow.com/questions/38933898/error-parsing-regexp-invalid-or-unsupported-perl-syntax skuNamePat = regexp.MustCompile(`([\((\[【][^\((\[【\))\]】]*[\))\]】])?(.*?)([((].*[))])?\s*约?([1-9][\d\.]*)(g|G|kg|kG|Kg|KG|l|L|ml|mL|Ml|ML|克)\s*([((].*[))])?\s*(?:\/|/|)\s*([^\s()()]{0,2})(\s.*)?$\s*([((].*[))])?$`) emailPat = regexp.MustCompile(`[A-Za-z0-9_\-.]+@(?:[A-Za-z0-9_\-]+\.)+[A-Za-z]+`) + orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() } func getJxStoreIDFromOrder(order *model.GoodsOrder) (retVal int) { @@ -159,11 +164,43 @@ func GetPossibleVendorIDFromVendorOrderID(vendorOrderID string) (vendorID int) { vendorID = model.VendorIDWSC } else if orderIDLen == len("1000004390") { vendorID = model.VendorIDJX + } else if orderIDLen == len("124557362562000001") || orderIDLen == len("13153183146800000100") { + vendorID = model.VendorIDJDShop } } return vendorID } +func GenOrderNo() (orderNo int64) { + const prefix = 88 + const randPartNum = 1000 + 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 GenAfsOrderNo() (orderNo int64) { + const prefix = 80 + const randPartNum = 100 + 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 GetPossibleVendorIDFromAfsOrderID(afsOrderID string) (vendorID int) { vendorID = model.VendorIDUnknown if afsOrderIDInt64 := utils.Str2Int64WithDefault(afsOrderID, 0); afsOrderIDInt64 > 0 { @@ -359,7 +396,7 @@ func ComposeSkuNameOriginal(prefix, name, comment, unit string, spec_quality flo return skuName } -func ComposeSkuNameForJds(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) { +func ComposeSkuNameForMTWM(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) { strBuilder := &strings.Builder{} if prefix != "" { strBuilder.WriteString("[") @@ -368,15 +405,15 @@ func ComposeSkuNameForJds(prefix, name, comment, unit string, spec_quality float } skuName += name strBuilder.WriteString(name) - if comment != "" { - strBuilder.WriteString(" ") - strBuilder.WriteString(comment) - } - if unit == "份" { - strBuilder.WriteString("约") - } if unit != "" { strBuilder.WriteString(ComposeSkuSpec(spec_quality, spec_unit)) + strBuilder.WriteString("/") + strBuilder.WriteString(unit) + } + if comment != "" { + strBuilder.WriteString("(") + strBuilder.WriteString(comment) + strBuilder.WriteString(")") } skuName = strBuilder.String() if maxLen > 0 { @@ -395,10 +432,12 @@ func ComposeSkuName(prefix, name, comment, unit string, spec_quality float32, sp return skuName } -func ComposeSkuNameSync(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) { +func ComposeSkuNameSync(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time, isEx bool) (skuName string) { if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { - skuName = exPrefix + if isEx { + skuName = exPrefix + } } if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { skuName = "" @@ -408,16 +447,18 @@ func ComposeSkuNameSync(prefix, name, comment, unit string, spec_quality float32 return skuName } -func ComposeSkuNameSync2(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) { +func ComposeSkuNameSync2(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time, isEx bool) (skuName string) { if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { - skuName = exPrefix + if isEx { + skuName = exPrefix + } } if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { skuName = "" } } - skuName += ComposeSkuNameForJds(prefix, name, comment, unit, spec_quality, spec_unit, maxLen) + skuName += ComposeSkuNameForMTWM(prefix, name, comment, unit, spec_quality, spec_unit, maxLen) return skuName } @@ -585,8 +626,25 @@ func RefreshOrderSkuRelated(order *model.GoodsOrder) *model.GoodsOrder { } func RefreshOrderEarningPrice2(order *model.GoodsOrder, payPercentage int) *model.GoodsOrder { - if payPercentage <= 50 { + if order.EarningType == model.EarningTypePoints { + // if order.VendorID == model.VendorIDJDShop || order.VendorID == model.VendorIDJX { + // order.NewEarningPrice = order.TotalShopMoney * int64((100 - payPercentage)) / 100 + // } else { order.NewEarningPrice = order.TotalShopMoney * int64((100 - payPercentage/2)) / 100 + // } + } else { + order.NewEarningPrice = order.EarningPrice + } + return order +} + +func RefreshOrderEarningPrice3(order *model.GoodsOrder, payPercentage int, bill *model.Waybill) *model.GoodsOrder { + if order.EarningType == model.EarningTypePoints { + // if order.VendorID == model.VendorIDJDShop || order.VendorID == model.VendorIDJX { + // order.NewEarningPrice = (order.TotalShopMoney - bill.DesiredFee) * int64((100 - payPercentage)) / 100 + // } else { + order.NewEarningPrice = order.TotalShopMoney*int64((100-payPercentage/2))/100 - bill.DesiredFee + // } } else { order.NewEarningPrice = order.EarningPrice } @@ -882,3 +940,118 @@ func TranslateSoundSize(vendorID, soundPercentage int) (soundSize string) { } return soundSize } + +//ECB,AES模式解密 +//目前就京东商城订单手机号解密用 +func DecryptDESECB(d, key []byte) string { + data, err := base64.StdEncoding.DecodeString(string(d)) + if err != nil { + return "" + } + block, err := aes.NewCipher(key) + if err != nil { + return "" + } + bs := block.BlockSize() + if len(data)%bs != 0 { + return "" + } + out := make([]byte, len(data)) + dst := out + for len(data) > 0 { + block.Decrypt(dst, data[:bs]) + data = data[bs:] + dst = dst[bs:] + } + out = PKCS5UnPadding(out) + return string(out) +} + +func PKCS5UnPadding(origData []byte) []byte { + length := len(origData) + unpadding := int(origData[length-1]) + return origData[:(length - unpadding)] +} + +//合成水印图 +func MixWatermarkImg(imgWatermark, img string, exPrefixBegin, exPrefixEnd *time.Time) (imgMix string) { + if exPrefixBegin != nil && exPrefixEnd != nil { + if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { + baseURL := base64.URLEncoding.EncodeToString([]byte(imgWatermark)) + var imgUrl string + if strings.Contains(img, "?") { + imgUrl = img + "/imageView2/0/q/75|watermark/1/image/" + baseURL + "/dissolve/100/gravity/Center/dx/0/dy/0" + } else { + imgUrl = img + "?imageView2/0/q/75|watermark/1/image/" + baseURL + "/dissolve/100/gravity/Center/dx/0/dy/0" + } + if resBinary, _, err := DownloadFileByURL(imgUrl); err == nil { + if downloadURL, err := UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+img[strings.LastIndex(img, "/")+1:len(img)]); err == nil { + if err == nil { + return downloadURL + } + } + } + } + if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { + return imgMix + } + } + return imgMix +} + +func GetDefendPriceIssue() (issue int) { + if time.Now().Hour() >= 22 { + issue = utils.Str2Int(time.Now().AddDate(0, 0, 1).Format("20060102")) + } else { + issue = utils.Str2Int(time.Now().Format("20060102")) + } + return issue +} + +func GetLastDefendPriceIssue() (issue int) { + return utils.Str2Int(time.Now().AddDate(0, 0, 1).Format("20060102")) +} + +//根据一堆坐标求面积 +//有待考证,不过暂时拿来用 +func ComputeSignedArea(path []string) (s float64) { + var ( + radius = 6371009 + len = len(path) + total float64 + prev = path[len-1] + ) + if len < 3 { + return + } + prevTanLat := math.Tan(((math.Pi/2 - utils.Str2Float64(strings.Split(prev, ",")[1])/180*math.Pi) / 2)) + prevLng := utils.Str2Float64(strings.Split(prev, ",")[0]) / 180 * math.Pi + for i := 0; i < len; i++ { + tanLat := math.Tan(((math.Pi/2 - utils.Str2Float64(strings.Split(path[i], ",")[1])/180*math.Pi) / 2)) + lng := utils.Str2Float64(strings.Split(path[i], ",")[0]) / 180 * math.Pi + total += polarTriangleArea(tanLat, lng, prevTanLat, prevLng) + prevTanLat = tanLat + prevLng = lng + } + return math.Abs(total * (float64(radius) * float64(radius))) +} + +func polarTriangleArea(tan1, lng1, tan2, lng2 float64) (s float64) { + deltaLng := lng1 - lng2 + t := tan1 * tan2 + return 2 * math.Atan2(t*math.Sin(deltaLng), 1+t*math.Cos(deltaLng)) +} + +func IntListToStrList(i []int) (s []string) { + for _, v := range i { + s = append(s, utils.Int2Str(v)) + } + return s +} + +func StrListToIntList(s []string) (i []int) { + for _, v := range s { + i = append(i, utils.Str2Int(v)) + } + return i +} diff --git a/business/jxutils/jxutils_cms.go b/business/jxutils/jxutils_cms.go index e6d99ceba..ed6c506d8 100644 --- a/business/jxutils/jxutils_cms.go +++ b/business/jxutils/jxutils_cms.go @@ -488,7 +488,7 @@ func GuessVendorIDFromVendorStoreID(vendorStoreID int64) (vendorID int) { vendorID = model.VendorIDJD } else if vendorStoreID > 1234567 && vendorStoreID < 9876543 { // 美团外卖 2461713,7位 vendorID = model.VendorIDMTWM - } else if vendorStoreID > 1234567890 && vendorStoreID < 99876543210 { // 饿百 2167002607,10位,11位 + } else if vendorStoreID > 1234567890 && vendorStoreID < 998765432109 { // 饿百 2167002607,10位,12位 vendorID = model.VendorIDEBAI } else if false { //vendorStoreID > 123456789 && vendorStoreID < 987654321 { // 微盟微商城 132091048,9位 // vendorID = model.VendorIDWSC diff --git a/business/jxutils/netprinter/netprinter.go b/business/jxutils/netprinter/netprinter.go index c1af8db20..f4f57530b 100644 --- a/business/jxutils/netprinter/netprinter.go +++ b/business/jxutils/netprinter/netprinter.go @@ -81,7 +81,14 @@ func PrintOrderByOrder4Store(ctx *jxcontext.Context, order *model.GoodsOrder, st PrintResult: partner.PrintResultNoPrinter, }, nil } - printResult, err = handler.PrintOrder(ctx, store, order) + storeDetail, _ := dao.GetStoreDetail(db, storeID, order.VendorID, order.VendorOrgCode) + if storeDetail == nil && order.VendorOrderID == testVendorOrderID { + storeDetail = &dao.StoreDetail{ + BrandName: testVendorOrderID, + BrandIsPrint: model.NO, + } + } + printResult, err = handler.PrintOrder(ctx, store, storeDetail, order) if err == nil { dao.SetOrderPrintFlag(db, ctx.GetUserName(), order.VendorOrderID, order.VendorID, true) } diff --git a/business/jxutils/smsmsg/smsmsg.go b/business/jxutils/smsmsg/smsmsg.go index 56d014418..434542fd7 100644 --- a/business/jxutils/smsmsg/smsmsg.go +++ b/business/jxutils/smsmsg/smsmsg.go @@ -42,11 +42,12 @@ func SendSMSMsg(mobileList []string, signName, templateCode string, templatePara } else { globals.SugarLogger.Infof(errMsg) } - } else { - if order != nil { - err = updateStoreSMSNotifyMark(order) - } } + // else { + // if order != nil { + // err = updateStoreSMSNotifyMark(order) + // } + // } } } } @@ -61,10 +62,29 @@ func getOrderNotifyPhone(order *model.GoodsOrder) (phoneList []string) { func NotifyNewOrder(order *model.GoodsOrder) (err error) { if isPushSMS(order) { - err = SendSMSMsg(getOrderNotifyPhone(order), globals.SMSSignName, globals.SMSNewOrderTemplate, map[string]interface{}{ + temp := "" + var price int64 + store, _ := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, order.VendorOrgCode) + if store.VendorPayPercentage < 50 && store.VendorPayPercentage != 0 { + temp = globals.SMSNewOrderTemplate + price = order.ActualPayPrice + } else if store.VendorPayPercentage > 50 { + temp = globals.SMSNewOrderTemplateQ + price = order.ShopPrice + } else if store.VendorPayPercentage == 0 { + if store.PayPercentage > 50 { + temp = globals.SMSNewOrderTemplateQ + price = order.ShopPrice + } else { + temp = globals.SMSNewOrderTemplate + price = order.ActualPayPrice + } + } + + err = SendSMSMsg(getOrderNotifyPhone(order), globals.SMSSignName, temp, map[string]interface{}{ "daySeq": order.OrderSeq, "consigneeName": order.ConsigneeName, - "payMoney": jxutils.IntPrice2StandardString(order.ActualPayPrice), + "payMoney": jxutils.IntPrice2StandardString(price), }, order) } return err @@ -86,10 +106,10 @@ func isPushSMS(order *model.GoodsOrder) bool { } else { storeID = order.StoreID } - stores, _ := dao.GetStoresMapList(dao.GetDB(), []int{order.VendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + stores, _ := dao.GetStoresMapList(dao.GetDB(), []int{order.VendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if len(stores) > 0 { if stores[0].IsOrder == model.NO { - if storeID == model.MatterStoreID { + if storeID == model.MatterStoreID || storeID == model.JdShopMainStoreID || storeID == model.JdShopMainStoreID2 { return false } else { return true @@ -104,7 +124,7 @@ func isPushSMS(order *model.GoodsOrder) bool { func updateStoreSMSNotifyMark(order *model.GoodsOrder) (err error) { var db = dao.GetDB() - stores, _ := dao.GetStoreList(db, []int{order.StoreID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{order.StoreID}, nil, nil, nil, nil, "") if len(stores) > 0 { stores[0].SMSNotifyMark = model.YES _, err = dao.UpdateEntity(db, stores[0], "SMSNotifyMark") @@ -128,7 +148,7 @@ func NotifyNewUserOrder(order *model.GoodsOrder) (err error) { if order.ConsigneeMobile2 != "" { mobile = order.ConsigneeMobile2 uoSMS, err := dao.GetUserOrderSMS(db, mobile, "") - stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") if len(stores) > 0 { if stores[0].Tel1 == "" { storeTel = stores[0].Tel2 @@ -185,7 +205,7 @@ func NotifyNewCourierOrder(bill *model.Waybill) (err error) { } else { storeID = order.StoreID } - stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "") if len(stores) > 0 { if stores[0].Tel1 == "" { storeTel = stores[0].Tel2 diff --git a/business/jxutils/tasks/configrefresh.go b/business/jxutils/tasks/configrefresh.go index abbff08c0..50f98b16c 100644 --- a/business/jxutils/tasks/configrefresh.go +++ b/business/jxutils/tasks/configrefresh.go @@ -28,6 +28,8 @@ const ( dingdingTokenExpires = 7200 * time.Second weimobTokenExpires = 7200 * time.Second yilianyunTokenExpires = 30 * 24 * 3600 * time.Second + pushTokenExpires = 7200 * time.Second + fnTokenExpires = 1 * time.Hour maxRefreshGap = 5 * 60 * time.Second errRefreshGap = 10 * time.Second @@ -138,6 +140,44 @@ func RefreshWeixinToken() (err error) { return err } +func RefreshFnToken() (err error) { + if api.FnAPI != nil { + err = RefreshConfig("fn", fnTokenExpires, func() (token string, expireTimeStr string) { + globals.SugarLogger.Debugf("RefreshFnToken RunMode:%s", beego.BConfig.RunMode) + if globals.IsMainProductEnv() { + if tokenInfo, err := api.FnAPI.GetAccessToken(); err == nil { + globals.SugarLogger.Debugf("RefreshFnToken tokenInfo:%s", utils.Format4Output(tokenInfo, true)) + token = tokenInfo.AccessToken + } else { + globals.SugarLogger.Errorf("RefreshFnToken RefreshToken failed with error:%v", err) + } + sql := ` + UPDATE jxgy.config SET token = ? WHERE thirdparty = ? + ` + sqlParams := []interface{}{ + token, "fn", + } + dao.ExecuteSQL(dao.GetDB(), sql, sqlParams) + } + if beego.BConfig.RunMode == "jxgy" { + config := &legacymodel.Config{} + sql := ` + SELECT * FROM config WHERE thirdparty = 'fn' + ` + if err := dao.GetRow(dao.GetDB(), &config, sql, nil); err == nil { + token = config.Token + } + } + return token, expireTimeStr + }, func(value string) { + globals.SugarLogger.Debugf("RefreshFnToken setter value:%s", value) + // syseventhub.SysEventHub.OnNewWXToken(value) + api.FnAPI.SetToken(value) + }) + } + return err +} + func RefreshWeixin2Token() (err error) { if api.WeixinMiniAPI2 != nil { err = RefreshConfig("wechat2", weixinTokenExpires, func() (token string, expireTimeStr string) { @@ -165,6 +205,60 @@ func RefreshWeixin2Token() (err error) { return err } +func RefreshPushToken() (err error) { + if api.PushAPI != nil { + err = RefreshConfig("push", pushTokenExpires, func() (token string, expireTimeStr string) { + globals.SugarLogger.Debugf("RefreshPushToken RunMode:%s", beego.BConfig.RunMode) + if globals.IsMainProductEnv() { + if tokenInfo, err := api.PushAPI.CBRetrieveToken(); err == nil { + globals.SugarLogger.Debugf("RefreshPushToken tokenInfo:%s", utils.Format4Output(tokenInfo, true)) + token = tokenInfo.Token + } else { + globals.SugarLogger.Errorf("RefreshPushToken RefreshToken failed with error:%v", err) + } + } else { + if tokenInfo := getPushTokenFromRemote(api.PushAPI.CBGetToken()); tokenInfo != nil { + expireTimeStr = utils.Time2Str(time.Now().Add(-pushTokenExpires)) + token = tokenInfo.Token + } + } + return token, expireTimeStr + }, func(value string) { + globals.SugarLogger.Debugf("RefreshPushToken setter value:%s", value) + syseventhub.SysEventHub.OnNewPushToken(value) + api.PushAPI.CBSetToken(value) + }) + } + return err +} + +func RefreshWeixin3Token() (err error) { + // if api.WeixinMiniAPI3 != nil { + // err = RefreshConfig("wechat3", weixinTokenExpires, func() (token string, expireTimeStr string) { + // globals.SugarLogger.Debugf("RefreshWeixin3Token RunMode:%s", beego.BConfig.RunMode) + // if globals.IsMainProductEnv() { + // if tokenInfo, err := api.WeixinMiniAPI3.CBRetrieveToken(); err == nil { + // globals.SugarLogger.Debugf("RefreshWeixin3Token tokenInfo:%s", utils.Format4Output(tokenInfo, true)) + // token = tokenInfo.AccessToken + // } else { + // globals.SugarLogger.Errorf("RefreshWeixin3Token RefreshToken failed with error:%v", err) + // } + // } else { + // if tokenInfo := getWX3TokenFromRemote(api.WeixinMiniAPI3.CBGetToken()); tokenInfo != nil { + // expireTimeStr = utils.Time2Str(time.Now().Add(-weixinTokenExpires)) + // token = tokenInfo.Token + // } + // } + // return token, expireTimeStr + // }, func(value string) { + // globals.SugarLogger.Debugf("RefreshWeixinToken setter value:%s", value) + // syseventhub.SysEventHub.OnNewWX3Token(value) + // api.WeixinMiniAPI3.CBSetToken(value) + // }) + // } + return err +} + func RefreshWeimobToken() (err error) { if api.WeimobAPI != nil { err = RefreshConfig("weimob", weimobTokenExpires, func() (token string, expireTimeStr string) { @@ -315,6 +409,24 @@ func getWX2TokenFromRemote(oldToken string) (tokenInfo *syseventhub.TokenInfo) { return tokenInfo } +func getPushTokenFromRemote(oldToken string) (tokenInfo *syseventhub.TokenInfo) { + if !globals.IsMainProductEnv() && globals.GetWeixinTokenKey != "" && globals.GetPushTokenURL != "" { + tokenInfo = PollingRemotEvent(globals.GetPushTokenURL, 0, map[string]interface{}{ + "oldToken": oldToken, + }) + } + return tokenInfo +} + +func getWX3TokenFromRemote(oldToken string) (tokenInfo *syseventhub.TokenInfo) { + if !globals.IsMainProductEnv() && globals.GetWeixinTokenKey != "" && globals.GetWeixinTokenURL != "" { + tokenInfo = PollingRemotEvent(globals.GetWeixinTokenURL, 0, map[string]interface{}{ + "oldToken": oldToken, + }) + } + return tokenInfo +} + func getYLYTokenFromRemote(oldToken string) (tokenInfo *syseventhub.TokenInfo) { if !globals.IsMainProductEnv() && globals.GetWeixinTokenKey != "" && globals.GetYLYTokenURL != "" { tokenInfo = PollingRemotEvent(globals.GetYLYTokenURL, 0, map[string]interface{}{ diff --git a/business/jxutils/tasksch/parallel_task.go b/business/jxutils/tasksch/parallel_task.go index f99361328..a396b84cc 100644 --- a/business/jxutils/tasksch/parallel_task.go +++ b/business/jxutils/tasksch/parallel_task.go @@ -80,6 +80,7 @@ func NewParallelTask2(taskName string, config *ParallelConfig, ctx *jxcontext.Co if config.ParallelCount > MaxParallelCount { config.ParallelCount = MaxParallelCount } + //?? realItemList := utils.Interface2Slice(itemList) jobList := jxutils.SplitSlice(realItemList, config.BatchSize) jobListLen := len(jobList) diff --git a/business/jxutils/unipush/push.go b/business/jxutils/unipush/push.go new file mode 100644 index 000000000..f6da07b7e --- /dev/null +++ b/business/jxutils/unipush/push.go @@ -0,0 +1,98 @@ +package push + +import ( + "fmt" + "strings" + + "git.rosy.net.cn/baseapi/platformapi/unipushapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" + "github.com/astaxie/beego" +) + +func pushToSingle(content, title string, storeID int) { + var ( + db = dao.GetDB() + ) + if !globals.IsProductEnv() { + return + } + storePushs, err := dao.GetStorePushClient(db, storeID, "") + if err != nil { + return + } + for _, v := range storePushs { + + status, err2 := api.PushAPI.PushToSingle(v.ClientID, false, &unipushapi.Notification{ + Title: title, + Body: content, + }) + if err = err2; err != nil { + globals.SugarLogger.Debugf("NotifyNewOrder push error: [%v]", err) + continue + } + if status == unipushapi.SuccessOffLine { + _, err = api.PushAPI.PushToSingle(v.ClientID, true, &unipushapi.Notification{ + Body: content, + }) + if err != nil { + globals.SugarLogger.Debugf("NotifyNewOrder push2 error: [%v]", err) + continue + } + } + + } +} + +func NotifyNewOrder(order *model.GoodsOrder) { + globals.SugarLogger.Debugf("NotifyNewOrder push begin orderID :[%v]", order.VendorOrderID) + if order == nil || len(order.Skus) == 0 { + return + } + sb := new(strings.Builder) + sb.WriteString("老板,") + sb.WriteString(order.ConsigneeName) + sb.WriteString("购买了商品") + sb.WriteString(getOrderDetailBrief(order)) + pushToSingle(sb.String(), "京西菜市新订单推送", jxutils.GetSaleStoreIDFromOrder(order)) +} + +func getOrderDetailBrief(order *model.GoodsOrder) (brief string) { + sb := new(strings.Builder) + sb.WriteString(order.Skus[0].SkuName) + sb.WriteString("等共") + sb.WriteString(utils.Int2Str(order.Skus[0].Count)) + sb.WriteString("份(") + sb.WriteString(jxutils.IntPrice2StandardString(order.Skus[0].SalePrice)) + sb.WriteString("元/份)等,预计收入") + //TODO 2020-07-20 果园和菜市不同 + var price int64 + if beego.BConfig.RunMode == "jxgy" { + price = order.EarningPrice + } else { + if order.EarningType == model.EarningTypePoints { + price = order.ActualPayPrice + } else { + price = order.ShopPrice + } + } + sb.WriteString(jxutils.IntPrice2StandardString(price)) + sb.WriteString("元") + return sb.String() +} + +func NotifyAfsOrder(afsOrder *model.AfsOrder) (err error) { + globals.SugarLogger.Debugf("NotifyAfsOrder push begin orderID :[%v]", afsOrder.VendorOrderID) + pushToSingle("老板,您有新的售后单,请尽快处理!", "京西菜市售后单推送", jxutils.GetSaleStoreIDFromAfsOrder(afsOrder)) + return err +} + +func NotifyOrderCanceled(order *model.GoodsOrder) (err error) { + title := fmt.Sprintf("老板,您的订单%s第%d号订单, %s被取消了!", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID) + pushToSingle(title, "京西菜市取消单推送", jxutils.GetSaleStoreIDFromOrder(order)) + return err +} diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 87795f53d..9288fe851 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -1,12 +1,17 @@ package weixinmsg import ( + "encoding/json" "fmt" + "math" "strings" "time" + "github.com/astaxie/beego" + "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/authz/autils" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/netprinter" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" @@ -56,11 +61,13 @@ const ( WX_SALE_BILL_TEMPLATE_ID = "eTUuFZMWH7IsVBfcxNMpmaHYaxRkUaD6zG8wSGJDcic" - WX_NORMAL_STORE_MSG_TEMPLATE_ID = "EUeIJEz2TLUAn4TU2EffOGYLd3dEaYndD_y6Sw9FcSU" - // WX_CHANGE_APPROVED_TEMPLATE_ID = "gIG2olBZtQbjXmp6doNB_dESu60By5xuXYOGxksLv3Y" - // WX_CHANGE_REJECTED_TEMPLATE_ID = "tn2QXWi4HtSIwaztmtN6Bb2uzNL-jBxWltCZTDNJuYE" + WX_NORMAL_STORE_ACT_MSG_TEMPLATE_ID = "eXsfOMvDOKVSht0Q0v4IsDrx3MBlRCVYwYl7Hi2uuuI" + WX_NORMAL_STORE_MSG_TEMPLATE_ID = "EUeIJEz2TLUAn4TU2EffOGYLd3dEaYndD_y6Sw9FcSU" + WX_CHANGE_APPROVED_TEMPLATE_ID = "gIG2olBZtQbjXmp6doNB_dESu60By5xuXYOGxksLv3Y" + WX_CHANGE_REJECTED_TEMPLATE_ID = "OBF4-d5inK95epHcUltpdb1zq9boVp2HESpASVRh1Oo" WX_ORDER_APPLY_CANCEL_TEMPLATE_ID = "e6urTtcm4PL0rgDMG_1qWNOwrE3Qxqcm_dx0kWWCmEI" WX_ORDER_ORDER_CANCELED_TEMPLATE_ID = "HXjuSAbIk77Xh18hjgwoxHzbciR9jX3Rn2CpLJz9dZw" + WX_ORDER_CHANGE_INFO_TEMPLATE_ID = "cjmEQFEpvcOuBNqQpTfMU5FeBpGRbQh_gWKz-WPW8Ro" WX_AFS_ORDER_WAIT4APPROVE_TEMPLATE_ID = "X29udtANvhX6x1Lyh-T40NGNjRXBbUj5oSBTfDhZAqU" WX_AFS_ORDER_STATUS_CHANGED_TEMPLATE_ID = "99T33rrXX0VboO1hljs4x8dDoLiSj3QX_rOikPHIXkg" @@ -68,6 +75,8 @@ const ( WS_NOTIFY_STORE_STATUS_CHHANGED_TEMPLATE_ID = "Fl0vOnBKTQqRFx3-shGKxdCnxMdQXNeODzgkuwd7oxw" WX_STORE_ALERT_TEMPLATE_ID = "0AjzVl1wPl6iO4nFOS4IEsJYSzBymlT37DciIvcCOxE" + + WX_KNOWLEDGE_BASE_TEMPLATE_ID = "0qAvaN7g8oveRgNw127Q7NdnCmmcN0H1a-uaBVjJWzk" //知识库模板 ) var ( @@ -173,7 +182,18 @@ func getOrderDetailBrief(order *model.GoodsOrder) (brief string) { sb.WriteString("份(") sb.WriteString(jxutils.IntPrice2StandardString(order.Skus[0].SalePrice)) sb.WriteString("元/份)等,预计收入") - sb.WriteString(jxutils.IntPrice2StandardString(order.ActualPayPrice)) + //TODO 2020-07-20 果园和菜市不同 + var price int64 + if beego.BConfig.RunMode == "jxgy" { + price = order.NewEarningPrice + } else { + if order.EarningType == model.EarningTypePoints { + price = order.ActualPayPrice + } else { + price = order.ShopPrice + } + } + sb.WriteString(jxutils.IntPrice2StandardString(price)) sb.WriteString("元") return sb.String() } @@ -184,12 +204,21 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) { return nil } + if len(order.Skus) == 0 { + return nil + } + if !model.IsOrderSolid(order) { globals.SugarLogger.Infof("NotifyNewOrder orderID:%s is not solid", order.VendorOrderID) return nil } + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } sb := new(strings.Builder) - sb.WriteString("老板,") + sb.WriteString(suffix + "老板,") sb.WriteString(order.ConsigneeName) sb.WriteString("购买了商品") sb.WriteString(getOrderDetailBrief(order)) @@ -234,6 +263,11 @@ func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlr return nil } var title string + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } templateID := "" remark := "" titleColor := "" @@ -264,7 +298,7 @@ func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlr if templateID != "" { data := map[string]interface{}{ "first": map[string]interface{}{ - "value": title, + "value": suffix + title, "color": titleColor, }, "keyword1": map[string]interface{}{ @@ -300,7 +334,12 @@ func NotifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) (err er globals.SugarLogger.Infof("NotifyUserApplyCancel orderID:%s is not solid", order.VendorOrderID) return nil } - title := "老板,您有订单申请取消!请及时联系客户处理!" + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } + title := suffix + "老板,您有订单申请取消!请及时联系客户处理!" data := map[string]interface{}{ "first": map[string]interface{}{ "value": title, @@ -329,6 +368,49 @@ func NotifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) (err er return err } +func NotifyOrderChanged(order *model.GoodsOrder) (err error) { + globals.SugarLogger.Debugf("NotifyOrderChanged orderID:%s", order.VendorOrderID) + if order.VendorID == model.VendorIDELM { + return nil + } + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } + title := fmt.Sprintf("您有订单的信息已被修改") + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": suffix + title, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword1": map[string]interface{}{ + "value": order.VendorOrderID, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword2": map[string]interface{}{ + "value": "用户修改订单", + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword3": map[string]interface{}{ + "value": order.ConsigneeAddress + "," + order.ConsigneeName + "," + order.ConsigneeMobile + "," + order.BuyerComment, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword4": map[string]interface{}{ + "value": utils.Time2Str(order.OrderCreatedAt), + "color": VendorColors[order.VendorID], + }, + "remark": map[string]interface{}{ + "value": "请及时处理", + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + } + storeID := jxutils.GetSaleStoreIDFromOrder(order) + err = SendMsgToStore(storeID, WX_ORDER_CHANGE_INFO_TEMPLATE_ID, "", "", data) + netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title) + return err +} + func NotifyOrderCanceled(order *model.GoodsOrder) (err error) { globals.SugarLogger.Debugf("NotifyOrderCanceled orderID:%s", order.VendorOrderID) if order.VendorID == model.VendorIDELM { @@ -339,7 +421,12 @@ func NotifyOrderCanceled(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("NotifyOrderCanceled orderID:%s is not solid", order.VendorOrderID) return nil } - title := fmt.Sprintf("老板,您的订单%s第%d号订单, %s被取消了!", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID) + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } + title := fmt.Sprintf(suffix+"老板,您的订单%s第%d号订单, %s被取消了!", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID) data := map[string]interface{}{ "first": map[string]interface{}{ "value": title, @@ -374,9 +461,13 @@ func NotifyOrderCanceled(order *model.GoodsOrder) (err error) { func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments, isBadComment bool, order *model.GoodsOrder) (err error) { globals.SugarLogger.Debugf("PushJDBadCommentToWeiXin orderID:%s", comment.OrderId) - + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } sb := new(strings.Builder) - sb.WriteString(fmt.Sprintf("你收到了%s客户(", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))])) + sb.WriteString(fmt.Sprintf(suffix+"你收到了%s客户(", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))])) sb.WriteString(comment.Userphone) sb.WriteString(")的一条") sb.WriteString(utils.Int2Str(comment.Score)) @@ -460,73 +551,111 @@ func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) { } func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName string, originalUnitPrice, unitPrice int, rejectReason string) (err error) { - // globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason) - // templateID := "" - // fileURL := globals.WxBackstageHost + fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID) - // data := make(map[string]interface{}) - // if isAccepted { - // templateID = WX_CHANGE_APPROVED_TEMPLATE_ID - // data = map[string]interface{}{ - // "first": map[string]interface{}{ - // "value": fmt.Sprintf("%s%s元,修改为%s元,已经通过审核。^_^", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice))), - // "color": "#333333", - // }, - // "keyword1": map[string]interface{}{ - // "value": "审核通过", - // "color": "#2E408E", - // }, - // "keyword2": map[string]interface{}{ - // "value": utils.Time2Str(time.Now()), - // "color": "#2E408E", - // }, - // "remark": map[string]interface{}{ - // "value": "点击查看详情", - // }, - // } - // } else { - // templateID = WX_CHANGE_REJECTED_TEMPLATE_ID - // data = map[string]interface{}{ - // "first": map[string]interface{}{ - // "value": fmt.Sprintf("您好!抱歉的通知您。%s%s元,修改为%s元,未通过审核。原因:%s", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice)), rejectReason), - // "color": "#E80000", - // }, - // "keyword1": map[string]interface{}{ - // "value": "1", - // "color": "#2E408E", - // }, - // "keyword2": map[string]interface{}{ - // "value": utils.Time2Str(time.Now()), - // "color": "#2E408E", - // }, - // "remark": map[string]interface{}{ - // "value": "请您及时到商品管理修改价格,修改后请重新提交。", - // }, - // } - // } - // err = SendMsgToStore(storeID, templateID, fileURL, WX_MINI_TO_STORE_SKU_PAGE_URL, data) + globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason) + templateID := "" + fileURL := globals.WxBackstageHost + fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID) + data := make(map[string]interface{}) + if isAccepted { + templateID = WX_CHANGE_APPROVED_TEMPLATE_ID + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": fmt.Sprintf("%s%s元,修改为%s元,已经通过审核。^_^", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice))), + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": "审核通过", + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.Time2Str(time.Now()), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "点击查看详情", + }, + } + } else { + templateID = WX_CHANGE_REJECTED_TEMPLATE_ID + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": fmt.Sprintf("您好!抱歉的通知您。%s%s元,修改为%s元,未通过审核。原因:%s", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice)), rejectReason), + "color": "#E80000", + }, + "keyword1": map[string]interface{}{ + "value": "1", + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": "审核不通过", + "color": "#2E408E", + }, + "keyword3": map[string]interface{}{ + "value": utils.Time2Str(time.Now()), + "color": "#2E408E", + }, + "keyword4": map[string]interface{}{ + "value": "审核不通过", + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "请您及时到商品管理修改价格,修改后请重新提交。", + }, + } + } + err = SendMsgToStore(storeID, templateID, fileURL, WX_MINI_TO_STORE_SKU_PAGE_URL, data) return err } -func NotifyStoreMessage(storeID, msgID, msgStatusID int, title, content string) (err error) { - globals.SugarLogger.Debugf("NotifyStoreMessage storeID:%d, msgID:%d, title:%s, content:%s", storeID, msgID, title, content) - templateID := WX_NORMAL_STORE_MSG_TEMPLATE_ID +func NotifyStoreMessage(storeID, msgID, msgStatusID int, msg *model.Message) (err error) { + globals.SugarLogger.Debugf("NotifyStoreMessage storeID:%d, msgID:%d, title:%s, content:%s", storeID, msgID, msg.Title, msg.Content) + templateID := "" fileURL := globals.WxBackstageHost + fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID) - data := map[string]interface{}{ - "first": map[string]interface{}{ - "value": content, - "color": "#333333", - }, - "keyword1": map[string]interface{}{ - "value": title, - "color": "#2E408E", - }, - "keyword2": map[string]interface{}{ - "value": utils.GetCurTimeStr(), - "color": "#2E408E", - }, - "remark": map[string]interface{}{ - "value": "", - }, + data := make(map[string]interface{}) + switch msg.Type { + case model.MessageTypeStore: + templateID = WX_NORMAL_STORE_MSG_TEMPLATE_ID + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": msg.Content, + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": msg.Title, + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.GetCurTimeStr(), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "", + }, + } + case model.MessageTypeStoreAct: + actMap := &model.MessageActInfo{} + err = json.Unmarshal([]byte(msg.ActInfo), &actMap) + templateID = WX_NORMAL_STORE_ACT_MSG_TEMPLATE_ID + data = map[string]interface{}{ + "first": map[string]interface{}{ + "value": "即将开展[" + msg.Title + "]活动,详情点击", + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": msg.Title, + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": actMap.BeginAt + "-" + actMap.EndAt, + "color": "#2E408E", + }, + "keyword3": map[string]interface{}{ + "value": model.VendorNames[int(utils.Interface2Float64WithDefault((actMap.VendorID), 0))], + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": msg.Content, + }, + } } return SendMsgToStore(storeID, templateID, fileURL, fmt.Sprintf(WX_MINI_TO_SHOW_MSG, msgID, msgStatusID), data) } @@ -536,7 +665,11 @@ func NotifyAfsOrderStatus(afsOrder *model.AfsOrder) (err error) { if afsOrder.VendorID == model.VendorIDELM { return nil } - + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromAfsOrder(afsOrder), afsOrder.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } var templateID, comment string if afsOrder.Status == model.AfsOrderStatusWait4Approve { templateID = WX_AFS_ORDER_WAIT4APPROVE_TEMPLATE_ID @@ -554,7 +687,7 @@ func NotifyAfsOrderStatus(afsOrder *model.AfsOrder) (err error) { data := map[string]interface{}{ "first": map[string]interface{}{ - "value": fmt.Sprintf("%s 第%d号订单, %s", model.VendorChineseNames[afsOrder.VendorID], order.OrderSeq, afsOrder.VendorOrderID), + "value": suffix + fmt.Sprintf("%s 第%d号订单, %s", model.VendorChineseNames[afsOrder.VendorID], order.OrderSeq, afsOrder.VendorOrderID), "color": WX_HIGHLEVEL_TEMPLATE_COLOR2, }, "keyword1": map[string]interface{}{ @@ -662,8 +795,27 @@ func NotifyStoreAlertMessage(storeID int, storeName, title, content string) (err return err } -func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { +func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs []int, actInfo string, messageType int, isAsync, isContinueWhenError bool) (hint string, err error) { db := dao.GetDB() + //权限 + if permission.IsRoled(ctx) { + if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { + var storeIDs2 []int + if len(storeIDs) > 0 { + for _, v := range storeIDs { + if storeIDsMap[v] != 0 { + storeIDs2 = append(storeIDs2, v) + } + } + } else { + for k, _ := range storeIDsMap { + storeIDs2 = append(storeIDs2, k) + } + } + storeIDs = nil + storeIDs = storeIDs2 + } + } dao.Begin(db) defer func() { if r := recover(); r != nil { @@ -674,7 +826,8 @@ func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs [] msg := &model.Message{ Title: title, Content: content, - Type: model.MessageTypeStore, + Type: int8(messageType), + ActInfo: actInfo, } dao.WrapAddIDCULDEntity(msg, ctx.GetUserName()) if err = dao.CreateEntity(db, msg); err != nil { @@ -700,7 +853,7 @@ func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs [] rootTask := tasksch.NewParallelTask("SendStoreMessage", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { db := dao.GetDB() msgStatus := batchItemList[0].(*model.MessageStatus) - if err = NotifyStoreMessage(msgStatus.StoreID, msgStatus.MessageID, msgStatus.ID, msg.Title, msg.Content); err == nil { + if err = NotifyStoreMessage(msgStatus.StoreID, msgStatus.MessageID, msgStatus.ID, msg); err == nil { msgStatus.Status = model.MessageStatusSendAllSuccess } else { msgStatus.Status = model.MessageStatusSendAllFailed @@ -725,13 +878,17 @@ func NotifyAdjustOrder(order *model.GoodsOrder) (err error) { if order.VendorID == model.VendorIDELM { return nil } - + suffix := "" + storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") + if err == nil && storeDetail != nil { + suffix = storeDetail.CityName + "," + storeDetail.Name + } if !model.IsOrderSolid(order) { globals.SugarLogger.Infof("NotifyAdjustOrder orderID:%s is not solid", order.VendorOrderID) return nil } sb := new(strings.Builder) - sb.WriteString("老板,") + sb.WriteString(suffix + "老板,") sb.WriteString(order.ConsigneeName) sb.WriteString("调整了订单商品,请及时查看!") sb.WriteString(getOrderDetailBrief(order)) @@ -741,7 +898,7 @@ func NotifyAdjustOrder(order *model.GoodsOrder) (err error) { "color": WX_NEW_ORDER_TEMPLATE_COLOR, }, "keyword1": map[string]interface{}{ - "value": jxutils.IntPrice2Standard(order.NewEarningPrice), + "value": math.Round(jxutils.IntPrice2Standard(order.NewEarningPrice)), "color": WX_NEW_ORDER_TEMPLATE_COLOR, }, "keyword2": map[string]interface{}{ @@ -756,3 +913,107 @@ func NotifyAdjustOrder(order *model.GoodsOrder) (err error) { storeID := jxutils.GetSaleStoreIDFromOrder(order) return SendMsgToStore(storeID, WX_ADJUSTORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) } + +func SendUserMessage(ctx *jxcontext.Context, title, content string, userIDs []string, isAsync, isContinueWhenError bool) (hint string, err error) { + db := dao.GetDB() + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + msg := &model.Message{ + Title: title, + Content: content, + Type: model.MessageTypeUser, + } + dao.WrapAddIDCULDEntity(msg, ctx.GetUserName()) + if err = dao.CreateEntity(db, msg); err != nil { + dao.Rollback(db) + return "", err + } + msgStatusList := make([]*model.MessageStatus, len(userIDs)) + for k, userID := range userIDs { + msgStatus := &model.MessageStatus{ + MessageID: msg.ID, + UserID: userID, + Status: model.MessageStatusNew, + } + dao.WrapAddIDCULDEntity(msgStatus, ctx.GetUserName()) + if err = dao.CreateEntity(db, msgStatus); err != nil { + dao.Rollback(db) + return "", err + } + msgStatusList[k] = msgStatus + } + dao.Commit(db) + + rootTask := tasksch.NewParallelTask("SendUserMessage", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + db := dao.GetDB() + msgStatus := batchItemList[0].(*model.MessageStatus) + if err = NotifyUserMessage(msgStatus.UserID, msg.Title, msg.Content); err == nil { + msgStatus.Status = model.MessageStatusSendAllSuccess + } else { + msgStatus.Status = model.MessageStatusSendAllFailed + } + dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName()) + _, err = dao.UpdateEntity(db, msgStatus) + return nil, err + }, msgStatusList) + tasksch.HandleTask(rootTask, nil, len(msgStatusList) > 5).Run() + if !isAsync { + _, err = rootTask.GetResult(0) + } else { + hint = rootTask.ID + } + return "", err +} + +func NotifyUserMessage(userID string, title, content string) (err error) { + globals.SugarLogger.Debugf("NotifyUserMessage userID:%d, title:%s, content:%s", userID, title, content) + templateID := WX_NORMAL_STORE_MSG_TEMPLATE_ID + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": content, + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": title, + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.GetCurTimeStr(), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "", + }, + } + return SendMsgToUser(userID, templateID, data) +} + +func SendMsgToUser(userID string, templateID string, data interface{}) (err error) { + globals.SugarLogger.Debugf("SendMsgToUser userID:%d, templateID:%s", userID, templateID) + authBinds, err := dao.GetUserBindAuthInfo(dao.GetDB(), userID, model.AuthBindTypeAuth, []string{"weixinsns"}, "", "", "wx2bb99eb5d2c9b82c") + if err != nil { + return err + } + successCount := 0 + if len(authBinds) == 0 { + return fmt.Errorf("此用户未找到微信认证方式!userID: %v", userID) + } + globals.SugarLogger.Debugf("SendMsgToUser userID:%d, openID:%s, templateID:%s", userID, authBinds[0].AuthID, templateID) + if err2 := SmartMessageTemplateSend(authBinds[0].AuthID, templateID, "", "", data); err2 == nil { + successCount++ + } else { + err = err2 + } + if successCount > 0 { + err = nil // 只要成功一个都当成成功 + } + if err != nil { + globals.SugarLogger.Debugf("SendMsgToUser all failed userID:%d, templateID:%s, error:%v", userID, templateID, err) + } + return err +} diff --git a/business/model/act.go b/business/model/act.go index 3003d0792..2eb89d230 100644 --- a/business/model/act.go +++ b/business/model/act.go @@ -9,8 +9,16 @@ import ( const ( ActTypeAll = -1 ActSkuFake = 0 // 假活动,只用于存储活动结算信息 - ActSkuDirectDown = 3 // 兼容之前的 - ActSkuSecKill = 4 // 兼容之前的 + ActSkuDirectDown = 3 // 直降 + ActSkuSecKill = 4 // 秒杀 + ActSkuDiscount = 5 // 折扣 + + ActDiscountTypePrice = 1 //折扣类型是最低价 + ActDiscountTypePercentage = 2 //折扣类型是最低折扣 + + TrendTypeUp = 1 //涨价趋势 + TrendTypeDown = 2 //降价趋势 + TrendTypeNothing = 0 //不变 ActOrderBegin = 10 ActOrderMoneyOff = 11 @@ -38,6 +46,7 @@ var ( ActSkuFake: "结算", ActSkuDirectDown: "直降", ActSkuSecKill: "秒杀", + ActSkuDiscount: "折扣", } ActStatusName = map[int]string{ @@ -73,6 +82,9 @@ type Act struct { EndAt time.Time `orm:"type(datetime);index" json:"endAt"` VendorMask int `json:"-"` Remark string `orm:"size(255)" json:"remark"` + DiscountType int `json:"discountType"` //折扣类型,1为最低价,2为最低折扣 + DiscountValue1 int `json:"DiscountValue1"` //第一档折扣 + DiscountValue2 int `json:"DiscountValue2"` //第二档折扣 } // test @@ -171,6 +183,8 @@ type ActStoreSkuMap struct { VendorPrice int64 `json:"vendorPrice"` // 创建活动时的平台价格 ActualActPrice int64 `json:"actualActPrice"` // 单品级活动用,创建活动时商品的活动价格 EarningPrice int64 `json:"earningPrice"` // 活动商品设置,结算给门店老板的钱 + TrendType int `json:"trendType"` //折扣活动使用,涨跌趋势,1为涨,2为跌,0为不动 + TrendPrice int `json:"trendPrice"` //涨跌具体多少 } func (*ActStoreSkuMap) TableUnique() [][]string { @@ -189,7 +203,10 @@ func (*ActStoreSkuMap) TableIndex() [][]string { type ActStoreSku2 struct { MapID int `orm:"column(map_id)"` - Type int `json:"type"` + Type int `json:"type"` + DiscountType int `json:"discountType"` + DiscountValue1 int `json:"discountValue1"` + DiscountValue2 int `json:"discountValue2"` ActStoreSku VendorID int `orm:"column(vendor_id)" json:"vendorID"` @@ -215,6 +232,8 @@ type ActStoreSku2 struct { SpecQuality float32 `json:"-"` SpecUnit string `json:"-"` Comment string `json:"-"` + TrendType int `json:"trendType"` //折扣活动使用,涨跌趋势,1为涨,2为跌,0为不动 + TrendPrice int `json:"trendPrice"` //涨跌具体多少 } type StoreSkuAct struct { diff --git a/business/model/api.go b/business/model/api.go index b70527b5f..3c2c812d9 100644 --- a/business/model/api.go +++ b/business/model/api.go @@ -35,9 +35,11 @@ type GoodsOrderExt struct { WaybillCreatedAt time.Time `orm:"type(datetime);index" json:"waybillCreatedAt"` WaybillFinishedAt time.Time `orm:"type(datetime)" json:"waybillFinishedAt"` - DistrictName string `json:"districtName"` - CityName string `json:"cityName"` - PayPercentage int `json:"payPercentage"` + DistrictName string `json:"districtName"` + CityName string `json:"cityName"` + PayPercentage int `json:"payPercentage"` + VendorPayPercentage int `json:"vendorPayPercentage"` + OldPayPercentage int `json:"oldPayPercentage"` SkuInfo string `json:"skuInfo,omitempty"` SkuInfo2 string `json:"skuInfo2,omitempty"` @@ -47,6 +49,9 @@ type GoodsOrderExt struct { ShopSumPrice int64 `json:"shopSumPrice"` AvgPrice int64 `json:"avgPrice"` BadCommentCount int `json:"badCommentCount"` + + FloatLng float64 `json:"floatLng"` + FloatLat float64 `json:"floatLat"` } type OrderSkuExt struct { diff --git a/business/model/api_config.go b/business/model/api_config.go index fb5b25ad0..c3028bbf9 100644 --- a/business/model/api_config.go +++ b/business/model/api_config.go @@ -26,7 +26,8 @@ const ( VendorIDDada = 101 VendorIDMTPS = 102 VendorIDFengNiao = 103 - VendorIDDeliveryEnd = 200 + VendorIDJDWL = 401 //京东物流 + VendorIDDeliveryEnd = 500 VendorIDPrinterBegin = 201 VendorIDFeiE = 201 // 飞鹅打印机 @@ -48,7 +49,6 @@ const ( VendorIDQiNiuCloud = 323 // 七牛云 VendorIDShowAPI = 325 // 万维易源 - VendorIDJDWL = 401 //京东物流 ) type VendorInfo struct { @@ -73,8 +73,9 @@ var ( VendorIDJX: "Jx", VendorIDJDShop: "Jds", - VendorIDDada: "Dada", - VendorIDMTPS: "Mtps", + VendorIDDada: "Dada", + VendorIDMTPS: "Mtps", + VendorIDFengNiao: "Fn", VendorIDFeiE: "Feie", VendorIDXiaoWM: "XiaoWM", @@ -82,6 +83,7 @@ var ( VendorIDZhongWu: "ZhongWu", VendorIDQiNiuCloud: "Qiniu", + VendorIDJDWL: "Jdwl", } VendorTypeName = map[int]string{ @@ -101,9 +103,10 @@ var ( VendorIDWSC: "微盟微商城", VendorIDJX: "京西商城", - VendorIDDada: "达达众包", - VendorIDMTPS: "美团配送", - VendorIDJDWL: "京东物流", + VendorIDDada: "达达众包", + VendorIDMTPS: "美团配送", + VendorIDJDWL: "京东物流", + VendorIDFengNiao: "蜂鸟配送", VendorIDFeiE: "飞鹅", VendorIDXiaoWM: "外卖管家", diff --git a/business/model/const.go b/business/model/const.go index 700f6d71d..517808e1d 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -53,6 +53,7 @@ var ( OrderStatusWait4Pay: "待付款", OrderStatusNew: "新订单", + OrderStatusWaitAccepted: "待接单", OrderStatusAccepted: "待拣货", OrderStatusFinishedPickup: "待配送", OrderStatusApplyFailedGetGoods: "取货失败待审核", @@ -76,6 +77,7 @@ var ( WaybillStatusPending: "压单", WaybillStatusAcceptCanceled: "取消接受", WaybillStatusAccepted: "已接单", + WaybillStatusCourierAssigned: "已分配骑手", WaybillStatusCourierArrived: "已到店", WaybillStatusApplyFailedGetGoods: "取货失败待审核", WaybillStatusAgreeFailedGetGoods: "取货失败", @@ -151,6 +153,15 @@ var ( VendorIDEBAI: 0, } + ZXCityCodeMap = map[int]string{ + 310100: "上海市", + 110100: "北京市", + 120100: "天津市", + 440300: "深圳市", + 500100: "重庆市", + 441900: "东莞", + } + PrinterVendorInfo = map[int][]string{ VendorIDFeiE: []string{ VendorChineseNames[VendorIDFeiE], @@ -191,6 +202,10 @@ var ( AfsAppealTypeReturnAndRefund: "退款", // 这个其实是退货退款,强制显示成退款 AfsAppealTypeNewGoods: "退款.", // 这个其实是重发商品,强制显示成退款 } + VendorStatus = map[int]string{ + 0: "休息", + 1: "营业", + } ) const ( @@ -234,6 +249,7 @@ const ( OrderStatusUnknown = 0 OrderStatusWait4Pay = 2 // 原值-60 下单待支付 + OrderStatusWaitAccepted = 3 // 待接单,目前饿百用 OrderStatusNew = 5 // 新订单,实际是已经支付 OrderStatusAccepted = 10 // 已经接单,也即待出库,待拣货 OrderStatusFinishedPickup = 15 // 拣货完成 @@ -291,11 +307,12 @@ const ( WaybillStatusRefuseFailedGetGoods = -70 WaybillStatusUnknown = 0 - WaybillStatusNew = 5 - WaybillStatusPending = 7 - WaybillStatusAcceptCanceled = 8 - WaybillStatusAccepted = 10 - WaybillStatusCourierArrived = 15 // 此状态是可选的,明确写出来是因为还是较重要的状态,但业务逻辑不应依赖此状态 + WaybillStatusNew = 5 + WaybillStatusPending = 7 + WaybillStatusAcceptCanceled = 8 + WaybillStatusAccepted = 10 + WaybillStatusCourierAssigned = 12 //已分配骑手 + WaybillStatusCourierArrived = 15 // 此状态是可选的,明确写出来是因为还是较重要的状态,但业务逻辑不应依赖此状态 WaybillStatusApplyFailedGetGoods = 17 // 取货失败待审核 WaybillStatusAgreeFailedGetGoods = 18 // 取货失败 @@ -406,6 +423,8 @@ const ( YES = 1 //通用 NO = 0 DISABLED = -1 + + Nothing = "nothing" ) func IsPurchaseVendorExist(vendorID int) bool { diff --git a/business/model/dao/act.go b/business/model/dao/act.go index 3ed92ef4c..a40220d8d 100644 --- a/business/model/dao/act.go +++ b/business/model/dao/act.go @@ -83,7 +83,7 @@ func GetActStoreSkuVendorList(db *DaoDB, actID int, vendorIDs, storeIDs, skuIDs sql := fmt.Sprintf(` SELECT SQL_CALC_FOUND_ROWS t1.*, - t2.id map_id, t2.vendor_id, t2.vendor_act_id, t2.sync_status, t2.actual_act_price, t2.vendor_price, + t2.id map_id, t2.vendor_id, t2.vendor_act_id, t2.sync_status, t2.actual_act_price, t2.vendor_price, t2.trend_type, t2.trend_price, t3.vendor_store_id, CASE t2.vendor_id WHEN 0 THEN @@ -373,9 +373,9 @@ func GetEffectiveActStoreSkuInfo(db *DaoDB, actID int, vendorIDs []int, actType } sql := ` SELECT - t1.type, + t1.type, t1.discount_type, t1.discount_value1, t1.discount_value2, t2.*, - t3.actual_act_price, t3.sync_status, t3.vendor_price, t3.vendor_id + t3.actual_act_price, t3.sync_status, t3.vendor_price, t3.vendor_id, t3.trend_type, t3.trend_price FROM act t1 JOIN act_store_sku t2 ON t2.act_id = t1.id AND t2.deleted_at = ? JOIN act_store_sku_map t3 ON t3.bind_id = t2.id AND t3.act_id = t1.id AND (t3.sync_status & ? = 0 OR t1.type = ?) diff --git a/business/model/dao/common.go b/business/model/dao/common.go index f3dbab71a..5ba50cd62 100644 --- a/business/model/dao/common.go +++ b/business/model/dao/common.go @@ -1,6 +1,7 @@ package dao import ( + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" ) @@ -30,3 +31,26 @@ func GetNeedUploadDataResource(db *DaoDB) (dataResList []*model.DataResource, er err = GetRows(db, &dataResList, sql) return dataResList, err } + +func GetVendorOrgCode(db *DaoDB, vendorID int, vendorOrgCode, vendorType string) (vendorOrgs []*model.VendorOrgCode, err error) { + sql := ` + SELECT * + FROM vendor_org_code + WHERE deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if vendorID != -1 { + sql += " AND vendor_id = ?" + sqlParams = append(sqlParams, vendorID) + } + if vendorOrgCode != "" { + sql += " AND vendor_org_code = ?" + sqlParams = append(sqlParams, vendorOrgCode) + } + if vendorType != "" { + sql += " AND vendor_type = ?" + sqlParams = append(sqlParams, vendorType) + } + err = GetRows(db, &vendorOrgs, sql, sqlParams) + return vendorOrgs, err +} diff --git a/business/model/dao/dao_order.go b/business/model/dao/dao_order.go index fc8994645..ddf5ba59c 100644 --- a/business/model/dao/dao_order.go +++ b/business/model/dao/dao_order.go @@ -31,6 +31,8 @@ type StoresOrderSaleInfo struct { DistanceFreightMoney int64 `json:"distanceFreightMoney"` // 商户承担的远距离配送费(当前只有京东到家有值) WaybillTipMoney int64 `json:"waybillTipMoney"` // 京西加的平台配送小费 + + RealEarningPrice int64 `json:"realEarningPrice"` } type OrderSkuWithActualPayPrice struct { @@ -43,8 +45,11 @@ type OrderSkuWithActualPayPrice struct { StoreID int `orm:"column(store_id)" json:"storeID"` // 外部系统里记录的 jxstoreid Status int `json:"status"` // 参见OrderStatus*相关的常量定义 - PayPercentage int `json:"payPercentage"` - NewEarningPrice int64 `json:"newEarningPrice"` + PayPercentage int `json:"payPercentage"` + OrderPayPercentage int `json:"orderPayPercentage"` + NewEarningPrice int64 `json:"newEarningPrice"` + EarningType int `json:"earningType"` + CityCode int `json:"cityCode"` } type tGoodsAndOrder struct { @@ -337,7 +342,7 @@ func GetStoresOrderSaleInfo(db *DaoDB, storeIDList []int, fromTime time.Time, to return saleInfoList, err } -func GetAfsOrderSkuInfo(db *DaoDB, vendorOrderID, afsOrderID string, vendorID int) (skus []*model.OrderFinancialSkuExt, err error) { +func GetAfsOrderSkuInfo(db *DaoDB, vendorOrderID, afsOrderID string, vendorID int, isNotFaild bool) (skus []*model.OrderFinancialSkuExt, err error) { if vendorOrderID == "" && afsOrderID == "" { return nil, fmt.Errorf("必须指定订单或售后单ID") } @@ -346,6 +351,7 @@ func GetAfsOrderSkuInfo(db *DaoDB, vendorOrderID, afsOrderID string, vendorID in FROM order_sku_financial t1 LEFT JOIN sku t2 ON t2.id = IF(t1.jx_sku_id <> 0, t1.jx_sku_id, t1.sku_id) LEFT JOIN sku_name t3 ON t3.id = t2.name_id + LEFT JOIN afs_order t4 ON t4.afs_order_id = t1.afs_order_id WHERE t1.is_afs_order = 1 AND t1.vendor_id = ?` sqlParams := []interface{}{ vendorID, @@ -359,7 +365,10 @@ func GetAfsOrderSkuInfo(db *DaoDB, vendorOrderID, afsOrderID string, vendorID in sql += " AND t1.afs_order_id = ?" sqlParams = append(sqlParams, afsOrderID) } - + if isNotFaild { + sql += " AND t4.status <> ?" + sqlParams = append(sqlParams, model.AfsOrderStatusFailed) + } err = GetRows(db, &skus, sql, sqlParams...) return skus, err } @@ -369,7 +378,7 @@ func GetStoreOrderSkuList(db *DaoDB, storeIDs []int, finishedAtBegin, finishedAt sql := ` SELECT t1.*, IF(t2.jx_store_id > 0, t2.jx_store_id, t2.store_id) store_id, t2.status, t2.actual_pay_price, t2.distance_freight_money, t2.waybill_tip_money, t2.new_earning_price, - t3.pay_percentage + t3.pay_percentage, t2.earning_type, t2.order_pay_percentage, t3.city_code FROM order_sku t1 JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id AND t2.vendor_id = t1.vendor_id LEFT JOIN store t3 ON t3.id = IF(t2.jx_store_id > 0, t2.jx_store_id, t2.store_id) @@ -763,11 +772,11 @@ func GetOrders(db *DaoDB, ids []int64, isIncludeSku, isIncludeFake bool, fromDat sql := fmt.Sprintf(` SELECT SQL_CALC_FOUND_ROWS - t1.*, + DISTINCT t1.*, CAST(IF(t1.earning_price <> 0, t1.earning_price, IF(t1.shop_price <> 0 && t1.shop_price < t1.sale_price, t1.shop_price, t1.sale_price) * IF(t5.pay_percentage > 0, t5.pay_percentage, %d) / 100) AS SIGNED) earning_price, t2.status waybill_status, t2.courier_name, t2.courier_mobile, t2.actual_fee, t2.desired_fee, t2.waybill_created_at, t2.waybill_finished_at, - t5.pay_percentage, + t5.pay_percentage, t5.old_pay_percentage, t6.vendor_pay_percentage, city.name city_name, district.name district_name`, model.DefaultEarningPricePercentage) if isIncludeSku { sql += `, @@ -780,8 +789,9 @@ func GetOrders(db *DaoDB, ids []int64, isIncludeSku, isIncludeFake bool, fromDat } sql += ` FROM goods_order t1 - LEFT JOIN waybill t2 ON t1.vendor_waybill_id = t2.vendor_waybill_id AND t1.waybill_vendor_id = t2.waybill_vendor_id + LEFT JOIN waybill t2 ON t1.vendor_waybill_id = t2.vendor_waybill_id AND t1.waybill_vendor_id = t2.waybill_vendor_id AND t1.vendor_order_id = t2.vendor_order_id LEFT JOIN store t5 ON t5.id = IF(t1.jx_store_id <> 0, t1.jx_store_id, t1.store_id) + LEFT JOIN store_map t6 ON t6.store_id = t5.id AND t6.deleted_at = '1970-01-01 00:00:00' AND t6.vendor_id = t1.vendor_id LEFT JOIN place city ON city.code = t5.city_code LEFT JOIN place district ON district.code = t5.district_code` if isIncludeSku { @@ -894,6 +904,12 @@ func GetOrders(db *DaoDB, ids []int64, isIncludeSku, isIncludeFake bool, fromDat sqlParams = append(sqlParams, lockStatuss) } } + if params["brandID"] != nil { + if utils.MustInterface2Int64(params["brandID"]) != 0 { + sqlWhere += " AND t5.brand_id = ?" + sqlParams = append(sqlParams, utils.MustInterface2Int64(params["brandID"])) + } + } if params["cities"] != nil { var cities []int if err = utils.UnmarshalUseNumber([]byte(params["cities"].(string)), &cities); err != nil { @@ -1259,12 +1275,12 @@ func GetWaybills(db *DaoDB, vendorOrderID string) (waybills []*model.Waybill, er func GetMatterChildOrders(db *DaoDB, vendorOrderID string) (goods []*model.GoodsOrder, err error) { sql := `SELECT * FROM goods_order - WHERE vendor_order_id LIKE ? OR vendor_order_id LIKE ? + WHERE vendor_order_id LIKE ? OR vendor_order_id LIKE ? OR vendor_order_id LIKE ? AND vendor_id = ? ORDER BY vendor_order_id DESC ` sqlParams := []interface{}{ - vendorOrderID + "0%", vendorOrderID + "1%", + vendorOrderID + "0%", vendorOrderID + "1%", vendorOrderID + "2%", model.VendorIDJX, } err = GetRows(db, &goods, sql, sqlParams) @@ -1281,3 +1297,313 @@ func GetSimpleOrder(db *DaoDB, vendorOrderID string) (goods *model.GoodsOrder, e err = GetRow(db, &goods, sql, sqlParams) return goods, err } + +func GetSimpleOrderSkus(db *DaoDB, vendorOrderID string, skuIDs []int) (skus []*model.OrderSku, err error) { + sql := ` + SELECT * + FROM order_sku + WHERE vendor_order_id = ? + ` + sqlParams := []interface{}{vendorOrderID} + if len(skuIDs) > 0 { + sql += " AND sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" + sqlParams = append(sqlParams, skuIDs) + } + err = GetRows(db, &skus, sql, sqlParams) + return skus, err +} + +func GetAfsOrdersByPage(db *DaoDB, vendorOrderID, afsOrderID, userID string, fromTime, toTime time.Time, offset, pageSize int) (afsOrderList []*model.AfsOrder, totalCount int, err error) { + pageSize = jxutils.FormalizePageSize(pageSize) + offset = jxutils.FormalizePageOffset(offset) + sql := ` + SELECT SQL_CALC_FOUND_ROWS t1.* + FROM afs_order t1 + LEFT JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id AND t2.vendor_id = t1.vendor_id + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if vendorOrderID != "" { + sql += " AND t1.vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) + } + if afsOrderID != "" { + sql += " AND t1.afs_order_id = ?" + sqlParams = append(sqlParams, afsOrderID) + } + if !utils.IsTimeZero(fromTime) { + sql += " AND t1.afs_created_at >= ?" + sqlParams = append(sqlParams, fromTime) + } + if !utils.IsTimeZero(toTime) { + sql += " AND t1.afs_created_at <= ?" + sqlParams = append(sqlParams, toTime) + } + if userID != "" { + sql += " AND t2.user_id = ?" + sqlParams = append(sqlParams, userID) + } + sql += ` ORDER BY t1.afs_order_id DESC + LIMIT ? OFFSET ? + ` + sqlParams = append(sqlParams, pageSize, offset) + Begin(db) + defer Commit(db) + if err = GetRows(db, &afsOrderList, sql, sqlParams...); err == nil { + totalCount = GetLastTotalRowCount(db) + } + return afsOrderList, totalCount, err +} + +func GetOrderStoreSkusCount(db *DaoDB, storeID, skuID int, fromTime, toTime time.Time) (count int64, err error) { + tmpOrderSku := &model.OrderSku{} + sql := ` + SELECT SUM(a.count) count + FROM order_sku a + JOIN goods_order b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id + WHERE IF(b.store_id = 0, b.jx_store_id, b.store_id) = ? + AND a.sku_id = ? + AND b.order_created_at BETWEEN ? AND ? + AND b.status >= ? + ` + sqlParams := []interface{}{ + storeID, + skuID, + fromTime, + toTime, + model.OrderStatusDelivering, + } + if err = GetRow(db, &tmpOrderSku, sql, sqlParams); err == nil { + return int64(tmpOrderSku.Count), nil + } + return count, err +} + +type GetSupplySupportStoreSkusResult struct { + SkuID int `orm:"column(sku_id)" json:"skuID"` + Count int `json:"count"` + SalePrice int `json:"salePrice"` + Stock int `json:"stock"` + model.SkuName +} + +func GetSupplySupportStoreSkus(db *DaoDB, fromDate, toDate time.Time, fromStoreID, storeID int, percentage float64) (getSupplySupportStoreSkusResult []*GetSupplySupportStoreSkusResult, err error) { + sql := ` + SELECT c.sku_id,CEIL(c.count) count,CEIL(c.count) * d.jx_price sale_price, d.stock, f.* + FROM + ( + SELECT a.sku_id,SUM(a.count * ? ) count FROM order_sku a + JOIN goods_order b ON b.vendor_order_id = a.vendor_order_id AND a.vendor_id = b.vendor_id + WHERE b.order_created_at > ? + AND b.order_created_at < ? + AND a.sku_id <> ? + AND IF(b.store_id = 0,b.jx_store_id,b.store_id) = ? + GROUP BY 1 + )c + JOIN store_sku_bind d ON d.store_id = ? AND d.sku_id = c.sku_id AND d.deleted_at = ? + JOIN sku e ON e.id = d.sku_id + JOIN sku_name f ON f.id = e.name_id + WHERE d.status <> ? + AND d.stock <> ? + ORDER BY c.count desc + ` + sqlParams := []interface{}{ + percentage, + fromDate, + toDate, + 6039481, //葱姜蒜 + fromStoreID, + storeID, utils.DefaultTimeValue, + model.StoreSkuBindStatusDontSale, + 0, + } + if err = GetRows(db, &getSupplySupportStoreSkusResult, sql, sqlParams); err == nil { + return getSupplySupportStoreSkusResult, err + } + return getSupplySupportStoreSkusResult, err +} + +func GetPriceDefendOrder(db *DaoDB, vendorOrderID string, storeIDs, skuIDs, issues []int, defendPrice, isBuyNowPrice, isSuccess, isPay int, userID string, beginAt, EndAt time.Time, isDesc bool) (priceDefendOrders []*model.PriceDefendOrder, err error) { + sql := ` + SELECT a.* + FROM price_defend_order a + JOIN user_delivery_address b ON a.address_id = b.id AND b.deleted_at = ? + WHERE 1 = 1 + AND a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + utils.DefaultTimeValue, + } + if vendorOrderID != "" { + sql += " AND a.vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) + } + if len(storeIDs) > 0 { + sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + if len(skuIDs) > 0 { + sql += " AND a.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" + sqlParams = append(sqlParams, skuIDs) + } + if len(issues) > 0 { + sql += " AND a.issue IN (" + GenQuestionMarks(len(issues)) + ")" + sqlParams = append(sqlParams, issues) + } + if defendPrice != 0 { + sql += " AND a.defend_price = ?" + sqlParams = append(sqlParams, defendPrice) + } + if isBuyNowPrice != -1 { + sql += " AND a.is_buy_now_price = ?" + sqlParams = append(sqlParams, isBuyNowPrice) + } + if isSuccess != -1 { + sql += " AND a.is_success = ?" + sqlParams = append(sqlParams, isSuccess) + } + if isPay != -1 { + sql += " AND a.is_pay = ?" + sqlParams = append(sqlParams, isPay) + } + if userID != "" { + sql += " AND b.user_id = ?" + sqlParams = append(sqlParams, userID) + } + if beginAt != utils.ZeroTimeValue { + sql += " AND a.created_at >= ?" + sqlParams = append(sqlParams, beginAt) + } + if EndAt != utils.ZeroTimeValue { + sql += " AND a.created_at <= ?" + sqlParams = append(sqlParams, EndAt) + } + if isDesc { + sql += " ORDER BY a.created_at DESC" + } else { + sql += " ORDER BY a.created_at" + } + err = GetRows(db, &priceDefendOrders, sql, sqlParams) + return priceDefendOrders, err +} + +func GetCoupons(db *DaoDB, couponType int, couponStatuss, storeIDs []int, userID, mobile, keyword string) (coupons []*model.Coupons, err error) { + sqlParams := []interface{}{} + sql := ` + SELECT DISTINCT a.* + FROM coupons a + ` + if userID != "" || mobile != "" { + sql += " JOIN user_coupons b ON a.id = b.coupon_id" + if userID != "" { + sql += " AND b.user_id = ?" + sqlParams = append(sqlParams, userID) + } + if mobile != "" { + sql += " AND b.mobile = ?" + sqlParams = append(sqlParams, mobile) + } + } + sql += ` + WHERE a.is_all = ? + ` + sqlParams = append(sqlParams, model.YES) + if couponType != 0 { + sql += " AND a.coupon_type = ?" + sqlParams = append(sqlParams, couponType) + } + if keyword != "" { + sql += " AND (a.name LIKE ? OR a.desc LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%") + } + if len(couponStatuss) > 0 { + sql += " AND a.coupon_status IN (" + GenQuestionMarks(len(couponStatuss)) + ")" + sqlParams = append(sqlParams, couponStatuss) + } + sql += ` + UNION + SELECT DISTINCT a.* + FROM coupons a + LEFT JOIN store_coupons b ON a.id = b.coupon_id AND b.deleted_at = ? + ` + if userID != "" || mobile != "" { + sql += " JOIN user_coupons c ON a.id = c.coupon_id" + if userID != "" { + sql += " AND c.user_id = ?" + sqlParams = append(sqlParams, userID) + } + if mobile != "" { + sql += " AND c.mobile = ?" + sqlParams = append(sqlParams, mobile) + } + } + sql += ` + WHERE 1 = 1 + ` + sqlParams = append(sqlParams, utils.DefaultTimeValue) + if couponType != 0 { + sql += " AND a.coupon_type = ?" + sqlParams = append(sqlParams, couponType) + } + if keyword != "" { + sql += " AND (a.name LIKE ? OR a.desc LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%") + } + if len(couponStatuss) > 0 { + sql += " AND a.coupon_status IN (" + GenQuestionMarks(len(couponStatuss)) + ")" + sqlParams = append(sqlParams, couponStatuss) + } + if len(storeIDs) > 0 { + sql += " AND b.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + err = GetRows(db, &coupons, sql, sqlParams) + return coupons, err +} + +func GetStoreCoupons(db *DaoDB, couponIDs, storeIDs []int) (storeCoupons []*model.StoreCoupons, err error) { + sql := ` + SELECT * + FROM store_coupons + WHERE deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if len(couponIDs) > 0 { + sql += " AND coupon_id IN (" + GenQuestionMarks(len(couponIDs)) + ")" + sqlParams = append(sqlParams, couponIDs) + } + if len(storeIDs) > 0 { + sql += " AND store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + err = GetRows(db, &storeCoupons, sql, sqlParams) + return storeCoupons, err +} + +func GetUserCoupons(db *DaoDB, couponIDs []int, userIDs, mobiles []string, userStatus int) (userCoupons []*model.UserCoupons, err error) { + sql := ` + SELECT * + FROM user_coupons + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if len(couponIDs) > 0 { + sql += " AND coupon_id IN (" + GenQuestionMarks(len(couponIDs)) + ")" + sqlParams = append(sqlParams, couponIDs) + } + if len(userIDs) > 0 { + sql += " AND user_id IN (" + GenQuestionMarks(len(userIDs)) + ")" + sqlParams = append(sqlParams, userIDs) + } + if len(mobiles) > 0 { + sql += " AND mobile IN (" + GenQuestionMarks(len(mobiles)) + ")" + sqlParams = append(sqlParams, mobiles) + } + if userStatus != 0 { + sql += " AND user_coupon_status = ?" + sqlParams = append(sqlParams, userStatus) + } + err = GetRows(db, &userCoupons, sql, sqlParams) + return userCoupons, err +} diff --git a/business/model/dao/dao_user.go b/business/model/dao/dao_user.go index 4206a2979..c394b9acd 100644 --- a/business/model/dao/dao_user.go +++ b/business/model/dao/dao_user.go @@ -20,6 +20,12 @@ type UserDeliveryAddressEx struct { UserName string `json:"userName"` CityName string `json:"cityName"` DistrictName string `json:"districtName"` + ParentCode int `json:"parentCode"` +} + +type GetSelfInfoResult struct { + model.User + UserMembers []*model.UserMember `json:"userMembers"` } func GetUserByID(db *DaoDB, fieldName, fieldValue string) (user *model.User, err error) { @@ -38,6 +44,22 @@ func GetUserByID(db *DaoDB, fieldName, fieldValue string) (user *model.User, err return user, err } +func GetUserByIDWithMembers(db *DaoDB, fieldName, fieldValue string) (getSelfInfoResult *GetSelfInfoResult, err error) { + sql := fmt.Sprintf(` + SELECT * + FROM user t1 + WHERE t1.deleted_at = ? AND t1.status = ? AND t1.%s = ? + `, fieldName) + sqlParams := []interface{}{ + utils.DefaultTimeValue, + model.UserStatusNormal, + fieldValue, + } + // globals.SugarLogger.Debugf("GetUserByID sql:%s, sqlParams:%s", sql, utils.Format4Output(sqlParams, false)) + err = GetRow(db, &getSelfInfoResult, sql, sqlParams...) + return getSelfInfoResult, err +} + func GetUsers(db *DaoDB, userType int, keyword string, userIDs, userID2s, mobiles []string, offset, pageSize int) (userList []*model.User, totalCount int, err error) { offset = jxutils.FormalizePageOffset(offset) pageSize = jxutils.FormalizePageSize(pageSize) @@ -162,11 +184,13 @@ func QueryUserDeliveryAddress(db *DaoDB, addressID int64, userIDs []string, offs t1.*, t2.name user_name, district.name district_name, - city.name city_name + city.name city_name, + cp.code parent_code FROM user_delivery_address t1 LEFT JOIN user t2 ON t2.user_id = t1.user_id LEFT JOIN place district ON district.code = t1.district_code LEFT JOIN place city ON city.code = t1.city_code + LEFT JOIN place cp ON cp.code = city.parent_code WHERE t1.deleted_at = ? ` sqlParams := []interface{}{ @@ -258,3 +282,30 @@ func GetUserOrderSMS(db *DaoDB, mobile, name string) (userOrderSms *model.UserOr err = GetRow(db, &userOrderSms, sql, sqlParams) return userOrderSms, err } + +func GetUserMember(db *DaoDB, userID, vendorOrderID string, memberType, isPay int) (userMembers []*model.UserMember, err error) { + sql := ` + SELECT * + FROM user_member + WHERE deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if userID != "" { + sql += " AND user_id = ?" + sqlParams = append(sqlParams, userID) + } + if vendorOrderID != "" { + sql += " AND vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) + } + if memberType != 0 { + sql += " AND member_type = ?" + sqlParams = append(sqlParams, memberType) + } + if isPay != -1 { + sql += " AND is_pay = ?" + sqlParams = append(sqlParams, isPay) + } + err = GetRows(db, &userMembers, sql, sqlParams) + return userMembers, err +} diff --git a/business/model/dao/event.go b/business/model/dao/event.go index 66768d1d8..ad4cce5d6 100644 --- a/business/model/dao/event.go +++ b/business/model/dao/event.go @@ -141,3 +141,32 @@ func GetOperateEvents(db *DaoDB, name string, apiFunctions []string, operateType } return operateEventExt, totalCount, err } + +func GetImMessageRecord(db *DaoDB, vendorOrderID, userID string, storeID, vendorID int) (msg []*model.ImMessageRecord, err error) { + sql := ` + SELECT * + FROM im_message_record + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if vendorOrderID != "" { + sql += " AND vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) + } + if userID != "" { + sql += " AND user_id = ?" + sqlParams = append(sqlParams, userID) + } + if storeID != 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if vendorID >= 0 { + sql += " AND vendor_id = ?" + sqlParams = append(sqlParams, vendorID) + } + err = GetRows(db, &msg, sql, sqlParams) + return msg, err +} diff --git a/business/model/dao/permission.go b/business/model/dao/permission.go new file mode 100644 index 000000000..94d4fc989 --- /dev/null +++ b/business/model/dao/permission.go @@ -0,0 +1,141 @@ +package dao + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" +) + +func GetMenu(db *DaoDB, name string, level int, userID string) (menus []*model.Menu, err error) { + sqlParams := []interface{}{} + sql := ` + SELECT DISTINCT a.* + FROM menu a + ` + if userID != "" { + sql += ` + JOIN menu d ON d.parent_id = a.id + JOIN user_role b ON b.user_id = ? AND b.deleted_at = ? + JOIN role_menu c ON c.menu_id = d.id AND c.role_id = b.role_id AND c.deleted_at = ? + ` + sqlParams = append(sqlParams, userID, utils.DefaultTimeValue, utils.DefaultTimeValue) + } + sql += " WHERE a.deleted_at = ?" + sqlParams = append(sqlParams, utils.DefaultTimeValue) + if name != "" { + sql += " AND a.name LIKE ?" + sqlParams = append(sqlParams, "%"+name+"%") + } + if level != 0 { + sql += " AND a.level = ?" + sqlParams = append(sqlParams, level) + } + sql += " ORDER BY a.id" + err = GetRows(db, &menus, sql, sqlParams) + return menus, err +} + +func GetMenuWithUser(db *DaoDB, name string, level int, userID string) (menus []*model.Menu, err error) { + sql := ` + SELECT DISTINCT b.* FROM ( + SELECT a.id,a.parent_id + FROM menu a + JOIN user_role b ON b.user_id = ? AND b.deleted_at = ? + JOIN role_menu c ON c.menu_id = a.id AND c.role_id = b.role_id AND c.deleted_at = ? + WHERE a.deleted_at = ?)a + JOIN menu b ON (b.id = a.id OR b.id = a.parent_id) + ORDER BY b.id + ` + sqlParams := []interface{}{userID, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue} + err = GetRows(db, &menus, sql, sqlParams) + return menus, err +} + +func GetRole(db *DaoDB, name, name2 string) (roles []*model.Role, err error) { + sql := ` + SELECT * + FROM role + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if name != "" { + sql += " AND name LIKE ?" + sqlParams = append(sqlParams, "%"+name+"%") + } + if name2 != "" { + sql += " AND name = ?" + sqlParams = append(sqlParams, name2) + } + err = GetRows(db, &roles, sql, sqlParams) + return roles, err +} + +func GetUserRole(db *DaoDB, userIDs []string, roleIDs []int) (userRoles []*model.UserRole, err error) { + sql := ` + SELECT * + FROM user_role + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(userIDs) > 0 { + sql += " AND user_id IN (" + GenQuestionMarks(len(userIDs)) + ")" + sqlParams = append(sqlParams, userIDs) + } + if len(roleIDs) > 0 { + sql += " AND role_id IN (" + GenQuestionMarks(len(roleIDs)) + ")" + sqlParams = append(sqlParams, roleIDs) + } + err = GetRows(db, &userRoles, sql, sqlParams) + return userRoles, err +} + +type GetUserRole2Result struct { + model.Role + model.UserRole +} + +func GetUserRole2(db *DaoDB, userIDs []string, roleIDs []int) (userRoles []*GetUserRole2Result, err error) { + sql := ` + SELECT * + FROM user_role a + JOIN role b ON a.role_id = b.id + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(userIDs) > 0 { + sql += " AND a.user_id IN (" + GenQuestionMarks(len(userIDs)) + ")" + sqlParams = append(sqlParams, userIDs) + } + if len(roleIDs) > 0 { + sql += " AND a.role_id IN (" + GenQuestionMarks(len(roleIDs)) + ")" + sqlParams = append(sqlParams, roleIDs) + } + err = GetRows(db, &userRoles, sql, sqlParams) + return userRoles, err +} + +func GetRoleMenu(db *DaoDB, roleIDs, menuIDs []int) (roleMenus []*model.RoleMenu, err error) { + sql := ` + SELECT * + FROM role_menu + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(roleIDs) > 0 { + sql += " AND role_id IN (" + GenQuestionMarks(len(roleIDs)) + ")" + sqlParams = append(sqlParams, roleIDs) + } + if len(menuIDs) > 0 { + sql += " AND menu_id IN (" + GenQuestionMarks(len(menuIDs)) + ")" + sqlParams = append(sqlParams, menuIDs) + } + err = GetRows(db, &roleMenus, sql, sqlParams) + return roleMenus, err +} diff --git a/business/model/dao/place.go b/business/model/dao/place.go index 522acad41..35a697715 100644 --- a/business/model/dao/place.go +++ b/business/model/dao/place.go @@ -74,3 +74,29 @@ func GetPlaceByJdCode(db *DaoDB, jdCode int) (place *model.Place, err error) { err = db.Db.Read(place, "JdCode") return place, err } + +func GetPlaceByJdsCode(db *DaoDB, jdsCode int) (place *model.Place, err error) { + if db == nil { + db = GetDB() + } + place = &model.Place{ + JdsCode: jdsCode, + } + err = db.Db.Read(place, "JdsCode") + return place, err +} + +func GetPlaces(db *DaoDB, cityCodes []int) (places []*model.Place, err error) { + sql := ` + SELECT * + FROM place + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if len(cityCodes) > 0 { + sql += " AND code IN (" + GenQuestionMarks(len(cityCodes)) + ")" + sqlParams = append(sqlParams, cityCodes) + } + err = GetRows(db, &places, sql, sqlParams) + return places, err +} diff --git a/business/model/dao/report.go b/business/model/dao/report.go index ca0e7542e..14047a9ac 100644 --- a/business/model/dao/report.go +++ b/business/model/dao/report.go @@ -34,6 +34,7 @@ type StatisticsReportForOrdersList struct { OperatorName2 string `json:"operatorName2"` OperatorName3 string `json:"operatorName3"` + Address string `json:"address"` CityName string `json:"cityName"` Status int `json:"status"` Tel1 string `orm:"size(32);index" json:"tel1"` @@ -54,6 +55,7 @@ func GetStatisticsReportForOrders(db *DaoDB, storeIDs []int, fromDate time.Time, SELECT c.id store_id, c.name store_name, + c.address, s.order_counts, s.sale_price, s.actual_pay_price, diff --git a/business/model/dao/sensitive_words.go b/business/model/dao/sensitive_words.go index 540801d41..1b75629b4 100644 --- a/business/model/dao/sensitive_words.go +++ b/business/model/dao/sensitive_words.go @@ -1,17 +1,71 @@ package dao import ( + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/globals" + "time" ) -func GetSensitiveWordList() (wordList []*model.SensitiveWord, err error) { - sql := `SELECT * FROM sensitive_word` - err = GetRows(nil, &wordList, sql) +/*VendorID = -2 的时候是通用,-1 查询所有,保留之前的1,看后面会不会有扩展*/ +func GetSensitiveWordList(vendorID int) (wordList []*model.SensitiveWord, err error) { + if vendorID == 0 { + vendorID = -2 + } + if vendorID == -1 { + sql := `SELECT * FROM sensitive_word WHERE deleted_at = ?` + err = GetRows(nil, &wordList, sql, utils.DefaultTimeValue) + } else { + sql := `SELECT * FROM sensitive_word WHERE deleted_at = ? AND vendor_id = ?` + err = GetRows(nil, &wordList, sql, utils.DefaultTimeValue, vendorID) + } return wordList, err } func InsertSensitiveWord(word string, vendorID int, userName string) error { + if vendorID == 0 { + vendorID = -2 + } sensitiveWord := &model.SensitiveWord{Word: word, VendorID: vendorID} WrapAddIDCULDEntity(sensitiveWord, userName) return CreateEntity(nil, sensitiveWord) } + +func DeleteSensitiveWord(wordList *model.SensitiveWord, id int, userName string, vendorID int) (word *model.SensitiveWord, err error) { + if vendorID == 0 { + vendorID = -2 + } + if id != 0 { + wordList.ID = id + } + wordList.VendorID = id + wordList.DeletedAt = time.Now() + wordList.LastOperator = userName + if _, err := UpdateEntity(nil, wordList, "deleted_at", "id", "last_operator", "vendor_id"); err != nil { + return nil, err + } + return wordList, nil +} + +func UpdateSensitiveWord(wordList *model.SensitiveWord, vendorID int, id int, userName string) (word *model.SensitiveWord, err error) { + if vendorID == 0 { + vendorID = -2 + } + if id != 0 { + wordList.ID = id + } + wordList.VendorID = vendorID + wordList.UpdatedAt = time.Now() + wordList.LastOperator = userName + globals.SugarLogger.Debug("wordList:", wordList) + if id != 0 { + if _, err := UpdateEntity(nil, wordList, "id", "word", "vendor_id", "last_operator"); err != nil { + return nil, err + } + } else { + if _, err := UpdateEntity(nil, wordList, "word", "vendor_id", "last_operator"); err != nil { + return nil, err + } + } + return wordList, err +} diff --git a/business/model/dao/sku.go b/business/model/dao/sku.go index be89fa4a9..3c991428d 100644 --- a/business/model/dao/sku.go +++ b/business/model/dao/sku.go @@ -1,6 +1,8 @@ package dao import ( + "time" + "git.rosy.net.cn/baseapi/platformapi/aliupcapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" @@ -48,6 +50,21 @@ func DeleteSkuNamePlace(db *DaoDB, nameID int, placeCodes []int) (num int64, err return ExecuteSQL(db, sql, sqlParams...) } +func GetCategoriesByName(db *DaoDB, name string) (cats []*model.SkuCategory, err error) { + sql := ` + SELECT t1.* + FROM sku_category t1 + WHERE t1.deleted_at = ?` + params := []interface{}{ + utils.DefaultTimeValue, + } + if name != "" { + sql += " AND t1.name = ?" + params = append(params, name) + } + return cats, GetRows(db, &cats, sql, params) +} + func GetCategories(db *DaoDB, parentID, level int, catIDs []int, isExd bool) (cats []*model.SkuCategory, err error) { sql := ` SELECT t1.* @@ -69,6 +86,8 @@ func GetCategories(db *DaoDB, parentID, level int, catIDs []int, isExd bool) (ca params = append(params, level) } if isExd { + sql += " AND t1.is_exd_sync <> ?" + params = append(params, 1) sql += " ORDER BY t1.level, t1.exd_seq" } else { sql += ` AND t1.is_exd_spec = 0 @@ -104,12 +123,13 @@ func GetSkus(db *DaoDB, skuIDs, nameIDs, statuss, catIDs []int, eclpIDs []string } if len(catIDs) > 0 { sql += ` - JOIN sku_category t3 ON t3.id = t2.category_id - LEFT JOIN sku_category t3p ON t3p.id = t3.parent_id + JOIN sku_category t3 ON t3.id = t2.category_id AND t3.is_exd_spec = ? + LEFT JOIN sku_category t3p ON t3p.id = t3.parent_id AND t3p.is_exd_spec = ? ` sqlWhere += " AND (t3.id IN (" + GenQuestionMarks(len(catIDs)) + ")" sqlWhere += " OR t3p.id IN (" + GenQuestionMarks(len(catIDs)) + ") )" - sqlParams = append(sqlParams, catIDs, catIDs) + sqlWhere += " AND t1.exd_sku_id = ''" + sqlParams = append(sqlParams, model.NO, model.NO, catIDs, catIDs) } if len(eclpIDs) > 0 { sqlWhere += " AND t1.eclp_id IN (" + GenQuestionMarks(len(eclpIDs)) + ")" @@ -186,33 +206,34 @@ func GetSkuCategoryWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, t1.*, t1m.vendor_thing_id vendor_cat_id, t1m.sync_status cat_sync_status, - + a.is_jx_cat, + b.vendor_category_name, + b.vendor_category_seq, + b.id vendor_category_id, t1pm.id parent_map_id, t1p.name parent_cat_name, t1pm.vendor_thing_id parent_vendor_cat_id, t1pm.sync_status parent_cat_sync_status FROM sku_category t1 - LEFT JOIN thing_map t1m ON t1m.thing_id = t1.id AND t1m.thing_type = ? AND t1m.deleted_at = ?` + LEFT JOIN thing_map t1m ON t1m.thing_id = t1.id AND t1m.thing_type = ? AND t1m.deleted_at = ? + LEFT JOIN vendor_org_code a ON a.vendor_org_code = t1m.vendor_org_code AND a.vendor_id = t1m.vendor_id AND a.deleted_at = ? + LEFT JOIN vendor_category_map b ON b.vendor_org_code = t1m.vendor_org_code AND b.vendor_id = t1m.vendor_id AND b.category_id = t1m.thing_id AND b.deleted_at = ? + ` sqlParams := []interface{}{ model.ThingTypeCategory, utils.DefaultTimeValue, - } - if len(vendorIDs) > 0 { - sql += " AND t1m.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" - sqlParams = append(sqlParams, vendorIDs) - } - if len(appOrgCodes) > 0 { - sql += " AND t1m.vendor_org_code IN (" + GenQuestionMarks(len(appOrgCodes)) + ")" - sqlParams = append(sqlParams, appOrgCodes) + utils.DefaultTimeValue, + utils.DefaultTimeValue, } sql += ` LEFT JOIN sku_category t1p ON t1p.id = t1.parent_id LEFT JOIN thing_map t1pm ON t1pm.thing_id = t1p.id AND t1pm.thing_type = ? AND t1m.deleted_at = ? AND t1pm.vendor_id = t1m.vendor_id AND t1pm.vendor_org_code = t1m.vendor_org_code + LEFT JOIN vendor_category_map c ON c.vendor_org_code = t1pm.vendor_org_code AND c.vendor_id = t1pm.vendor_id AND c.category_id = t1pm.thing_id AND c.deleted_at = ? WHERE 1 = 1 AND t1.is_sync <> ? ` - sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue, model.YES) + sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue, utils.DefaultTimeValue, model.YES) if mustDirty { sql += " AND t1m.sync_status IS NOT NULL AND t1m.sync_status <> 0" } else { @@ -227,6 +248,14 @@ func GetSkuCategoryWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, sql += " AND t1.parent_id = ?" sqlParams = append(sqlParams, parentCatID) } + if len(vendorIDs) > 0 { + sql += " AND t1m.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sqlParams = append(sqlParams, vendorIDs) + } + if len(appOrgCodes) > 0 { + sql += " AND t1m.vendor_org_code IN (" + GenQuestionMarks(len(appOrgCodes)) + ")" + sqlParams = append(sqlParams, appOrgCodes) + } sql += " ORDER BY t1.seq" err = GetRows(db, &catList, sql, sqlParams...) return catList, err @@ -255,13 +284,11 @@ func GetSkusWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, nameIDs IF(t11.resource_type IS NULL OR t11.resource_type <> ?, t2.img, '') img, IF(t12.resource_type IS NULL OR t12.resource_type <> ?, t2.img2, '') img2, t2.desc_img, - t2.ex_prefix, - t2.ex_prefix_begin, - t2.ex_prefix_end, t3.jd_category_id vendor_vendor_cat_id, - + tsu.ex_prefix, tsu.begin_at ex_prefix_begin, tsu.end_at ex_prefix_end, tsu.img_watermark, t3m.sync_status cat_sync_status, - t3m.vendor_thing_id vendor_cat_id + t3m.vendor_thing_id vendor_cat_id, + tsy.vendor_category_id sku_vendor_map_cat_id FROM sku t1 LEFT JOIN thing_map t1m ON t1m.thing_id = t1.id AND t1m.thing_type = ? AND t1m.deleted_at = ?` @@ -286,9 +313,11 @@ func GetSkusWithVendor(db *DaoDB, vendorIDs []int, appOrgCodes []string, nameIDs AND t3m.vendor_id = t1m.vendor_id AND t3m.vendor_org_code = t1m.vendor_org_code LEFT JOIN data_resource t11 ON t11.main_url = t2.img LEFT JOIN data_resource t12 ON t12.main_url = t2.img2 + LEFT JOIN sku_exinfo_map tsu ON tsu.name_id = t2.id AND tsu.deleted_at = ? AND tsu.vendor_id = t1m.vendor_id + LEFT JOIN sku_vendor_category_map tsy ON tsy.name_id = t2.id AND tsy.vendor_id = ? AND tsy.deleted_at = ? WHERE 1 = 1 ` - sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue) + sqlParams = append(sqlParams, model.ThingTypeCategory, utils.DefaultTimeValue, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue) if mustDirty { sql += " AND t1m.sync_status IS NOT NULL AND t1m.sync_status <> 0" } else { @@ -379,3 +408,142 @@ func InsertUpcDepot(db *DaoDB, result *aliupcapi.GetAliUpcInfoResult) (err error _, err = ExecuteSQL(db, sql, sqlParams) return err } + +func GetSkuExinfos(db *DaoDB, nameIDs []int, vendorIDs []int, exPrefix string, fromTime, toTime time.Time) (skuExinfoMaps []*model.SkuExinfoMap, err error) { + sql := ` + SELECT * + FROM sku_exinfo_map + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(nameIDs) > 0 { + sql += " AND name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")" + sqlParams = append(sqlParams, nameIDs) + } + if len(vendorIDs) > 0 { + sql += " AND vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sqlParams = append(sqlParams, vendorIDs) + } + if exPrefix != "" { + sql += " AND ex_prefix LIKE ?" + sqlParams = append(sqlParams, "%"+exPrefix+"%") + } + if fromTime != utils.ZeroTimeValue && toTime != utils.ZeroTimeValue { + sql += " AND NOT (begin_at > ? OR end_at < ?)" + sqlParams = append(sqlParams, toTime, fromTime) + } + if err = GetRows(db, &skuExinfoMaps, sql, sqlParams...); err == nil { + return skuExinfoMaps, nil + } + return nil, err +} + +func GetSkuVendorCategoryMaps(db *DaoDB, nameIDs, vendorIDs []int, vendorCategoryIDs []string) (skuVendorCategoryMaps []*model.SkuVendorCategoryMap, err error) { + sql := ` + SELECT * + FROM sku_vendor_category_map + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(nameIDs) > 0 { + sql += " AND name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")" + sqlParams = append(sqlParams, nameIDs) + } + if len(vendorIDs) > 0 { + sql += " AND vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sqlParams = append(sqlParams, vendorIDs) + } + if len(vendorCategoryIDs) > 0 { + sql += " AND vendor_category_id IN (" + GenQuestionMarks(len(vendorCategoryIDs)) + ")" + sqlParams = append(sqlParams, vendorCategoryIDs) + } + if err = GetRows(db, &skuVendorCategoryMaps, sql, sqlParams...); err == nil { + return skuVendorCategoryMaps, nil + } + return nil, err +} + +func GetVendorCategoryMap(db *DaoDB, parentID, level, vendorID int, vendorOrgCode string, categoryID int) (vendorMaps []*model.VendorCategoryMap, err error) { + sql := ` + SELECT a.* + FROM vendor_category_map a + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if parentID >= 0 { + sql += " AND a.parent_id = ?" + sqlParams = append(sqlParams, parentID) + } + if level > 0 { + sql += " AND a.level = ?" + sqlParams = append(sqlParams, level) + } + if vendorID != -1 { + sql += " AND a.vendor_id = ?" + sqlParams = append(sqlParams, vendorID) + } + if vendorOrgCode != "" { + sql += " AND a.vendor_org_code = ?" + sqlParams = append(sqlParams, vendorOrgCode) + } + if categoryID > 0 { + sql += " AND a.category_id = ?" + sqlParams = append(sqlParams, categoryID) + } + sql += " ORDER BY a.level, a.vendor_category_seq" + err = GetRows(db, &vendorMaps, sql, sqlParams) + if err != nil { + return nil, err + } + return vendorMaps, err +} + +type GetVendorCategoryMapExtResult struct { + model.VendorCategoryMap + VendorThingID string `orm:"column(vendor_thing_id)" json:"vendorThingID"` +} + +func GetVendorCategoryMapExt(db *DaoDB, parentID, level, vendorID int, vendorOrgCode string, categoryID int) (vendorMaps []*GetVendorCategoryMapExtResult, err error) { + sql := ` + SELECT a.*, b.vendor_thing_id + FROM vendor_category_map a + JOIN thing_map b ON b.thing_id = a.category_id AND b.vendor_org_code = a.vendor_org_code AND b.vendor_id = a.vendor_id AND b.thing_type = ? + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + model.ThingTypeCategory, + utils.DefaultTimeValue, + } + if parentID >= 0 { + sql += " AND a.parent_id = ?" + sqlParams = append(sqlParams, parentID) + } + if level > 0 { + sql += " AND a.level = ?" + sqlParams = append(sqlParams, level) + } + if vendorID != -1 { + sql += " AND a.vendor_id = ?" + sqlParams = append(sqlParams, vendorID) + } + if vendorOrgCode != "" { + sql += " AND a.vendor_org_code = ?" + sqlParams = append(sqlParams, vendorOrgCode) + } + if categoryID > 0 { + sql += " AND a.category_id = ?" + sqlParams = append(sqlParams, categoryID) + } + sql += " ORDER BY a.vendor_category_seq" + err = GetRows(db, &vendorMaps, sql, sqlParams) + if err != nil { + return nil, err + } + return vendorMaps, err +} diff --git a/business/model/dao/store.go b/business/model/dao/store.go index cea3c67b6..d339b7bfb 100644 --- a/business/model/dao/store.go +++ b/business/model/dao/store.go @@ -18,7 +18,8 @@ type StoreDetail struct { VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` VendorStoreName string `json:"vendorStoreName"` - VendorStatus int `json:"vendor_status"` // 取值同Store.Status + VendorStatus int `json:"vendor_status"` // 取值同Store.Status + VendorPayPercentage int `json:"vendorPayPercentage"` //平台结算比例 DeliveryFeeDeductionSill int `json:"deliveryFeeDeductionSill"` DeliveryFeeDeductionFee int `json:"deliveryFeeDeductionFee"` SyncStatus int8 `orm:"default(2)" json:"syncStatus"` @@ -26,6 +27,7 @@ type StoreDetail struct { PricePercentage int16 `orm:"default(100)" json:"pricePercentage"` // todo 厂商价格相对于本地价格的百分比,这个字段的修改会比较特殊,因为可能需要刷新厂商价格 PricePercentagePackStr string `orm:"size(4096)" json:"-"` // PricePercentagePackObj model.PricePercentagePack `orm:"-" json:"-"` + CreateDeliveryType int `orm:"default(0)" json:"createDeliveryType"` //默认0系统发单,1为门店发单 FreightDeductionPackStr string `orm:"size(4096)" json:"-"` // FreightDeductionPackObj *model.FreightDeductionPack `orm:"-" json:"-"` @@ -37,8 +39,9 @@ type StoreDetail struct { DistrictName string `json:"districtName"` CityName string `json:"cityName"` - ProvinceName string `json:"provinceName"` //省名 - JdCode int `json:"jdCode"` + ProvinceName string `json:"provinceName"` //省名 + JdCityCode int `json:"jdCityCode"` //京东市code + JdCode int `json:"jdCode"` //京东区code JdsCode int `json:"jdsCode"` //京东商城地址代码 JdsStreetCode int `json:"jdsStreetCode"` //京东商城直辖市街道code JdsStreetName string `json:"jdsStreetName"` //京东商城直辖市街道 @@ -49,12 +52,21 @@ type StoreDetail struct { OperatorName2 string `json:"operatorName2"` OperatorName3 string `json:"operatorName3"` - JdStoreLevel string `json:"jdStoreLevel"` //京东门店等级 - IsOrder int `json:"isOrder"` //是否是下预订单门店 + JdStoreLevel string `json:"jdStoreLevel"` //京东门店等级 + IsOrder int `json:"isOrder"` //是否是下预订单门店 + IsSupplyGoods int `json:"isSupplyGoods"` YbAppID string `orm:"column(yb_app_id)" json:"ybAppID"` YbAppKey string `json:"ybAppKey"` YbStorePrefix string `json:"ybStorePrefix"` + + MtwmToken string `json:"mtwmToken"` + EbaiSupplierID string `json:"ebaiSupplierID"` + + BrandName string `json:"brandName"` //品牌信息 + BrandLogo string `json:"brandLogo"` + BrandIsOpen int `json:"brandIsOpen"` + BrandIsPrint int `json:"brandIsPrint"` } // 带快递门店信息的 @@ -94,23 +106,28 @@ func (s *StoreDetail) GetPricePerentage(price int) (pricePercentage int) { return pricePercentage } -func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (storeDetail *StoreDetail, err error) { +func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID, vendorOrgCode string) (storeDetail *StoreDetail, err error) { sql := ` SELECT t1.*, t2.vendor_store_id, t2.status vendor_status, t2.delivery_fee_deduction_sill, t2.delivery_fee_deduction_fee, t2.sync_status, t2.vendor_org_code, t2.price_percentage, t2.auto_pickup, t2.delivery_type, t2.delivery_competition, t2.is_sync, t2.vendor_store_name, t2.is_order, t2.yb_app_id, t2.yb_app_key, t2.yb_store_prefix, - t2.jds_street_code, t2.jds_street_name, + t2.jds_street_code, t2.jds_street_name, t2.is_supply_goods, t2.vendor_pay_percentage, t2.mtwm_token, t2.ebai_supplier_id, t2.create_delivery_type, t3.value price_percentage_pack_str, t4.value freight_deduction_pack_str, province.name province_name, district.name district_name, district.jds_code jds_code, district.jd_code jd_code, + city.jd_code jd_city_code, city.name city_name, IF(mm.name <> '', mm.name, mm.user_id2) market_man_name, IF(om.name <> '', om.name, om.user_id2) operator_name, IF(om2.name <> '', om2.name, om2.user_id2) operator_name2, - IF(om3.name <> '', om3.name, om3.user_id2) operator_name3 + IF(om3.name <> '', om3.name, om3.user_id2) operator_name3, + b.name brand_name, + b.logo brand_logo, + b.is_open brand_is_open, + b.is_print brand_is_print FROM store t1 LEFT JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND t2.deleted_at = ? LEFT JOIN place city ON city.code = t1.city_code @@ -122,6 +139,7 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto LEFT JOIN user om ON om.mobile <> '' AND om.mobile = t1.operator_phone LEFT JOIN user om2 ON om2.mobile <> '' AND om2.mobile = t1.operator_phone2 LEFT JOIN user om3 ON om3.mobile <> '' AND om3.mobile = t1.operator_phone3 + LEFT JOIN brand b ON b.id = t1.brand_id AND b.deleted_at = ? WHERE t1.deleted_at = ? ` sqlParams := []interface{}{ @@ -132,6 +150,7 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto model.ConfigTypeFreightPack, utils.DefaultTimeValue, utils.DefaultTimeValue, + utils.DefaultTimeValue, } // if vendorID != model.VendorIDJX { // sql += " AND t2.id IS NOT NULL" @@ -144,6 +163,13 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto sql += " AND t2.vendor_store_id = ?" sqlParams = append(sqlParams, vendorStoreID) } + if vendorOrgCode != "" { + sql += " AND t2.vendor_org_code = ?" + sqlParams = append(sqlParams, vendorOrgCode) + } + if vendorID == model.VendorIDJDShop && vendorOrgCode == "" { + sql += " AND t2.vendor_org_code = 1" + } if err = GetRow(db, &storeDetail, sql, sqlParams...); err == nil { storeDetail.PricePercentagePackObj = PricePercentagePack2Obj(storeDetail.PricePercentagePackStr) storeDetail.FreightDeductionPackObj = FreightDeductionPack2Obj(storeDetail.FreightDeductionPackStr) @@ -162,15 +188,15 @@ func getStoreDetail(db *DaoDB, storeID, vendorID int, vendorStoreID string) (sto return nil, err } -func GetStoreDetail(db *DaoDB, storeID, vendorID int) (storeDetail *StoreDetail, err error) { - return getStoreDetail(db, storeID, vendorID, "") +func GetStoreDetail(db *DaoDB, storeID, vendorID int, vendorOrgCode string) (storeDetail *StoreDetail, err error) { + return getStoreDetail(db, storeID, vendorID, "", vendorOrgCode) } -func GetStoreDetailByVendorStoreID(db *DaoDB, vendorStoreID string, vendorID int) (storeDetail *StoreDetail, err error) { +func GetStoreDetailByVendorStoreID(db *DaoDB, vendorStoreID string, vendorID int, vendorOrgCode string) (storeDetail *StoreDetail, err error) { if vendorID != model.VendorIDJX { - return getStoreDetail(db, 0, vendorID, vendorStoreID) + return getStoreDetail(db, 0, vendorID, vendorStoreID, vendorOrgCode) } - if storeDetail, err = getStoreDetail(db, int(utils.Str2Int64WithDefault(vendorStoreID, 0)), vendorID, ""); err == nil { + if storeDetail, err = getStoreDetail(db, int(utils.Str2Int64WithDefault(vendorStoreID, 0)), vendorID, "", vendorOrgCode); err == nil { storeDetail.VendorStoreID = vendorStoreID } return storeDetail, err @@ -204,7 +230,7 @@ func GetStoreDetail2(db *DaoDB, storeID int, vendorStoreID string, vendorID int) return storeDetail, err } -func GetStoreCourierList(db *DaoDB, storeIDs []int, status, auditStatus int) (courierStoreList []*model.StoreCourierMap, err error) { +func GetStoreCourierList(db *DaoDB, storeIDs, vendorIDs []int, status, auditStatus int) (courierStoreList []*model.StoreCourierMap, err error) { sql := ` SELECT t1.* FROM store_courier_map t1 @@ -217,6 +243,10 @@ func GetStoreCourierList(db *DaoDB, storeIDs []int, status, auditStatus int) (co sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } + if len(vendorIDs) > 0 { + sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sqlParams = append(sqlParams, vendorIDs) + } if status != model.StoreStatusAll { sql += " AND t1.status = ?" sqlParams = append(sqlParams, status) @@ -231,7 +261,38 @@ func GetStoreCourierList(db *DaoDB, storeIDs []int, status, auditStatus int) (co return nil, err } -func GetStoresMapList2(db *DaoDB, vendorIDs, storeIDs, storeStatuss []int, status, isSync int, pricePack string, mustDirty bool) (storeMapList []*model.StoreMap, err error) { +func GetStoreCourierList2(db *DaoDB, storeIDs, vendorIDs []int, status int, auditStatuss []int) (courierStoreList []*model.StoreCourierMap, err error) { + sql := ` + SELECT t1.* + FROM store_courier_map t1 + WHERE t1.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(storeIDs) > 0 { + sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + if len(vendorIDs) > 0 { + sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" + sqlParams = append(sqlParams, vendorIDs) + } + if status != model.StoreStatusAll { + sql += " AND t1.status = ?" + sqlParams = append(sqlParams, status) + } + if len(auditStatuss) > 0 { + sql += " AND t1.audit_status IN (" + GenQuestionMarks(len(auditStatuss)) + ")" + sqlParams = append(sqlParams, auditStatuss) + } + if err = GetRows(db, &courierStoreList, sql, sqlParams...); err == nil { + return courierStoreList, nil + } + return nil, err +} + +func GetStoresMapList2(db *DaoDB, vendorIDs, storeIDs, storeStatuss []int, status, isSync int, pricePack, name, vendorOrgCode string, mustDirty bool) (storeMapList []*model.StoreMap, err error) { sql := ` SELECT t1.* FROM store_map t1 @@ -266,10 +327,18 @@ func GetStoresMapList2(db *DaoDB, vendorIDs, storeIDs, storeStatuss []int, statu sql += " AND t1.price_percentage_pack = ?" sqlParams = append(sqlParams, pricePack) } + if name != "" { + sql += " AND t2.name LIKE ?" + sqlParams = append(sqlParams, "%"+name+"%") + } + if vendorOrgCode != "" { + sql += " AND t1.vendor_org_code = ?" + sqlParams = append(sqlParams, vendorOrgCode) + } if mustDirty { sql += " AND t1.sync_status <> 0" } - sql += " ORDER BY t1.store_id DESC, t1.vendor_id" + sql += " ORDER BY t1.store_id , t1.vendor_id" if err = GetRows(db, &storeMapList, sql, sqlParams...); err == nil { return storeMapList, nil } @@ -300,8 +369,8 @@ func SetStoresMapSyncStatus(db *DaoDB, vendorIDs, storeIDs []int, syncStatus int return err } -func GetStoresMapList(db *DaoDB, vendorIDs, storeIDs, storeStatuss []int, status, isSync int, pricePack string) (storeMapList []*model.StoreMap, err error) { - return GetStoresMapList2(db, vendorIDs, storeIDs, storeStatuss, status, isSync, pricePack, false) +func GetStoresMapList(db *DaoDB, vendorIDs, storeIDs, storeStatuss []int, status, isSync int, pricePack, name, vendorOrgCode string) (storeMapList []*model.StoreMap, err error) { + return GetStoresMapList2(db, vendorIDs, storeIDs, storeStatuss, status, isSync, pricePack, name, vendorOrgCode, false) } func StoreMapList2Map(storeMapList []*model.StoreMap) (storeMapMap map[int][]*model.StoreMap) { @@ -493,7 +562,7 @@ func GetOpenedStoreCouriersByStoreID(db *DaoDB, storeID, vendorID int) (storeMap return storeMaps, nil } -func GetStoreList(db *DaoDB, idList, cityCodes, statuss []int, mobileList []string, shortRoleName string) (storeList []*model.Store, err error) { +func GetStoreList(db *DaoDB, idList, cityCodes, statuss, brandIDs []int, mobileList []string, shortRoleName string) (storeList []*model.Store, err error) { sql := ` SELECT t1.* FROM store t1 @@ -513,6 +582,10 @@ func GetStoreList(db *DaoDB, idList, cityCodes, statuss []int, mobileList []stri sql += " AND t1.status IN (" + GenQuestionMarks(len(statuss)) + ")" sqlParams = append(sqlParams, statuss) } + if len(brandIDs) > 0 { + sql += " AND t1.brand_id IN (" + GenQuestionMarks(len(brandIDs)) + ")" + sqlParams = append(sqlParams, brandIDs) + } if len(mobileList) > 0 { sql += " AND (t1.tel1 IN (" + GenQuestionMarks(len(mobileList)) + ") OR t1.tel2 IN (" + GenQuestionMarks(len(mobileList)) + "))" sqlParams = append(sqlParams, mobileList, mobileList) @@ -740,42 +813,44 @@ func GetRealLinkStoreID(db *DaoDB, linkStoreID int) (realLinkStoreID int, err er return realLinkStoreID, err } -// func GetStoreCategoryMap(db *DaoDB, parentID, storeID, categoryID int) (storeCatMaps []*StoreCatMap, err error) { -// sql := ` -// SELECT a.*, b.level, b.parent_id, b.seq, b.name -// FROM store_category_map a -// JOIN sku_category b ON b.id = a.category_id -// AND a.deleted_at = ? -// AND b.deleted_at = ? -// ` -// sqlParams := []interface{}{ -// utils.DefaultTimeValue, -// utils.DefaultTimeValue, -// } -// if parentID != -1 { -// sql += " AND b.parent_id = ?" -// sqlParams = append(sqlParams, parentID) -// } -// if storeID > 0 { -// sql += " AND a.store_id = ?" -// sqlParams = append(sqlParams, storeID) -// } -// if categoryID > 0 { -// sql += " AND a.category_id = ?" -// sqlParams = append(sqlParams, categoryID) -// } -// err = GetRows(db, &storeCatMaps, sql, sqlParams) -// if err != nil { -// return nil, err -// } -// return storeCatMaps, err -// } +func GetStoreCategoryMap(db *DaoDB, parentID, level, storeID, categoryID int) (storeCatMaps []*model.StoreCategoryMap, err error) { + sql := ` + SELECT a.* + FROM store_category_map a + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if parentID >= 0 { + sql += " AND a.parent_id = ?" + sqlParams = append(sqlParams, parentID) + } + if level > 0 { + sql += " AND a.level = ?" + sqlParams = append(sqlParams, level) + } + if storeID > 0 { + sql += " AND a.store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if categoryID > 0 { + sql += " AND a.category_id = ?" + sqlParams = append(sqlParams, categoryID) + } + sql += " ORDER BY a.level, a.store_category_seq" + err = GetRows(db, &storeCatMaps, sql, sqlParams) + if err != nil { + return nil, err + } + return storeCatMaps, err +} func InsertStoreCategories(db *DaoDB, userName string, storeID int) (err error) { sql := ` INSERT INTO store_category_map - (created_at, updated_at, last_operator, deleted_at, store_id, category_id, store_category_name, store_category_seq) - SELECT ?, ?, ?, ?, ?, id, name, seq + (created_at, updated_at, last_operator, deleted_at, store_id, category_id, store_category_name, store_category_seq, level, parent_id) + SELECT ?, ?, ?, ?, ?, id, name, seq, level, parent_id FROM sku_category WHERE deleted_at = ? AND is_exd_spec = ? @@ -803,3 +878,245 @@ func DeleteStoreCategroies(db *DaoDB, userName string, storeID int) (err error) _, err = ExecuteSQL(db, sql, sqlParams) return err } + +func DeleteStoreCategroies2(db *DaoDB, storeID int) (err error) { + sql := ` + DELETE FROM store_category_map WHERE store_id = ? + ` + sqlParams := []interface{}{ + storeID, + } + _, err = ExecuteSQL(db, sql, sqlParams) + return err +} + +func GetStorePushClient(db *DaoDB, storeID int, cID string) (storePushClient []*model.StorePushClient, err error) { + sql := ` + SELECT * + FROM store_push_client + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if storeID > 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if cID != "" { + sql += " AND client_id = ?" + sqlParams = append(sqlParams, cID) + } + err = GetRows(db, &storePushClient, sql, sqlParams) + if err != nil { + return nil, err + } + return storePushClient, err +} + +func GetStoreAudit(db *DaoDB, auditStatuss []int, userID, keyword string) (storeAudit []*model.StoreAudit, err error) { + sql := ` + SELECT * + FROM store_audit + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(auditStatuss) > 0 { + sql += " AND audit_status IN (" + GenQuestionMarks(len(auditStatuss)) + ")" + sqlParams = append(sqlParams, auditStatuss) + } + if userID != "" { + sql += " AND user_id = ?" + sqlParams = append(sqlParams, userID) + } + if keyword != "" { + sql += " AND (user_id LIKE ? OR name LIKE ? OR tel1 LIKE ? OR tel2 LIKE ? OR address LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } + err = GetRows(db, &storeAudit, sql, sqlParams) + if err != nil { + return nil, err + } + return storeAudit, err +} + +type tStoreAudit struct { + model.StoreAudit + UserName string `json:"userName"` + CityName string `json:"cityName"` +} + +func GetStoreAuditPage(db *DaoDB, statuss []int, keyword string, applyTimeStart, applyTimeEnd, auditTimeStart, auditTimeEnd time.Time, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) { + var requestList []*tStoreAudit + sql := ` + SELECT SQL_CALC_FOUND_ROWS DISTINCT a.*, b.name user_name, c.name city_name + FROM store_audit a + LEFT JOIN user b ON b.user_id = a.user_id + LEFT JOIN place c ON c.code = a.city_code + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if len(statuss) > 0 { + sql += " AND a.audit_status IN (" + GenQuestionMarks(len(statuss)) + ")" + sqlParams = append(sqlParams, statuss) + } + if applyTimeStart != utils.ZeroTimeValue && applyTimeEnd != utils.ZeroTimeValue { + sql += " AND a.created_at BETWEEN ? AND ?" + sqlParams = append(sqlParams, applyTimeStart, applyTimeEnd) + } + if auditTimeStart != utils.ZeroTimeValue && auditTimeEnd != utils.ZeroTimeValue { + sql += " AND a.updated_at BETWEEN ? AND ?" + sqlParams = append(sqlParams, auditTimeStart, auditTimeEnd) + } + if keyword != "" { + sql += " AND (a.user_id LIKE ? OR a.name LIKE ? OR a.tel1 LIKE ? OR a.tel2 LIKE ? OR a.address LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } + sql += " ORDER BY a.updated_at LIMIT ? OFFSET ?" + pageSize = jxutils.FormalizePageSize(pageSize) + sqlParams = append(sqlParams, pageSize, offset) + Begin(db) + defer Commit(db) + if err = GetRows(db, &requestList, sql, sqlParams...); err == nil { + return &model.PagedInfo{ + TotalCount: GetLastTotalRowCount(db), + Data: requestList, + }, nil + } + return pagedInfo, err +} + +func GetBrands(db *DaoDB, name string, brandID int) (brands []*model.Brand, err error) { + sql := ` + SELECT * + FROM brand + WHERE deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + } + if name != "" { + sql += " AND name LIKE ?" + sqlParams = append(sqlParams, "%"+name+"%") + } + if brandID != 0 { + sql += " AND id = ?" + sqlParams = append(sqlParams, brandID) + } + err = GetRows(db, &brands, sql, sqlParams) + return brands, err +} + +func GetStoreAcctIncome(db *DaoDB, storeID, incomeType int, fromTime, toTime time.Time) (storeAcctIncomes []*model.StoreAcctIncome, err error) { + sql := ` + SELECT * + FROM store_acct_income + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if storeID != 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if incomeType != 0 { + sql += " AND type = ?" + sqlParams = append(sqlParams, incomeType) + } + if utils.IsTimeZero(fromTime) { + sql += " AND created_at >= ?" + sqlParams = append(sqlParams, fromTime) + } + if utils.IsTimeZero(toTime) { + sql += " AND created_at <= ?" + sqlParams = append(sqlParams, toTime) + } + err = GetRows(db, &storeAcctIncomes, sql, sqlParams) + return storeAcctIncomes, err +} + +func GetStoreAcctIncomeTotal(db *DaoDB, storeID, incomeType int, fromTime, toTime time.Time) (incomeTotal int, err error) { + var income *model.StoreAcctIncome + sql := ` + SELECT SUM(income_price) income_price + FROM store_acct_income + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if storeID != 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if incomeType != 0 { + sql += " AND type = ?" + sqlParams = append(sqlParams, incomeType) + } + if utils.IsTimeZero(fromTime) { + sql += " AND created_at >= ?" + sqlParams = append(sqlParams, fromTime) + } + if utils.IsTimeZero(toTime) { + sql += " AND created_at <= ?" + sqlParams = append(sqlParams, toTime) + } + err = GetRow(db, &income, sql, sqlParams) + return income.IncomePrice, err +} + +func GetStoreAcctExpend(db *DaoDB, storeID, expendType int, fromTime, toTime time.Time) (storeAcctExpends []*model.StoreAcctExpend, err error) { + sql := ` + SELECT * + FROM store_acct_expend + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if storeID != 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if expendType != 0 { + sql += " AND type = ?" + sqlParams = append(sqlParams, expendType) + } + if utils.IsTimeZero(fromTime) { + sql += " AND created_at >= ?" + sqlParams = append(sqlParams, fromTime) + } + if utils.IsTimeZero(toTime) { + sql += " AND created_at <= ?" + sqlParams = append(sqlParams, toTime) + } + err = GetRows(db, &storeAcctExpends, sql, sqlParams) + return storeAcctExpends, err +} + +func GetStoreAcctExpendTotal(db *DaoDB, storeID, expendType int, fromTime, toTime time.Time) (expendTotal int, err error) { + var expend *model.StoreAcctExpend + sql := ` + SELECT SUM(expend_price) expend_price + FROM store_acct_expend + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if storeID != 0 { + sql += " AND store_id = ?" + sqlParams = append(sqlParams, storeID) + } + if expendType != 0 { + sql += " AND type = ?" + sqlParams = append(sqlParams, expendType) + } + if utils.IsTimeZero(fromTime) { + sql += " AND created_at >= ?" + sqlParams = append(sqlParams, fromTime) + } + if utils.IsTimeZero(toTime) { + sql += " AND created_at <= ?" + sqlParams = append(sqlParams, toTime) + } + err = GetRow(db, &expend, sql, sqlParams) + return expend.ExpendPrice, err +} diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index 0820bcc70..be3e7032d 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -41,6 +41,18 @@ type SkuStoreCatInfo struct { ParentCatName string ParentVendorCatID string `orm:"column(parent_vendor_cat_id)"` ParentCatSyncStatus int8 + + StoreCatID int `orm:"column(store_category_id)"` + StoreCatName string + StoreCatSeq int + StoreParentCatName string + IsSysCat int + CityCode int + IsJxCat int + + VendorCategoryName string + VendorCategorySeq int + VendorCategoryID int `orm:"column(vendor_category_id)"` } type StoreSkuSyncInfo struct { @@ -57,6 +69,7 @@ type StoreSkuSyncInfo struct { Price int64 UnitPrice int64 + Stock int // 平台相关的store sku信息 StoreSkuStatus int @@ -68,6 +81,8 @@ type StoreSkuSyncInfo struct { model.Sku ExdSkuID string `orm:"column(exd_sku_id)"` ExdCategoryThirdID int `orm:"column(exd_category_third_id)"` + BrandID int `orm:"column(brand_id)"` + ExBrandID int `orm:"column(ex_brand_id)"` StoreName string // sku_name @@ -75,22 +90,29 @@ type StoreSkuSyncInfo struct { ExPrefix string ExPrefixBegin *time.Time ExPrefixEnd *time.Time + // NameID int `orm:"column(name_id)"` - VendorNameID string `orm:"column(vendor_name_id)"` // 暂时无用 - Name string - Unit string - Upc string - IsGlobal int8 `orm:"default(1)" json:"isGlobal"` // 是否是全部(全国)可见,如果否的话,可见性由SkuPlace决定 - NameStatus int - SellCities []string - NameCategoryID int `orm:"column(name_category_id)"` - YbNameSuffix string //银豹的商品条码后缀 - YbBarCode string //银豹的商品条码 + VendorNameID string `orm:"column(vendor_name_id)"` // 暂时无用 + Name string + Unit string + Upc string + IsGlobal int8 `orm:"default(1)" json:"isGlobal"` // 是否是全部(全国)可见,如果否的话,可见性由SkuPlace决定 + NameStatus int + SellCities []string + NameCategoryID int `orm:"column(name_category_id)"` + YbNameSuffix string //银豹的商品条码后缀 + YbBarCode string //银豹的商品条码 + JdsStockSwitch int + PreparationTime int // 平台相关的图片信息 - Img string - Img2 string - DescImg string + Img string + Img2 string + Img3 string + DescImg string + ImgWatermark string `json:"imgWatermark"` //图片水印 + ImgMix string //合成水印后的图片 + ImgOrigin string //skuname里的img VendorVendorCatID int64 `orm:"column(vendor_vendor_cat_id)"` // 平台商品分类(叶子结点) CategoryName string `json:"categoryName"` //分类名 @@ -99,14 +121,16 @@ type StoreSkuSyncInfo struct { SkuVendorCatID string `orm:"column(sku_vendor_cat_id)"` // sku_name的商家分类信息 - CatSyncStatus int8 - VendorCatID string `orm:"column(vendor_cat_id)"` + CatSyncStatus int8 + VendorCatID string `orm:"column(vendor_cat_id)"` + SkuVendorMapCatID string `orm:"column(sku_vendor_map_cat_id)"` VendorPrice int64 LockTime *time.Time MergedStatus int SkuName string + SkuNameOrigin string StatusSaleBegin int16 `json:"statusSaleBegin"` //商品可售时间范围 StatusSaleEnd int16 `json:"statusSaleEnd"` @@ -114,6 +138,8 @@ type StoreSkuSyncInfo struct { ActPercentage int `json:"actPercentage"` // 直降活动百分比 ActSyncStatus int8 `orm:"default(2)" json:"actSyncStatus"` VendorActPrice int64 `json:"vendorActPrice"` // 保存数据用,实际的活动价 + + IsDeletedBySku bool `json:"isDeletedBySku"` //京东商城用,同步下架的商品库里的sku时,要做区分来决定调的api } type MissingStoreSkuInfo struct { @@ -155,6 +181,7 @@ type StoreSkuNameExt struct { RealMidUnitPrice int `json:"realMidUnitPrice"` Count int `json:"count"` YbSkuName string `json:"ybSkuName"` + AuditUnitPrice int `json:"auditUnitPrice"` //审核价格 } // GetStoreSkus用 @@ -195,6 +222,7 @@ type StoreSkuExt struct { SkuSpecUnit string `orm:"size(8)" json:"specUnit"` // 质量或容量 Weight int `json:"weight"` // 重量/质量,单位为克,当相应的SkuName的SpecUnit为g或kg时,必须等于SpecQuality SkuStatus int `json:"status"` + Stock int `json:"stock"` BindCreatedAt time.Time `orm:"auto_now_add;type(datetime)" json:"createdAt"` BindUpdatedAt time.Time `orm:"auto_now;type(datetime)" json:"updatedAt"` @@ -241,14 +269,19 @@ type StoreSkuExt struct { JxLockTime *time.Time `orm:"null" json:"jxLockTime,omitempty"` YbLockTime *time.Time `orm:"null" json:"ybLockTime,omitempty"` - ActPrice int `json:"actPrice"` - ActID int `orm:"column(act_id)" json:"actID"` - ActType int `orm:"column(act_type)" json:"actType"` + ActPrice int `json:"actPrice"` + ActID int `orm:"column(act_id)" json:"actID"` + ActType int `orm:"column(act_type)" json:"actType"` + DiscountType int `json:"discountType"` + DiscountValue1 int `json:"discountValue1"` + DiscountValue2 int `json:"discountValue2"` EarningPrice int `json:"earningPrice"` EarningActID int `orm:"column(earning_act_id)" json:"earningActID"` - EclpID string `orm:"column(eclp_id)" json:"eclpID"` + EclpID string `orm:"column(eclp_id)" json:"eclpID"` + TrendType int `json:"trendType"` + TrendPrice int `json:"trendPrice"` } type SkuNameAndPlace struct { @@ -267,6 +300,12 @@ type StoreSkuPriceAndWeight struct { SkuID int `orm:"column(sku_id)"` Weight int Price int + Prefix string + Name string + Unit string + Comment string + SpecQuality float32 + SpecUnit string } type StoreSkuAndName struct { @@ -336,12 +375,16 @@ func GetSkusCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int func GetStoreCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int, mustDirty bool) (cats []*SkuStoreCatInfo, err error) { fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` - SELECT t4.*, + SELECT t4.*, ts.store_category_name store_cat_name, ts.store_category_seq store_cat_seq, ts.id store_category_id, t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status cat_sync_status, t4p.name parent_cat_name, - t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status + tsp.store_category_name store_parent_cat_name, + t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status, + t1.is_sys_cat, t1.vendor_org_code, + t6.city_code FROM store_sku_category_map t5 - JOIN sku_category t4 ON t5.category_id = t4.id AND t4.deleted_at = ? + JOIN sku_category t4 ON t5.category_id = t4.id + LEFT JOIN store_category_map ts ON ts.store_id = t5.store_id AND ts.category_id = t4.id AND ts.deleted_at = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, @@ -361,9 +404,12 @@ func GetStoreCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level in } sql += ` LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id - LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id AND t5p.deleted_at = ? - WHERE t5.store_id = ? AND t5.deleted_at = ? AND t4.is_sync <> ?` - sqlParams = append(sqlParams, utils.DefaultTimeValue, storeID, utils.DefaultTimeValue, model.YES) + LEFT JOIN store_category_map tsp ON tsp.store_id = t5.store_id AND tsp.category_id = t4p.id AND tsp.deleted_at = ? + LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id + LEFT JOIN store_map t1 ON t1.store_id = t5.store_id AND t1.vendor_id = ? + LEFT JOIN store t6 ON t6.id = t5.store_id + WHERE t5.store_id = ? AND t5.deleted_at = ? AND t4.is_sync <> ?` + sqlParams = append(sqlParams, utils.DefaultTimeValue, vendorID, storeID, utils.DefaultTimeValue, model.YES) if mustDirty { sql += " AND t5.%s_sync_status <> 0" fieldPrefixParams = append(fieldPrefixParams, fieldPrefix) @@ -372,6 +418,11 @@ func GetStoreCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level in sql += " AND t4.level = ?" sqlParams = append(sqlParams, level) } + if storeID == 102902 { + fmt.Println(sql) + fmt.Println(sqlParams) + } + if err = GetRows(db, &cats, fmt.Sprintf(sql, fieldPrefixParams...), sqlParams...); err != nil { return nil, err } @@ -399,20 +450,26 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty boo t14.vendor_id, t14.vendor_org_code, t1.id bind_id, t1.sku_id, t1.price, t1.unit_price, t1.status store_sku_status, %s vendor_sku_id, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time, - t1.store_id, t1.deleted_at bind_deleted_at,t1.status_sale_begin,t1.status_sale_end, t1.jds_ware_id, + t1.store_id, t1.deleted_at bind_deleted_at,t1.status_sale_begin,t1.status_sale_end, t1.jds_ware_id, t1.stock, t2.*, - t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.status name_status, t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end, t3.category_id name_category_id, t3.yb_name_suffix, + t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.status name_status, t3.category_id name_category_id, t3.yb_name_suffix, + t3.jds_stock_switch, t3.preparation_time, t3.img_watermark, t3.ex_vendor_id, t3.img img_origin, IF(t11.%s <> '', t11.%s, t3.img) img, IF(t12.%s <> '', t12.%s, t3.img2) img2, + IF(t15.%s <> '', t15.%s, t3.img3) img3, IF(t13.%s <> '', t13.%s, t3.desc_img) desc_img, t4.%s_category_id vendor_vendor_cat_id, t4.name category_name, - ts.name store_name` + ts.name store_name, + ts.brand_id, + tsu.ex_prefix, tsu.begin_at ex_prefix_begin, tsu.end_at ex_prefix_end, tsu.img_watermark, tsu.img_watermark_mix img_mix, tsu.brand_id ex_brand_id, + tsu1.vendor_category_id sku_vendor_map_cat_id` fmtParams := []interface{}{ skuVendorIDField, fieldPrefix, fieldPrefix, fieldPrefix, GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), + GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), fieldPrefix, } if isSingleStorePF { @@ -438,7 +495,10 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty boo LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ? LEFT JOIN data_resource t11 ON t11.main_url = t3.img LEFT JOIN data_resource t12 ON t12.main_url = t3.img2 + LEFT JOIN data_resource t15 ON t15.main_url = t3.img3 LEFT JOIN data_resource t13 ON t13.main_url = t3.desc_img + LEFT JOIN sku_exinfo_map tsu ON tsu.name_id = t3.id AND tsu.deleted_at = ? AND tsu.vendor_id = t14.vendor_id + LEFT JOIN sku_vendor_category_map tsu1 ON tsu1.name_id = t3.id AND tsu1.deleted_at = ? AND tsu1.vendor_id = t14.vendor_id ` sqlParams := []interface{}{ vendorID, utils.DefaultTimeValue, @@ -446,6 +506,8 @@ func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, mustDirty boo utils.DefaultTimeValue, // model.SkuStatusNormal, utils.DefaultTimeValue, utils.DefaultTimeValue, + utils.DefaultTimeValue, + utils.DefaultTimeValue, } if globals.IsStoreSkuAct { sql += ` @@ -523,7 +585,7 @@ func GetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInf sm.vendor_id, sm.vendor_org_code, sm.yb_app_id, sm.yb_app_key, t1.id bind_id, t1.price, t1.unit_price, t1.status store_sku_status, t1.%s_sync_status sku_sync_status, t1.%s_price vendor_price, t1.%s_lock_time lock_time, - t1.store_id, t1.deleted_at bind_deleted_at, + t1.store_id, t1.deleted_at bind_deleted_at, t1.stock, t2.*, t2.id sku_id, t2m.vendor_thing_id vendor_sku_id, t3.id name_id, t3.prefix, t3.name, t3.unit, t3.upc, t3.status name_status, t3.ex_prefix, t3.ex_prefix_begin, t3.ex_prefix_end, t3.category_id name_category_id, IF(t11.%s <> '', t11.%s, t3.img) img, @@ -563,8 +625,6 @@ func GetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInf GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), GetDataResFieldName(vendorID), fieldPrefix) - // globals.SugarLogger.Debug(sql) - // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) if err = GetRows(db, &skus, sql, sqlParams...); err != nil { return nil, err } @@ -587,10 +647,12 @@ func GetStoreSkuPriceAndWeight(db *DaoDB, vendorStoreID string, vendorID int, ve vendorSkuIDField = fmt.Sprintf("t2.%s_id", ConvertDBFieldPrefix(model.VendorNames[vendorID])) } sql := fmt.Sprintf(` - SELECT %s vendor_sku_id, t1.id sku_id, t2.price, t1.weight + SELECT %s vendor_sku_id, t1.id sku_id, t2.price, t1.weight, + t5.prefix, t5.name, t1.comment, t5.unit, t1.spec_quality, t1.spec_unit FROM sku t1 JOIN store_sku_bind t2 ON t2.sku_id = t1.id AND t2.deleted_at = ? JOIN store_map t3 ON t3.store_id = t2.store_id AND t3.vendor_id = ? AND t3.vendor_store_id = ? AND t3.deleted_at = ? + JOIN sku_name t5 ON t5.id = t1.name_id %s WHERE %s IN (`+GenQuestionMarks(len(vendorSkuIDs))+`)`, vendorSkuIDField, sqlThingMap, vendorSkuIDField) sqlParams := []interface{}{ @@ -603,7 +665,6 @@ func GetStoreSkuPriceAndWeight(db *DaoDB, vendorStoreID string, vendorID int, ve } else { sqlParams = append(sqlParams, vendorSkuIDs) } - // globals.SugarLogger.Debugf(sql) err = GetRows(db, &l, sql, sqlParams...) return l, err } @@ -870,7 +931,8 @@ func UpdateStoreSkuBindSyncStatusForSaleStatus(db *DaoDB, vendorIDs []int, store if len(vendorIDs) > 0 { for _, v := range vendorIDs { fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[v]) - sql += ` %s_sync_status = ?,` + sql += ` %s_sync_status = %s_sync_status | ?,` + fmtParams = append(fmtParams, fieldPrefix) fmtParams = append(fmtParams, fieldPrefix) sqlParams = append(sqlParams, model.SyncFlagSaleMask) } @@ -962,22 +1024,27 @@ func DeleteSkuNameExPrefixOverdue(db *DaoDB) (num int64, err error) { func GetStoreSkusByNameIDs(db *DaoDB, storeIDs []int, nameID int) (skuList []*StoreSkuSyncInfo, err error) { sql := ` - SELECT a.*,c.unit,c.name + SELECT a.*, c.unit, c.name, b.name_id, a.status store_sku_status FROM store_sku_bind a JOIN sku b ON a.sku_id = b.id JOIN sku_name c ON b.name_id = c.id - WHERE b.name_id = ? + WHERE 1=1 AND a.deleted_at = ? ` sqlParams := []interface{}{ - nameID, utils.DefaultTimeValue, } + if nameID != 0 { + sql += " AND b.name_id = ?" + sqlParams = append(sqlParams, nameID) + } if len(storeIDs) > 0 { sql += " AND a.store_id in (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } - sql += " AND a.status != ?" + sql += ` AND a.status != ? + ORDER BY a.updated_at DESC + ` sqlParams = append(sqlParams, model.SkuStatusDeleted) err = GetRows(db, &skuList, sql, sqlParams...) return skuList, err @@ -1060,7 +1127,8 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk t4.sub_store_id, t4.price bind_price, IF(t4.unit_price IS NOT NULL, t4.unit_price, t1.price) unit_price, t4.status store_sku_status, t4.auto_sale_at, t4.ebai_id, t4.mtwm_id, t4.ebai_sync_status, t4.mtwm_sync_status, - t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price, a.spec_quality sku_spec_quality, a.spec_unit sku_spec_unit + t4.jd_price, t4.ebai_price, t4.mtwm_price, t4.jx_price, t4.stock, + a.spec_quality sku_spec_quality, a.spec_unit sku_spec_unit FROM sku a JOIN sku_name t1 ON a.name_id = t1.id AND t1.deleted_at = ? JOIN store_sku_bind t4 ON t4.sku_id = a.id AND t4.deleted_at = ? @@ -1156,6 +1224,7 @@ func GetTopCategoriesByStoreIDs(db *DaoDB, storeIDs []int, limit int) (skuCatego func GetStoreSkuCategories(db *DaoDB, storeID, parentID int) (catList []*model.SkuCategory, err error) { sql := ` + SELECT * FROM( SELECT t1.* FROM sku_category t1 @@ -1178,19 +1247,35 @@ func GetStoreSkuCategories(db *DaoDB, storeID, parentID int) (catList []*model.S sql += " AND t1.parent_id = ?" sqlParams = append(sqlParams, parentID) } - sql += " ORDER BY t1.level, t1.seq" - if err = GetRows(db, &catList, sql, sqlParams...); err == nil && len(catList) > 0 { - parentIDMap := make(map[int]int) - for _, v := range catList { - parentIDMap[v.ParentID] = 1 - } - paretnCats, err2 := GetCategories(db, -1, 0, jxutils.IntMap2List(parentIDMap), false) - if err = err2; err == nil { - catList = append(catList, paretnCats...) - } else { - catList = nil - } + sql += ` UNION + SELECT + DISTINCT + t3.* + FROM sku_category t1 + JOIN + ( + SELECT DISTINCT t3.category_id + FROM store_sku_bind t1 + JOIN sku t2 ON t2.id = t1.sku_id AND t2.deleted_at = ? AND t2.status = ? + JOIN sku_name t3 ON t3.id = t2.name_id AND t3.deleted_at = ? AND t3.status = ? + WHERE t1.deleted_at = ? AND t1.status = ? AND t1.store_id = ? + ) t2 ON t2.category_id = t1.id + JOIN sku_category t3 ON t3.id = t1.parent_id AND t3.deleted_at = ? + WHERE t1.deleted_at = ? + ` + sqlParams = append(sqlParams, utils.DefaultTimeValue, model.SkuStatusNormal, + utils.DefaultTimeValue, model.SkuStatusNormal, + utils.DefaultTimeValue, model.SkuStatusNormal, storeID, + utils.DefaultTimeValue, utils.DefaultTimeValue, + ) + if parentID >= 0 { + sql += " AND t1.parent_id = ?" + sqlParams = append(sqlParams, parentID) } + sql += ` + ) a + ORDER BY a.level, a.seq` + err = GetRows(db, &catList, sql, sqlParams...) return catList, err } @@ -1288,7 +1373,7 @@ func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesI vendorIDs = []int{actVendorID} } } else { - storeMapList, err := GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "") + storeMapList, err := GetStoresMapList(db, nil, storeIDs, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") if err != nil { return err } @@ -1319,6 +1404,11 @@ func UpdateActPrice4StoreSkuNameNew(db *DaoDB, storeIDs, skuIDs []int, skuNamesI v.ActID = actStoreSku.ActID v.ActType = actStoreSku.Type v.EarningPrice = int(jxutils.CaculateSkuEarningPrice(int64(v.BindPrice), int64(v.ActPrice), skuName.PayPercentage)) + v.TrendType = actStoreSku.TrendType + v.TrendPrice = actStoreSku.TrendPrice + v.DiscountType = actStoreSku.DiscountType + v.DiscountValue1 = actStoreSku.DiscountValue1 + v.DiscountValue2 = actStoreSku.DiscountValue2 } if actStoreSku := actStoreSkuMap4EarningPrice.GetActStoreSku(skuName.StoreID, v.SkuID, -1); actStoreSku != nil { v.EarningPrice = int(actStoreSku.EarningPrice) @@ -1404,14 +1494,12 @@ func GetStoreSkuBindByNameID(db *DaoDB, storeID, nameID, status int) (storeSkuBi AND a.name_id = ? AND c.deleted_at = ? AND a.deleted_at = ? - AND c.status = ? ` sqlParams := []interface{}{ storeID, nameID, utils.DefaultTimeValue, utils.DefaultTimeValue, - status, } err = GetRows(db, &storeSkuBind, sql, sqlParams...) return storeSkuBind, err @@ -1519,13 +1607,14 @@ func UpdateYbOtherSku(db *DaoDB, storeSkuSyncInfo *StoreSkuSyncInfo) (err error) func UpdateJdsWareID(db *DaoDB, storeSkuSyncInfo *StoreSkuSyncInfo) (err error) { sql := ` UPDATE store_sku_bind - SET jds_ware_id = ? + SET jds_ware_id = ?, jds_id = ? WHERE store_id = ? AND sku_id = ? AND deleted_at = ? ` sqlParams := []interface{}{ storeSkuSyncInfo.JdsWareID, + storeSkuSyncInfo.VendorSkuID, storeSkuSyncInfo.StoreID, storeSkuSyncInfo.SkuID, utils.DefaultTimeValue, @@ -1533,3 +1622,193 @@ func UpdateJdsWareID(db *DaoDB, storeSkuSyncInfo *StoreSkuSyncInfo) (err error) _, err = ExecuteSQL(db, sql, sqlParams) return err } + +type tStoreSkuAudit struct { + model.StoreSkuAudit + SkuName string `orm:"size(255)" json:"skuName"` + StoreName string `json:"storeName"` + Prefix string `orm:"size(255)" json:"prefix"` + Unit string `orm:"size(8)" json:"unit"` + SpecQuality float32 `json:"-"` // 为份必然为500,这个主要作用只是用于确保SkuName的唯一性 + SpecUnit string `orm:"size(8)" json:"-"` // 为份必然为克,这个主要作用只是用于确保SkuName的唯一性 + Img string `orm:"size(512)" json:"img"` + Name string `json:"name"` + MidUnitPrice int `json:"midUnitPrice"` + CityName string `json:"cityName"` + PayPercentage int `json:"payPercentage"` + StoreLevel string `json:"storeLevel"` +} + +func GetStoreSkuAudit(db *DaoDB, storeIDs, nameIDs, skuIDs, statuss, types []int, name, remark, keyword, marketManPhone, cityName string, applyTimeStart, applyTimeEnd, auditTimeStart, auditTimeEnd time.Time, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) { + var requestList []*tStoreSkuAudit + sql := ` + SELECT SQL_CALC_FOUND_ROWS DISTINCT a.*, + c.name sku_name, c.prefix, c.unit, c.spec_quality, c.spec_unit, c.img, + d.name store_name, b.name, e.mid_unit_price, f.name city_name, d.pay_percentage, d.store_level + FROM store_sku_audit a + LEFT JOIN user b ON a.user_id = b.user_id + LEFT JOIN sku_name c ON c.id = a.name_id AND c.deleted_at = ? + LEFT JOIN store d ON d.id = a.store_id AND d.deleted_at = ? + LEFT JOIN place f ON f.code = d.city_code + LEFT JOIN price_refer_snapshot e ON e.name_id = c.id AND e.city_code = ? AND e.snapshot_at = ? + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, utils.DefaultTimeValue, + 0, utils.Time2Date(time.Now().AddDate(0, 0, -1)), + utils.DefaultTimeValue} + if len(storeIDs) > 0 { + sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + if len(nameIDs) > 0 { + sql += " AND a.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")" + sqlParams = append(sqlParams, nameIDs) + } + if len(statuss) > 0 { + sql += " AND a.status IN (" + GenQuestionMarks(len(statuss)) + ")" + sqlParams = append(sqlParams, statuss) + } + if remark != "" { + sql += " AND a.remark LIKE ? " + sqlParams = append(sqlParams, "%"+remark+"%") + } + if name != "" { + sql += " AND b.name LIKE ? " + sqlParams = append(sqlParams, "%"+name+"%") + } + if applyTimeStart != utils.ZeroTimeValue && applyTimeEnd != utils.ZeroTimeValue { + sql += " AND a.created_at BETWEEN ? AND ?" + sqlParams = append(sqlParams, applyTimeStart, applyTimeEnd) + } + if auditTimeStart != utils.ZeroTimeValue && auditTimeEnd != utils.ZeroTimeValue { + sql += " AND a.updated_at BETWEEN ? AND ?" + sqlParams = append(sqlParams, auditTimeStart, auditTimeEnd) + } + if len(types) > 0 { + sql += " AND a.type IN (" + GenQuestionMarks(len(types)) + ")" + sqlParams = append(sqlParams, types) + } + if keyword != "" { + sql += " AND (b.name LIKE ? OR a.remark LIKE ? OR a.name_id LIKE ? OR a.user_id LIKE ? OR a.store_id LIKE ? OR f.name LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } + if marketManPhone != "" { + sql += " AND d.market_man_phone LIKE ? " + sqlParams = append(sqlParams, "%"+marketManPhone+"%") + } + if cityName != "" { + sql += " AND f.name LIKE ? " + sqlParams = append(sqlParams, "%"+cityName+"%") + } + sql += " ORDER BY a.updated_at LIMIT ? OFFSET ?" + pageSize = jxutils.FormalizePageSize(pageSize) + sqlParams = append(sqlParams, pageSize, offset) + Begin(db) + defer Commit(db) + if err = GetRows(db, &requestList, sql, sqlParams...); err == nil { + return &model.PagedInfo{ + TotalCount: GetLastTotalRowCount(db), + Data: requestList, + }, nil + } + return pagedInfo, err +} + +func GetStoreSkuAuditLight(db *DaoDB, storeIDs, nameIDs []int, status int) (storeSkuAudit []*model.StoreSkuAudit, err error) { + sql := ` + SELECT a.* + FROM store_sku_audit a + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if len(storeIDs) > 0 { + sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + if len(nameIDs) > 0 { + sql += " AND a.name_id IN (" + GenQuestionMarks(len(nameIDs)) + ")" + sqlParams = append(sqlParams, nameIDs) + } + if status != model.StoreAuditStatusAll { + sql += " AND a.status = ? " + sqlParams = append(sqlParams, status) + } + err = GetRows(db, &storeSkuAudit, sql, sqlParams...) + return storeSkuAudit, err +} + +func GetTopSkusByNoCityCode(db *DaoDB) (skuNameAndPlace []*SkuNameAndPlace, err error) { + var skuName1 []model.SkuName + _, err = db.Db.QueryTable("sku_name").Filter("best_seller", "1").All(&skuName1) + for k, _ := range skuName1 { + skuNameAndPlace1 := &SkuNameAndPlace{ + SkuName: skuName1[k], + } + skuNameAndPlace = append(skuNameAndPlace, skuNameAndPlace1) + } + return skuNameAndPlace, err +} + +func GetStoreSkuHistory(db *DaoDB, storeIDs, skuIDs []int, status int, snapShot time.Time) (storeSkuHistory []*model.StoreSkuBindHistory, err error) { + sql := ` + SELECT a.* + FROM store_sku_bind_history a + WHERE a.deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if len(storeIDs) > 0 { + sql += " AND a.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" + sqlParams = append(sqlParams, storeIDs) + } + if len(skuIDs) > 0 { + sql += " AND a.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" + sqlParams = append(sqlParams, skuIDs) + } + if status != model.StoreAuditStatusAll { + sql += " AND a.status = ? " + sqlParams = append(sqlParams, status) + } + if !utils.IsTimeZero(snapShot) { + sql += " AND a.snapshot_at = ? " + sqlParams = append(sqlParams, snapShot) + } + err = GetRows(db, &storeSkuHistory, sql, sqlParams...) + return storeSkuHistory, err +} + +func GetStoreSkuCategoryMap(db *DaoDB, categoryID, storeID int) (storeSkuCategoryMap *model.StoreSkuCategoryMap, err error) { + sql := ` + SELECT * + FROM store_sku_category_map + WHERE deleted_at = ? + ` + sqlParams := []interface{}{utils.DefaultTimeValue} + if categoryID != 0 { + sql += " AND category_id = ? " + sqlParams = append(sqlParams, categoryID) + } + if storeID != 0 { + sql += " AND store_id = ? " + sqlParams = append(sqlParams, storeID) + } + GetRow(db, &storeSkuCategoryMap, sql, sqlParams) + return storeSkuCategoryMap, err +} + +func GetStoreSkuListWithVendor(db *DaoDB, storeID, vendorID int, vendorOrgCode string) (skuList []*StoreSkuSyncInfo, err error) { + sql := ` + SELECT DISTINCT b.*, c.vendor_thing_id vendor_sku_id + FROM store_sku_bind a + JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ? AND b.status = ? + LEFT JOIN thing_map c ON c.thing_id = b.id AND c.thing_type = ? AND c.vendor_id = ? AND c.vendor_org_code = ? AND c.deleted_at = ? + WHERE a.deleted_at = ? AND a.status = ? AND a.store_id = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, model.SkuStatusNormal, + model.ThingTypeSku, vendorID, vendorOrgCode, utils.DefaultTimeValue, + utils.DefaultTimeValue, model.StoreSkuBindStatusNormal, storeID, + } + err = GetRows(db, &skuList, sql, sqlParams) + return skuList, err +} diff --git a/business/model/dao/store_test.go b/business/model/dao/store_test.go index b77ffffba..049f82bd8 100644 --- a/business/model/dao/store_test.go +++ b/business/model/dao/store_test.go @@ -17,7 +17,7 @@ func TestGetStoreDetail(t *testing.T) { } func TestGetStoreCourierList(t *testing.T) { - storeCourierList, err := GetStoreCourierList(GetDB(), []int{100119}, model.StoreStatusOpened, model.StoreAuditStatusOnline) + storeCourierList, err := GetStoreCourierList(GetDB(), []int{100119}, nil, model.StoreStatusOpened, model.StoreAuditStatusOnline) if err != nil { t.Fatal(err) } diff --git a/business/model/dao/thing_map.go b/business/model/dao/thing_map.go index 15f312ac4..8445a1f69 100644 --- a/business/model/dao/thing_map.go +++ b/business/model/dao/thing_map.go @@ -6,7 +6,7 @@ import ( "git.rosy.net.cn/jx-callback/globals" ) -func GetThingMapList(db *DaoDB, thingType int, vendorIDs, thingIDs []int) (cats []*model.ThingMap, err error) { +func GetThingMapList(db *DaoDB, thingType int, vendorIDs, thingIDs []int, vendorOrgCodes []string) (cats []*model.ThingMap, err error) { sql := ` SELECT t1.* FROM thing_map t1 @@ -19,13 +19,17 @@ func GetThingMapList(db *DaoDB, thingType int, vendorIDs, thingIDs []int) (cats if len(thingIDs) > 0 { // 必须要指定ID sql += " AND t1.thing_id IN (" + GenQuestionMarks(len(thingIDs)) + ")" sqlParams = append(sqlParams, thingIDs) - err = GetRows(db, &cats, sql, sqlParams...) } + if len(vendorOrgCodes) > 0 { + sql += " AND t1.vendor_org_code IN (" + GenQuestionMarks(len(vendorOrgCodes)) + ")" + sqlParams = append(sqlParams, vendorOrgCodes) + } + err = GetRows(db, &cats, sql, sqlParams...) return cats, err } func GetThingMapMap(db *DaoDB, thingType int, vendorIDs, thingIDs []int) (thingMapMap map[int64][]*model.ThingMap, err error) { - thingMapList, err := GetThingMapList(db, thingType, vendorIDs, thingIDs) + thingMapList, err := GetThingMapList(db, thingType, vendorIDs, thingIDs, nil) if err == nil { thingMapMap = make(map[int64][]*model.ThingMap) for _, thingMap := range thingMapList { diff --git a/business/model/message.go b/business/model/message.go index 5efb4023c..ef8475cb4 100644 --- a/business/model/message.go +++ b/business/model/message.go @@ -1,7 +1,9 @@ package model const ( - MessageTypeStore = 1 + MessageTypeStore = 1 + MessageTypeUser = 2 + MessageTypeStoreAct = 3 ) const ( @@ -22,9 +24,10 @@ var ( type Message struct { ModelIDCULD - Type int8 `json:"type"` + Type int8 `json:"type"` //1发给门店,2发给用户,3发给门店的统计活动参与信息 Title string `json:"title"` Content string `orm:"type(text)" json:"content"` + ActInfo string `json:"actInfo"` //活动信息,时间平台等 } func (*Message) TableIndex() [][]string { @@ -36,10 +39,12 @@ func (*Message) TableIndex() [][]string { type MessageStatus struct { ModelIDCULD - MessageID int `orm:"column(message_id)" json:"messageID"` - StoreID int `orm:"column(store_id)" json:"storeID"` - Status int8 `json:"status"` - ReadCount int `json:"readCount"` + MessageID int `orm:"column(message_id)" json:"messageID"` + StoreID int `orm:"column(store_id)" json:"storeID"` + Status int8 `json:"status"` + ReadCount int `json:"readCount"` + UserID string `orm:"column(user_id)" json:"userID"` + ConfirmStatus int `json:"confirmStatus"` //商家确认活动,默认0不确认,1确认 } func (*MessageStatus) TableIndex() [][]string { @@ -48,3 +53,31 @@ func (*MessageStatus) TableIndex() [][]string { []string{"StoreID", "MessageID", "Status"}, } } + +type MessageActInfo struct { + VendorID int `orm:"colmun(vendor_id)" json:"vendorID"` + BeginAt string `json:"beginAt"` + EndAt string `json:"endAt"` +} + +type ImMessageRecord struct { + ModelIDCULD + UserID string `orm:"size(48);column(user_id)" json:"userID"` //消息发送方userID + ReceiveID string `orm:"size(48);column(receive_id)" json:"receiveID"` //接收方ID,可以是userID,也可以是群ID + Name string `json:"name"` + Content string `orm:"type(text)" json:"content"` //消息内容 + MessageType int `json:"messageType"` //消息类型,文字,图片 + StoreID int `orm:"column(store_id)" json:"storeID"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` +} + +func (*ImMessageRecord) TableIndex() [][]string { + return [][]string{ + []string{"UserID"}, + []string{"ReceiveID"}, + []string{"StoreID"}, + []string{"VendorID"}, + []string{"VendorOrderID"}, + } +} diff --git a/business/model/model.go b/business/model/model.go index 303eb9fab..de01880c6 100644 --- a/business/model/model.go +++ b/business/model/model.go @@ -51,7 +51,8 @@ const ( FieldActID = "ActID" FieldVendorActID = "VendorActID" - FieldSkuSeq = "Seq" + FieldSkuSeq = "Seq" + FieldVendorStatus = "VendorStatus" ) type ModelIDCUL struct { @@ -91,7 +92,7 @@ const ( SyncFlagSeqMask = 64 // 门店商家分类下的排序顺序 // combine - SyncFlagStoreSkuOnlyMask = SyncFlagSaleMask | SyncFlagPriceMask + SyncFlagStoreSkuOnlyMask = SyncFlagSaleMask | SyncFlagPriceMask | SyncFlagStockMask SyncFlagStoreSkuModifiedMask = SyncFlagStoreSkuOnlyMask | SyncFlagModifiedMask SyncFlagChangedMask = SyncFlagSpecMask | SyncFlagNewMask | SyncFlagDeletedMask | SyncFlagStoreSkuModifiedMask ) @@ -116,6 +117,10 @@ func IsSyncStatusPrice(syncStatus int8) bool { return (syncStatus & SyncFlagPriceMask) != 0 } +func IsSyncStatusStock(syncStatus int8) bool { + return (syncStatus & SyncFlagStockMask) != 0 +} + func IsSyncStatusSeq(syncStatus int8) bool { return (syncStatus & SyncFlagSeqMask) != 0 } diff --git a/business/model/new_config.go b/business/model/new_config.go index a2f1bc131..495bddd32 100644 --- a/business/model/new_config.go +++ b/business/model/new_config.go @@ -1,13 +1,14 @@ package model const ( - ConfigTypeSys = "Sys" - ConfigTypePricePack = "PricePack" - ConfigTypeFreightPack = "FreightPack" - ConfigTypeBank = "Bank" - ConfigTypeRole = "Role" - ConfigTypeJxStore = "JxStore" - ConfigTypeCookie = "Cookie" + ConfigTypeSys = "Sys" + ConfigTypePricePack = "PricePack" + ConfigTypeFreightPack = "FreightPack" + ConfigTypeBank = "Bank" + ConfigTypeRole = "Role" + ConfigTypeJxStore = "JxStore" + ConfigTypeCookie = "Cookie" + ConfigTypeDiscountCard = "DiscountCard" ) const ( @@ -19,13 +20,14 @@ const ( var ( ConfigTypeName = map[string]string{ - ConfigTypeSys: "系统", - ConfigTypePricePack: "价格包", - ConfigTypeFreightPack: "免运包", - ConfigTypeBank: "银行", - ConfigTypeRole: "角色", - ConfigTypeJxStore: "京西商城", - ConfigTypeCookie: "Cookie", + ConfigTypeSys: "系统", + ConfigTypePricePack: "价格包", + ConfigTypeFreightPack: "免运包", + ConfigTypeBank: "银行", + ConfigTypeRole: "角色", + ConfigTypeJxStore: "京西商城", + ConfigTypeCookie: "Cookie", + ConfigTypeDiscountCard: "会员折扣卡", } ) diff --git a/business/model/order.go b/business/model/order.go index a1a3cd677..96f0638b1 100644 --- a/business/model/order.go +++ b/business/model/order.go @@ -1,6 +1,8 @@ package model -import "time" +import ( + "time" +) const ( OrderDeliveryTypePlatform = "platform" // 平台负责配送 @@ -9,8 +11,10 @@ const ( ) const ( - PayTypeWX = 1 // 微信支付 - PayTypeTL = 2 // 通联宝支付 + PayTypeWX = 1 // 微信支付 + PayTypeTL = 2 // 通联宝支付 + PayTypeTL_DiscountCard = 3 // 通联宝支付(会员折扣卡) + PayTypeTL_StoreAcctPay = 4 PayStatusNo = 0 PayStatusYes = 1 @@ -21,6 +25,32 @@ const ( RefundStatusNo = 0 RefundStatusYes = 1 RefundStatusFailed = 2 + + EarningTypeQuote = 1 //报价模式 + EarningTypePoints = 2 //扣点模式 +) + +const ( + OrderTypeAddressErr = -1 //地址异常订单 + OrderTypeNormal = 0 //普通订单 + OrderTypeMatter = 1 //物料订单 + OrderTypeSupplyGoods = 2 //进货订单 + OrderTypeDefendPrice = 3 //守价订单 + OrderTypeStoreAcct = 4 //门店账户订单 +) + +const ( + CouponStatusRe = -2 //优惠券状态还没生效 + CouponStatusOverdue = -1 //已过期 + CouponStatusNormal = 0 //正常 + CouponStatusDeleted = -4 //被删了 + + CouponTypeDiscount = 1 //优惠券类型,总额满减 + CouponTypeDelivery = 2 //运费优惠 +) + +const ( + UserCouponStatusUsed = 1 // 已被使用 ) var ( @@ -37,6 +67,14 @@ var ( RefundStatusYes: "已退款", RefundStatusFailed: "退款失败", } + + CouponStatusName = map[int]string{ + CouponStatusRe: "还没生效", + CouponStatusOverdue: "已过期", + CouponStatusNormal: "正常", + UserCouponStatusUsed: "已被使用", + CouponStatusDeleted: "已删除", + } ) type ModelTimeInfo struct { @@ -45,68 +83,74 @@ type ModelTimeInfo struct { } type GoodsOrder struct { - ID int64 `orm:"column(id)" json:"id"` - VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` - VendorOrderID2 string `orm:"column(vendor_order_id2);size(48);index" json:"vendorOrderID2"` - VendorID int `orm:"column(vendor_id)" json:"vendorID"` - VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` - StoreID int `orm:"column(store_id)" json:"storeID"` // 外部系统里记录的 jxstoreid - JxStoreID int `orm:"column(jx_store_id)" json:"jxStoreID"` // 根据VendorStoreID在本地系统里查询出来的 jxstoreid - StoreName string `orm:"size(64)" json:"storeName"` - ShopPrice int64 `json:"shopPrice"` // 京西价 - VendorPrice int64 `json:"vendorPrice"` // 平台价 - SalePrice int64 `json:"salePrice"` // 售卖价 - ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付 - TotalShopMoney int64 `json:"totalShopMoney"` // 应结金额-第三方平台结算给京西的金额(包括了所有的补贴,扣除) - DiscountMoney int64 `json:"discountMoney"` // 订单总优惠金额 - PmSubsidyMoney int64 `json:"pmSubsidyMoney"` // 平台活动补贴(订单主体活动补贴+订单单条sku补贴)1+ - BaseFreightMoney int64 `json:"baseFreightMoney"` // 商户承担的配送费(不包括DistanceFreightMoney) - DistanceFreightMoney int64 `json:"distanceFreightMoney"` // 商户承担的远距离配送费(当前只有京东到家有值) - WaybillTipMoney int64 `json:"waybillTipMoney"` // 京西加的平台配送小费 - EarningPrice int64 `json:"earningPrice"` // 结算给门店老板的钱(未扣除可能的三方配送费) - NewEarningPrice int64 `json:"newEarningPrice"` // 结算给门店老板的钱(未扣除可能的三方配送费)(新规则) - Weight int `json:"weight"` // 单位为克 - VendorUserID string `orm:"column(vendor_user_id);size(48)" json:"vendorUserID"` - UserID string `orm:"column(user_id);size(48);index" json:"userID"` - ConsigneeName string `orm:"size(32)" json:"consigneeName"` - ConsigneeMobile string `orm:"size(32)" json:"consigneeMobile"` // 订单中的收货手机号 - ConsigneeMobile2 string `orm:"size(32)" json:"consigneeMobile2"` // 收货人真实手机号 - ConsigneeAddress string `orm:"size(255)" json:"consigneeAddress"` - CoordinateType int `json:"coordinateType"` - ConsigneeLng int `json:"consigneeLng"` // 坐标 * (10的六次方) - ConsigneeLat int `json:"consigneeLat"` // 坐标 * (10的六次方) - SkuCount int `json:"skuCount"` // 商品类别数量,即有多少种商品(注意在某些情况下,相同SKU的商品由于售价不同,也会当成不同商品在这个值里) - GoodsCount int `json:"goodsCount"` // 商品个数 - Status int `json:"status"` // 参见OrderStatus*相关的常量定义 - VendorStatus string `orm:"size(255)" json:"vendorStatus"` - LockStatus int `json:"lockStatus"` // 当前只支持单一锁定 - LockStatusTime time.Time `orm:"type(datetime);null" json:"lockStatusTime"` // last lock status time - OrderSeq int `json:"orderSeq"` // 门店订单序号 - BuyerComment string `orm:"size(255)" json:"buyerComment"` - BusinessType int `json:"businessType"` - ExpectedDeliveredTime time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间 - CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请,不为null表示用户正在取消申请 - DeliveryType string `orm:"size(32)" json:"deliveryType"` // 订单配送方式,缺省是平台配送 - VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"` - WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排 - AdjustCount int8 `json:"adjustCount"` // 调整单(次数) - DeliveryFlag int8 `json:"deliveryFlag"` // 第1位为1表示禁止调度器调度三方配送 - DuplicatedCount int `json:"-"` // 重复新订单消息数,这个一般不是由于消息重发造成的(消息重发由OrderStatus过滤),一般是业务逻辑造成的 - OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间) - OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"` - StatusTime time.Time `orm:"type(datetime)" json:"statusTime"` // last status time - PickDeadline time.Time `orm:"type(datetime);null" json:"pickDeadline"` - DeliveryFeeFrom *time.Time `orm:"type(datetime);null" json:"deliveryFeeFrom,omitempty"` // 三方配置费计算的开始基准时间 - ModelTimeInfo `json:"-"` - Flag int `json:"flag"` //非运单调整相关的其它状态 + ID int64 `orm:"column(id)" json:"id"` + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` + VendorOrderID2 string `orm:"column(vendor_order_id2);size(200);index" json:"vendorOrderID2"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` + StoreID int `orm:"column(store_id)" json:"storeID"` // 外部系统里记录的 jxstoreid + JxStoreID int `orm:"column(jx_store_id)" json:"jxStoreID"` // 根据VendorStoreID在本地系统里查询出来的 jxstoreid + StoreName string `orm:"size(64)" json:"storeName"` + ShopPrice int64 `json:"shopPrice"` // 京西价 + VendorPrice int64 `json:"vendorPrice"` // 平台价 + SalePrice int64 `json:"salePrice"` // 售卖价 + ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付 + TotalShopMoney int64 `json:"totalShopMoney"` // 应结金额-第三方平台结算给京西的金额(包括了所有的补贴,扣除) + DiscountMoney int64 `json:"discountMoney"` // 订单总优惠金额 + PmSubsidyMoney int64 `json:"pmSubsidyMoney"` // 平台活动补贴(订单主体活动补贴+订单单条sku补贴)1+ + BaseFreightMoney int64 `json:"baseFreightMoney"` // 商户承担的配送费(不包括DistanceFreightMoney) + DistanceFreightMoney int64 `json:"distanceFreightMoney"` // 商户承担的远距离配送费(当前只有京东到家有值) + WaybillTipMoney int64 `json:"waybillTipMoney"` // 京西加的平台配送小费 + EarningPrice int64 `json:"earningPrice"` // 结算给门店老板的钱(未扣除可能的三方配送费) + NewEarningPrice int64 `json:"newEarningPrice"` // 结算给门店老板的钱(未扣除可能的三方配送费)(新规则) + Weight int `json:"weight"` // 单位为克 + VendorUserID string `orm:"column(vendor_user_id);size(48)" json:"vendorUserID"` + UserID string `orm:"column(user_id);size(48);index" json:"userID"` + ConsigneeName string `orm:"size(32)" json:"consigneeName"` + ConsigneeMobile string `orm:"size(32)" json:"consigneeMobile"` // 订单中的收货手机号 + ConsigneeMobile2 string `orm:"size(32)" json:"consigneeMobile2"` // 收货人真实手机号 + ConsigneeAddress string `orm:"size(255)" json:"consigneeAddress"` + CoordinateType int `json:"coordinateType"` + ConsigneeLng int `json:"consigneeLng"` // 坐标 * (10的六次方) + ConsigneeLat int `json:"consigneeLat"` // 坐标 * (10的六次方) + SkuCount int `json:"skuCount"` // 商品类别数量,即有多少种商品(注意在某些情况下,相同SKU的商品由于售价不同,也会当成不同商品在这个值里) + GoodsCount int `json:"goodsCount"` // 商品个数 + Status int `json:"status"` // 参见OrderStatus*相关的常量定义 + VendorStatus string `orm:"size(255)" json:"vendorStatus"` + LockStatus int `json:"lockStatus"` // 当前只支持单一锁定 + LockStatusTime time.Time `orm:"type(datetime);null" json:"lockStatusTime"` // last lock status time + OrderSeq int `json:"orderSeq"` // 门店订单序号 + BuyerComment string `orm:"size(255)" json:"buyerComment"` + BusinessType int `json:"businessType"` + ExpectedDeliveredTime time.Time `orm:"type(datetime)" json:"expectedDeliveredTime"` // 预期送达时间 + CancelApplyReason string `orm:"size(255)" json:"-"` // ""表示没有申请,不为null表示用户正在取消申请 + DeliveryType string `orm:"size(32)" json:"deliveryType"` // 订单配送方式,缺省是平台配送 + CreateDeliveryType int `orm:"default(0)" json:"createDeliveryType"` //默认0系统发单,1为门店发单 - InvoiceTitle string `orm:"size(64)" json:"invoiceTitle"` // 发票抬头 - InvoiceTaxerID string `orm:"size(32);column(invoice_taxer_id)" json:"invoiceTaxerID"` // 发票纳税人识别码 - InvoiceEmail string `orm:"size(64)" json:"invoiceEmail"` // 发票邮箱 - VendorOrgCode string `orm:"size(64)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 - FromStoreID int `orm:"column(from_store_id)" json:"fromStoreID"` //物料配送门店 - EclpOutID string `orm:"column(eclp_out_id)" json:"eclpOutID"` //物料配送的出库单号 - AddressID int64 `orm:"column(address_id)" json:"addressID"` //配送地址ID + VendorWaybillID string `orm:"column(vendor_waybill_id);size(48)" json:"vendorWaybillID"` + WaybillVendorID int `orm:"column(waybill_vendor_id)" json:"waybillVendorID"` // 表示当前承运商,-1表示还没有安排 + AdjustCount int8 `json:"adjustCount"` // 调整单(次数) + DeliveryFlag int8 `json:"deliveryFlag"` // 第1位为1表示禁止调度器调度三方配送 + DuplicatedCount int `json:"-"` // 重复新订单消息数,这个一般不是由于消息重发造成的(消息重发由OrderStatus过滤),一般是业务逻辑造成的 + OrderCreatedAt time.Time `orm:"type(datetime);index" json:"orderCreatedAt"` // 这里记录的是订单生效时间,即用户支付完成(货到付款即为下单时间) + OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"` + StatusTime time.Time `orm:"type(datetime)" json:"statusTime"` // last status time + PickDeadline time.Time `orm:"type(datetime);null" json:"pickDeadline"` + DeliveryFeeFrom *time.Time `orm:"type(datetime);null" json:"deliveryFeeFrom,omitempty"` // 三方配置费计算的开始基准时间 + ModelTimeInfo `json:"-"` + Flag int `json:"flag"` //非运单调整相关的其它状态 + + InvoiceTitle string `orm:"size(64)" json:"invoiceTitle"` // 发票抬头 + InvoiceTaxerID string `orm:"size(32);column(invoice_taxer_id)" json:"invoiceTaxerID"` // 发票纳税人识别码 + InvoiceEmail string `orm:"size(64)" json:"invoiceEmail"` // 发票邮箱 + VendorOrgCode string `orm:"size(64)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 + FromStoreID int `orm:"column(from_store_id)" json:"fromStoreID"` //物料配送门店 + EclpOutID string `orm:"column(eclp_out_id)" json:"eclpOutID"` //物料配送的出库单号 + AddressID int64 `orm:"column(address_id)" json:"addressID"` //配送地址ID + EarningType int `json:"earningType"` //订单结算方式,2为扣点,1为报价 + OrderType int `json:"orderType"` //订单类型,0为普通订单,1为物料订单,2为进货订单 + OrderPayPercentage int `json:"orderPayPercentage"` + CouponIDs string `orm:"column(coupon_ids)" json:"couponIDs"` //优惠券IDs(京西商城) // 以下只是用于传递数据 OriginalData string `orm:"-" json:"-"` @@ -370,6 +414,97 @@ func (v *OrderSupplementFee) TableIndex() [][]string { } } +type PriceDefendOrder struct { + ModelIDCULD + + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` + StoreID int `orm:"column(store_id)" json:"storeID"` + SkuID int `orm:"column(sku_id)" json:"skuID"` + AddressID int64 `orm:"column(address_id)" json:"addressID"` + Count int `json:"count"` + DefendPrice int64 `json:"defendPrice"` //守的价格 + OriginPrice int64 `json:"originPrice"` //商品原价 + ActualPayPrice int64 `json:"actualPayPrice"` //单位为分 顾客实际支付 + RealPrice int64 `json:"realPrice"` //实际成交价 + IsBuyNowPrice int `json:"isBuyNowPrice"` //库存剩x(x=当前客户购买的数量)时以当时价抢购 + Issue int `json:"issue"` //期数,每晚22:00以后的守价单是归在第二天的期数中 + IsSuccess int `json:"isSuccess"` //是否抢购成功 + IsPay int `json:"isPay"` //是否支付 +} + +func (v *PriceDefendOrder) TableIndex() [][]string { + return [][]string{ + []string{"StoreID", "VendorOrderID", "SkuID"}, + } +} + +type Coupons struct { + ModelIDCUL + + CouponType int `json:"couponType"` //优惠券类型 ,1为总额满减, 2为运费优惠, + Name string `json:"name"` //优惠券名字 + Desc string `json:"desc"` //优惠券详情描述 + BeginAt time.Time `json:"beginAt"` //开始时间 + EndAt time.Time `json:"endAt"` //到期时间 + UpperLimit int `json:"upperLimit"` //满多少 + Cut int `json:"cut"` //减多少 + CouponStatus int `json:"couponStatus"` //优惠券状态,0为正常可使用,-1为已过期, -2为还没开始 + IsAll int `json:"isAll"` //是否全国有效,1是 +} + +func (v *Coupons) TableIndex() [][]string { + return [][]string{ + []string{"BeginAt"}, + } +} + +type UserCoupons struct { + ModelIDCUL + + CouponID int `orm:"column(coupon_id)" json:"couponID"` //优惠券ID + UserID string `orm:"column(user_id)" json:"userID"` //userID + Mobile string `json:"moblie"` //电话,可能他还没注册 + UserCouponStatus int `json:"userCouponStatus"` //优惠券状态,0为正常可使用,-1为已过期, 1为已使用 +} + +func (v *UserCoupons) TableIndex() [][]string { + return [][]string{ + []string{"CouponID", "UserID", "Mobile"}, + } +} + +type StoreCoupons struct { + ModelIDCULD + + CouponID int `orm:"column(coupon_id)" json:"couponID"` //优惠券ID + StoreID int `orm:"column(store_id)" json:"storeID"` //storeID +} + +func (v *StoreCoupons) TableIndex() [][]string { + return [][]string{ + []string{"CouponID", "StoreID"}, + } +} + +type StoreAcctOrder struct { + ModelIDCUL + + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + StoreID int `orm:"column(store_id)" json:"storeID"` // 外部系统里记录的 jxstoreid + ActualPayPrice int `json:"actualPayPrice"` // 单位为分 顾客实际支付 + UserID string `orm:"column(user_id);size(48);index" json:"userID"` + OrderType int `json:"orderType"` + Status int `json:"status"` // 参见OrderStatus*相关的常量定义 // 重复新订单消息数,这个一般不是由于消息重发造成的(消息重发由OrderStatus过滤),一般是业务逻辑造成的 + OrderFinishedAt time.Time `orm:"type(datetime)" json:"orderFinishedAt"` +} + +func (v *StoreAcctOrder) TableUnique() [][]string { + return [][]string{ + []string{"VendorOrderID", "VendorID"}, + } +} + // 判断是否是购买平台自有物流 // 对于京东,饿百来说,就是其自有的物流,对于微商城来说,是达达 func IsWaybillPlatformOwn(bill *Waybill) bool { @@ -396,6 +531,11 @@ func IsOrderDeliveryByPlatform(order *GoodsOrder) bool { return order.DeliveryType == OrderDeliveryTypePlatform } +//订单是否是自提单 +func IsOrderDeliveryBySelf(order *GoodsOrder) bool { + return order.DeliveryType == OrderDeliveryTypeStoreSelf +} + func IsOrderJXTemp(order *GoodsOrder) bool { return order.VendorID == VendorIDJX && order.Flag&OrderFlagMaskTempJX != 0 } diff --git a/business/model/sku.go b/business/model/sku.go index 25c31e894..857a8a01a 100644 --- a/business/model/sku.go +++ b/business/model/sku.go @@ -92,6 +92,9 @@ var ( SkuStatusDeleted: "删除", SkuStatusDontSale: "下架", SkuStatusNormal: "上架", + 2: "删除", + 3: "不可售", + 4: "可售", } ) @@ -137,6 +140,8 @@ type SkuCategory struct { ExdName string `json:"exdName"` //饿鲜达对应分类名 ExdSeq int `json:"exdSeq"` IsExdSpec int `json:"isExdSpec"` //是否是饿鲜达特有新建的分类 + IsExdSync int `json:"isExdSync"` //饿鲜达分类是否同步到平台 + // JdID int64 `orm:"column(jd_id);index" json:"jdID"` // 这个是指商家自己的商品类别在京东平台上的ID // JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"` IsSync int `json:"isSync"` //是否同步到平台 @@ -151,12 +156,13 @@ func (*SkuCategory) TableUnique() [][]string { type SkuName struct { ModelIDCULD - Prefix string `orm:"size(255)" json:"prefix"` - Name string `orm:"size(255)" json:"name"` - ExPrefix string `orm:"size(255)" json:"exPrefix"` + Prefix string `orm:"size(255)" json:"prefix"` + Name string `orm:"size(255)" json:"name"` + ExPrefix string `orm:"size(255)" json:"exPrefix"` ExPrefixBegin *time.Time `orm:"null" json:"exPrefixBegin"` ExPrefixEnd *time.Time `orm:"null" json:"exPrefixEnd"` + ExVendorID int `orm:"column(ex_vendor_id)" json:"exVendorID"` BrandID int `orm:"column(brand_id);default(0)" json:"brandID"` // todo,此属性暂时没有使用,且有问题,应该是不同平台都有一个brandid CategoryID int `orm:"column(category_id);index" json:"categoryID"` // 标准类别 @@ -168,8 +174,11 @@ type SkuName struct { SpecUnit string `orm:"size(8)" json:"-"` // 为份必然为克,这个主要作用只是用于确保SkuName的唯一性 Price int `json:"price"` // 单位为分,标准价,不为份的就为实际标准价,为份的为每市斤价,实际还要乘质量。todo 为份的确定必须有质量 - Img string `orm:"size(512)" json:"img"` - Img2 string `orm:"size(512)" json:"img2"` // 第二张图片 + Img string `orm:"size(512)" json:"img"` + Img2 string `orm:"size(512)" json:"img2"` // 第二张图片 + Img3 string `orm:"size(512)" json:"img3"` //第三张图片 + ImgWatermark string `orm:"size(512)" json:"imgWatermark"` //图片水印 + ImgMix string `orm:"size(512)" json:"imgMix"` //图片混合水印的图片 // ImgEbai string `orm:"size(255)" json:"imgEbai"` // 饿百图片地址 // ImgHashCode string `orm:"size(255);index" json:"img_hash_code"` @@ -184,7 +193,10 @@ type SkuName struct { // JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"` // LinkID int `orm:"column(link_id);null;index" json:"linkID"` - YbNameSuffix string `json:"ybNameSuffix"` //银豹商品后缀 + YbNameSuffix string `json:"ybNameSuffix"` //银豹商品后缀 + JdsStockSwitch int8 `orm:"default(1)" json:"jdsStockSwitch"` //京东商城总库存 + PreparationTime int `orm:"default(1)" json:"preparationTime"` //商品准备时长 + BestSeller int `json:"bestSeller"` //畅销品 0不是 1是 } func (*SkuName) TableUnique() [][]string { @@ -216,6 +228,9 @@ type Sku struct { ExdSkuID string `orm:"column(exd_sku_id)" json:"exdSkuID"` //饿鲜达商品ID ExdCategoryThirdID int `orm:"column(exd_category_third_id)" json:"exdCategoryThirdID"` EclpID string `orm:"column(eclp_id)" json:"eclpID"` //eclp物料商品ID + MinOrderCount int `json:"minOrderCount"` //最少起购份数,美团用 + LadderBoxNum int `json:"ladderBoxNum"` //包装费x件 ,美团用 + LadderBoxPrice int `json:"ladderBoxPrice"` //包装费y元 ,美团用 // JdID int64 `orm:"column(jd_id);null;index" json:"jdID"` // JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"` @@ -274,4 +289,60 @@ type SkuNameExt struct { Places []int `orm:"-" json:"places"` PlacesStr string `json:"-"` MidUnitPrice int `json:"midUnitPrice"` + + JdCategoryID string `json:"jdCategoryID"` + JdsCategoryID string `json:"jdsCategoryID"` + EbaiCategoryID string `json:"ebaiCategoryID"` + MtwmCategoryID string `json:"mtwmCategoryID"` +} + +type SkuExinfoMap struct { + ModelIDCULD + + NameID int `orm:"column(name_id)" json:"nameID"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + BeginAt time.Time `orm:"type(datetime);index" json:"beginAt"` //设置起始时间 + EndAt time.Time `orm:"type(datetime);index" json:"endAt"` //设置结束时间 + ExPrefix string `orm:"size(255)" json:"exPrefix"` //额外前缀 + ImgWatermark string `orm:"size(512)" json:"imgWatermark"` //图片水印 + ImgWatermarkMix string `orm:"size(512)" json:"imgWatermark"` //合成水印图 + BrandID int `orm:"column(brand_id);default(0)" json:"brandID"` //品牌ID +} + +func (*SkuExinfoMap) TableIndex() [][]string { + return [][]string{ + []string{"NameID", "VendorID", "BeginAt", "EndAt"}, + } +} + +type SkuVendorCategoryMap struct { + ModelIDCULD + + NameID int `orm:"column(name_id)" json:"nameID"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + VendorCategoryID string `orm:"column(vendor_category_id)" json:"vendorCategoryID"` +} + +func (*SkuVendorCategoryMap) TableIndex() [][]string { + return [][]string{ + []string{"NameID", "VendorID"}, + } +} + +type VendorCategoryMap struct { + ModelIDCULD + + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + VendorOrgCode string `json:"vendorOrgCode"` + CategoryID int `orm:"column(category_id)" json:"categoryID"` // 这个是指对应的sku_category + VendorCategoryName string `orm:"size(255)" json:"vendorCategoryName"` // 平台类别单独的名字 + VendorCategorySeq int `orm:"default(0)" json:"vendorCategorySeq"` // 平台类别单独的序号 + Level int `json:"level"` // 平台类别单独的等级 + ParentID int `orm:"column(parent_id)" json:"parentID"` //门店类别父ID,和sku_category一致 +} + +func (*VendorCategoryMap) TableUnique() [][]string { + return [][]string{ + []string{"VendorID", "VendorOrgCode", "CategoryID", "DeletedAt"}, + } } diff --git a/business/model/store.go b/business/model/store.go index 647cc86d4..e6aa597f6 100644 --- a/business/model/store.go +++ b/business/model/store.go @@ -22,9 +22,15 @@ const ( StoreAuditStatusCreated = 1 StoreAuditStatusOnline = 0 StoreAuditStatusRejected = -1 + StoreAuditStatusUpdated = 2 StoreAuditStatusAll = -9 ) +const ( + StoreSkuAuditTypePrice = 1 //改价 + StoreSkuAuditTypeFocus = 2 //关注 +) + const ( MainSubStoreName = "本店" MainSubStoreAddress = "本店" @@ -56,10 +62,12 @@ const ( ) const ( - ExdStoreName = "饿鲜达" - MatterStoreID = 666666 - JdShopMainVendorStoreID = "999999" - JdShopMainStoreID = 102919 + ExdStoreName = "饿鲜达" + MatterStoreID = 666666 + JdShopMainVendorStoreID = "999999" + JdShopMainVendorStoreID2 = "9999999" + JdShopMainStoreID = 102919 + JdShopMainStoreID2 = 100000 VendorStoreTel = "18011597879" ) @@ -251,9 +259,9 @@ var ( StoreAuditStatusRejected: "拒绝", } StorePriceTypeName = map[int]string{ - StoreChangePriceTypeDirect: "普通门店", - StoreChangePriceTypeBossDisabled: "普通门店禁止改价", - StoreChangePriceTypeManagedStore: "直营门店禁止改价", + StoreChangePriceTypeDirect: "普通门店", + // StoreChangePriceTypeBossDisabled: "普通门店禁止改价", + // StoreChangePriceTypeManagedStore: "直营门店禁止改价", } AutoReplyTypeName = map[int]string{ AutoReplyAll: "全部自动回复", @@ -287,6 +295,8 @@ type Store struct { SMSNotifyMark int8 `orm:"column(sms_notify_mark);" json:"smsNotifyMark"` //今天是否已经推送过订单消息 AutoReplyType int8 `json:"autoReplyType"` // 订单评价自动回复类型 LinkStoreID int `orm:"column(link_store_id);default(0);index" json:"linkStoreID"` // 关联门店ID + StoreLevel string `orm:"default(C);size(32)" json:"storeLevel"` // 门店等级(筛选用,京西的) + Comment string `orm:"size(255)" json:"comment"` //门店备注 PrinterDisabled int8 `orm:"default(0)" json:"printerDisabled"` // 是否禁用网络打印机 PrinterFontSize int8 `orm:"default(0)" json:"printerFontSize"` // 打印字体-1:小,0:正常,1:大 @@ -330,6 +340,10 @@ type Store struct { PayeeBankBranchName string `orm:"size(255)" json:"payeeBankBranchName"` // 开户支行 PayeeBankCode string `orm:"size(8)" json:"payeeBankCode"` // 开户行代码 PayPercentage int `json:"payPercentage"` + OldPayPercentage int `json:"oldPayPercentage"` + + StoreFrontPic string `orm:"size(255)" json:"storeFrontPic"` //门面照 + StoreInPic string `orm:"size(255)" json:"storeInPic"` //门店内照片 // OperatorName string `orm:"size(8)" json:"operatorName"` // 运营人姓名 OperatorPhone string `orm:"size(16)" json:"operatorPhone"` // 京东运营人电话 @@ -341,9 +355,11 @@ type Store struct { OperatorPhone3 string `orm:"size(16)" json:"operatorPhone3"` // 饿百运营人电话 OperatorRole3 string `orm:"size(32)" json:"operatorRole3"` // 饿百运营人组(角色) - PromoteInfo string `orm:"size(255)" json:"promoteInfo"` //门店公告(所有平台统一的公告) - IsBoughtMatter int `json:"isBoughtMatter"` //这周是否申请过物料 - SoundPercentage int `json:"soundPercentage"` //打印机声音大小比例 + PromoteInfo string `orm:"size(255)" json:"promoteInfo"` //门店公告(所有平台统一的公告) + IsBoughtMatter int `json:"isBoughtMatter"` //这周是否申请过物料 + SoundPercentage int `json:"soundPercentage"` //打印机声音大小比例 + Banner string `orm:"size(9999)" json:"banner"` //门店商城bannar图 + BrandID int `orm:"column(brand_id)" json:"brandID"` //品牌ID } func (*Store) TableUnique() [][]string { @@ -405,10 +421,11 @@ type StoreMap struct { VendorID int `orm:"column(vendor_id)" json:"vendorID"` VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 - VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` - Status int `json:"status"` // 取值同Store.Status - StoreName string `orm:"size(255)" json:"storeName"` // 平台门店的名字,由平台到京西 - VendorStoreName string `orm:"size(255)" json:"vendorStoreName"` //平台门店名,由京西到平台 + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` + Status int `json:"status"` // 取值同Store.Status + StoreName string `orm:"size(255)" json:"storeName"` // 平台门店的名字,由平台到京西 + VendorStoreName string `orm:"size(255)" json:"vendorStoreName"` //平台门店名,由京西到平台 + VendorPayPercentage int `json:"vendorPayPercentage"` //平台结算比例 PricePercentage int16 `orm:"default(100)" json:"pricePercentage"` // todo 厂商价格相对于本地价格的百分比,这个字段的修改会比较特殊,因为可能需要刷新厂商价格 PricePercentagePack string `orm:"size(32)" json:"pricePercentagePack"` // @@ -420,6 +437,7 @@ type StoreMap struct { DeliveryFeeDeductionSill int `json:"deliveryFeeDeductionSill"` DeliveryFeeDeductionFee int `json:"deliveryFeeDeductionFee"` DeliveryCompetition int8 `orm:"default(1)" json:"deliveryCompetition"` // 是否支持配送竞争 + CreateDeliveryType int `orm:"default(0)" json:"createDeliveryType"` //默认0系统发单,1为门店发单 SyncStatus int8 `orm:"default(2)" json:"syncStatus"` IsSync int8 `orm:"default(1)" json:"isSync"` // 是否同步 @@ -430,28 +448,37 @@ type StoreMap struct { JdsStreetCode int `orm:"default(0)" json:"jdsStreetCode"` //京东商城直辖市街道code JdsStreetName string `orm:"size(32)" json:"jdsStreetName"` //京东商城直辖市街道 - IsOrder int `orm:"default(0)" json:"isOrder"` //是否是下预订单门店 + IsOrder int `orm:"default(0)" json:"isOrder"` //是否是下预订单门店 + IsSysCat int `orm:"default(0)" json:"isSysCat"` //是否使用京西分类 + IsSupplyGoods int `orm:"default(0)" json:"isSupplyGoods"` // 是否是货源门店 YbAppID string `orm:"column(yb_app_id);size(255)" json:"ybAppID"` YbAppKey string `orm:"size(255)" json:"ybAppKey"` YbStorePrefix string `orm:"size(255)" json:"ybStorePrefix"` + + MtwmToken string `orm:"size(255)" json:"mtwmToken"` //美团外卖商超token,有效期30天,每20天刷一次 + MtwmRefreshToken string `orm:"size(255)" json:"mtwmRefreshToken"` //美团外卖商超refreshToken + EbaiSupplierID string `orm:"column(ebai_supplier_id)" json:"ebaiSupplierID"` //饿百供应商ID } func (*StoreMap) TableUnique() [][]string { return [][]string{ - []string{"StoreID", "VendorID", "DeletedAt"}, - []string{"VendorStoreID", "VendorID", "DeletedAt"}, + []string{"StoreID", "VendorID", "DeletedAt", "VendorOrgCode"}, + []string{"VendorStoreID", "VendorID", "DeletedAt", "VendorOrgCode"}, } } type StoreCourierMap struct { ModelIDCULD - StoreID int `orm:"column(store_id)" json:"storeID"` - VendorID int `orm:"column(vendor_id)" json:"vendorID"` - VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` - Status int `json:"status"` - AuditStatus int `json:"auditStatus"` + StoreID int `orm:"column(store_id)" json:"storeID"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` + Status int `json:"status"` + AuditStatus int `json:"auditStatus"` + VendorStatus int `json:"vendorStatus"` + VendorStoreName string `orm:"size(255)" json:"vendorStoreName"` //平台门店名,由京西到平台 + Comment string `orm:"size(255)" json:"comment"` // 以下数据仅用于同步使用 Lng int `json:"-"` // 乘了10的6次方 @@ -659,3 +686,175 @@ func (l *FreightDeductionPack) Swap(i, j int) { l2[i] = l2[j] l2[j] = tmp } + +type StoreCategoryMap struct { + ModelIDCULD + StoreID int `orm:"column(store_id)" json:"storeID"` + CategoryID int `orm:"column(category_id)" json:"categoryID"` // 这个是指对应的sku_category + StoreCategoryName string `orm:"size(255)" json:"name"` // 门店类别单独的名字 + StoreCategorySeq int `orm:"default(0)" json:"storeCategorySeq"` // 门店类别单独的序号 + Level int `json:"level"` // 门店类别单独的等级 + ParentID int `orm:"column(parent_id)" json:"parentID"` //门店类别父ID,和sku_category一致 +} + +func (*StoreCategoryMap) TableUnique() [][]string { + return [][]string{ + []string{"StoreID", "CategoryID", "DeletedAt"}, + } +} + +type StorePushClient struct { + ModelIDCULD + StoreID int `orm:"column(store_id)" json:"storeID"` + ClientID string `orm:"column(client_id);size(255)" json:"clientID"` +} + +func (*StorePushClient) TableUnique() [][]string { + return [][]string{ + []string{"StoreID", "ClientID"}, + } +} + +type StoreAudit struct { + ModelIDCULD + + Name string `orm:"size(255)" json:"name"` + CityCode int `orm:"default(0);null" json:"cityCode"` // todo ? + DistrictCode int `orm:"default(0);null" json:"districtCode"` // todo ? + Address string `orm:"size(255)" json:"address"` + Tel1 string `orm:"size(32);index" json:"tel1"` + Tel2 string `orm:"size(32);index" json:"tel2"` + OpenTime1 int16 `json:"openTime1" validate:"max=2359,min=1,ltfield=CloseTime1"` // 930就表示9点半,用两个的原因是为了支持中午休息,1与2的时间段不能交叉,为0表示没有 + CloseTime1 int16 `json:"closeTime1" validate:"max=2359,min=1` // 格式同上 + OpenTime2 int16 `json:"openTime2" validate:"max=2359,min=1,ltfield=CloseTime2"` // 格式同上 + CloseTime2 int16 `json:"closeTime2" validate:"max=2359,min=1` // 格式同上 + Lng int `json:"lng"` // 乘了10的6次方 + Lat int `json:"lat"` // 乘了10的6次方 + DeliveryRangeType int8 `json:"deliveryRangeType"` // 参见相关常量定义 + DeliveryRange string `orm:"type(text)" json:"deliveryRange"` // 如果DeliveryRangeType为DeliveryRangeTypePolygon,则为逗号分隔坐标,分号分隔的坐标点(坐标与Lng和Lat一样,都是整数),比如 121361504,31189308;121420555,31150238。否则为半径,单位为米 + Status int `json:"status"` + SMSNotify int8 `orm:"column(sms_notify);" json:"smsNotify"` // 是否通过短信接收订单消息(每天只推一条) + + IDCardFront string `orm:"size(255);column(id_card_front)" json:"idCardFront"` + IDCardBack string `orm:"size(255);column(id_card_back)" json:"idCardBack"` + IDCardHand string `orm:"size(255);column(id_card_hand)" json:"idCardHand"` + Licence string `orm:"size(255)" json:"licence"` // 营业执照图片 + LicenceCode string `orm:"size(32)" json:"licenceCode"` + + LicenceType int8 `json:"licenceType"` // 营业执照类型,0:个人,1:公司 + LicenceCorpName string `orm:"size(64)" json:"licenceCorpName"` // 营业执照公司名称 + LicenceOwnerName string `orm:"size(8)" json:"licenceOwnerName"` // 法人姓名 + LicenceAddress string `orm:"size(255)" json:"licenceAddress"` // 地址 + LicenceValid string `orm:"size(32)" json:"licenceValid"` // 有效期开始 + LicenceExpire string `orm:"size(32)" json:"licenceExpire"` // 有效期结束 + + IDName string `orm:"size(8);column(id_name)" json:"idName"` // 身份证姓名 + IDCode string `orm:"size(32);column(id_code)" json:"idCode"` // 身份证号 + IDValid string `orm:"column(id_valid);size(32)" json:"idValid"` // 有效期开始 + IDExpire string `orm:"column(id_expire);size(32)" json:"idExpire"` // 有效期结束 + + Licence2Image string `orm:"size(255)" json:"licence2Image"` // 食品经营许可证 + Licence2Code string `orm:"size(32)" json:"licence2Code"` // 食品经营许可证编号 + Licence2Valid string `orm:"size(32)" json:"licence2Valid"` // 有效期开始 + Licence2Expire string `orm:"size(32)" json:"licence2Expire"` // 有效期结束 + + UserID string `orm:"column(user_id);size(32)" json:"userID"` //谁发起的审核就把谁添加到这个门店里 + AuditStatus int `json:"auditStatus"` //0是待审核,1是通过,-1是不通过 + Remark string `orm:"size(255)" json:"remark"` //不通过原因 +} + +func (*StoreAudit) TableUnique() [][]string { + return [][]string{ + []string{"Name"}, + } +} + +func (*StoreAudit) TableIndex() [][]string { + return [][]string{ + []string{"UserID"}, + } +} + +type Brand struct { + ModelIDCULD + + Name string `orm:"size(255)" json:"name"` //品牌名 + Logo string `orm:"size(255)" json:"logo"` //品牌logo + BrandType int `json:"brandType"` //品牌类型 + IsOpen int `json:"isOpen"` //主要三方配送用,是否配送,默认0表示打开,1表示关 + IsPrint int `json:"isPrint"` //是否打印小票中的标题,默认0表示打,1表示不打 +} + +func (*Brand) TableUnique() [][]string { + return [][]string{ + []string{"Name"}, + } +} + +type BrandStore struct { + ModelIDCULD + + Name string `orm:"size(255)" json:"name"` //门店名 +} + +func (*BrandStore) TableUnique() [][]string { + return [][]string{ + []string{"Name"}, + } +} + +//门店账户收入 +type StoreAcctIncome struct { + ModelIDCUL + + StoreID int `orm:"column(store_id)" json:"storeID"` //门店ID + UserID string `orm:"column(user_id)" json:"userID"` //用户ID (谁消费的) + Type int `json:"type"` //收入类型 + IncomePrice int `json:"incomePrice"` //收入金额 +} + +func (v *StoreAcctIncome) TableIndex() [][]string { + return [][]string{ + []string{"StoreID"}, + []string{"CreatedAt"}, + } +} + +//门店账户支出 +type StoreAcctExpend struct { + ModelIDCUL + + StoreID int `orm:"column(store_id)" json:"storeID"` //门店ID + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` + UserID string `orm:"column(user_id)" json:"userID"` //用户ID (谁消费的) + Type int `json:"type"` //支出类型 + ExpendPrice int `json:"expendPrice"` //支出金额 +} + +func (v *StoreAcctExpend) TableIndex() [][]string { + return [][]string{ + []string{"StoreID"}, + []string{"CreatedAt"}, + } +} + +//门店账单表 +type StoreAcct struct { + ModelIDCULD + + StoreID int `orm:"column(store_id)" json:"storeID"` //门店ID + AccountBalance int `json:"accountBalance"` //账户余额 +} + +func (v *StoreAcct) TableUnique() [][]string { + return [][]string{ + []string{"StoreID"}, + } +} + +func (v *StoreAcct) TableIndex() [][]string { + return [][]string{ + []string{"CreatedAt"}, + []string{"AccountBalance"}, + } +} diff --git a/business/model/store_sku.go b/business/model/store_sku.go index 89e0fb996..9b924990e 100644 --- a/business/model/store_sku.go +++ b/business/model/store_sku.go @@ -20,8 +20,8 @@ const ( const ( RequestStatusNew = 0 - RequestStatusRejected = 1 - RequestStatusAccepted = 2 + RequestStatusRejected = -1 + RequestStatusAccepted = 1 RequestStatusCanceled = 3 ) @@ -95,6 +95,7 @@ type StoreSkuBind struct { SubStoreID int `orm:"column(sub_store_id)"` Price int // 单位为分,不用int64的原因是这里不需要累加 UnitPrice int // 这个是一斤的门店商品价,放在这里的原因是避免额外增加一张store sku_name表,逻辑上要保证同一SKU NAME中的所有SKU这个字段的数据一致 + Stock int `json:"stock"` //门店商品库存 Status int // ElmID int64 `orm:"column(elm_id);index"` @@ -192,3 +193,23 @@ func (*StoreOpRequest) TableIndex() [][]string { []string{"StoreID", "Status", "Type"}, } } + +type StoreSkuAudit struct { + ModelIDCULD // DeletedAt用于表示请求操作结束,而并不一定是删除 + + Type int8 `json:"type"` //1为改价 + StoreID int `orm:"column(store_id)" json:"storeID"` + NameID int `orm:"column(name_id)" json:"nameID"` // 这个根据type不同,可能是SKUNAME ID或SKU ID + Status int8 `json:"status"` // + UserID string `orm:"size(48);column(user_id)" json:"userID"` + OriginUnitPrice int `json:"originPrice"` // 表示原价 + UnitPrice int `json:"unitPrice"` //老板申请的审核价格 + AuditPrice int `json:"auditPrice"` //运营录入的审核价格 + Remark string `orm:"size(255)" json:"remark"` +} + +func (*StoreSkuAudit) TableIndex() [][]string { + return [][]string{ + []string{"StoreID", "Type", "NameID", "Status", "DeletedAt"}, + } +} diff --git a/business/model/sync_map.go b/business/model/sync_map.go index 6fc3a7d09..955e8c4c8 100644 --- a/business/model/sync_map.go +++ b/business/model/sync_map.go @@ -18,7 +18,7 @@ type ThingMap struct { VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 VendorThingID string `orm:"size(32);column(vendor_thing_id);index" json:"vendorThingID"` - SyncStatus int8 `orm:"default(2)" json:"syncStatus"` + SyncStatus int8 `orm:"default(0)" json:"syncStatus"` Remark string `orm:"size(255)" json:"remark"` } diff --git a/business/model/user.go b/business/model/user.go index 91011fbbf..62b71b07a 100644 --- a/business/model/user.go +++ b/business/model/user.go @@ -16,7 +16,10 @@ const ( UserTypeStoreBoss = 2 UserTypeOperator = 4 UserTypeBoss = 8 + UserTypeRole = 16 UserTypeNonConsumer = ^1 + + MemberTypeDiscountCard = 1 //会员折扣卡 ) var ( @@ -25,9 +28,16 @@ var ( UserTypeStoreBoss: "门店老板", UserTypeOperator: "运营", UserTypeBoss: "老板", + UserTypeRole: "受权限管理", } ) +type DiscountCard struct { + ID int `orm:"column(id)" json:"id"` + PicePercentage int `json:"pricePercentage"` + Price int `json:"price"` +} + type User struct { ModelIDCULD UserID string `orm:"size(48);column(user_id)" json:"userID" compact:"userID"` // 内部唯一标识 @@ -49,6 +59,8 @@ type User struct { LastLoginAt *time.Time `orm:"null" json:"lastLoginAt"` LastLoginIP string `orm:"size(64);column(last_login_ip)" json:"lastLoginIP"` LastLoginType string `orm:"size(16)" json:"lastLoginType"` + LastBrandID int `orm:"column(last_brand_id)" json:"lastBrandID"` + LastStoreID int `orm:"column(last_store_id)" json:"lastStoreID"` //上次浏览过的店铺 ParentMobile string `orm:"size(32)" json:"parentMobile"` DividePercentage int `json:"dividePercentage"` @@ -194,3 +206,81 @@ func (*UserOrderSms) TableUnique() [][]string { []string{"Mobile"}, } } + +type UserMember struct { + ModelIDCULD + + VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` //和order_pay关联的,不知道有没用,先加上把 + UserID string `orm:"size(48);column(user_id)" json:"userID"` //内部唯一标识 + MemberType int `json:"memberType"` //会员类型, 1为折扣卡 + MemberTypeID int `orm:"column(member_type_id)" json:"memberTypeID"` //会员类型ID,折扣卡的话代表几档 + EndAt time.Time `json:"endAt"` //会员过期时间 + IsPay int `json:"isPay"` +} + +func (v *UserMember) TableIndex() [][]string { + return [][]string{ + []string{"UserID"}, + []string{"CreatedAt"}, + } +} + +type Role struct { + ModelIDCULD + + Name string `json:"name"` //角色名 + BrandID int `orm:"column(brand_id)" json:"brandID"` + CityCodes string `orm:"type(text)" json:"cityCodes"` + StoreIDs string `orm:"column(store_ids);type(text)" json:"storeIDs"` + CityInfo []*Place `orm:"-" json:"cityInfo"` + Stores []*Store `orm:"-" json:"storeInfo"` +} + +func (*Role) TableUnique() [][]string { + return [][]string{ + []string{"Name", "DeletedAt"}, + } +} + +type UserRole struct { + ModelIDCULD + + UserID string `orm:"column(user_id)" json:"userID"` //用户ID + RoleID int `orm:"column(role_id)" json:"roleID"` //角色ID +} + +func (*UserRole) TableUnique() [][]string { + return [][]string{ + []string{"UserID", "RoleID", "DeletedAt"}, + } +} + +type Menu struct { + ModelIDCULD + + Name string `json:"name"` //功能名 + URL string `orm:"column(url)" json:"url"` //路径 + ImgURL string `orm:"column(img_url)" json:"imgURL"` //图标 + Level int `json:"level"` //级别 + ParentID int `orm:"column(parent_id)" json:"parentID"` //父功能ID + Color string `json:"color"` //颜色 +} + +func (*Menu) TableUnique() [][]string { + return [][]string{ + []string{"Name", "DeletedAt"}, + } +} + +type RoleMenu struct { + ModelIDCULD + + RoleID int `orm:"column(role_id)" json:"roleID"` //角色ID + MenuID int `orm:"column(menu_id)" json:"menuID"` //功能ID +} + +func (*RoleMenu) TableUnique() [][]string { + return [][]string{ + []string{"MenuID", "RoleID", "DeletedAt"}, + } +} diff --git a/business/model/vendor_org_code.go b/business/model/vendor_org_code.go new file mode 100644 index 000000000..46467af57 --- /dev/null +++ b/business/model/vendor_org_code.go @@ -0,0 +1,24 @@ +package model + +const ( + VendorOrgTypePlatform = "platform" //外卖平台 + VendorOrgTypeDelivery = "delivery" //配送平台 +) + +type VendorOrgCode struct { + ModelIDCULD + + VendorID int `orm:"column(vendor_id)" json:"code"` + VendorOrgCode string `orm:"size(32)" json:"key"` // 同一平台下不同的商户代码,如果只有一个,可以为空 + Comment string `json:"name"` //备注 + //appkey,secret token等 + + VendorType string `json:"vendorType"` //platform 普通平台, delivery 三方配送平台 + IsJxCat int `json:"isJxCat"` //是否使用京西分类,0默认使用 + IsOpen int `json:"isOpen"` //主要三方配送用,是否配送,默认0表示打开,1表示关 + EmpowerURL string `orm:"column(empower_url)" json:"empowerURL"` //授权地址 + StoreBrandName string `json:"storeBrandName"` //建店品牌名(和饿百供应商不同,美团是根据平台账号划分) + Token string `json:"token"` + AppKey string `json:"appKey"` + AppSecret string `json:"appSecret"` +} diff --git a/business/partner/delivery/dada/waybill.go b/business/partner/delivery/dada/waybill.go index 0d9e54de3..d305ef610 100644 --- a/business/partner/delivery/dada/waybill.go +++ b/business/partner/delivery/dada/waybill.go @@ -18,8 +18,8 @@ import ( ) const ( - maxOrderPrice = 6399 // 单位为分,达达最大价格,超过这个价格配送费会增加 - maxOrderWeight = 5000 // 5公斤 + maxOrderPrice = 50000 // 单位为分,达达最大价格,超过这个价格配送费会增加,2020-11-25改为50000,之前是6399 + maxOrderWeight = 5000 // 5公斤 ) var ( @@ -76,6 +76,7 @@ func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaap order.Status = model.WaybillStatusNew case dadaapi.OrderStatusAccepted: order.Status = model.WaybillStatusAccepted + order.Remark = order.CourierName + "," + order.CourierMobile case dadaapi.OrderStatusDelivering: order.Status = model.WaybillStatusDelivering case dadaapi.OrderStatusFinished: @@ -126,7 +127,7 @@ func StoreDetail2ShopInfo(storeDetail *dao.StoreDetail2) (shopInfo *dadaapi.Shop } shopInfo = &dadaapi.ShopInfo{ OriginShopID: storeDetail.VendorStoreID, - StationName: storeDetail.Name, + StationName: globals.StoreName + "-" + storeDetail.Name, Business: dadaapi.BusinessTypeConvStore, // 故意设置成这个的 CityName: cityName, AreaName: districtName, @@ -228,8 +229,14 @@ func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder) } if billParams.ShopNo, err = c.getDadaShopID(order, db); err == nil { if billParams.CityCode, err = c.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.BuyerComment)) + 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 @@ -241,6 +248,15 @@ func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder) // IDeliveryPlatformHandler func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) { db := dao.GetDB() + if vendorOrgCode, err := dao.GetVendorOrgCode(db, model.VendorIDDada, "", model.VendorOrgTypeDelivery); err == nil { + if len(vendorOrgCode) > 0 { + if vendorOrgCode[0].IsOpen == model.YES { + return nil, fmt.Errorf("此平台配送已被系统关闭,暂不发配送 [%v]", vendorOrgCode[0].Comment) + } + } + } else { + return nil, err + } billParams, err := c.getBillParams(db, order) if err == nil { if globals.EnableStoreWrite { diff --git a/business/partner/delivery/fn/store.go b/business/partner/delivery/fn/store.go new file mode 100644 index 000000000..cfb9ccb38 --- /dev/null +++ b/business/partner/delivery/fn/store.go @@ -0,0 +1,84 @@ +package fn + +import ( + "strings" + + "git.rosy.net.cn/baseapi/platformapi/fnpsapi" + "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/globals" + "git.rosy.net.cn/jx-callback/globals/api" +) + +func (c *DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) { + err = api.FnAPI.CreateStore(&fnpsapi.CreateStoreParam{ + ChainStoreCode: utils.Int2Str(storeDetail.ID), + ChainStoreName: globals.StoreName + "-" + storeDetail.Name, + ContactPhone: storeDetail.Tel1, + Address: storeDetail.Address, + PositionSource: 3, + Longitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng)), + Latitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat)), + }) + if err == nil { + vendorStoreID = utils.Int2Str(storeDetail.ID) + } + return vendorStoreID, status, err +} + +func shopStatus2JX(status int) (jxStatus int) { + if status == 1 { + return 0 + } else { + return 1 + } +} + +func (c *DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) { + shopInfo, err := api.FnAPI.GetStore(vendorStoreID) + if err == nil { + storeDetail = &dao.StoreDetail2{ + Store: model.Store{ + Name: shopInfo.ChainStoreName, + Tel1: shopInfo.ContactPhone, + Address: shopInfo.Address, + Lng: jxutils.StandardCoordinate2Int(utils.Str2Float64(shopInfo.Longitude)), + Lat: jxutils.StandardCoordinate2Int(utils.Str2Float64(shopInfo.Latitude)), + }, + VendorID: model.VendorIDFengNiao, + VendorStoreID: shopInfo.ChainStoreCode, + CourierStatus: shopStatus2JX(shopInfo.Status), + } + } + return storeDetail, err +} + +func (c *DeliveryHandler) IsErrStoreExist(err error) bool { + return fnpsapi.IsErrShopExist(err) +} + +func (c *DeliveryHandler) IsErrStoreNotExist(err error) bool { + return fnpsapi.IsErrShopNotExist(err) +} + +func (c *DeliveryHandler) UpdateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (err error) { + params := &fnpsapi.CreateStoreParam{ + ChainStoreCode: utils.Int2Str(storeDetail.ID), + // ChainStoreName: globals.StoreName + "-" + storeDetail.Name, + ContactPhone: storeDetail.Tel1, + Address: storeDetail.Address, + PositionSource: 3, + Longitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng)), + Latitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat)), + } + if !strings.Contains(storeDetail.Name, globals.StoreName+"-") { + params.ChainStoreName = globals.StoreName + "-" + storeDetail.Name + } else { + params.ChainStoreName = storeDetail.Name + } + err = api.FnAPI.UpdateStore(params) + return err +} diff --git a/business/partner/delivery/fn/waybill.go b/business/partner/delivery/fn/waybill.go new file mode 100644 index 000000000..fb534debc --- /dev/null +++ b/business/partner/delivery/fn/waybill.go @@ -0,0 +1,220 @@ +package fn + +import ( + "fmt" + "strings" + "time" + + "git.rosy.net.cn/baseapi/utils" + "github.com/astaxie/beego" + "github.com/astaxie/beego/orm" + + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/partner/delivery" + + "git.rosy.net.cn/jx-callback/business/model/dao" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/baseapi/platformapi/fnpsapi" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/globals/api" +) + +var ( + curDeliveryHandler *DeliveryHandler +) + +type DeliveryHandler struct { +} + +func init() { + if api.FnAPI != nil { + curDeliveryHandler = new(DeliveryHandler) + partner.RegisterDeliveryPlatform(curDeliveryHandler, true) + } +} + +func (c *DeliveryHandler) GetVendorID() int { + return model.VendorIDFengNiao +} + +func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) { + err = api.FnAPI.CancelOrder(&fnpsapi.CancelOrderParam{ + PartnerOrderCode: bill.VendorOrderID, + OrderCancelReasonCode: 1, //用户取消 + OrderCancelCode: fnpsapi.OrderCancelReson8, + OrderCancelTime: time.Now().UnixNano() / 1e6, + }) + if err != nil { + if strings.Contains(err.Error(), "运单暂未生成") { + err = nil + } + } + bill.Status = model.WaybillStatusCanceled + bill.Remark = cancelReason + partner.CurOrderManager.OnWaybillStatusChanged(bill) + return err +} + +func (c *DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) { + + return err +} + +func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) { + var ( + db = dao.GetDB() + ) + if vendorOrgCode, err := dao.GetVendorOrgCode(db, model.VendorIDFengNiao, "", model.VendorOrgTypeDelivery); err == nil { + if len(vendorOrgCode) > 0 { + if vendorOrgCode[0].IsOpen == model.YES { + return nil, fmt.Errorf("此平台配送已被系统关闭,暂不发配送 [%v]", vendorOrgCode[0].Comment) + } + } + } else { + return nil, err + } + storeDetail, err := dao.GetStoreDetail(db, order.StoreID, order.VendorID, order.VendorOrgCode) + deliveryFee, _, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) + if err == nil { + if err = delivery.CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee, order, model.VendorIDFengNiao); err != nil { + return nil, err + } + params := &fnpsapi.CreateOrderParam{ + PartnerOrderCode: order.VendorOrderID, + NotifyURL: globals.FnNotifyURL, + ChainStoreCode: utils.Int2Str(jxutils.GetSaleStoreIDFromOrder(order)), + OrderType: 1, //即时达 + TransportInfo: &fnpsapi.TransportInfo{ + TransportName: order.StoreName, + TransportAddress: storeDetail.Address, + TransportLongitude: jxutils.IntCoordinate2Standard(storeDetail.Lng), + TransportLatitude: jxutils.IntCoordinate2Standard(storeDetail.Lat), + PositionSource: 3, + TransportTel: storeDetail.Tel1, + }, + OrderAddTime: order.OrderCreatedAt.UnixNano() / 1e6, + OrderTotalAmount: jxutils.IntPrice2Standard(order.SalePrice), + OrderActualAmount: jxutils.IntPrice2Standard(order.ActualPayPrice), + OrderWeight: float64(jxutils.IntWeight2Float(order.Weight)), + OrderRemark: utils.FilterMb4("客户电话:" + order.ConsigneeMobile + "," + order.BuyerComment + ",取货失败或配送遇到问题请联系18048531223,禁止未配送直接完成定单!"), + IsInvoiced: 0, + OrderPaymentStatus: 1, + OrderPaymentMethod: 1, + IsAgentPayment: 0, + GoodsCount: order.GoodsCount, + ReceiverInfo: &fnpsapi.ReceiverInfo{ + ReceiverName: order.ConsigneeName, + ReceiverAddress: order.ConsigneeAddress, + ReceiverLongitude: jxutils.IntCoordinate2Standard(order.ConsigneeLng), + ReceiverLatitude: jxutils.IntCoordinate2Standard(order.ConsigneeLat), + ReceiverPrimaryPhone: order.ConsigneeMobile, + ReceiverSecondPhone: order.ConsigneeMobile2, + PositionSource: 3, + }, + SerialNumber: model.VendorNames[order.VendorID] + " #" + utils.Int2Str(order.OrderSeq), + } + var skuInfo []*fnpsapi.ItemsJSON + for _, v := range order.Skus { + skuInfo = append(skuInfo, &fnpsapi.ItemsJSON{ + ItemID: utils.Int2Str(v.SkuID), + ItemName: v.SkuName, + ItemQuantity: v.Count, + ItemPrice: jxutils.IntPrice2Standard(v.SalePrice), + ItemActualPrice: jxutils.IntPrice2Standard(v.SalePrice), + }) + } + params.ItemsJSON = skuInfo + //要求饿百的订单要传来源 + if order.VendorID == model.VendorIDEBAI { + params.OrderSource = "109" + params.ChannelOrderCode = order.VendorOrderID + } + err = api.FnAPI.CreateOrder(params) + if err == nil { + bill = &model.Waybill{ + VendorOrderID: order.VendorOrderID, + OrderVendorID: order.VendorID, + VendorWaybillID: "", + VendorWaybillID2: "", + WaybillVendorID: model.VendorIDFengNiao, + DesiredFee: deliveryFee, + } + delivery.OnWaybillCreated(bill) + } else { + globals.SugarLogger.Debugf("CreateWaybill failed, orderID:%s, billParams:%v, error:%v", order.VendorOrderID, params, err) + } + } + return bill, err +} + +func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) { + saleStoreID := jxutils.GetSaleStoreIDFromOrder(order) + storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDFengNiao) + if err = err2; err != nil && err != orm.ErrNoRows { + 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 (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) { + db := dao.GetDB() + deliveryFeeInfo = &partner.WaybillFeeInfo{} + deliveryFeeInfo.RefDeliveryFee, deliveryFeeInfo.RefAddFee, err = delivery.CalculateOrderDeliveryFee(order, time.Now(), db) + if err == nil { + if _, err = c.getMTPSShopID(order, db); err == nil { + deliveryFeeInfo.DeliveryFee = deliveryFeeInfo.RefDeliveryFee + } + } + return deliveryFeeInfo, err +} + +func OnWaybillMsg(msg *fnpsapi.WayBillInfo) { + order := &model.Waybill{ + VendorWaybillID: utils.Int64ToStr(msg.OpenOrderCode), + VendorWaybillID2: msg.PartnerOrderCode, + WaybillVendorID: model.VendorIDFengNiao, + CourierName: msg.CarrierDriverName, + CourierMobile: msg.CarrierDriverPhone, + VendorStatus: utils.Int2Str(msg.OrderStatus), + StatusTime: utils.Timestamp2Time(msg.PushTime), + Remark: msg.Description, + } + order.VendorOrderID, order.OrderVendorID = jxutils.SplitUniversalOrderID(msg.PartnerOrderCode) + switch msg.OrderStatus { + case fnpsapi.OrderStatusAccept: + order.Status = model.WaybillStatusNew + case fnpsapi.OrderStatusAssigned: + order.DesiredFee = GetDesiredFee(order.VendorOrderID) + order.Status = model.WaybillStatusAccepted + order.Remark = order.CourierName + "," + order.CourierMobile + case fnpsapi.OrderStatusArrived: + order.DesiredFee = GetDesiredFee(order.VendorOrderID) + order.Status = model.WaybillStatusCourierArrived + case fnpsapi.OrderStatusDelivering: + order.Status = model.WaybillStatusDelivering + case fnpsapi.OrderStatusDelivered: + order.Status = model.WaybillStatusDelivered + case fnpsapi.OrderStatusException: + order.Status = model.WaybillStatusDeliverFailed + default: + globals.SugarLogger.Warnf("onWaybillMsg unknown msg:%v", msg) + } + partner.CurOrderManager.OnWaybillStatusChanged(order) +} + +func GetDesiredFee(vendorOrderID string) (desiredFee int64) { + if result, err := api.FnAPI.QueryOrder(vendorOrderID); err == nil { + return jxutils.StandardPrice2Int(result.OrderTotalDeliveryCost) + } + return desiredFee +} diff --git a/business/partner/delivery/jdeclp/waybill.go b/business/partner/delivery/jdeclp/waybill.go new file mode 100644 index 000000000..c88bf0b47 --- /dev/null +++ b/business/partner/delivery/jdeclp/waybill.go @@ -0,0 +1,104 @@ +package jdeclp + +import ( + "fmt" + "time" + + "git.rosy.net.cn/baseapi/platformapi/jdeclpapi" + "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/api" +) + +var ( + CurDeliveryHandler *DeliveryHandler +) + +type DeliveryHandler struct { +} + +func init() { + CurDeliveryHandler = new(DeliveryHandler) + partner.RegisterDeliveryPlatform(CurDeliveryHandler, true) +} + +func (c *DeliveryHandler) GetVendorID() int { + return model.VendorIDJDWL +} + +func OnWaybillMsg() { +} + +func (c *DeliveryHandler) OnWaybillMsg() { + +} + +func (c *DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) { + return vendorStoreID, status, err +} +func (c *DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) { + return storeDetail, err +} +func (c *DeliveryHandler) IsErrStoreNotExist(err error) bool { + return false +} +func (c *DeliveryHandler) IsErrStoreExist(err error) bool { + return false +} +func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) { + storeID := jxutils.GetShowStoreIDFromOrder(order) + stores, err := dao.GetStoreList(dao.GetDB(), []int{storeID}, nil, nil, nil, "") + if len(stores) == 0 || err != nil { + return bill, fmt.Errorf("未查询到该门店! 门店id :[%v]", storeID) + } + vendorWaybillID, err := api.JdEclpAPI.WaybillReceive(&jdeclpapi.WaybillReceiveParam{ + SalePlat: jdeclpapi.SalePlatSourceDelivery, + CustomerCode: jdeclpapi.CustomerCode, + OrderID: order.VendorOrderID, + SenderName: order.StoreName, + SenderAddress: stores[0].Address, + SenderTel: stores[0].Tel1, + ReceiveName: order.ConsigneeName, + ReceiveAddress: order.ConsigneeAddress, + ReceiveTel: order.ConsigneeMobile, + Weight: order.Weight, + Vloumn: order.Weight, + PackageCount: 1, + Description: "生鲜", + Aging: 5, + PromiseTimeType: 1, //特惠送 + }) + waybill := &model.Waybill{ + VendorOrderID: order.VendorOrderID, + OrderVendorID: model.VendorIDJDShop, + VendorWaybillID: vendorWaybillID, + WaybillVendorID: model.VendorIDJDWL, + Status: model.WaybillStatusDelivering, + WaybillCreatedAt: time.Now(), + StatusTime: time.Now(), + WaybillFinishedAt: utils.DefaultTimeValue, + DeliveryFlag: model.OrderDeliveryFlagMaskScheduleDisabled, + } + dao.CreateEntity(dao.GetDB(), waybill) + return waybill, err +} +func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) { + err = api.JdEclpAPI.CancelWayBill(&jdeclpapi.CancelWayBillParam{ + WaybillCode: bill.VendorWaybillID, + CustomerCode: jdeclpapi.CustomerCode, + Source: "JOS", + CancelReason: cancelReason, + OperatorName: "jxadmin", + }) + return err +} +func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) { + return deliveryFeeInfo, err +} +func (c *DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) { + return err +} diff --git a/business/partner/delivery/jdeclp/waybill_test.go b/business/partner/delivery/jdeclp/waybill_test.go new file mode 100644 index 000000000..b954e8be9 --- /dev/null +++ b/business/partner/delivery/jdeclp/waybill_test.go @@ -0,0 +1,7 @@ +package jdeclp + +import "git.rosy.net.cn/jx-callback/globals/testinit" + +func init() { + testinit.Init() +} diff --git a/business/partner/delivery/mtps/store.go b/business/partner/delivery/mtps/store.go index ff4acd128..677514135 100644 --- a/business/partner/delivery/mtps/store.go +++ b/business/partner/delivery/mtps/store.go @@ -18,10 +18,12 @@ const ( var ( auditStatusMap = map[int]int{ - mtpsapi.ShopStatusAuditCreated: model.StoreAuditStatusCreated, - mtpsapi.ShopStatusAuditRejected: model.StoreAuditStatusRejected, - mtpsapi.ShopStatusAuditPassed: model.StoreAuditStatusCreated, - mtpsapi.ShopStatusAuditOnline: model.StoreAuditStatusOnline, + mtpsapi.ShopStatusAuditCreated: model.StoreAuditStatusCreated, + mtpsapi.ShopStatusAuditRejected: model.StoreAuditStatusRejected, + mtpsapi.ShopStatusAuditPassed: model.StoreAuditStatusCreated, + mtpsapi.ShopStatusAuditOnline: model.StoreAuditStatusOnline, + mtpsapi.ShopStatusAuditUpdatePassed: model.StoreAuditStatusOnline, + mtpsapi.ShopStatusAuditUpdateRejected: model.StoreAuditStatusRejected, } ) @@ -38,42 +40,44 @@ func OnStoreStatus(msg *mtpsapi.CallbackShopStatusMsg) (retVal *mtpsapi.Callback func (c *DeliveryHandler) OnStoreStatus(msg *mtpsapi.CallbackShopStatusMsg) (retVal *mtpsapi.CallbackResponse) { globals.SugarLogger.Debugf("mtps OnStoreStatus, msg:%s", utils.Format4Output(msg, true)) - err := partner.CurStoreManager.OnCourierStoreStatusChanged(jxcontext.AdminCtx, msg.ShopID, model.VendorIDMTPS, getAuditStatus(msg.Status)) + err := partner.CurStoreManager.OnCourierStoreStatusChanged(jxcontext.AdminCtx, msg.ShopID, model.VendorIDMTPS, getAuditStatus(msg.Status), msg.RejectMessage) retVal = mtpsapi.Err2CallbackResponse(err, "mtps OnStoreStatus") return retVal } func (c *DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) { - businessHours := []*mtpsapi.BusinessHour{ - &mtpsapi.BusinessHour{ - BeginTime: "06:00", - EndTime: "22:00", - }, - } - shopInfo := &mtpsapi.ShopInfo{ - ShopID: storeDetail.VendorStoreID, - ShopName: storeDetail.Name, - Category: mtpsapi.ShopCategoryFruit, - SecondCategory: mtpsapi.ShopCategoryFruitFruit, - ContactName: storeDetail.PayeeName, - ContactPhone: storeDetail.Tel1, - ContactEmail: fakeContactEmail, - ShopAddress: storeDetail.Address, - ShopLng: storeDetail.Lng, - ShopLat: storeDetail.Lat, - CoordinateType: mtpsapi.CoordinateTypeMars, - BusinessHours: string(utils.MustMarshal(businessHours)), - } - shopStatus := mtpsapi.ShopStatusAuditCreated if globals.EnableStoreWrite { - shopStatus, err = api.MtpsAPI.ShopCreate(shopInfo) - if err == nil { - vendorStoreID = shopInfo.ShopID - status = getAuditStatus(shopStatus) + businessHours := []*mtpsapi.BusinessHour{ + &mtpsapi.BusinessHour{ + BeginTime: "06:00", + EndTime: "22:00", + }, + } + shopInfo := &mtpsapi.ShopInfo{ + ShopID: storeDetail.VendorStoreID, + ShopName: storeDetail.Name, + Category: mtpsapi.ShopCategoryFruit, + SecondCategory: mtpsapi.ShopCategoryFruitFruit, + ContactName: storeDetail.PayeeName, + ContactPhone: storeDetail.Tel1, + ContactEmail: fakeContactEmail, + ShopAddress: storeDetail.Address, + ShopLng: storeDetail.Lng, + ShopLat: storeDetail.Lat, + CoordinateType: mtpsapi.CoordinateTypeMars, + BusinessHours: string(utils.MustMarshal(businessHours)), + } + shopStatus := mtpsapi.ShopStatusAuditCreated + if globals.EnableStoreWrite { + shopStatus, err = api.MtpsAPI.ShopCreate(shopInfo) + if err == nil { + vendorStoreID = shopInfo.ShopID + status = getAuditStatus(shopStatus) + } + } else { + vendorStoreID = utils.Int64ToStr(jxutils.GenFakeID()) + status = model.StoreAuditStatusOnline } - } else { - vendorStoreID = utils.Int64ToStr(jxutils.GenFakeID()) - status = model.StoreAuditStatusOnline } return vendorStoreID, status, err } @@ -98,8 +102,8 @@ func (c *DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorSt } result, err := api.MtpsAPI.GetStoreStatus(shopInfo.ShopName) if err == nil { - storeDetail.AuditStatus = mtpsOpenTypeToJx(result.OpenType) - storeDetail.CourierStatus = mtpsOpenTypeToJx2(result.OpenType) + storeDetail.AuditStatus = mtpsOpenTypeToJx(result.DataList[0].OpenType) + storeDetail.CourierStatus = mtpsOpenTypeToJx2(result.DataList[0].OpenType) } } return storeDetail, err @@ -133,7 +137,16 @@ func (c *DeliveryHandler) IsErrStoreExist(err error) bool { func (c *DeliveryHandler) UpdateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (err error) { if globals.EnableStoreWrite { - err = api.MtpsAPI.PagePoiUpdate(storeDetail.VendorStoreID, storeDetail.PayeeName, storeDetail.Tel1, fakeContactEmail) + // err = api.MtpsAPI.PagePoiUpdate(storeDetail.VendorStoreID, storeDetail.PayeeName, storeDetail.Tel1, fakeContactEmail) + shopInfo := &mtpsapi.ShopInfo{ + ShopID: utils.Int2Str(storeDetail.ID), + ContactName: storeDetail.PayeeName, + ContactPhone: storeDetail.Tel1, + ShopAddress: storeDetail.Address, + ShopLat: storeDetail.Lat, + ShopLng: storeDetail.Lng, + } + _, err = api.MtpsAPI.ShopUpdate(shopInfo) } return err } diff --git a/business/partner/delivery/mtps/waybill.go b/business/partner/delivery/mtps/waybill.go index 20c18c817..769896de5 100644 --- a/business/partner/delivery/mtps/waybill.go +++ b/business/partner/delivery/mtps/waybill.go @@ -1,8 +1,13 @@ package mtps import ( + "crypto/sha1" "errors" "fmt" + "net/http" + "net/url" + "sort" + "strings" "time" "git.rosy.net.cn/baseapi/platformapi/mtpsapi" @@ -89,6 +94,7 @@ func (c *DeliveryHandler) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *m case mtpsapi.OrderStatusAccepted: order.DesiredFee, _ = delivery.CalculateBillDeliveryFee(order) // 美团外卖可能会丢失新运单事件,这里补一下 order.Status = model.WaybillStatusAccepted + order.Remark = order.CourierName + "," + order.CourierMobile case mtpsapi.OrderStatusPickedUp: order.Status = model.WaybillStatusDelivering case mtpsapi.OrderStatusDeliverred: @@ -99,9 +105,62 @@ func (c *DeliveryHandler) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *m globals.SugarLogger.Warnf("onWaybillMsg unknown msg:%v", msg) return mtpsapi.SuccessResponse } + order2, _ := partner.CurOrderManager.LoadOrder(order.VendorOrderID, order.OrderVendorID) + // order2, _ := dao.GetSimpleOrder(dao.GetDB(), order.VendorOrderID) + //查不到订单可能就是果园的订单 + if order2 == nil { + c.pushToGy(msg) + return mtpsapi.SuccessResponse + } return mtpsapi.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order), order.VendorStatus) } +func (c *DeliveryHandler) pushToGy(msg *mtpsapi.CallbackOrderMsg) { + cl := http.Client{} + params := make(map[string]interface{}) + params["mt_peisong_id"] = msg.MtPeisongID + params["courier_name"] = msg.CourierName + params["delivery_id"] = msg.DeliveryID + params["appkey"] = msg.AppKey + params["order_id"] = msg.OrderID + params["courier_phone"] = msg.CourierPhone + params["status"] = msg.Status + params["timestamp"] = msg.Timestamp + params["cancel_reason_id"] = msg.CancelReasonId + params["cancel_reason"] = msg.CancelReason + urls := utils.Map2URLValues(params) + sign := signParams(urls) + params["sign"] = sign + globals.SugarLogger.Debugf("pushToGy", utils.Format4Output(msg, false)) + request, err := http.NewRequest(http.MethodPost, "http://callback-jxgy.jxc4.com/mtps/status", strings.NewReader(utils.Map2URLValues(params).Encode())) + if err != nil { + return + } + request.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") + cl.Do(request) +} + +func signParams(params url.Values) string { + keys := make([]string, 0) + for k := range params { + if k != "sign" { + keys = append(keys, k) + } + } + + sort.Strings(keys) + finalStr := "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE" + for _, key := range keys { + valStr := strings.Join(params[key], "") + if valStr != "" { + finalStr += key + valStr + } + } + + // baseapi.SugarLogger.Debug(finalStr) + return fmt.Sprintf("%x", sha1.Sum([]byte(finalStr))) +} + func (c *DeliveryHandler) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) (retVal *model.Waybill) { retVal = &model.Waybill{ VendorWaybillID: msg.MtPeisongID, @@ -132,6 +191,15 @@ func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInf // IDeliveryPlatformHandler func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) { db := dao.GetDB() + if vendorOrgCode, err := dao.GetVendorOrgCode(db, model.VendorIDMTPS, "", model.VendorOrgTypeDelivery); err == nil { + if len(vendorOrgCode) > 0 { + if vendorOrgCode[0].IsOpen == model.YES { + return nil, fmt.Errorf("此平台配送已被系统关闭,暂不发配送 [%v]", vendorOrgCode[0].Comment) + } + } + } else { + return nil, err + } deliveryFee, _, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) if err == nil { if err = delivery.CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee, order, model.VendorIDMTPS); err != nil { @@ -180,7 +248,13 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee // "goods_pickup_info": fmt.Sprintf("%s第%d号单", model.VendorChineseNames[order.VendorID], order.OrderSeq), // "poi_seq": fmt.Sprintf("#%d", order.OrderSeq), // } - billParams.Note = utils.FilterMb4(order.BuyerComment) + // storeTel := "" + // storeID := jxutils.GetSaleStoreIDFromOrder(order) + // storeDeatail, _ := dao.GetStoreDetail(db, storeID, order.VendorID) + // if storeDeatail.Tel2 != "" { + // storeTel = ",门店电话:" + storeDeatail.Tel2 + // } + billParams.Note = utils.FilterMb4("客户电话:" + order.ConsigneeMobile + "," + order.BuyerComment + ",取货失败或配送遇到问题请联系18048531223,禁止未配送直接完成定单!") billParams.GoodsDetail = string(utils.MustMarshal(goods)) billParams.GoodsPickupInfo = fmt.Sprintf("%s第%d号单", model.VendorChineseNames[order.VendorID], order.OrderSeq) billParams.PoiSeq = fmt.Sprintf("#%d", order.OrderSeq) diff --git a/business/partner/partner.go b/business/partner/partner.go index a24968fb8..8106abe66 100644 --- a/business/partner/partner.go +++ b/business/partner/partner.go @@ -71,6 +71,7 @@ var ( CancelWaybillReasonStrSwitch2SelfFailed = "转自送失败" CancelWaybillReasonStrOrderAlreadyFinished = "订单已经结束" CancelWaybillReasonStrActive = "操作由人员主动发起" + CancelWaybillReasonNotInStoreOpenTime = "不在门店的营业时间范围内" ) var ( @@ -105,6 +106,7 @@ type IOrderManager interface { UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error) UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error) + LoadStoreDetail(storeID, vendorID int) (storeDetail *dao.StoreDetail, err error) LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error) OnOrderComments(orderCommentList []*model.OrderComment) (err error) @@ -114,7 +116,7 @@ type IOrderManager interface { GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded, isGetPos bool) (bills []*model.WaybillExt, err error) - ChangeOrderInfo(order *model.GoodsOrder, valid map[string]interface{}) (err error) + ChangeOrderInfo(order *model.GoodsOrder) (err error) // afs order OnAfsOrderAdjust(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error) OnAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error) @@ -127,7 +129,7 @@ type IOrderManager interface { type IStoreManager interface { OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error) - OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int) (err error) + OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int, message string) (err error) } // purchase handler中 @@ -147,7 +149,7 @@ type IPurchasePlatformHandler interface { // Store ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (store *dao.StoreDetail, err error) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) - CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) + CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) diff --git a/business/partner/partner_order.go b/business/partner/partner_order.go index dace71dc7..5d7498973 100644 --- a/business/partner/partner_order.go +++ b/business/partner/partner_order.go @@ -12,7 +12,7 @@ type OrderPhoneNumberInfo struct { type IPurchasePlatformOrderHandler interface { Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) - GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) + GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams) diff --git a/business/partner/partner_printer.go b/business/partner/partner_printer.go index d72388153..faa3d7eca 100644 --- a/business/partner/partner_printer.go +++ b/business/partner/partner_printer.go @@ -3,6 +3,8 @@ package partner import ( "fmt" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" ) @@ -58,7 +60,7 @@ type IPrinterHandler interface { BindPrinter(ctx *jxcontext.Context, mapData map[string]interface{}) (bindResult *BindPrinterResult, err error) RebindPrinter(ctx *jxcontext.Context, lastBindResult *BindPrinterResult) (bindResult *BindPrinterResult, err error) - PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *PrinterStatus, err error) + PrintOrder(ctx *jxcontext.Context, store *model.Store, storeDetail *dao.StoreDetail, order *model.GoodsOrder) (printerStatus *PrinterStatus, err error) EmptyPrintList(ctx *jxcontext.Context, id1, id2 string) (err error) PlayText(ctx *jxcontext.Context, id1, id2, orderID, text string) (printerStatus *PrinterStatus, err error) diff --git a/business/partner/partner_store_acct.go b/business/partner/partner_store_acct.go new file mode 100644 index 000000000..02a574a70 --- /dev/null +++ b/business/partner/partner_store_acct.go @@ -0,0 +1,30 @@ +package partner + +import ( + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + "git.rosy.net.cn/jx-callback/business/model/dao" +) + +const ( + StoreAcctType1 = 1 //主动充值 +) + +var ( + CurStoreAcctManager IStoreAcctManager +) + +func InitStoreAcctManager(curStoreManager IStoreAcctManager) { + CurStoreAcctManager = curStoreManager +} + +type IStoreAcctManager interface { + //增加一条收入流水 + InsertStoreAcctIncome(ctx *jxcontext.Context, db *dao.DaoDB, storeID, price, acctType int) (err error) + //增加一条支出流水 + InsertStoreAcctExpend(ctx *jxcontext.Context, db *dao.DaoDB, storeID, price, acctType int, vendorOrderID string) (err error) + //更新门店账户 + UpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price int, isIncome bool) (err error) + InsertStoreAcctExpendAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int, vendorOrderID string) (err error) + InsertStoreAcctIncomeAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int) (err error) + CheckStoreAcctExpendExist(storeID int, vendorOrderID string) (result bool, err error) +} diff --git a/business/partner/partner_store_sku.go b/business/partner/partner_store_sku.go index 89867ba3c..17854a2ae 100644 --- a/business/partner/partner_store_sku.go +++ b/business/partner/partner_store_sku.go @@ -46,12 +46,15 @@ type StoreSkuInfo struct { Seq int `json:"seq,omitempty"` - ActPrice int64 `json:"actPrice,omitempty"` - VendorActID string `json:"vendorActID,omitempty"` - IsSpecialty int `json:"isSpecialty,omitempty"` - JxPrice int64 `json:"jxPrice,omitempty"` - JxUnitPrice int64 `json:"jxUnitPrice,omitempty"` - VendorSkuID2 string `json:"vendorSkuID2,omitempty"` + ActPrice int64 `json:"actPrice,omitempty"` + VendorActID string `json:"vendorActID,omitempty"` + IsSpecialty int `json:"isSpecialty,omitempty"` + JxPrice int64 `json:"jxPrice,omitempty"` + JxUnitPrice int64 `json:"jxUnitPrice,omitempty"` + VendorSkuID2 string `json:"vendorSkuID2,omitempty"` + JdsStockSwitch int `json:"jdsStockSwitch"` + IsDeletedBySku bool `json:"isDeletedBySku"` + VendorOrgCode string `json:"vendorOrgCode"` } type StoreSkuInfoWithErr struct { diff --git a/business/partner/printer/feie/feie.go b/business/partner/printer/feie/feie.go index 95df6cd28..c940f9b23 100644 --- a/business/partner/printer/feie/feie.go +++ b/business/partner/printer/feie/feie.go @@ -5,6 +5,8 @@ import ( "strings" "time" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/baseapi/platformapi/feieapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" @@ -27,17 +29,30 @@ func init() { partner.RegisterPrinterPlatform(CurPrinterHandler) } -func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) } + orderParams := []interface{}{} getCode := "" if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s

\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -%s

+ orderFmt := `` + if storeDetail != nil { + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` + %s

+ ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + } + orderFmt += ` 手机买菜上京西
极速到家送惊喜
--------------------------------
@@ -62,8 +77,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin 品名 数量 单价 小计
--------------------------------
` // 实际支付:%s
- orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -75,7 +89,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s
` @@ -101,7 +115,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin return fmt.Sprintf(strings.Replace(orderFmt, "\n", "", -1), orderParams...) } -func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -110,8 +124,21 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s

\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -%s

+ orderParams := []interface{}{} + orderFmt := `` + if storeDetail != nil { + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` + %s

+ ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + } + orderFmt += ` 手机买菜上京西
极速到家送惊喜
--------------------------------
@@ -136,8 +163,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st 品名数量单价小计
--------------------------------
` // 实际支付:%s
- orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -149,7 +175,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s
` @@ -208,13 +234,16 @@ func (c *PrinterHandler) GetPrinterStatus(ctx *jxcontext.Context, printerSN, pri return printerStatus, err } -func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { +func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, storeDetail *dao.StoreDetail, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { globals.SugarLogger.Debugf("feie PrintOrderByOrder orderID:%s, storeID:%d", order.VendorOrderID, store.ID) + if len(order.Skus) == 0 { + return + } content := "" if store.PrinterFontSize == partner.PrinterFontSizeBig { - content = c.getOrderContentBig(order, store.Tel1) + content = c.getOrderContentBig(order, store.Tel1, storeDetail) } else { - content = c.getOrderContent(order, store.Tel1) + content = c.getOrderContent(order, store.Tel1, storeDetail) } return c.PrintMsg(ctx, store.PrinterSN, store.PrinterKey, order.VendorOrderID, content) } diff --git a/business/partner/printer/xiaowm/xiaowm.go b/business/partner/printer/xiaowm/xiaowm.go index 036ae90ed..0281451ad 100644 --- a/business/partner/printer/xiaowm/xiaowm.go +++ b/business/partner/printer/xiaowm/xiaowm.go @@ -5,6 +5,8 @@ import ( "strings" "time" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/baseapi/platformapi/xiaowmapi" "git.rosy.net.cn/baseapi/utils" @@ -28,7 +30,7 @@ func init() { partner.RegisterPrinterPlatform(CurPrinterHandler) } -func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -103,7 +105,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin return content } -func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -211,7 +213,7 @@ func (c *PrinterHandler) getOrderContent2(order *model.GoodsOrder, storeTel stri |5 |5 |5商品明细: -|5品名 数量 单价 小计 +|5品名 数量 |5-------------------------------- ` // |6实际支付: %s @@ -231,8 +233,9 @@ func (c *PrinterHandler) getOrderContent2(order *model.GoodsOrder, storeTel stri } for _, sku := range order.Skus { orderFmt += `|5%s` - orderFmt += `|5%8s%10s%10s` - orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count))) + orderFmt += `|5%8s` + orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count)) + // jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count)) } orderFmt += ` |5 @@ -289,16 +292,16 @@ func (c *PrinterHandler) GetPrinterStatus(ctx *jxcontext.Context, printerNumber, return printerStatus, err } -func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { +func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, storeDetail *dao.StoreDetail, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { globals.SugarLogger.Debugf("xiaowm PrintOrderByOrder orderID:%s, storeID:%d", order.VendorOrderID, store.ID) var content string if isV500(store.PrinterSN) { content = c.getOrderContent2(order, store.Tel1) } else { if store.PrinterFontSize == partner.PrinterFontSizeBig { - content = c.getOrderContentBig(order, store.Tel1) + content = c.getOrderContentBig(order, store.Tel1, storeDetail) } else { - content = c.getOrderContent(order, store.Tel1) + content = c.getOrderContent(order, store.Tel1, storeDetail) } } return c.PrintMsg(ctx, store.PrinterSN, store.PrinterKey, order.VendorOrderID, content) diff --git a/business/partner/printer/yilianyun/yilianyun.go b/business/partner/printer/yilianyun/yilianyun.go index f9036496f..1241812aa 100644 --- a/business/partner/printer/yilianyun/yilianyun.go +++ b/business/partner/printer/yilianyun/yilianyun.go @@ -10,6 +10,7 @@ import ( "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" "git.rosy.net.cn/jx-callback/globals/api" @@ -27,7 +28,7 @@ func init() { partner.RegisterPrinterPlatform(CurPrinterHandler) } -func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -36,8 +37,21 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s\\n\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -
%s
\n\n + orderParams := []interface{}{} + orderFmt := `` + if storeDetail != nil { + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` +
%s
\n\n + ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + } + orderFmt += `
手机买菜上京西
极速到家送惊喜
\n -------------------------------- @@ -60,8 +74,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin 品名 数量 单价 小计\n --------------------------------\n` // 实际支付:%s\n - orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -73,7 +86,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s\n` @@ -95,7 +108,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin return strings.Replace(fmt.Sprintf(strings.Replace(orderFmt, "\n", "", -1), orderParams...), "\\n", "\r\n", -1) } -func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -104,8 +117,21 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s\\n\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -
%s
\n\n + orderParams := []interface{}{} + orderFmt := `` + if storeDetail != nil { + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` +
%s
\n\n + ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + } + orderFmt += `
手机买菜上京西
极速到家送惊喜
\n -------------------------------- @@ -128,8 +154,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st 品名数量单价小计\n --------------------------------\n` // 实际支付:%s\n - orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -141,7 +166,7 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s\n` @@ -201,13 +226,16 @@ func (c *PrinterHandler) GetPrinterStatus(ctx *jxcontext.Context, machineCode, p return printerStatus, err } -func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { +func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, storeDetail *dao.StoreDetail, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { globals.SugarLogger.Debugf("yilianyun PrintOrderByOrder orderID:%s, storeID:%d", order.VendorOrderID, store.ID) + if len(order.Skus) == 0 { + return + } content := "" if store.PrinterFontSize == partner.PrinterFontSizeBig { - content = c.getOrderContentBig(order, store.Tel1) + content = c.getOrderContentBig(order, store.Tel1, storeDetail) } else { - content = c.getOrderContent(order, store.Tel1) + content = c.getOrderContent(order, store.Tel1, storeDetail) } return c.PrintMsg(ctx, store.PrinterSN, store.PrinterKey, order.VendorOrderID, content) } diff --git a/business/partner/printer/zhongwu/zhongwu.go b/business/partner/printer/zhongwu/zhongwu.go index 312c8979f..c16bb59bc 100644 --- a/business/partner/printer/zhongwu/zhongwu.go +++ b/business/partner/printer/zhongwu/zhongwu.go @@ -11,6 +11,7 @@ import ( "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" "git.rosy.net.cn/jx-callback/globals/api" @@ -28,7 +29,7 @@ func init() { partner.RegisterPrinterPlatform(CurPrinterHandler) } -func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -37,8 +38,21 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -%s + orderParams := []interface{}{} + orderFmt := `` + if storeDetail != nil { + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` + %s + ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + } + orderFmt += ` 手机买菜上京西 极速到家送惊喜 ******************************** @@ -58,11 +72,10 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin 商品明细: -品名 数量 单价 小计 +品名 数量 ********************************` // 实际支付:%s - orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -74,12 +87,13 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s` - orderFmt += `%8s%10s%10s` - orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count))) + orderFmt += `%8s` + orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count)) + //jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count)) } orderFmt += ` 共%d种%d件商品 @@ -96,7 +110,7 @@ func (c *PrinterHandler) getOrderContent(order *model.GoodsOrder, storeTel strin return fmt.Sprintf(strings.Replace(orderFmt, "\n", "", -1), orderParams...) } -func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string) (content string) { +func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { expectedDeliveryTime = order.OrderCreatedAt.Add(1 * time.Hour) @@ -105,8 +119,19 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st if order.VendorID == model.VendorIDEBAI { getCode = fmt.Sprintf("饿百取货码:%s\n", jxutils.GetEbaiOrderGetCode(order)) } - orderFmt := ` -%s + orderParams := []interface{}{} + orderFmt := `` + if storeDetail.BrandIsPrint == model.NO { + orderFmt += ` + %s + ` + if order.VendorOrgCode == "34665" { + orderParams = append(orderParams, globals.StoreNameEbai2) + } else { + orderParams = append(orderParams, storeDetail.BrandName) + } + } + orderFmt += ` 手机买菜上京西 极速到家送惊喜 ******************************** @@ -126,11 +151,10 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st 商品明细: -品名数量单价小计 +品名 数量 ********************************` // 实际支付:%s - orderParams := []interface{}{ - globals.StoreName, + orderParams = append(orderParams, utils.Time2Str(order.OrderCreatedAt), utils.Time2Str(expectedDeliveryTime), order.VendorOrderID, @@ -142,12 +166,13 @@ func (c *PrinterHandler) getOrderContentBig(order *model.GoodsOrder, storeTel st order.ConsigneeAddress, order.BuyerComment, // jxutils.IntPrice2StandardCurrencyString(order.ActualPayPrice), - } + ) for _, sku := range order.Skus { orderFmt += `%s` - orderFmt += `%s %s %s` - orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count))) + orderFmt += `%s` + orderParams = append(orderParams, sku.SkuName, "x"+utils.Int2Str(sku.Count)) + //jxutils.IntPrice2StandardCurrencyString(sku.SalePrice), jxutils.IntPrice2StandardCurrencyString(sku.SalePrice*int64(sku.Count)) } orderFmt += ` 共%d种%d件商品 @@ -194,13 +219,13 @@ func (c *PrinterHandler) GetPrinterStatus(ctx *jxcontext.Context, deviceID, devi return printerStatus, err } -func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { +func (c *PrinterHandler) PrintOrder(ctx *jxcontext.Context, store *model.Store, storeDetail *dao.StoreDetail, order *model.GoodsOrder) (printerStatus *partner.PrinterStatus, err error) { globals.SugarLogger.Debugf("zhongwu PrintOrderByOrder orderID:%s, storeID:%d", order.VendorOrderID, store.ID) content := "" if store.PrinterFontSize == partner.PrinterFontSizeBig { - content = c.getOrderContentBig(order, store.Tel1) + content = c.getOrderContentBig(order, store.Tel1, storeDetail) } else { - content = c.getOrderContent(order, store.Tel1) + content = c.getOrderContent(order, store.Tel1, storeDetail) } return c.PrintMsg(ctx, store.PrinterSN, store.PrinterKey, order.VendorOrderID, content) } diff --git a/business/partner/purchase/ebai/act.go b/business/partner/purchase/ebai/act.go index beda910c4..b7838419a 100644 --- a/business/partner/purchase/ebai/act.go +++ b/business/partner/purchase/ebai/act.go @@ -84,7 +84,7 @@ func act2EbaiActivity(act *model.Act2, actOrderRules []*model.ActOrderRule) (act ActivityDesc: act.Advertising, ShowCategory: model.ActTypeName[act.Type], PromotionSkuDesc: utils.LimitMixedStringLen(act.Advertising, ebaiapi.MaxActivityDescLength), - DayLimit: act.LimitDaily, + DayLimit: 1, ActivityPlatform: ebaiapi.ActivityPFAll, } if act.LimitCount > 0 { diff --git a/business/partner/purchase/ebai/ebai.go b/business/partner/purchase/ebai/ebai.go index 3a222d025..04d3de1ff 100644 --- a/business/partner/purchase/ebai/ebai.go +++ b/business/partner/purchase/ebai/ebai.go @@ -13,6 +13,22 @@ import ( "git.rosy.net.cn/jx-callback/globals/api" ) +const ( + EbaiSupplierIDsc = "1921188187760" + EbaiSupplierIDc4 = "22267134648" + EbaiSupplierIDhc = "2233065879" + EbaiSupplierIDgy = "2267230126" +) + +var ( + EbaiSupplierIDMap = map[string]string{ + EbaiSupplierIDsc: "饿百商超", + EbaiSupplierIDc4: "饿百菜市", + EbaiSupplierIDhc: "饿百好菜", + EbaiSupplierIDgy: "饿百果园", + } +) + var ( CurPurchaseHandler *PurchaseHandler ) diff --git a/business/partner/purchase/ebai/order.go b/business/partner/purchase/ebai/order.go index 067fbeb2d..e1fa80c26 100644 --- a/business/partner/purchase/ebai/order.go +++ b/business/partner/purchase/ebai/order.go @@ -6,9 +6,10 @@ import ( "strings" "time" + "github.com/astaxie/beego" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" - "git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/platformapi/ebaiapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" @@ -24,7 +25,7 @@ import ( const ( // acceptOrderDelay = 180 * time.Second // pickupOrderDelay = 260 * time.Second - pickupOrderDelay = 1 * time.Second + pickupOrderDelay = 1 * time.Minute callDeliveryDelay = 10 * time.Minute callDeliveryDelayGap = 30 @@ -38,8 +39,8 @@ const ( var ( VendorStatus2StatusMap = map[string]int{ - ebaiapi.CmdOrderCreate: model.OrderStatusNew, - ebaiapi.OrderStatusNew: model.OrderStatusNew, + ebaiapi.CmdOrderCreate: model.OrderStatusWaitAccepted, + ebaiapi.OrderStatusNew: model.OrderStatusWaitAccepted, fakeAcceptOrder: model.OrderStatusAccepted, ebaiapi.OrderStatusAccepted: model.OrderStatusFinishedPickup, ebaiapi.OrderStatusCourierAccepted: model.OrderStatusDelivering, @@ -80,7 +81,7 @@ func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int { return model.OrderStatusUnknown } -func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) { +func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) { order, _, err = p.getOrder(vendorOrderID) return order, err } @@ -134,6 +135,7 @@ func (p *PurchaseHandler) GetOrder4PartRefund(vendorOrderID string) (order *mode order.DiscountMoney = discountMoney order.Skus = append(order.Skus, giftSkus...) order.ActualPayPrice = utils.MustInterface2Int64(result2["user_fee"]) + order.TotalShopMoney = utils.MustInterface2Int64(result2["shop_fee"]) jxutils.RefreshOrderSkuRelated(order) } else if err2Ext, ok := err2.(*utils.ErrorWithCode); !ok || err2Ext.IntCode() != ebaiapi.ErrOrderIsNotPartRefund { err = err2 @@ -217,7 +219,7 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo ConsigneeName: utils.Interface2String(userMap["name"]), ConsigneeMobile: jxutils.FormalizeMobile(utils.Interface2String(userMap["phone"])), ConsigneeAddress: utils.Interface2String(userMap["address"]), - CoordinateType: model.CoordinateTypeBaiDu, + CoordinateType: model.CoordinateTypeMars, BuyerComment: utils.TrimBlankChar(utils.Interface2String(orderMap["remark"])), ExpectedDeliveredTime: getExpectedDeliveredTime(orderMap), PickDeadline: utils.DefaultTimeValue, @@ -268,12 +270,12 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo deliveryGeo := userMap["coord_amap"].(map[string]interface{}) originalLng := utils.Interface2Float64WithDefault(deliveryGeo["longitude"], 0.0) // 饿百的订单在过一段时间后,经纬度信息会变成字符串"**" originalLat := utils.Interface2Float64WithDefault(deliveryGeo["latitude"], 0.0) - lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysBaidu) - if err2 == nil { - originalLng = lng - originalLat = lat - order.CoordinateType = model.CoordinateTypeMars - } + // lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysBaidu) + // if err2 == nil { + // originalLng = lng + // originalLat = lat + // order.CoordinateType = model.CoordinateTypeMars + // } order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng) order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat) @@ -340,6 +342,18 @@ func getSkuSalePrice2(product *ebaiapi.OrderProductInfo) (salePrice, baiduRate i func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { globals.SugarLogger.Debugf("ebai AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) if isAcceptIt { + if globals.EnableEbaiStoreWrite { + err = api.EbaiAPI.OrderConfirm(order.VendorOrderID) + if beego.BConfig.RunMode == "jxgy" { + utils.AfterFuncWithRecover(time.Minute*10, func() { + err = api.EbaiAPI.OrderPickComplete(order.VendorOrderID) + }) + } else { + utils.AfterFuncWithRecover(time.Minute, func() { + err = api.EbaiAPI.OrderPickComplete(order.VendorOrderID) + }) + } + } p.postFakeMsg(order.VendorOrderID, fakeAcceptOrder) } else { if globals.EnableEbaiStoreWrite { @@ -352,8 +366,9 @@ func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { globals.SugarLogger.Debugf("ebai PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery) if globals.EnableEbaiStoreWrite { - err = api.EbaiAPI.OrderConfirm(order.VendorOrderID) - } else { + // err = api.EbaiAPI.OrderPickComplete(order.VendorOrderID) + } + if err == nil { p.postFakeMsg(order.VendorOrderID, ebaiapi.OrderStatusAccepted) } return err @@ -460,7 +475,7 @@ func (c *PurchaseHandler) onOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi. if status.Status == model.OrderStatusDelivering || status.Status == model.OrderStatusFinished { if order, err2 := partner.CurOrderManager.LoadOrder(status.VendorOrderID, status.VendorID); err2 == nil { if order.TotalShopMoney == 0 { - if order2, err2 := c.GetOrder(msg.Source, status.VendorOrderID); err2 == nil { + if order2, err2 := c.GetOrder(msg.Source, status.VendorOrderID, ""); err2 == nil { order.TotalShopMoney = order2.TotalShopMoney order.PmSubsidyMoney = order2.PmSubsidyMoney partner.CurOrderManager.UpdateOrderFields(order, []string{"TotalShopMoney", "PmSubsidyMoney"}) diff --git a/business/partner/purchase/ebai/order_afs.go b/business/partner/purchase/ebai/order_afs.go index d06c917a0..b4f782af6 100644 --- a/business/partner/purchase/ebai/order_afs.go +++ b/business/partner/purchase/ebai/order_afs.go @@ -36,7 +36,7 @@ var ( func (c *PurchaseHandler) isAfsMsg(msg *ebaiapi.CallbackMsg) bool { if msg.Cmd == ebaiapi.CmdOrderPartRefund { msgType := int(utils.MustInterface2Int64(msg.Body["type"])) - return msgType == ebaiapi.OrderPartRefuncTypeCustomer + return msgType == ebaiapi.OrderPartRefuncTypeCustomer || msgType == ebaiapi.OrderPartRefuncTypeCS } else if msg.Cmd == ebaiapi.CmdOrderUserCancel { cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"])) return cancelType == ebaiapi.OrderUserCancelTypeAfterSale @@ -119,7 +119,43 @@ func (c *PurchaseHandler) onAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaia err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) } } else { - err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + if afsOrder2, err := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, orderStatus.VendorID); afsOrder2 == nil && err == nil { + partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo) + afsOrder := &model.AfsOrder{ + VendorID: model.VendorIDEBAI, + AfsOrderID: orderStatus.VendorOrderID, + VendorOrderID: orderStatus.RefVendorOrderID, + VendorStoreID: "", + StoreID: 0, + AfsCreatedAt: utils.Timestamp2Time(msg.Timestamp), + VendorAppealType: "", + AppealType: model.AfsAppealTypeRefund, + VendorReasonType: partRefundData.ReasonType, + ReasonType: c.convertAfsReasonType(partRefundData.ReasonType), + ReasonDesc: utils.LimitUTF8StringLen(buildFullReason(partRefundData.Reason, partRefundData.AdditionReason), 1024), + ReasonImgList: utils.LimitUTF8StringLen(strings.Join(partRefundData.Photos, ","), 1024), + RefundType: model.AfsTypePartRefund, + VendorOrgCode: msg.Source, + } + for _, sku := range partRefundData.RefundProducts { + orderSku := &model.OrderSkuFinancial{ + Count: sku.Number, + VendorSkuID: sku.SkuID, + SkuID: int(utils.Str2Int64WithDefault(sku.CustomSkuID, 0)), + Name: sku.Name, + UserMoney: sku.TotalRefund, + PmSkuSubsidyMoney: sku.ShopEleRefund, + } + afsOrder.SkuUserMoney += orderSku.UserMoney + afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney + afsOrder.Skus = append(afsOrder.Skus, orderSku) + } + if afsOrder != nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } + } else { + err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + } } retVal = api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil) } @@ -204,10 +240,24 @@ func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, ord // 发起全款退款 func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - return fmt.Errorf("%s不支持售后全额退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDEBAI]) + return c.PartRefundOrder(ctx, order, order.Skus, reason) } // 发起部分退款 func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { - return fmt.Errorf("%s不支持售后部分退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDEBAI]) + if globals.EnableEbaiStoreWrite { + err = api.EbaiAPI.OrderPartRefund(order.VendorOrderID, orderSkus2AfsSkus(refundSkuList)) + } + return err +} + +func orderSkus2AfsSkus(refundSkuList []*model.OrderSku) (removeSkuList []*ebaiapi.RefundSku) { + for _, v := range refundSkuList { + refundSku := &ebaiapi.RefundSku{ + CustomeSkuID: utils.Int2Str(v.SkuID), + Number: utils.Int2Str(v.Count), + } + removeSkuList = append(removeSkuList, refundSku) + } + return removeSkuList } diff --git a/business/partner/purchase/ebai/store.go b/business/partner/purchase/ebai/store.go index 4ae71f077..b48985dae 100644 --- a/business/partner/purchase/ebai/store.go +++ b/business/partner/purchase/ebai/store.go @@ -18,6 +18,99 @@ import ( "git.rosy.net.cn/jx-callback/globals/api" ) +type tEbaiSupplierInfo struct { + SupplierID string `json:"supplierID"` + Logo string `json:"logo"` + Categorys []map[string]interface{} + BusinessFormID int //门店业态 + BrandName string +} + +var ( + EbaiSupplierInfo = map[string]*tEbaiSupplierInfo{ + EbaiSupplierIDsc: &tEbaiSupplierInfo{ + SupplierID: EbaiSupplierIDsc, + Logo: "https://image-star.elemecdn.com/pb/dab294b0d3e9fa4b5fa63007ff02d06e98", + Categorys: []map[string]interface{}{ + map[string]interface{}{ + "category1": 166, + "category2": 222, + }, + }, + BusinessFormID: 1672214913, + BrandName: "京西到家", + }, + EbaiSupplierIDhc: &tEbaiSupplierInfo{ + SupplierID: EbaiSupplierIDhc, + Logo: "https://fuss10.elemecdn.com/1/ce/e94124a856ea83d733832ca05b269jpeg.jpeg", + Categorys: []map[string]interface{}{ + map[string]interface{}{ + "category1": 277, + "category2": 180, + }, + map[string]interface{}{ + "category1": 277, + "category2": 184, + }, + map[string]interface{}{ + "category1": 277, + "category2": 183, + }, + map[string]interface{}{ + "category1": 277, + "category2": 181, + }, + map[string]interface{}{ + "category1": 277, + "category2": 182, + }, + }, + BusinessFormID: 1917869373, + BrandName: "好菜鲜生", + }, + EbaiSupplierIDc4: &tEbaiSupplierInfo{ + SupplierID: EbaiSupplierIDc4, + Logo: "https://fuss10.elemecdn.com/1/34/c6d76d8e3aa86cf214e6bff5514c1jpeg.jpeg", + Categorys: []map[string]interface{}{ + map[string]interface{}{ + "category1": 277, + "category2": 180, + }, + map[string]interface{}{ + "category1": 277, + "category2": 184, + }, + map[string]interface{}{ + "category1": 277, + "category2": 183, + }, + map[string]interface{}{ + "category1": 277, + "category2": 181, + }, + map[string]interface{}{ + "category1": 277, + "category2": 182, + }, + }, + BusinessFormID: 1917869373, + BrandName: "京西菜市", + }, + EbaiSupplierIDgy: &tEbaiSupplierInfo{ + SupplierID: EbaiSupplierIDgy, + Logo: "https://fuss10.elemecdn.com/7/21/a4b2877a916e1af6c5bdbf5945d51jpeg.jpeg", + Categorys: []map[string]interface{}{ + map[string]interface{}{ + "category1": 274, + "category2": 190, + }, + }, + BusinessFormID: 1917867465, + BrandName: "京西果园", + }, + } +) + type tEbaiStoreInfo struct { model.Store VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 @@ -30,6 +123,7 @@ type tEbaiStoreInfo struct { CityID int `orm:"column(city_id)"` DistrictID int `orm:"column(district_id)"` VendorStoreName string + BrandName string } func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { @@ -151,9 +245,11 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin SELECT t1.*, t2.status ebai_store_status, t2.vendor_store_id, t2.vendor_org_code, - IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, t2.sync_status, t2.vendor_store_name + IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, t2.sync_status, t2.vendor_store_name, + t3.name brand_name FROM store t1 JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?) + LEFT JOIN brand t3 ON t3.id = t1.brand_id WHERE t1.id = ? ORDER BY t2.updated_at ` @@ -390,6 +486,7 @@ func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} { phone = model.VendorStoreTel } params["ivr_phone"] = phone //统一改为这个电话 + if store.VendorStoreID != "" { params["baidu_shop_id"] = store.VendorStoreID } @@ -397,12 +494,16 @@ func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} { if store.VendorStoreName != "" { params["name"] = store.VendorStoreName } else { - params["name"] = jxutils.ComposeStoreName(store.Name, model.VendorIDEBAI) + if store.BrandID != 1 { + params["name"] = store.Name + } else { + params["name"] = jxutils.ComposeStoreName(store.Name, model.VendorIDEBAI) + } } } boxFee, _ := dao.GetSysConfigAsInt64(dao.GetDB(), model.ConfigSysEbaiBoxFee) params["package_box_price"] = boxFee - + params["service_phone"] = store.Tel1 params["address"] = store.Address // todo 饿百 开店审核通过后不允许修改商户信息 if store.SyncStatus&(model.SyncFlagNewMask /*|model.SyncFlagStoreAddress*/) != 0 { @@ -542,10 +643,215 @@ func (c *PurchaseHandler) GetShopIDsByPage() (vendorStoreIDs []string, err error return vendorStoreIDs, err } -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { +func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { + param := make(map[string]interface{}) + param["shop_id"] = utils.Int2Str(storeID) + // param["supplier_id"] = params["supplierID"] + param["supplier_id"] = params["supplierID"].(string) + + //省市区 + placeCity, err := dao.GetPlaceByCode(db, storeDetail.CityCode) + param["city"] = placeCity.EbaiCode + placeProvince, err := dao.GetPlaceByCode(db, placeCity.ParentCode) + param["province"] = placeProvince.EbaiCode + placeCounty, err := dao.GetPlaceByCode(db, storeDetail.DistrictCode) + param["county"] = placeCounty.EbaiCode + + phone := "" + if storeDetail.MarketManPhone != "" { + phone = storeDetail.MarketManPhone + } else { + phone = model.VendorStoreTel + } + ebaiInfo := EbaiSupplierInfo[params["supplierID"].(string)] + param["name"] = params["vendorStoreName"] + param["phone"] = phone + param["ivr_phone"] = phone + param["service_phone"] = storeDetail.Tel1 + // param["phone"] = "18160030913" + // param["ivr_phone"] = "18160030913" + // param["service_phone"] = "18160030913" + param["address"] = storeDetail.Address + param["longitude"] = jxutils.IntCoordinate2Standard(storeDetail.Lng) + param["latitude"] = jxutils.IntCoordinate2Standard(storeDetail.Lat) + param["coord_type"] = "amap" //高德坐标系 + param["shop_logo"] = ebaiInfo.Logo + param["categorys"] = ebaiInfo.Categorys + time1map := map[string]string{ + "start": jxutils.JxOperationTime2StrTime(storeDetail.OpenTime1), + "end": jxutils.JxOperationTime2StrTime(storeDetail.CloseTime1), + } + var time2map = make(map[string]string) + if storeDetail.OpenTime2 != 0 && storeDetail.CloseTime2 != 0 { + time2map["start"] = jxutils.JxOperationTime2StrTime(storeDetail.OpenTime2) + time2map["end"] = jxutils.JxOperationTime2StrTime(storeDetail.CloseTime2) + } + var timeLis []map[string]string + timeLis = append(timeLis, time1map) + if len(time2map) > 0 { + timeLis = append(timeLis, time2map) + } + param["business_time"] = timeLis + param["business_form_id"] = ebaiInfo.BusinessFormID + if baiduShopID, err2 := api.EbaiAPI.ShopCreate(param); err2 == nil { + //上传资质 + + return utils.Int64ToStr(baiduShopID), nil + } else { + err = err2 + } return vendorStoreID, err } func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) { return err } + +func (c *PurchaseHandler) SyncQualify(ctx *jxcontext.Context, storeDetail *dao.StoreDetail) (err error) { + if storeDetail.LicenceCode == "" || storeDetail.Licence == "" { + return fmt.Errorf("营业执照信息不全, [%v]", storeDetail.ID) + } + if storeDetail.IDCode == "" || storeDetail.IDCardFront == "" || storeDetail.IDCardBack == "" || storeDetail.IDValid == "" { + return fmt.Errorf("个人信息不全, [%v]", storeDetail.ID) + } + if storeDetail.StoreFrontPic == "" || storeDetail.StoreInPic == "" { + return fmt.Errorf("门面门店照不全!, [%v]", storeDetail.ID) + } + if storeDetail.EbaiSupplierID == EbaiSupplierIDsc { + if storeDetail.Licence2Code == "" || storeDetail.Licence2Image == "" { + return fmt.Errorf("食品经营许可证不全, [%v]", storeDetail.ID) + } + } + + //营业执照 + licenceMap := make(map[string]interface{}) + licenceMap["type_1"] = 1 + licenceMap["type_2"] = 101 + licenceMap["license_number"] = storeDetail.LicenceCode + licenceMap["license_address"] = storeDetail.LicenceAddress + licenceMap["legal_representative_name"] = storeDetail.LicenceOwnerName + licenceMap["license_name"] = storeDetail.LicenceCorpName + licence, _ := api.EbaiAPI.PictureUpload(storeDetail.Licence, nil) + licenceMap["photos"] = []map[string]interface{}{ + map[string]interface{}{ + "photo_url": licence, + "waterprinter_url": licence, + }, + } + if storeDetail.LicenceExpire == "" { + licenceMap["long_term_valid"] = 1 + } else { + if storeDetail.LicenceValid != "" { + if utils.Str2Time(storeDetail.LicenceExpire).Sub(utils.Str2Time(storeDetail.LicenceValid)) > 0 { + licenceMap["license_validdate"] = storeDetail.LicenceExpire + } else { + licenceMap["license_validdate"] = storeDetail.LicenceValid + } + } else { + licenceMap["license_validdate"] = storeDetail.LicenceExpire + } + } + + licence2Map := make(map[string]interface{}) + if storeDetail.EbaiSupplierID == EbaiSupplierIDsc { + //食品经营许可证 + licence2Map["type_1"] = 2 + licence2Map["type_2"] = 202 + licence2Map["license_number"] = storeDetail.Licence2Code + licence2Map["license_address"] = storeDetail.LicenceAddress + licence2Map["legal_representative_name"] = storeDetail.LicenceOwnerName + licence2Map["license_name"] = storeDetail.LicenceCorpName + licence2, _ := api.EbaiAPI.PictureUpload(storeDetail.Licence2Image, nil) + licence2Map["photos"] = []map[string]interface{}{ + map[string]interface{}{ + "photo_url": licence2, + "waterprinter_url": licence2, + }, + } + if storeDetail.Licence2Expire == "" { + licence2Map["long_term_valid"] = 1 + } else { + if storeDetail.Licence2Valid != "" { + if utils.Str2Time(storeDetail.Licence2Expire).Sub(utils.Str2Time(storeDetail.Licence2Valid)) > 0 { + licence2Map["license_validdate"] = storeDetail.Licence2Expire + } else { + licence2Map["license_validdate"] = storeDetail.Licence2Valid + } + } else { + licence2Map["license_validdate"] = storeDetail.Licence2Expire + } + } + } + + //身份证 + idMap := make(map[string]interface{}) + idMap["type_1"] = 3 + idMap["type_2"] = 301 + idMap["license_number"] = storeDetail.IDCode + idMap["legal_representative_name"] = storeDetail.IDName + idMap["license_name"] = storeDetail.IDName + idCardFront, _ := api.EbaiAPI.PictureUpload(storeDetail.IDCardFront, nil) + idCardBack, _ := api.EbaiAPI.PictureUpload(storeDetail.IDCardBack, nil) + idCardHand, _ := api.EbaiAPI.PictureUpload(storeDetail.IDCardHand, nil) + + // idCardFront, _ := api.EbaiAPI.PictureUpload("http://image.jxc4.com/image/db790784e3a06202d00706c3141035dd.jpg", nil) + // idCardBack, _ := api.EbaiAPI.PictureUpload("http://image.jxc4.com/image/45a7aae6758edb33f5dc2656358b1afb.jpg", nil) + // idCardHand, _ := api.EbaiAPI.PictureUpload("http://image.jxc4.com/image/2d47385bbcb211bb08c8c0b76f5b7a21.jpg", nil) + idMap["photos"] = []map[string]interface{}{ + map[string]interface{}{ + "photo_url": idCardFront, + "waterprinter_url": idCardFront, + }, + map[string]interface{}{ + "photo_url": idCardBack, + "waterprinter_url": idCardBack, + }, + map[string]interface{}{ + "photo_url": idCardHand, + "waterprinter_url": idCardHand, + }, + } + if storeDetail.IDExpire == "" { + idMap["long_term_valid"] = 1 + } else { + if storeDetail.Licence2Valid != "" { + if utils.Str2Time(storeDetail.IDExpire).Sub(utils.Str2Time(storeDetail.IDValid)) > 0 { + idMap["license_validdate"] = storeDetail.IDExpire + } else { + idMap["license_validdate"] = storeDetail.IDValid + } + } else { + idMap["license_validdate"] = storeDetail.IDExpire + } + } + params := make(map[string]interface{}) + storeFrontPic, _ := api.EbaiAPI.PictureUpload(storeDetail.StoreFrontPic, nil) + storeInPic, _ := api.EbaiAPI.PictureUpload(storeDetail.StoreInPic, nil) + maps := []map[string]interface{}{ + licenceMap, idMap, map[string]interface{}{ + "type_1": 5, + "type_2": 501, + "photos": []map[string]interface{}{ + map[string]interface{}{ + "photo_url": storeFrontPic, + "waterprinter_url": storeFrontPic, + }, + }, + }, map[string]interface{}{ + "type_1": 5, + "type_2": 502, + "photos": []map[string]interface{}{ + map[string]interface{}{ + "photo_url": storeInPic, + "waterprinter_url": storeInPic, + }, + }, + }, + } + if storeDetail.EbaiSupplierID == EbaiSupplierIDsc { + maps = append(maps, licence2Map) + } + params["aptitude"] = maps + err = api.EbaiAPI.ShopAptitudeUpload("", utils.Str2Int64(storeDetail.VendorStoreID), params) + return err +} diff --git a/business/partner/purchase/ebai/store_sku2.go b/business/partner/purchase/ebai/store_sku2.go index be00e1a67..9bd96fbf8 100644 --- a/business/partner/purchase/ebai/store_sku2.go +++ b/business/partner/purchase/ebai/store_sku2.go @@ -28,6 +28,84 @@ var ( 175: "赠品专区", 18: "烧烤吧台", } + + //果园果切的饿百分类ID + gygqVendorCatID = map[int]int{ + 201227732: 1, + 201220933: 1, + 201223525: 1, + 201220334: 1, + } + + ebaiExSkuCatMap3 = map[int]int{ + 35062: 1, + 34759: 1, + 6042855: 1, + 6041992: 1, + 27259: 1, + 6046862: 1, + 6046864: 1, + } + + ebaiExSkuCatMap2 = map[int]int{ + 6046399: 1, + 6046283: 1, + 23001: 1, + 30768: 1, + 24037: 1, + 24838: 1, + 35052: 1, + 30859: 1, + 28490: 1, + 6040798: 1, + 6046267: 1, + 31029: 1, + 35508: 1, + 33727: 1, + } + + ebaiExSkuCatMap = map[int]int{ + 32576: 1, + 22856: 1, + 35231: 1, + 30593: 1, + 6045151: 1, + 6046299: 1, + 31237: 1, + 28854: 1, + 29605: 1, + 26330: 1, + 6045121: 1, + 6045448: 1, + 30629: 1, + 6045163: 1, + 30876: 1, + 6041954: 1, + 23814: 1, + 6045621: 1, + 33298: 1, + 27136: 1, + 6043711: 1, + 30822: 1, + 25019: 1, + 30704: 1, + 30644: 1, + 23868: 1, + 26049: 1, + 30635: 1, + 6045955: 1, + 30672: 1, + 30641: 1, + 6045863: 1, + 30781: 1, + 6046413: 1, + 30686: 1, + 34417: 1, + 30611: 1, + 23065: 1, + 30676: 1, + 30706: 1, + } ) func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { @@ -76,7 +154,7 @@ func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) { } func getCheckExdStoreNameAndSeq(storeID int, storeCat *dao.SkuStoreCatInfo) (name string, seq int, isCheck bool) { - store, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDEBAI) + store, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDEBAI, "") if err != nil || store == nil { return storeCat.Name, storeCat.Seq, false } @@ -154,10 +232,12 @@ func (p *PurchaseHandler) updateStoreSkus(ctx *jxcontext.Context, storeID int, v if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品基础信息") } - if isNeedMapCat && !isExd { - utils.CallFuncAsync(func() { - api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku)) - }) + if ebaiExSkuCatMap[storeSku.SkuID] == 0 && ebaiExSkuCatMap2[storeSku.SkuID] == 0 && ebaiExSkuCatMap3[storeSku.SkuID] == 0 { + if isNeedMapCat && !isExd { + utils.CallFuncAsync(func() { + api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku)) + }) + } } err = nil } @@ -316,10 +396,16 @@ func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrg } func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate, isExd bool) (params map[string]interface{}) { + var img string + if storeSku.ImgMix != "" && ((storeSku.BrandID == storeSku.ExBrandID && storeSku.ExBrandID != 0) || storeSku.ExBrandID == 0) { + img = storeSku.ImgMix + } else { + img = storeSku.Img + } photos := []map[string]interface{}{ map[string]interface{}{ "is_master": true, - "url": storeSku.Img, + "url": img, }, } if storeSku.Img2 != "" { @@ -328,17 +414,53 @@ func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate, isE "url": storeSku.Img2, }) } + if storeSku.Img3 != "" { + photos = append(photos, map[string]interface{}{ + "is_master": false, + "url": storeSku.Img3, + }) + } params = map[string]interface{}{ // "name": utils.LimitMixedStringLen(storeSku.SkuName, ebaiapi.MaxSkuNameByteCount), "left_num": model.MaxStoreSkuStockQty, // "category_id": utils.Str2Int64(storeSku.VendorCatID), "predict_cat": 0, // 不使用推荐类目 // "cat3_id": getEbaiCat(storeSku.VendorVendorCatID), - "weight": storeSku.Weight, - "photos": photos, + "weight": storeSku.Weight, + "photos": photos, + "preparation_time": storeSku.PreparationTime, } if !isExd { - params["category_id"] = utils.Str2Int64(storeSku.VendorCatID) + var categoryID = utils.Str2Int64(storeSku.VendorCatID) + if ebaiExSkuCatMap[storeSku.SkuID] != 0 { + if store, err := dao.GetStoreDetail(dao.GetDB(), storeSku.StoreID, model.VendorIDEBAI, ""); err == nil && store != nil { + if store.CityCode == 510100 { + if s, err2 := dao.GetStoreSkuCategoryMap(dao.GetDB(), 439, storeSku.StoreID); err2 == nil && s != nil { + categoryID = s.EbaiID + } + } + } + + } + if ebaiExSkuCatMap2[storeSku.SkuID] != 0 { + if store, err := dao.GetStoreDetail(dao.GetDB(), storeSku.StoreID, model.VendorIDEBAI, ""); err == nil && store != nil { + if store.CityCode == 510100 { + if s, err2 := dao.GetStoreSkuCategoryMap(dao.GetDB(), 440, storeSku.StoreID); err2 == nil && s != nil { + categoryID = s.EbaiID + } + } + } + } + if ebaiExSkuCatMap3[storeSku.SkuID] != 0 { + if store, err := dao.GetStoreDetail(dao.GetDB(), storeSku.StoreID, model.VendorIDEBAI, ""); err == nil && store != nil { + if store.CityCode == 510100 { + if s, err2 := dao.GetStoreSkuCategoryMap(dao.GetDB(), 175, storeSku.StoreID); err2 == nil && s != nil { + categoryID = s.EbaiID + } + } + } + } + params["category_id"] = categoryID params["name"] = utils.LimitMixedStringLen(storeSku.SkuName, ebaiapi.MaxSkuNameByteCount) params["cat3_id"] = getEbaiCat(storeSku.VendorVendorCatID) } else { @@ -347,6 +469,21 @@ func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate, isE params["cat3_id"] = storeSku.ExdCategoryThirdID params["category_id"] = utils.Str2Int64WithDefault(storeSku.VendorCatID, 0) } + //证明是果园的几个果切分类,需要填加工服务 + if gygqVendorCatID[int(storeSku.VendorVendorCatID)] == 1 { + params["process_type"] = model.YES + processDetail := []map[string]interface{}{ + map[string]interface{}{ + "type": "去皮", + "time": 2, + }, + map[string]interface{}{ + "type": "不加工", + "time": 0, + }, + } + params["process_detail"] = processDetail + } if storeSku.DescImg != "" { params["rtf"] = storeSku.DescImg } diff --git a/business/partner/purchase/ebai/waybill.go b/business/partner/purchase/ebai/waybill.go index b8c202914..1005cac19 100644 --- a/business/partner/purchase/ebai/waybill.go +++ b/business/partner/purchase/ebai/waybill.go @@ -5,6 +5,7 @@ import ( "git.rosy.net.cn/baseapi/platformapi/ebaiapi" "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/globals" @@ -50,6 +51,13 @@ func (c *PurchaseHandler) onWaybillMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiap order.CourierName = utils.Interface2String(result["name"]) order.CourierMobile = utils.Interface2String(result["phone"]) } + if order.Status == model.WaybillStatusNew { + order2, _ := partner.CurOrderManager.LoadOrder(order.VendorOrderID, order.WaybillVendorID) + if order2.Status == model.OrderStatusWaitAccepted { + order2.Status = model.OrderStatusNew + scheduler.CurrentScheduler.OnOrderNew(order2, false, false) + } + } } else if order.Status == model.WaybillStatusCanceled { utils.AfterFuncWithRecover(timeout4WaybillCancel, func() { if localOrder, err2 := partner.CurOrderManager.LoadOrder(order.VendorOrderID, model.VendorIDEBAI); err2 == nil { diff --git a/business/partner/purchase/jd/order.go b/business/partner/purchase/jd/order.go index 055ca98d8..660cb2b15 100644 --- a/business/partner/purchase/jd/order.go +++ b/business/partner/purchase/jd/order.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg" + "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" @@ -73,6 +75,7 @@ func (c *PurchaseHandler) updateOrderFinancialInfo(a *jdapi.API, orderID string) if err == nil { if orderSettlement != nil { updateOrderBySettleMent(order, orderSettlement) + globals.SugarLogger.Debugf("updateOrderBySettleMent: %v , %v", order.NewEarningPrice, order.TotalShopMoney) err = partner.CurOrderManager.UpdateOrderFields(order, []string{ /*"WaybillTipMoney", */ "TotalShopMoney", "PmSubsidyMoney", "NewEarningPrice"}) } } @@ -106,6 +109,16 @@ func (c *PurchaseHandler) onOrderMsg(vendorOrgCode string, msg *jdapi.CallbackOr c.onOrderComment2(a, msg) }) } + // if msg.StatusID == jdapi.OrderStatusVenderAgreeCancel { + // order := &model.GoodsOrder{ + // VendorOrgCode: vendorOrgCode, + // VendorOrderID: msg.BillID, + // } + // err2 := c.PickupGoods(order, false, jxcontext.AdminCtx.GetUserName()) + // if err2 != nil { + // globals.SugarLogger.Warnf("京东取消拣货:%v", err2) + // } + // } err := partner.CurOrderManager.OnOrderStatusChanged(vendorOrgCode, status) retVal = jdapi.Err2CallbackResponse(err, status.VendorStatus) } @@ -122,30 +135,55 @@ func (c *PurchaseHandler) OnOrderInfoChangeMsg(vendorOrgCode string, msg *jdapi. } func (c *PurchaseHandler) onOrderInfoChangeMsg(vendorOrgCode string, msg *jdapi.CallbackOrderInfoChangeMsg) (retVal *jdapi.CallbackResponse) { - a := getAPI(vendorOrgCode) - order, _, err := c.getOrder(a, msg.BillID) + db := dao.GetDB() + order, err := dao.GetSimpleOrder(db, msg.BillID) if err == nil { - globals.SugarLogger.Debugf("onOrderInfoChangeMsg orderID:%s", msg.BillID) - valid := orderInfoChangeSet(order, msg) - partner.CurOrderManager.ChangeOrderInfo(order, valid) + globals.SugarLogger.Debugf("onOrderInfoChangeMsg msg:%v", utils.Format4Output(msg, false)) + if msg.BuyerFullAddress != "" { + order.ConsigneeAddress = msg.BuyerFullAddress + } + if msg.BuyerFullName != "" { + order.ConsigneeName = msg.BuyerFullName + } + if msg.BuyerMobile != "" { + order.ConsigneeMobile = msg.BuyerMobile + } + if msg.BuyerLat != "" { + order.ConsigneeLat = jxutils.StandardCoordinate2Int(utils.Str2Float64(msg.BuyerLat)) + } + if msg.BuyerLng != "" { + order.ConsigneeLng = jxutils.StandardCoordinate2Int(utils.Str2Float64(msg.BuyerLng)) + } + if msg.OrderBuyerRemark != "" { + order.BuyerComment = msg.OrderBuyerRemark + } + _, err = dao.UpdateEntity(db, order, "ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeLat", "ConsigneeLng", "BuyerComment") + weixinmsg.NotifyOrderChanged(order) } - return retVal + return jdapi.SuccessResponse } func updateOrderBySettleMent(order *model.GoodsOrder, orderSettlement *jdapi.OrderSettlementInfo) { if orderSettlement != nil { - // order.WaybillTipMoney = orderSettlement.VenderPaidTips order.TotalShopMoney = orderSettlement.SettlementAmount order.PmSubsidyMoney = orderSettlement.PlatOrderGoodsDiscountMoney + orderSettlement.PlatSkuGoodsDiscountMoney if order.TotalShopMoney > 0 { - stores, _ := dao.GetStoreList(dao.GetDB(), []int{order.StoreID}, nil, nil, nil, "") - if len(stores) > 0 { - if stores[0].PayPercentage <= 50 { - order.NewEarningPrice = order.TotalShopMoney * int64((100 - stores[0].PayPercentage/2)) / 100 - } else { - order.NewEarningPrice = order.EarningPrice + if jxutils.GetSaleStoreIDFromOrder(order) != 0 { + storeDetail, err := partner.CurOrderManager.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID) + if storeDetail != nil && err == nil { + jxutils.RefreshOrderEarningPrice2(order, storeDetail.PayPercentage) + } + } else { + order2, err := partner.CurOrderManager.LoadOrder(order.VendorOrderID, order.VendorID) + if order2 != nil && err == nil { + storeDetail, err := partner.CurOrderManager.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order2), order.VendorID) + if storeDetail != nil && err == nil { + jxutils.RefreshOrderEarningPrice2(order, storeDetail.PayPercentage) + } } } + } else { + order.NewEarningPrice = order.EarningPrice } } } @@ -178,11 +216,12 @@ func (c *PurchaseHandler) getOrder(a *jdapi.API, orderID string) (order *model.G _, err = task.GetResult(0) if order != nil && orderSettlement != nil { updateOrderBySettleMent(order, orderSettlement) + err = partner.CurOrderManager.UpdateOrderFields(order, []string{"NewEarningPrice"}) } return order, orderMap, err } -func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) { +func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID, vendorStoreID string) (order *model.GoodsOrder, err error) { order, _, err = c.getOrder(getAPI(vendorOrgCode), orderID) return order, err } @@ -209,6 +248,11 @@ func Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { if result[statusTimeField] == nil { // 814560888003021 orderPurchaseTime为空 statusTimeField = "orderStartTime" } + //物竞天择订单备注改一下 + comment := utils.TrimBlankChar(utils.Interface2String(result["orderBuyerRemark"])) + if strings.Contains(comment, "【JD】") { + comment += "【京东商城】" + } order = &model.GoodsOrder{ VendorOrderID: orderID, VendorID: model.VendorIDJD, @@ -220,7 +264,7 @@ func Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { ConsigneeMobile: jxutils.FormalizeMobile(utils.Interface2String(result["buyerMobile"])), ConsigneeAddress: utils.Interface2String(result["buyerFullAddress"]), CoordinateType: model.CoordinateTypeMars, - BuyerComment: utils.TrimBlankChar(utils.Interface2String(result["orderBuyerRemark"])), + BuyerComment: comment, ExpectedDeliveredTime: utils.Str2TimeWithDefault(utils.Interface2String(result["orderPreEndDeliveryTime"]), utils.DefaultTimeValue), PickDeadline: utils.Str2TimeWithDefault(utils.Interface2String(result["pickDeadline"]), utils.DefaultTimeValue), // 813951615000022 pickDeadline为空 VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(result["orderStatus"])), @@ -388,6 +432,12 @@ func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bo } else { c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.OrderStatusFinishedPickup) } + if err == nil { + orderSettlement, _ := getAPI(order.VendorOrgCode).OrderShoudSettlementService2(order.VendorOrderID) + updateOrderBySettleMent(order, orderSettlement) + globals.SugarLogger.Debugf("jd PickupGoods, %v", order.NewEarningPrice) + err = partner.CurOrderManager.UpdateOrderFields(order, []string{"NewEarningPrice"}) + } return err } @@ -419,7 +469,7 @@ func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName s if err != nil { if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 { globals.SugarLogger.Infof("Swtich2SelfDeliver failed with error:%v try get current status", err) - if order2, err2 := c.GetOrder(order.VendorOrgCode, order.VendorOrderID); err2 == nil { + if order2, err2 := c.GetOrder(order.VendorOrgCode, order.VendorOrderID, ""); err2 == nil { var mapData map[string]interface{} if err2 = utils.UnmarshalUseNumber([]byte(order2.OriginalData), &mapData); err2 == nil { if utils.Interface2String(mapData["deliveryCarrierNo"]) == "2938" { // 当前已经是自送状态了 @@ -570,26 +620,3 @@ func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, order *model.G } return err } - -func orderInfoChangeSet(order *model.GoodsOrder, msg *jdapi.CallbackOrderInfoChangeMsg) (valid map[string]interface{}) { - valid = make(map[string]interface{}) - if msg.BuyerFullAddress != "" { - valid["consigneeAddress"] = msg.BuyerFullAddress - } - if msg.BuyerFullName != "" { - valid["consigneeName"] = msg.BuyerFullName - } - if msg.BuyerMobile != "" { - valid["consigneeMobile"] = msg.BuyerMobile - } - if msg.BuyerLat != 0 { - valid["consigneeLat"] = jxutils.StandardCoordinate2Int(msg.BuyerLat) - } - if msg.BuyerLng != 0 { - valid["consigneeLng"] = jxutils.StandardCoordinate2Int(msg.BuyerLng) - } - if msg.OrderBuyerRemark != "" { - valid["buyerComment"] = msg.OrderBuyerRemark - } - return valid -} diff --git a/business/partner/purchase/jd/order_afs.go b/business/partner/purchase/jd/order_afs.go index 37a935747..7994fc028 100644 --- a/business/partner/purchase/jd/order_afs.go +++ b/business/partner/purchase/jd/order_afs.go @@ -219,7 +219,7 @@ func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.Goods // 发起部分退款 func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { if globals.EnableJdStoreWrite { - _, err = getAPI(order.VendorOrgCode).AfsSubmit(order.VendorOrderID, ctx.GetUserName(), utils.Int2Str(jdapi.AfsReasonWrongPurchase), reason, "", order.ConsigneeName, order.ConsigneeMobile, order.ConsigneeAddress, orderSkus2AfsSkus(refundSkuList)) + _, err = getAPI(order.VendorOrgCode).AfsSubmit(order.VendorOrderID, ctx.GetUserName(), utils.Int2Str(jdapi.AfsReasonTypeGoodsQuality), reason, "", order.ConsigneeName, order.ConsigneeMobile, order.ConsigneeAddress, orderSkus2AfsSkus(refundSkuList)) } return err } diff --git a/business/partner/purchase/jd/sku2.go b/business/partner/purchase/jd/sku2.go index 5d2717984..8cd8043cb 100644 --- a/business/partner/purchase/jd/sku2.go +++ b/business/partner/purchase/jd/sku2.go @@ -2,6 +2,7 @@ package jd import ( "fmt" + "strings" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" @@ -114,7 +115,7 @@ func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCo func (p *PurchaseHandler) getVendorCategories(level int, pid int64) (vendorCats []*model.SkuVendorCategory, err error) { // 得到平台的分类,不需要指定分账号 - cats, err := api.Jd2API.QueryChildCategoriesForOP(pid) + cats, err := api.JdAPI.QueryChildCategoriesForOP(pid) if err != nil { return nil, err } @@ -155,7 +156,7 @@ func skuInfo2Param(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (param *jd param = &jdapi.OpSkuParam{ TraceID: ctx.GetTrackInfo(), OutSkuID: utils.Int2Str(sku.SkuID), - ShopCategories: []int64{utils.Str2Int64(sku.VendorCatID)}, + ShopCategories: []int64{}, CategoryID: sku.VendorVendorCatID, BrandID: DefBrandID, SkuName: utils.LimitUTF8StringLen(sku.SkuName, jdapi.MaxSkuNameCharCount), @@ -164,9 +165,18 @@ func skuInfo2Param(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (param *jd FixedStatus: jxStatus2jdStatus(sku.MergedStatus), IsSale: jdapi.IsSaleNo, // todo ? - Upc: sku.Upc, - Images: jxutils.BatchString2Slice(sku.Img, sku.Img2), + Upc: sku.Upc, + // Images: jxutils.BatchString2Slice(sku.Img, sku.Img2), } + if sku.VendorCatID != "" { + param.ShopCategories = append(param.ShopCategories, utils.Str2Int64(sku.VendorCatID)) + } + if sku.ImgMix != "" { + param.Images = jxutils.BatchString2Slice(sku.ImgMix, sku.Img2, sku.Img3) + } else { + param.Images = jxutils.BatchString2Slice(sku.Img, sku.Img2, sku.Img3) + } + if param.CategoryID == 0 { param.CategoryID = int64(getDefJdCategoryID()) } @@ -188,6 +198,21 @@ func (p *PurchaseHandler) CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSy param := skuInfo2Param(ctx, sku) if globals.EnableJdStoreWrite { sku.VendorSkuID, err = getAPI(sku.VendorOrgCode).AddSku2(param) + if err != nil && strings.Contains(err.Error(), jdapi.ErrMustUPC) { + result, err2 := getAPI(sku.VendorOrgCode).BatchAddSkuByUPC([]*jdapi.CreateByUpcParam2{ + &jdapi.CreateByUpcParam2{ + OutSkuId: utils.Int2Str(sku.SkuID), + Upc: sku.Upc, + JdPrice: utils.Int64ToStr(sku.Price), + ShopCategoryID: utils.Str2Int64WithDefault((sku.VendorCatID), 0), + }, + }) + if err2 == nil { + sku.VendorSkuID = result.SkuID + } else { + err = err2 + } + } } else { sku.VendorSkuID = utils.Int64ToStr(jxutils.GenFakeID()) } diff --git a/business/partner/purchase/jd/store.go b/business/partner/purchase/jd/store.go index aca822b80..111b53717 100644 --- a/business/partner/purchase/jd/store.go +++ b/business/partner/purchase/jd/store.go @@ -33,6 +33,7 @@ type tJdStoreInfo struct { RealLastOperator string SyncStatus int VendorStoreName string + BrandName string } var ( @@ -127,9 +128,11 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin t1.*, city.jd_code jd_city_code, district.jd_code jd_district_code, t2.status jd_store_status, t2.vendor_store_id, IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, - t2.sync_status, t2.freight_deduction_pack, t2.vendor_org_code, t2.vendor_store_name + t2.sync_status, t2.freight_deduction_pack, t2.vendor_org_code, t2.vendor_store_name, + t3.name brand_name FROM store t1 JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?) + LEFT JOIN brand t3 ON t3.id = t1.brand_id LEFT JOIN place city ON t1.city_code = city.code LEFT JOIN place district ON t1.district_code = district.code WHERE t1.id = ? @@ -138,17 +141,17 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin if err = dao.GetRows(db, &stores, sql, model.VendorIDJD, utils.DefaultTimeValue, storeID); err == nil { for _, store := range stores { a := getAPI(store.VendorOrgCode) - phone := "" - if store.MarketManPhone != "" { - phone = store.MarketManPhone - } else { - phone = model.VendorStoreTel - } + // phone := "" + // if store.MarketManPhone != "" { + // phone = store.MarketManPhone + // } else { + // phone = model.VendorStoreTel + // } storeParams := &jdapi.OpStoreParams{ StationNo: store.VendorStoreID, Operator: userName, - Phone: phone, - Mobile: store.Tel2, + Phone: store.Tel1, + Mobile: store.Tel1, } if store.SyncStatus&model.SyncFlagDeletedMask == 0 { storeParams.OutSystemID = utils.Int2Str(int(store.ID)) @@ -159,7 +162,11 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin if store.VendorStoreName != "" { storeParams.StationName = store.VendorStoreName } else { - storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD) + if store.BrandID != 1 { + storeParams.StationName = store.Name + } else { + storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD) + } } storeParams.StationName = utils.LimitUTF8StringLen(storeParams.StationName, jdapi.MaxStoreNameLen) } @@ -204,16 +211,20 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin errList.AddErr(a.UpdateStoreInfo4Open2(storeParams, modifyCloseStatus)) } if store.FreightDeductionPack != "" { - storeDetail, err2 := dao.GetStoreDetail(db, store.ID, model.VendorIDJD) + storeDetail, err2 := dao.GetStoreDetail(db, store.ID, model.VendorIDJD, "") if err2 == nil { if storeDetail.FreightDeductionPackObj != nil { freightParams := &jdapi.UpdateStoreFreightParam{ - StationNo: store.VendorStoreID, - UserPin: userName, - OpenDistanceFreight: true, - StartCharge: int64(storeDetail.FreightDeductionPackObj.StartPrice), + StationNo: store.VendorStoreID, + UserPin: userName, + OpenDistanceFreight: true, + StartCharge: int64(storeDetail.FreightDeductionPackObj.StartPrice), + DistanceFreightThreshold: 1000, + DistanceUnit: 1000, + DistanceFreight: 200, } if len(storeDetail.FreightDeductionPackObj.FreightDeductionList) > 0 { + globals.SugarLogger.Debug("FreightDeductionPackObj", utils.Format4Output(storeDetail.FreightDeductionPackObj, false)) for _, v := range storeDetail.FreightDeductionPackObj.FreightDeductionList { if v.DeductFreight > 0 { freightParams.FreeFreightInfoList = append(freightParams.FreeFreightInfoList, &jdapi.FreeFreightInfo{ @@ -511,8 +522,60 @@ func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgC return err } -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { - return vendorStoreID, err +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("平台账号必传!") + } + + //营业时间1开始;传值规则:每30分钟加1,即00:00为0,00:30为1,以此类推,23:30为47,23:59为48 + serviceTimeStart1, serviceTimeStart2, serviceTimeEnd1, serviceTimeEnd2 := 0, 0, 0, 0 + if storeDetail.OpenTime1 != 0 && storeDetail.CloseTime1 != 0 { + serviceTimeStart1 = (int(storeDetail.OpenTime1)/100)*2 + int(storeDetail.OpenTime1)%100/30 + serviceTimeEnd1 = (int(storeDetail.CloseTime1)/100)*2 + int(storeDetail.CloseTime1)%100/30 + if storeDetail.OpenTime1 == 2359 || (storeDetail.OpenTime1 < 30 && storeDetail.OpenTime1 > 0) { + serviceTimeStart1++ + } + if storeDetail.CloseTime1 == 2359 || (storeDetail.CloseTime1 < 30 && storeDetail.CloseTime1 > 0) { + serviceTimeEnd1++ + } + if storeDetail.OpenTime2 != 0 && storeDetail.CloseTime2 != 0 { + serviceTimeStart2 = (int(storeDetail.OpenTime2)/100)*2 + int(storeDetail.OpenTime2)%100/30 + serviceTimeEnd2 = (int(storeDetail.CloseTime2)/100)*2 + int(storeDetail.CloseTime2)%100/30 + if storeDetail.OpenTime2 == 2359 || (storeDetail.OpenTime2 < 30 && storeDetail.OpenTime2 > 0) { + serviceTimeStart2++ + } + if storeDetail.CloseTime2 == 2359 || (storeDetail.CloseTime2 < 30 && storeDetail.CloseTime2 > 0) { + serviceTimeEnd2++ + } + } + } + + createParams := &jdapi.OpStoreParams{ + StationName: params["vendorStoreName"].(string), + OutSystemID: utils.Int2Str(storeDetail.ID), + Phone: storeDetail.Tel1, + Mobile: storeDetail.Tel1, + City: storeDetail.JdCityCode, + County: storeDetail.JdCode, + StationAddress: storeDetail.Address, + Operator: vendorOrgCode, + ServiceTimeStart1: serviceTimeStart1, + ServiceTimeStart2: serviceTimeStart2, + ServiceTimeEnd1: serviceTimeEnd1, + ServiceTimeEnd2: serviceTimeEnd2, + Lat: jxutils.IntCoordinate2Standard(storeDetail.Lat), + Lng: jxutils.IntCoordinate2Standard(storeDetail.Lng), + CoordinateType: 3, //使用的地图类型(1,谷歌), (2,百度), (3,高德), (4,腾讯) + DeliveryRangeType: storeDetail.DeliveryRangeType, + DeliveryRangeRadius: utils.Str2Int(storeDetail.DeliveryRange), + StandByPhone: storeDetail.Tel1 + "," + "18048531223", + } + result, err := getAPI(vendorOrgCode).CreateStore(createParams) + if err != nil { + return "", err + } + return result.StationNo, err } func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) { diff --git a/business/partner/purchase/jd/store_sku2.go b/business/partner/purchase/jd/store_sku2.go index 0cd83d594..dd3279665 100644 --- a/business/partner/purchase/jd/store_sku2.go +++ b/business/partner/purchase/jd/store_sku2.go @@ -55,9 +55,9 @@ func (p *PurchaseHandler) getStoreSkusBareInfoLimitSize(ctx *jxcontext.Context, sku := storeSkuMap[utils.Int64ToStr(v.SkuID)] sku.Status = jdStoreSkuStatus2Jx(v.Vendibility) sku.Stock = v.UsableQty - if sku.Stock > 0 { - outStoreSkuList = append(outStoreSkuList, sku) - } + // if sku.Stock > 0 { + outStoreSkuList = append(outStoreSkuList, sku) + // } } for _, v := range priceInfo { sku := storeSkuMap[utils.Int64ToStr(v.SkuID)] @@ -205,7 +205,7 @@ func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrg func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { globals.SugarLogger.Debugf("jd SyncStoreProducts, storeID:%d", storeID) db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD) + storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD, "") if err != nil { return "", err } diff --git a/business/partner/purchase/jdshop/callback.go b/business/partner/purchase/jdshop/callback.go index 77c54ac2c..58550388c 100644 --- a/business/partner/purchase/jdshop/callback.go +++ b/business/partner/purchase/jdshop/callback.go @@ -1,35 +1,473 @@ package jdshop import ( + "bytes" + "encoding/base64" + "encoding/hex" "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" + "github.com/astaxie/beego" + + "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/jxstore/common" + "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" ) -func OnCallbackMsg(msg *jdshopapi.CallBackResult) { - fmt.Println("testcallback") - // if CurPurchaseHandler != nil { - // if msg.Cmd == mtwmapi.MsgTypeStoreStatusChanged { - // response = CurPurchaseHandler.onStoreStatusChanged(msg) - // } else if msg.Cmd == mtwmapi.MsgTypePrivateNumberDowngrade { - // response = CurPurchaseHandler.onNumberDowngrade(msg) - // } else { - // if orderID := GetOrderIDFromMsg(msg); orderID != "" { - // jxutils.CallMsgHandler(func() { - // switch msg.Cmd { - // case mtwmapi.MsgTypeWaybillStatus: - // response = CurPurchaseHandler.onWaybillMsg(msg) - // default: - // response = CurPurchaseHandler.onOrderMsg(msg) - // } - // }, jxutils.ComposeUniversalOrderID(orderID, model.VendorIDMTWM)) - // } - // /*if msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund { - // utils.CallFuncAsync(func() { - // OnFinancialMsg(msg) - // }) - // } */ - // } - // } - // return response +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) { + 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+"000001", model.VendorIDJDShop) + if orderE != nil { + return order, fmt.Errorf("已经存在此订单!") + } + order = &model.GoodsOrder{ + VendorOrderID2: msg.OrderID, + VendorOrderID: msg.OrderID + "000001", + 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)) + } + 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 + } + 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) + } + 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 { + 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) + //结算类型 + storeDetail, _ := dao.GetStoreDetail(db, order.StoreID, model.VendorIDJDShop, "") + if storeDetail != nil { + if storeDetail.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 + } 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) + continue + } else { + if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { + buildOrderTo102919(order) + continue + } + } + } else { + if saleNormalSum <= len(order.Skus)/2 { + buildOrderTo102919(order) + continue + } else { + if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) { + buildOrderTo102919(order) + continue + } + } + } + break + } + } else { + buildOrderTo102919(order) + } + storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, []int{order.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", msg.VendorOrgCode) + if len(storeMaps) > 0 { + order.VendorStoreID = storeMaps[0].VendorStoreID + } + // 如果是暂停,表示是预订单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) + } + } + order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour) + } else if msg.OrderState == jdshopapi.OrderStatusWait || msg.OrderState == "WAIT_GOODS_RECEIVE_CONFIRM" { + 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) + } + billParams, _ := GetDaDaBillParams(db, order) + if result, err := api.DadaAPI.QueryDeliverFee(billParams); err == nil { + if result.Fee > 10 { + buildOrderTo102919(order) + } + } + 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.JdShopMainStoreID2 + order.JxStoreID = model.JdShopMainStoreID2 + order.StoreName = "商城模板店2" + order.VendorStoreID = model.JdShopMainVendorStoreID2 + } + 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/jdshop/jds.go b/business/partner/purchase/jdshop/jds.go index 8f73f40d4..d3951126a 100644 --- a/business/partner/purchase/jdshop/jds.go +++ b/business/partner/purchase/jdshop/jds.go @@ -1,6 +1,7 @@ package jdshop import ( + "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" @@ -32,6 +33,13 @@ func New() (obj *PurchaseHandler) { return obj } +func getAPI(appOrgCode string) (apiObj *jdshopapi.API) { + if appOrgCode == "" { + globals.SugarLogger.Warnf("getAPI appOrgCode is empty") + } + return partner.CurAPIManager.GetAPI(model.VendorIDJDShop, appOrgCode).(*jdshopapi.API) +} + func (p *PurchaseHandler) GetVendorID() int { return model.VendorIDJDShop } @@ -51,7 +59,7 @@ func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgUR } func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) { - result, err := api.JdShopAPI.FindVendorCategories() + result, err := api.JdShop2API.FindVendorCategories() for _, v := range result { cat := &model.SkuVendorCategory{ VendorID: model.VendorIDJDShop, diff --git a/business/partner/purchase/jdshop/key.go b/business/partner/purchase/jdshop/key.go new file mode 100644 index 000000000..3c6197512 --- /dev/null +++ b/business/partner/purchase/jdshop/key.go @@ -0,0 +1,71 @@ +package jdshop + +import ( + "encoding/base64" + "encoding/hex" + "encoding/json" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/jx-callback/globals/api" +) + +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() { + keyResult, err := api.JdShopAPI.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 := api.JdShop2API.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 + } + } + } + globals.SugarLogger.Debugf("no key can equal..") + return key +} diff --git a/business/partner/purchase/jdshop/order.go b/business/partner/purchase/jdshop/order.go index 075526bc6..061a4f9dc 100644 --- a/business/partner/purchase/jdshop/order.go +++ b/business/partner/purchase/jdshop/order.go @@ -1,8 +1,22 @@ package jdshop import ( + "fmt" + "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/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) { @@ -10,19 +24,63 @@ func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, o } func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { + result := &jdshopapi.AllOrdersResult{} + utils.Map2StructByJson(orderData, &result, false) + 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)), + } return order } -func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) { - return order, err +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: 1, + }) + return p.Map2Order(utils.Struct2FlatMap(resultOrders)), err } func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { - return status, err + jdsOrder, err := GetJdsOrder(vendorOrderID, vendorOrgCode) + return status2Jxstatus(jdsOrder.OrderState), err } func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { - return err + var ( + status int + remark string + ) + if isAcceptIt { + status = model.OrderStatusAccepted + //京东商城第二个号要自动接单 + if order.VendorOrgCode == "2" { + err = api.JdShop2API.SetOrderStateToWait(utils.Str2Int64(order.VendorOrderID2)) + } + } else { + status = model.OrderStatusCanceled + } + return ChangeOrderStatus(order.VendorOrderID, status, remark) } func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { + status, err := p.GetOrderStatus(order.VendorOrgCode, order.VendorOrderID2) + //说明此时该订单在平台上已经取消了 + if status == model.OrderStatusCanceled { + err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单在京东商城已被取消!") + } else { + if jxutils.GetSaleStoreIDFromOrder(order) != model.JdShopMainStoreID { + err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "自动拣货完成") + if status == model.OrderStatusAccepted { + err = p.OrderExport(jxcontext.AdminCtx, order.VendorOrderID, order.VendorOrderID, true) + } + } + } return err } @@ -42,9 +100,14 @@ func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName 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" { + api.JdShop2API.SetOrderStateToFinish(utils.Str2Int64(order.VendorOrderID2)) + } return err } func (p *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) { @@ -57,20 +120,141 @@ func (p *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *mod 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) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { + +func (p *PurchaseHandler) GetJdsOrders(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd string, current, pageSize int) (orderResult *jdshopapi.AllOrdersResult, err error) { + orderResult, err = api.JdShopAPI.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) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) { + +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) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { + +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 (p *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) { - return err + +func status2Jxstatus(status string) (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 + } + 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.GetOrderResult, 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{} + err = utils.UnmarshalUseNumber([]byte(strings.ReplaceAll(result["data"].(string), "\\", "")), &jdsOrder2) + return jdsOrder2, err } diff --git a/business/partner/purchase/jdshop/order_afs.go b/business/partner/purchase/jdshop/order_afs.go new file mode 100644 index 000000000..bc0c8ec51 --- /dev/null +++ b/business/partner/purchase/jdshop/order_afs.go @@ -0,0 +1,134 @@ +package jdshop + +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, orderID :%v", order.VendorOrderID) + 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 +} diff --git a/business/partner/purchase/jdshop/store.go b/business/partner/purchase/jdshop/store.go index 0a308695b..1d7b8be90 100644 --- a/business/partner/purchase/jdshop/store.go +++ b/business/partner/purchase/jdshop/store.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "git.rosy.net.cn/baseapi/platformapi/jdshopapi" "git.rosy.net.cn/baseapi/utils" @@ -38,7 +39,7 @@ func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendo // stoerIDs为nil表示所有 func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { - store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop) + store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop, "") if err != nil { return err } @@ -76,8 +77,8 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin return err } -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { - store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop) +func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { + store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop, "") if err != nil { return vendorStoreID, err } @@ -99,13 +100,119 @@ func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName stri CategoryName: jdshopapi.JdsStoreCategoryName, CustomerID: utils.Int2Str(store.ID), } + url, _ := api.JdShop2API.UploadImageNew(data, "2659335b16e3880e367759b8fc675933.tem.png") + ex := store.LicenceExpire + if ex == "" { + ex = utils.Time2Str(utils.Str2Time(store.LicenceValid).AddDate(0, 6, 0)) + } + if !strings.Contains(ex, "00:00:00") { + ex += " 00:00:00" + } + var url2 string + if store.Licence != "" { + data2, _, _ := jxutils.DownloadFileByURL(store.Licence) + fileName := store.Licence[strings.LastIndex(store.Licence, "/")+1 : len(store.Licence)] + url2, _ = api.JdShop2API.UploadImageNew(data2, fileName) + } + storeName := store.Name + if strings.Contains(storeName, "(") { + storeName = storeName[0:strings.Index(storeName, "(")] + storeName[strings.Index(storeName, ")")+3:len(storeName)] + } + if strings.Contains(storeName, "(") { + storeName = storeName[0:strings.Index(storeName, "(")] + storeName[strings.Index(storeName, ")")+3:len(storeName)] + } + if strings.Contains(storeName, ".") { + storeName = strings.ReplaceAll(storeName, ".", "") + } + if strings.Contains(storeName, "-") { + storeName = strings.ReplaceAll(storeName, "-", "") + } + if strings.Contains(storeName, " ") { + storeName = strings.ReplaceAll(storeName, " ", "") + } + storeName = "京西菜市" + strings.ReplaceAll(storeName, "店", "") + "生鲜店" + if len(storeName) > 30 { + storeName = utils.LimitUTF8StringLen2(storeName, 30) + } + param := &jdshopapi.UpdateBasicParam{ + StoreName: storeName, + CategoryID2: 4, + Coordinate: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)), + BussinessBeginTime: int2TimeStr(int(store.OpenTime1)), + BussinessEndTime: int2TimeStr(int(store.CloseTime1)), + ImgURL: url, + StorePhone: store.Tel1, + AddName: store.Address, + AddCode3: store.JdsCode, + CategoryID1: 3, + } + if url2 != "" { + param.CategoryID1 = 34 + param.CategoryID2 = 62 + param.QualificationRequests = []*jdshopapi.QualificationRequests{ + &jdshopapi.QualificationRequests{ + QualificationID: 41, + QualificationName: "营业执照", + QualificationNo: store.LicenceCode, + QualificationURL: url2, + StartTime: utils.Time2Str(utils.Str2Time(store.LicenceValid)), + EndingTime: ex, + Time: []string{utils.Time2Str(utils.Str2Time(store.LicenceValid)), ex}, + }, + } + } if store.JdsStreetCode != 0 { createEntityStoreParam.AddCode = store.JdsStreetCode + param.AddCode3 = store.JdsStreetCode } if createEntityStoreParam.AddCode == 0 { createEntityStoreParam.AddCode = store.JdCode + param.AddCode3 = store.JdCode + } + //证明这个店可能隶属直辖市或者东莞 + if model.ZXCityCodeMap[store.CityCode] != "" { + result, _ := api.AutonaviAPI.GetCoordinateAreaInfo(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat)) + if result["regeocode"] != nil { + street := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})["township"].(string) + if street != "" { + result1, _ := api.JdShopAPI.GetProvince() + for _, v := range result1 { + if strings.Contains(store.CityName, v.AreaName) { + result2, _ := api.JdShopAPI.GetCity(v.AreaID) + for _, vv := range result2 { + if strings.Contains(store.DistrictName, vv.AreaName) { + result3, _ := api.JdShopAPI.GetCounty(vv.AreaID) + for _, vvv := range result3 { + if street == vvv.AreaName { + createEntityStoreParam.AddCode = vvv.AreaID + param.AddCode3 = vvv.AreaID + break + } + } + } + } + } + } + } + } } vendorStoreID, err = api.JdShopAPI.CreateEntityStore(createEntityStoreParam) + if vendorStroeID2, err := api.JdShop2API.SubmitBasic(param); err == nil { + time.Sleep(time.Second) + err = api.JdShop2API.UpdateExpand(int(vendorStroeID2)) + var storeMap *model.StoreMap + sql := ` + SELECT * FROM store_map WHERE deletad_at = ? AND store_id = ? AND vendor_id = ? AND vendor_org_code = ? + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, storeID, model.VendorIDJDShop, "2", + } + err = dao.GetRow(db, &storeMap, sql, sqlParams) + if storeMap != nil { + storeMap.VendorStoreID = utils.Int64ToStr(vendorStroeID2) + _, err = dao.UpdateEntity(db, storeMap, "VendorStoreID") + } + } return vendorStoreID, err } diff --git a/business/partner/purchase/jdshop/store_sku.go b/business/partner/purchase/jdshop/store_sku.go index 8a6f64e8c..d4d03ea94 100644 --- a/business/partner/purchase/jdshop/store_sku.go +++ b/business/partner/purchase/jdshop/store_sku.go @@ -2,6 +2,7 @@ package jdshop import ( "fmt" + "math" "regexp" "strings" "time" @@ -22,95 +23,265 @@ import ( "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 && vendorStoreID == model.JdShopMainVendorStoreID { - for _, v := range storeSkuList { - //判断京东商城上是否有这个商品了,如果有就是添加规格而不是创建商品 - name := filterSensitiveWord(v.Name) - flag := false - result, err := api.JdShopAPI.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 - break - } - } - if result.TotalItem > 0 && len(result.Data) > 0 && flag { - for _, vv := range v.StoreSkuSyncInfoJds { - v.JdsWareID = result.Data[0].WareID - vv.JdsWareID = result.Data[0].WareID - updateSkusParam, err := buildUpdateSkusParam(v, vv, true) - if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") - return failedList, err - } - vendorSkuID, err := api.JdShopAPI.UpdateSkus(updateSkusParam) - if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") - return failedList, err - } - vv.VendorSkuID = vendorSkuID - } - } else { - createSkuParamWare, createSkuParamSkus, err := buildCreateWareParam(v) + if globals.EnableJdShopWrite { + if vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2 { + for _, v := range storeSkuList { + //判断京东商城上是否有这个商品了,如果有就是添加规格而不是创建商品 + //如果是京东商城2,是下架的商品,弄上架 + name := filterSensitiveWord(v.Name) + flag := false + flag2 := 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 } - createSkuResult, err := api.JdShopAPI.CreateWare(createSkuParamWare, createSkuParamSkus) - 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 { + flag2 = true + } + break + } + } + if v.VendorOrgCode == "2" && flag2 { + err = api.JdShop2API.WareDoUpdate("op", utils.Int64ToStr(v.JdsWareID)) } else { - //追加商品透图 - 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") + if result.TotalItem > 0 && len(result.Data) > 0 && flag { + //jds2 + 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 + //先把已有的规格放进去 + if v.VendorOrgCode == "2" { + wareResult, _ := api.JdShop2API.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, _, _ := api.JdShop2API.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 + updateSkusParam, 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 + } + if v.VendorOrgCode == "1" { + vendorSkuID, err := getAPI(v.VendorOrgCode).UpdateSkus(updateSkusParam) + if err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") + return failedList, err + } + vv.VendorSkuID = vendorSkuID + } else { + 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 = api.JdShop2API.WareDoUpdate("up", utils.Int64ToStr(wareSaveParam.WareID)); err == nil { + err = api.JdShop2API.StoreSkuBindStore(true, []string{vv.VendorSkuID}, nil) + } + } + } + } + } else { + createSkuParamWare, createSkuParamSkus, 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) + ) + if v.VendorOrgCode == "1" { + createSkuResult, err2 := getAPI(v.VendorOrgCode).CreateWare(createSkuParamWare, createSkuParamSkus) + err = err2 + wareID = createSkuResult.WareID + + var paramAttrs = make(map[string]*jdshopapi.CreateSkuParamSkus) + for _, vv := range createSkuParamSkus { + for _, vvv := range vv.SaleAttrs { + paramAttrs[vvv.AttrValues[0]] = vv + } + } + for _, vv1 := range createSkuResult.Skus { + for _, vvv1 := range vv1.SaleAttrs { + if paramAttrs[vvv1.AttrValues[0]] != nil { + resultAttrs[paramAttrs[vvv1.AttrValues[0]].OuterID] = vv1.SkuID + } + } + } + for _, vv2 := range v.StoreSkuSyncInfoJds { + vv2.JdsWareID = createSkuResult.WareID + if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 { + vv2.VendorSkuID = utils.Int64ToStr(resultAttrs[utils.Int2Str(vv2.SkuID)]) + } } } else { - imageURL, err = uploadImg(img, name, "tou") + var createSkuResult []*jdshopapi.WareSaveResult + for i := 0; i < 10; i++ { + createSkuResult, err = api.JdShop2API.WareSave(wareSaveParam) + if len(createSkuResult) > 0 { + break + } + time.Sleep(time.Second) + } + 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 = api.JdShop2API.WareDoUpdate("up", utils.Int64ToStr(wareID)); err == nil { + for _, vv2 := range v.StoreSkuSyncInfoJds { + if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 { + err = api.JdShop2API.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) + } } } - err2 := api.JdShopAPI.TransparentImageAdd(createSkuResult.WareID, imageURL) - if err2 != nil { + if err != nil { failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") return failedList, err } } - var paramAttrs = make(map[string]*jdshopapi.CreateSkuParamSkus) - var resultAttrs = make(map[string]int64) - for _, vv := range createSkuParamSkus { - for _, vvv := range vv.SaleAttrs { - paramAttrs[vvv.AttrValues[0]] = vv - } - } - for _, vv1 := range createSkuResult.Skus { - for _, vvv1 := range vv1.SaleAttrs { - if paramAttrs[vvv1.AttrValues[0]] != nil { - resultAttrs[paramAttrs[vvv1.AttrValues[0]].OuterID] = vv1.SkuID + } + } else { + //如果是普通店关注商品 + for _, v := range storeSkuList { + for _, vv := range v.StoreSkuSyncInfoJds { + if vv.VendorOrgCode == "2" { + storeSkus, _ := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.JdShopMainStoreID2}, []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 = api.JdShop2API.StoreWareDoUpdate(status, storeSku.JdsID, vendorStoreID) + if err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") + return failedList, err + } + } + if stock != 0 { + err = api.JdShop2API.StoreUpdateStock(stock, storeSku.JdsID, vendorStoreID) + if err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") + return failedList, err + } + } + err = api.JdShop2API.StoreUpdatePrice(utils.Float64ToStr(jxutils.IntPrice2Standard(int64(price))), storeSku.JdsID, vendorStoreID) + } + } + if err != nil { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品") + return failedList, err + } } } } - for _, vv2 := range v.StoreSkuSyncInfoJds { - vv2.JdsWareID = createSkuResult.WareID - if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 { - vv2.VendorSkuID = utils.Int64ToStr(resultAttrs[utils.Int2Str(vv2.SkuID)]) - } - } } } } @@ -118,84 +289,158 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v } 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 { - for _, v := range storeSkuList { - name := filterSensitiveWord(v.Name) - updateWareParam := &jdshopapi.UpdateWareParam{ - WareID: v.JdsWareID, - Title: name, - VenderID: jdshopapi.VenderID, - PromiseID: jdshopapi.JdsPromiseID, - } - var desc string - if v.DescImg != "" { - pic3, err2 := uploadImg2(v.DescImg, name, "desc") - err = err2 - desc = `



` - } else { - desc = `



` - } - updateWareParam.Introduction = desc - updateWareParam.MobileDesc = desc - if v.Img != "" { - pic1, err2 := uploadImg2(v.Img, name, "1") - err = err2 - err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 1, pic1) - if v.Img2 != "" { - pic2, err2 := uploadImg2(v.Img2, name, "2") - err = err2 - err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 2, pic2) - } else { - err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 2, pic1) + if globals.EnableJdShopWrite && (vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2) { + 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 } - - } - var features = []*jdshopapi.CreateSkuParamFeatures{ - &jdshopapi.CreateSkuParamFeatures{ - Key: "is7ToReturn", //不支持7天无理由退货 - Value: "0", - }, - &jdshopapi.CreateSkuParamFeatures{ - Key: "tssp", //支持自提 - Value: "4", - }, - // &jdshopapi.CreateSkuParamFeatures{ - // Key: "fdms", //分单? - // Value: "1", - // }, - } - updateWareParam.Features = features - err = api.JdShopAPI.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") - } + 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 { - imageURL, err = uploadImg(img, name, "tou") + 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) } } - err2 := api.JdShopAPI.TransparentImageAdd(v.JdsWareID, imageURL) - if err2 != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "更新商品基础信息") - return failedList, err + 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) } } - 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 + } 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{}{}, } - vendorSkuID, err := api.JdShopAPI.UpdateSkus(updateSkusParam) - vv.VendorSkuID = vendorSkuID + 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) + } + api.JdShop2API.WareSave(wareSaveParam) } } if err != nil { @@ -206,16 +451,23 @@ func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, v } func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { + if globals.EnableJdShopWrite && (vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2) { for _, v := range storeSkuList { - // err = api.JdShopAPI.DeleteSku(utils.Str2Int64(v.VendorSkuID)) - err = api.JdShopAPI.UpOrDown(utils.Str2Int64(v.VendorSkuID2), 2) - if err == nil { - err = api.JdShopAPI.DeleteWare(utils.Str2Int(v.VendorSkuID2)) + if v.IsDeletedBySku { + err = getAPI(v.VendorOrgCode).DeleteSku(utils.Str2Int64(v.VendorSkuID)) + } else { + if v.VendorOrgCode == "1" { + err = getAPI(v.VendorOrgCode).UpOrDown(utils.Str2Int64(v.VendorSkuID2), 2) + if err == nil { + err = getAPI(v.VendorOrgCode).DeleteWare(utils.Str2Int(v.VendorSkuID2)) + } + } else { + err = api.JdShop2API.WareDoUpdate("down", v.VendorSkuID2) + } + } + if err != nil { + failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "删除商品")...) } - } - if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "删除商品") } } return failedList, err @@ -224,13 +476,13 @@ func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, v 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 = 100 + pageSize = 20 ) - pageResult, err := api.JdShopAPI.SearchWare4Valid("", pageNo, pageSize) - for ; pageNo <= pageResult.TotalItem/pageSize+1; pageNo++ { - result, err := api.JdShopAPI.SearchWare4Valid("", pageNo, pageSize) + _, totalCount, err := api.JdShopAPI.SearchSkuList(pageNo, pageSize) + for ; pageNo <= totalCount/pageSize+1; pageNo++ { + result, _, err := api.JdShopAPI.SearchSkuList(pageNo, pageSize) if err == nil { - for _, v := range result.Data { + for _, v := range result { if skuName := vendorSku2Jx(v); skuName != nil { skuNameList = append(skuNameList, skuName) } @@ -240,21 +492,46 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas return skuNameList, err } +func getMainStoreVendorSkuID(mainStoreID int, skuID int) (vendorSkuID int64, err error) { + var ( + db = dao.GetDB() + ) + storeSkus, err := dao.GetStoresSkusInfo(db, []int{mainStoreID}, []int{skuID}) + if len(storeSkus) > 0 { + vendorSkuID = storeSkus[0].JdsID + } + return vendorSkuID, 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 { var stock = 0 for _, v := range storeSkuList { - if status == model.SkuStatusNormal { - stock = 9999 - } if storeID == model.JdShopMainStoreID { - err = api.JdShopAPI.UpdateSkuStock(utils.Str2Int(v.VendorSkuID), stock) + if status == model.SkuStatusNormal { + stock = 9999 + } + if v.JdsStockSwitch == model.NO { + stock = 0 + } + err = getAPI(v.VendorOrgCode).UpdateSkuStock(utils.Str2Int(v.VendorSkuID), stock) + } else if storeID == model.JdShopMainStoreID2 { + } else { - storeSkus, err2 := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.JdShopMainStoreID}, []int{v.SkuID}) - err = err2 - if len(storeSkus) > 0 { - if storeSkus[0].JdsID != 0 { - err = api.JdShopAPI.UpdateSkuSiteStock(storeSkus[0].JdsID, stock, utils.Str2Int(vendorStoreID)) + if v.VendorOrgCode == "1" { + storeSkus, err2 := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.JdShopMainStoreID}, []int{v.SkuID}) + err = err2 + if len(storeSkus) > 0 { + if storeSkus[0].JdsID != 0 && vendorStoreID != "" { + if storeSkus[0].Status == model.SkuStatusNormal { + stock = 9999 + } + err = getAPI(v.VendorOrgCode).UpdateSkuSiteStock(storeSkus[0].JdsID, stock, utils.Str2Int(vendorStoreID)) + } + } + } else { + if vendorSkuID, err := getMainStoreVendorSkuID(model.JdShopMainStoreID2, v.SkuID); err == nil && vendorSkuID != 0 { + err = api.JdShop2API.StoreWareDoUpdate(status, vendorSkuID, vendorStoreID) } } } @@ -267,12 +544,24 @@ func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOr } func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { + if globals.EnableJdShopWrite { for _, v := range storeSkuList { - err = api.JdShopAPI.UpdateSkuJdPrice(utils.Str2Int(v.VendorSkuID), jxutils.IntPrice2Standard(v.VendorPrice)) - } - if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品价格") + if storeID == model.JdShopMainStoreID { + err = getAPI(v.VendorOrgCode).UpdateSkuJdPrice(utils.Str2Int(v.VendorSkuID), jxutils.IntPrice2Standard(v.VendorPrice)) + } else if storeID == model.JdShopMainStoreID2 { + //修改京东商城商品库价格 + } else { + if v.VendorOrgCode == "1" { + // null + } else { + if vendorSkuID, err := getMainStoreVendorSkuID(model.JdShopMainStoreID2, v.SkuID); err == nil && vendorSkuID != 0 { + err = api.JdShop2API.StoreUpdatePrice(utils.Float64ToStr(jxutils.IntPrice2Standard(v.VendorPrice)), vendorSkuID, vendorStoreID) + } + } + } + if err != nil { + failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品价格")...) + } } } return failedList, err @@ -280,7 +569,24 @@ func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrg 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 storeID == model.JdShopMainStoreID { + } else if storeID == model.JdShopMainStoreID2 { + + } else { + if v.VendorOrgCode == "1" { + + } else { + if vendorSkuID, err := getMainStoreVendorSkuID(model.JdShopMainStoreID2, v.SkuID); err == nil && vendorSkuID != 0 { + err = api.JdShop2API.StoreUpdateStock(v.Stock, vendorSkuID, vendorStoreID) + } + } + } + } + if err != nil { + failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品库存")...) + } } return failedList, err } @@ -303,36 +609,42 @@ func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID } func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { + if globals.EnableJdShopWrite && (vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2) { status, err2 := updateOrCreateCategories(storeCat, true) err = err2 if status == -1 { return fmt.Errorf("京东商城店内分类创建失败!") } - flag := false - for { - result, err := api.JdShopAPI.FindShopCategories() - if err != nil { - return err - } - for _, v := range result { - if v.Name == storeCat.Name { - storeCat.VendorCatID = utils.Int64ToStr(v.CID) - flag = true - break - } - } - time.Sleep(time.Second * 2) - if flag { + if err != nil { + return err + } + time.Sleep(time.Second * 2) + // flag := false + // for { + result, err := getAPI(storeCat.VendorOrgCode).FindShopCategories() + if err != nil { + return err + } + for _, v := range result { + if v.Name == storeCat.Name { + storeCat.VendorCatID = utils.Int64ToStr(v.CID) + // flag = true break } } + if storeCat.VendorCatID == "" { + return fmt.Errorf("京东商城店内分类创建可能失败了!storeID: %v", storeID) + } + // if flag { + // break + // } + // } } return err } func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { + if globals.EnableJdShopWrite && (vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2) { status, err2 := updateOrCreateCategories(storeCat, false) err = err2 if status == -1 { @@ -343,7 +655,7 @@ func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID in } func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { - if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID { + if globals.EnableJdShopWrite && (vendorStoreID == model.JdShopMainVendorStoreID || vendorStoreID == model.JdShopMainVendorStoreID2) { _, err = api.JdShopAPI.DeleteShopCategory(utils.Str2Int64(vendorCatID)) } return err @@ -370,6 +682,9 @@ func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp { } 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 } @@ -384,25 +699,32 @@ func ybSkuStatus2Jx(ybStatus int) (jxSkuStatus int) { return jxSkuStatus } -func vendorSku2Jx(result *jdshopapi.SearchWare4ValidResultData) (skuName *partner.SkuNameInfo) { +func vendorSku2Jx(result *jdshopapi.SearchSkuListResult) (skuName *partner.SkuNameInfo) { if result == nil { globals.SugarLogger.Warnf("vendorSku2Jx, strange result:%s", utils.Format4Output(result, true)) return nil } - // prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(result.Title) skuName = &partner.SkuNameInfo{ - Name: result.Title, - VendorNameID: utils.Int64ToStr(result.WareID), - Status: result.WareStatus, - VendorCatIDList: []string{utils.Int2Str(result.CategoryID)}, - NameID: utils.Str2Int(result.OuterID), + VendorNameID: utils.Int64ToStr(result.WareID), + SkuList: []*partner.SkuInfo{ + &partner.SkuInfo{ + StoreSkuInfo: partner.StoreSkuInfo{ + SkuID: utils.Str2Int(result.OuterID), + VendorSkuID: utils.Int64ToStr(result.SkuID), + VendorNameID: utils.Int64ToStr(result.WareID), + Stock: result.StockNum, + VendorPrice: utils.Float64TwoInt64(result.JdPrice * 100), + }, + Comment: result.SaleAttrs[0].AttrValueAlias[0], + }, + }, } return skuName } func updateOrCreateCategories(storeCat *dao.SkuStoreCatInfo, isCreate bool) (status int64, err error) { var createShopCategoryParams []*jdshopapi.CreateShopCategoryParam - result, err := api.JdShopAPI.FindShopCategories() + result, err := getAPI(storeCat.VendorOrgCode).FindShopCategories() if err != nil { return -1, err } @@ -437,17 +759,17 @@ func updateOrCreateCategories(storeCat *dao.SkuStoreCatInfo, isCreate bool) (sta } } } - status, err = api.JdShopAPI.CreateShopCategory(createShopCategoryParams) + status, err = getAPI(storeCat.VendorOrgCode).CreateShopCategory(createShopCategoryParams) return status, err } -func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *jdshopapi.CreateSkuParamWare, createSkuParamSkus []*jdshopapi.CreateSkuParamSkus, err error) { +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, _ := api.JdShopAPI.FindShopCategories() + resultCat, _ := getAPI(storeSku.VendorOrgCode).FindShopCategories() for _, v := range resultCat { if v.Name == storeSku.CategoryName { vendorCatID = int(v.CID) @@ -458,6 +780,30 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j 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}, @@ -466,19 +812,31 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j // 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), + // 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, + // 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") + pic1, err := uploadImg(storeSku.Img, name, "1", storeSku.VendorOrgCode) img1 := &jdshopapi.CreateSkuParamImages{ ColorID: "0000000000", ImgIndex: 1, @@ -491,18 +849,32 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j if storeSku.Img2 == "" { img2.ImgURL = pic1 } else { - pic2, err2 := uploadImg(storeSku.Img, name, "2") + 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") + pic3, err2 := uploadImg(storeSku.DescImg, name, "desc", storeSku.VendorOrgCode) err = err2 desc = `



` } else { @@ -510,6 +882,7 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j } createSkuParamWare.MobileDesc = desc createSkuParamWare.Introduction = desc + wareSaveParam.Notes = desc //设置商品属性值 var ( @@ -517,9 +890,11 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j zctjValueID int64 //贮存条件冷藏0-4的id gcjkValueID int64 //国产,进口的id lbValueID int64 //类别的ID + bcztValueID int64 //保存状态ID + rmsjValueID int64 //热卖时间ID attrsProp []*jdshopapi.CreateSkuParamAttrs ) - attrs, err := api.JdShopAPI.FindAttrs(int(storeSku.VendorVendorCatID)) + attrs, err := getAPI(storeSku.VendorOrgCode).FindAttrs(int(storeSku.VendorVendorCatID)) for _, v := range attrs { if v.Name == "保质期" { attrIDs[v.Name] = v.ID @@ -533,16 +908,20 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j 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 := api.JdShopAPI.FindValuesByAttrId(attrIDs["贮存条件"]) + values, _, err := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["贮存条件"]) for _, v := range values { if v.Name == "冷藏 0-4℃" { zctjValueID = v.ID } } if attrIDs["国产/进口"] != 0 { - values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["国产/进口"]) + values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["国产/进口"]) err = err2 for _, v := range values2 { if v.Name == "国产" { @@ -555,6 +934,51 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j } 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)}, @@ -576,10 +1000,10 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j Key: "is7ToReturn", //不支持7天无理由退货 Value: "0", }, - &jdshopapi.CreateSkuParamFeatures{ - Key: "tssp", //支持自提 - Value: "4", - }, + // &jdshopapi.CreateSkuParamFeatures{ + // Key: "tssp", //支持自提 + // Value: "", + // }, // &jdshopapi.CreateSkuParamFeatures{ // Key: "fdms", //分单? // Value: "1", @@ -587,29 +1011,55 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j } createSkuParamWare.Features = features //组合sku - var vendorPrice int64 = 0 + var ( + vendorPrice int64 = 0 + wareSaveSkus []*jdshopapi.WareSaveSkus + ) + for _, v := range storeSku.StoreSkuSyncInfoJds { var ( - ggValueID int64 //规格的属性id - attrsPropSku []*jdshopapi.CreateSkuParamAttrs - multiPropSku []*jdshopapi.CreateSkuParamAttrs + ggValueID int64 //规格的属性id + ggValueName string //规格的属性名 + attrsPropSku []*jdshopapi.CreateSkuParamAttrs + attrsPropSku2 []*jdshopapi.WareSaveSkusProp //jds2 + multiPropSku []*jdshopapi.CreateSkuParamAttrs + specQuality string ) - valuesSku, maxNo, _ := api.JdShopAPI.FindValuesByAttrId(attrIDs["规格"]) - specQuality := utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit + 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, _ := api.JdShopAPI.SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1) + 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, @@ -618,8 +1068,15 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j 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 := api.JdShopAPI.FindValuesByAttrId(attrIDs["类别"]) + values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["类别"]) err = err2 lbValueID = values2[len(values2)-1].ID attrlb := &jdshopapi.CreateSkuParamAttrs{ @@ -636,18 +1093,22 @@ func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *j } 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 - return createSkuParamWare, createSkuParamSkus, err + wareSaveParam.Skus = wareSaveSkus + return createSkuParamWare, createSkuParamSkus, wareSaveParam, err } //京东商城上传图片,若平台上已经有了这个图就直接拿来用了 -func uploadImg(img, name, index string) (imgURL string, err error) { - result, err := api.JdShopAPI.QueryPicture(name + index) +func uploadImg(img, name, index, vendorOrgCode string) (imgURL string, err error) { + result, err := getAPI(vendorOrgCode).QueryPicture(name + index) if len(result) > 0 { imgURL = result[0].PictureURL } else { @@ -655,7 +1116,7 @@ func uploadImg(img, name, index string) (imgURL string, err error) { if err != nil { return imgURL, err } - uploadResult, err := api.JdShopAPI.UploadPicture(data, 0, name+index) + uploadResult, err := getAPI(vendorOrgCode).UploadPicture(data, 0, name+index) if err != nil { return imgURL, err } @@ -664,12 +1125,12 @@ func uploadImg(img, name, index string) (imgURL string, err error) { return imgURL, err } -func uploadImg2(img, name, index string) (imgURL string, err error) { +func uploadImg2(img, name, index, vendorOrgCode string) (imgURL string, err error) { data, _, err := jxutils.DownloadFileByURL(img) if err != nil { return imgURL, err } - uploadResult, err := api.JdShopAPI.UploadPicture(data, 0, name+index) + uploadResult, err := getAPI(vendorOrgCode).UploadPicture(data, 0, name+index) if err != nil { return imgURL, err } @@ -686,41 +1147,19 @@ func filterSensitiveWord(name string) (result string) { return name } -func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInfo, isCreate bool) (updateSkusParam *jdshopapi.UpdateSkusParam, err error) { +func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInfo, isCreate bool) (updateSkusParam *jdshopapi.UpdateSkusParam, wareSku *jdshopapi.WareSaveSkus, err error) { + var ( + ggValueID int64 //规格的属性id + ggValueName string //规格名 + attrsPropSku []*jdshopapi.CreateSkuParamAttrs + attrsPropSku2 []*jdshopapi.WareSaveSkusProp + skus []*jdshopapi.UpdateSkusParamSkus + multiPropSku []*jdshopapi.CreateSkuParamAttrs + specQuality string + ) updateSkusParam = &jdshopapi.UpdateSkusParam{ WareID: storeSku.JdsWareID, } - attrIDs := make(map[string]int) - attrs, err := api.JdShopAPI.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 - } - } - var ( - ggValueID int64 //规格的属性id - attrsPropSku []*jdshopapi.CreateSkuParamAttrs - skus []*jdshopapi.UpdateSkusParamSkus - multiPropSku []*jdshopapi.CreateSkuParamAttrs - ) - valuesSku, maxNo, _ := api.JdShopAPI.FindValuesByAttrId(attrIDs["规格"]) - specQuality := utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit - for _, v := range valuesSku { - if v.Name == specQuality { - ggValueID = v.ID - } - } - if ggValueID == 0 { //说明没有建这个规格,要建上 - catID, _ := api.JdShopAPI.SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1) - ggValueID = catID - } - attrSku := &jdshopapi.CreateSkuParamAttrs{ - AttrID: utils.Int2Str(attrIDs["规格"]), - AttrValues: []string{utils.Int64ToStr(ggValueID)}, - } - attrsPropSku = append(attrsPropSku, attrSku) sku := &jdshopapi.UpdateSkusParamSkus{ WareID: storeSku.JdsWareID, JdPrice: jxutils.IntPrice2Standard(v.VendorPrice), @@ -728,21 +1167,32 @@ func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInf Type2: "com.jd.pop.ware.ic.api.domain.Sku", OuterID: utils.Int2Str(v.SkuID), } - sku.SaleAttrs = attrsPropSku - if v.Status == model.SkuStatusNormal { + //jds2 + wareSku = &jdshopapi.WareSaveSkus{ + JdPrice: utils.Float64ToStr(jxutils.IntPrice2Standard(v.VendorPrice)), + OuterID: utils.Int2Str(v.SkuID), + } + + //库存设置 + if v.StoreSkuStatus == model.SkuStatusNormal { sku.StockNum = "9999" + wareSku.StockNum = 9999 } else { sku.StockNum = "0" + wareSku.StockNum = 0 } - if !isCreate { - result, err2 := api.JdShopAPI.FindSkuById(utils.Str2Int64(v.VendorSkuID)) - err = err2 - if specQuality != result.SaleAttrs[0].AttrValueAlias[0] { - api.JdShopAPI.DeleteSku(utils.Str2Int64(v.VendorSkuID)) + //规格类别设置 + attrIDs := make(map[string]int) + 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 } } if attrIDs["类别"] != 0 { - values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["类别"]) + values2, _, err2 := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["类别"]) err = err2 lbValueID := values2[len(values2)-1].ID attrlb := &jdshopapi.CreateSkuParamAttrs{ @@ -752,7 +1202,73 @@ func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInf multiPropSku = append(multiPropSku, attrlb) } sku.MultiCateProps = multiPropSku + if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] { + if math.Mod(float64(v.SpecQuality), 10) != 0 { + specQuality = strings.TrimRight(fmt.Sprintf("%.2f", float64(v.SpecQuality)), "0.") + v.SpecUnit + } else { + specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit + } + } else { + specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit + } + valuesSku, maxNo, _ := getAPI(storeSku.VendorOrgCode).FindValuesByAttrId(attrIDs["规格"]) + if isCreate { + for _, vv := range valuesSku { + if vv.Name == specQuality { + ggValueID = vv.ID + ggValueName = vv.Name + break + } + } + if ggValueID == 0 { //说明没有建这个规格,要建上 + catID, _ := getAPI(storeSku.VendorOrgCode).SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1) + ggValueID = catID + ggValueName = specQuality + } + attrSku := &jdshopapi.CreateSkuParamAttrs{ + AttrID: utils.Int2Str(attrIDs["规格"]), + AttrValues: []string{utils.Int64ToStr(ggValueID)}, + } + attrsPropSku = append(attrsPropSku, attrSku) + sku.SaleAttrs = attrsPropSku + //jds2 + attrSku2 := &jdshopapi.WareSaveSkusProp{ + AttrID: attrIDs["规格"], + AttrValues: ggValueID, + AttrValueAlias: ggValueName, + } + attrsPropSku2 = append(attrsPropSku2, attrSku2) + wareSku.Props = attrsPropSku2 + } else { + vendorSku, err2 := getAPI(storeSku.VendorOrgCode).FindSkuById(utils.Str2Int64(v.VendorSkuID)) + err = err2 + vendorAttrValue := vendorSku.SaleAttrs[0].AttrValueAlias[0] + if v.Comment != "" { + specQuality = v.Comment + } + if v.Comment != vendorAttrValue { + err = getAPI(storeSku.VendorOrgCode).UpdateWareSaleAttrvalueAlias(&jdshopapi.UpdateWareSaleAttrvalueAliasParam{ + WareID: v.JdsWareID, + Props: []*jdshopapi.CreateSkuParamAttrs2{ + &jdshopapi.CreateSkuParamAttrs2{ + AttrID: vendorSku.SaleAttrs[0].AttrID, + AttrValues: []string{vendorSku.SaleAttrs[0].AttrValues[0]}, + AttrValueAlias: []string{specQuality}, + Type: "com.jd.pop.ware.ic.api.domain.prop", + Type2: "com.jd.pop.ware.ic.api.domain.Prop", + }, + }, + }) + sku.SkuID = utils.Str2Int64(v.VendorSkuID) + } + attrSku := &jdshopapi.CreateSkuParamAttrs{ + AttrID: vendorSku.SaleAttrs[0].AttrID, + AttrValues: []string{vendorSku.SaleAttrs[0].AttrValues[0]}, + } + attrsPropSku = append(attrsPropSku, attrSku) + sku.SaleAttrs = attrsPropSku + } skus = append(skus, sku) updateSkusParam.Skus = skus - return updateSkusParam, err + return updateSkusParam, wareSku, err } diff --git a/business/partner/purchase/jx/localjx/order.go b/business/partner/purchase/jx/localjx/order.go index 4613a34fd..327c9bb70 100644 --- a/business/partner/purchase/jx/localjx/order.go +++ b/business/partner/purchase/jx/localjx/order.go @@ -1,14 +1,14 @@ package localjx import ( - "crypto/md5" "fmt" "math" "regexp" - "sort" "strings" "time" + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" + "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" "git.rosy.net.cn/jx-callback/business/jxstore/event" @@ -21,6 +21,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxutils/ddmsg" "git.rosy.net.cn/jx-callback/business/jxutils/netprinter" + "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/baseapi/platformapi/dingdingapi" "git.rosy.net.cn/baseapi/utils" @@ -31,7 +32,6 @@ import ( "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/delivery" ) const ( @@ -46,10 +46,12 @@ const ( wxAppID = "wx4b5930c13f8b1170" - autoCancelOrderReason = "支付超时,系统自动取消!" - cancelMatterOrderReason = "失败重发!" + autoCancelOrderReason = "支付超时,系统自动取消!" + cancelMatterOrderReason = "失败重发!" + settleDiscountActRefundReason = "守价订单生成补退款" - splitMatterOrderMinWeight = 4500 //物料订单分包最少要4.5kg + splitMatterOrderMinWeight = 4500 //物料订单分包最少要4.5kg + jxwxfMatterEclpID = "EMG4418113943423" //京西五香粉物料编码 ) type JxSkuInfo struct { @@ -62,6 +64,8 @@ type JxSkuInfo struct { Name string `json:"name"` Weight int `json:"weight"` GroupSign bool `json:"groupSign"` + + DefendPrice int64 `json:"defendPrice"` //守价 } type JxSkuInfo2 struct { @@ -105,10 +109,16 @@ type JxOrderInfo struct { OrderPrice int64 `json:"orderPrice"` // 单位为分 订单商品价格 ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付 - OrderID int64 `json:"orderID"` - StoreName string `json:"storeName"` - Weight int `json:"weight"` - FromStoreID int `json:"fromStoreID"` + OrderID int64 `json:"orderID"` + StoreName string `json:"storeName"` + Weight int `json:"weight"` + FromStoreID int `json:"fromStoreID"` + EarningType int `json:"earningType"` + OrderType int `json:"orderType"` + IsBuyNowPrice int `json:"isBuyNowPrice"` + IsPriceDefend int `json:"isPriceDefend"` + OrderID2 string `json:"-"` + UserID string `json:"userID"` } type DeliveryTimeItem struct { @@ -130,8 +140,6 @@ type MatterOrderStatus struct { } var ( - orderNoBeginTimestamp int64 - weekdayMap = map[int]string{ 1: "一", 2: "二", @@ -164,7 +172,6 @@ var ( ) func init() { - orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() } func GetMyOrders(ctx *jxcontext.Context, fromDateStr, toDateStr string, params map[string]interface{}, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { @@ -201,38 +208,86 @@ func GetMyOrders(ctx *jxcontext.Context, fromDateStr, toDateStr string, params m return pagedInfo, err } +func GetMyAfsOrders(ctx *jxcontext.Context, vendorOrderID, afsOrderID, userID, fromTime, toTime string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { + afsOrderList, totalCount, err := dao.GetAfsOrdersByPage(dao.GetDB(), vendorOrderID, afsOrderID, userID, utils.Str2Time(fromTime), utils.Str2Time(toTime), offset, pageSize) + pagedInfo = &model.PagedInfo{ + TotalCount: totalCount, + Data: afsOrderList, + } + return pagedInfo, err +} + func GetMyOrderCountInfo(ctx *jxcontext.Context, fromDate, toDate time.Time, statuss []int) (countInfo []*model.GoodsOrderCountInfo, err error) { countInfo, err = dao.GetMyOrderCountInfo(dao.GetDB(), ctx.GetUserID(), fromDate, toDate, statuss) return countInfo, err } //fromStoreID 为0 表示非物料订单(京西商城订单等) -//fromStoreID 为 门店ID ,表示是物料订单,fromStoreID表示是哪个门店申请的物料 +//fromStoreID 为 门店ID ,表示是物料订单,fromStoreID表示是哪个门店申请的物料,或者进货方门店 //fromStoreID 为-1 表示也是物料订单,但是不是门店申请,是个人申请的 //fromStoreID 在后面 generateOrder中有用 -func CreateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, createType int, fromStoreID int, IsDeliverySelf bool) (outJxOrder *JxOrderInfo, err error) { - outJxOrder, deliveryAddress, err := generateOrder(ctx, jxOrder, addressID, fromStoreID, "", IsDeliverySelf) +//IsAuto 是否是守价结算而自动创建的守价订单 +func CreateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, createType int, fromStoreID int, IsDeliverySelf bool, couponIDs []int) (outJxOrder *JxOrderInfo, err error) { + outJxOrder, deliveryAddress, err := generateOrder(ctx, jxOrder, addressID, fromStoreID, "", IsDeliverySelf, couponIDs) if err != nil { return nil, err } - if fromStoreID != 0 { + if jxOrder.OrderType == model.OrderTypeMatter { checkMatterDeliveryAddress(deliveryAddress) } - if createType != OrderCreateTypePre { - if outJxOrder.TotalPrice != jxOrder.TotalPrice { + if createType == OrderCreateTypeNormal { + if jxOrder.OrderType == model.OrderTypeDefendPrice && jxOrder.IsPriceDefend != model.YES { + vendorOrderID := buildDefendPriceOrder(ctx, jxOrder, addressID) + outJxOrder.OrderID = utils.Str2Int64(vendorOrderID) + return outJxOrder, err + } + if outJxOrder.TotalPrice != jxOrder.TotalPrice && jxOrder.IsPriceDefend != model.YES { return nil, fmt.Errorf("商品或配送信息发生改变,请重新下单") } - outJxOrder.OrderID = GenOrderNo(ctx) - order, err2 := jxOrder2GoodsOrder(ctx, outJxOrder, deliveryAddress, "", IsDeliverySelf) + if jxOrder.IsPriceDefend == model.YES { + outJxOrder.OrderID = jxOrder.OrderID + } else { + outJxOrder.OrderID = jxutils.GenOrderNo() + } + order, err2 := jxOrder2GoodsOrder(ctx, outJxOrder, deliveryAddress, "", IsDeliverySelf, couponIDs) if err = err2; err == nil { order.AddressID = addressID - order.Status = model.OrderStatusWait4Pay + if jxOrder.IsPriceDefend == model.YES { + order.Status = model.OrderStatusAccepted + } else { + order.Status = model.OrderStatusWait4Pay + } callNewOrder(order) } } return outJxOrder, err } +func buildDefendPriceOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64) (vendorOrderID string) { + var ( + issue = 0 + db = dao.GetDB() + ) + issue = jxutils.GetDefendPriceIssue() + priceDefendOrder := &model.PriceDefendOrder{ + VendorOrderID: utils.Int64ToStr(jxutils.GenOrderNo()), + StoreID: jxOrder.StoreID, + SkuID: jxOrder.Skus[0].SkuID, + AddressID: addressID, + Count: jxOrder.Skus[0].Count, + DefendPrice: jxOrder.Skus[0].DefendPrice, + OriginPrice: jxOrder.Skus[0].Price, + IsBuyNowPrice: jxOrder.IsBuyNowPrice, + Issue: issue, + IsSuccess: model.NO, //默认是不成功 + IsPay: model.NO, + } + dao.WrapAddIDCULDEntity(priceDefendOrder, ctx.GetUserName()) + priceDefendOrder.ActualPayPrice = int64(priceDefendOrder.Count)*jxOrder.Skus[0].Price + jxOrder.FreightPrice + dao.CreateEntity(db, priceDefendOrder) + return priceDefendOrder.VendorOrderID +} + // 买家取消(或申请取消)订单 func BuyerCancelOrder(ctx *jxcontext.Context, orderID int64, reason string) (canceled bool, err error) { order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX) @@ -251,7 +306,10 @@ func BuyerCancelOrder(ctx *jxcontext.Context, orderID int64, reason string) (can return canceled, err } -func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) { +func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType, subAppID string) (orderPay *model.OrderPay, err error) { + var ( + db = dao.GetDB() + ) order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX) if err == nil { switch payType { @@ -261,24 +319,131 @@ func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType err = dao.CreateEntity(dao.GetDB(), orderPay) } case model.PayTypeTL: - if orderPay, err = pay4OrderByTL(ctx, order, vendorPayType); err == nil && orderPay != nil { + if orderPay, err = pay4OrderByTL(ctx, order, payType, vendorPayType, subAppID); err == nil && orderPay != nil { dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) err = dao.CreateEntity(dao.GetDB(), orderPay) } default: err = fmt.Errorf("支付方式:%d当前不支持", payType) } + } else { + priceDefendOrders, _ := dao.GetPriceDefendOrder(db, utils.Int64ToStr(orderID), nil, nil, []int{jxutils.GetDefendPriceIssue()}, 0, -1, -1, 0, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefendOrders) == 0 { + err = fmt.Errorf("未查询到待支付订单!order_id: %v", orderID) + } + order2 := &model.GoodsOrder{ + VendorOrderID: priceDefendOrders[0].VendorOrderID, + ActualPayPrice: priceDefendOrders[0].ActualPayPrice, + VendorID: model.VendorIDJX, + } + if orderPay, err = pay4OrderByTL(ctx, order2, payType, vendorPayType, subAppID); err == nil && orderPay != nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } } return orderPay, err } +func Pay4User(ctx *jxcontext.Context, thingID int, vendorOrderID string, payType int, vendorPayType, subAppID string) (orderPay *model.OrderPay, err error) { + var ( + db = dao.GetDB() + order *model.GoodsOrder + dicountCards []*model.DiscountCard + ) + switch payType { + case model.PayTypeTL_DiscountCard: + if configList, err := dao.QueryConfigs(db, "会员折扣卡", model.ConfigTypeDiscountCard, ""); err == nil { + jxutils.Strings2Objs(configList[0].Value, &dicountCards) + if err != nil { + return nil, err + } + discountCard := findDiscountCard(dicountCards, thingID) + flag, userMemberOrigin, err := checkMember(db, ctx.GetUserID(), discountCard) + if err != nil { + return nil, err + } + vendorOrderID = utils.Int64ToStr(jxutils.GenOrderNo()) + order = &model.GoodsOrder{ + VendorOrderID: vendorOrderID, + ActualPayPrice: int64(discountCard.Price), + VendorID: model.VendorIDJX, + } + if orderPay, err = pay4OrderByTL(ctx, order, payType, vendorPayType, subAppID); err == nil && orderPay != nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } + userMember := &model.UserMember{ + VendorOrderID: vendorOrderID, + UserID: ctx.GetUserID(), + MemberType: model.MemberTypeDiscountCard, + EndAt: utils.Str2Time(time.Now().AddDate(0, 1, 0).AddDate(0, 0, -1).Format("2006-01-02") + " 23:59:59"), + MemberTypeID: thingID, + IsPay: model.NO, + } + dao.WrapAddIDCULDEntity(userMember, ctx.GetUserName()) + if flag == 0 { + dao.CreateEntity(db, userMember) + } else if flag == 1 { + userMemberOrigin.EndAt = userMemberOrigin.EndAt.AddDate(0, 1, 0) + dao.UpdateEntity(db, userMemberOrigin, "EndAt") + } + } + case model.PayTypeTL_StoreAcctPay: + storeOrder := &model.StoreAcctOrder{ + VendorOrderID: vendorOrderID, + } + if err = dao.GetEntity(db, storeOrder, "VendorOrderID"); err == nil && storeOrder.ID != 0 { + order = &model.GoodsOrder{ + VendorOrderID: vendorOrderID, + ActualPayPrice: int64(storeOrder.ActualPayPrice), + VendorID: model.VendorIDJX, + } + if orderPay, err = pay4OrderByTL(ctx, order, payType, vendorPayType, subAppID); err == nil && orderPay != nil { + dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName()) + err = dao.CreateEntity(dao.GetDB(), orderPay) + } + } + default: + err = fmt.Errorf("支付方式:%d当前不支持", payType) + } + return orderPay, err +} + +//flag +//0 正常购买 +//1 续费 +//-1 不能购买 +func checkMember(db *dao.DaoDB, userID string, discountCard *model.DiscountCard) (flag int, userMember *model.UserMember, err error) { + userMembers, err := dao.GetUserMember(db, userID, "", model.MemberTypeDiscountCard, model.YES) + if len(userMembers) > 0 { + userMember = userMembers[0] + if userMember.ID < discountCard.ID { + return 0, userMember, err + } else if userMember.ID == discountCard.ID { + return 1, userMember, err + } else { + return -1, userMember, fmt.Errorf("已购买更高档次的会员,无法继续购买!") + } + } + return 0, userMember, err +} + func time2ShortTimeStr(t time.Time) string { return t.Format("15:04") } +func findDiscountCard(dicountCards []*model.DiscountCard, thingID int) (dicountCard *model.DiscountCard) { + for _, v := range dicountCards { + if v.ID == thingID { + return v + } + } + return dicountCard +} + func GetAvailableDeliverTime(ctx *jxcontext.Context, storeID int) (deliverTimerList []*DeliveryDayTimeInfo, err error) { db := dao.GetDB() - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX) + storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX, "") if err != nil { return nil, err } @@ -360,30 +525,51 @@ func OnPayFinished(orderPay *model.OrderPay) (err error) { order.StatusTime = *orderPay.PayFinishedAt err = callNewOrder(order) //如果是物料的订单,直接到拣货完成,配送中的状态 - if order.FromStoreID != 0 { - netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) + if order.OrderType != model.OrderTypeNormal { + // if order.FromStoreID != 0 { + if order.OrderType != model.OrderTypeDefendPrice { + netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order) + } PickupGoods(order, false, "jxadmin") + // } + } else { + //普通的订单要看用没用优惠券,用了的话,要把这个用户用过的优惠券状态改了 + if order.CouponIDs != "" { + sCouponIDs := strings.Split(order.CouponIDs, ",") + couponIDs := []int{} + for _, v := range sCouponIDs { + couponIDs = append(couponIDs, utils.Str2Int(v)) + } + if userCoupons, err := dao.GetUserCoupons(db, couponIDs, []string{order.UserID}, nil, model.CouponStatusNormal); err == nil { + for _, vv := range userCoupons { + vv.UserCouponStatus = model.UserCouponStatusUsed + vv.UpdatedAt = time.Now() + dao.UpdateEntity(db, vv, "UserCouponStatus", "UpdatedAt") + } + } + } + } + } else { + switch orderPay.PayType { + case model.PayTypeTL_DiscountCard: + userMembers, _ := dao.GetUserMember(dao.GetDB(), "", orderPay.VendorOrderID, model.MemberTypeDiscountCard, model.NO) + if len(userMembers) > 0 { + userMembers[0].IsPay = model.YES + dao.UpdateEntity(dao.GetDB(), userMembers[0], "IsPay") + err = nil + } + default: + priceDefendOrders, _ := dao.GetPriceDefendOrder(dao.GetDB(), orderPay.VendorOrderID, nil, nil, []int{jxutils.GetDefendPriceIssue()}, 0, -1, -1, 0, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefendOrders) > 0 { + priceDefendOrders[0].IsPay = model.YES + dao.UpdateEntity(dao.GetDB(), priceDefendOrders[0], "IsPay") + err = nil + } } } return err } -func GenOrderNo(ctx *jxcontext.Context) (orderNo int64) { - const prefix = 88 - const randPartNum = 1000 - orderNo = time.Now().Unix() - orderNoBeginTimestamp - // fmt.Println(orderNo) - 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 GenPayOrderID(order *model.GoodsOrder) (payOrderID int64) { return utils.Str2Int64(order.VendorOrderID) } @@ -429,13 +615,13 @@ func isTimeInOpTime(openTime1, closeTime1, openTime2, closeTime2 int16, time2Che return false } -func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, fromStoreID int, userID string, IsDeliverySelf bool) (outJxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, err error) { +func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, fromStoreID int, userID string, IsDeliverySelf bool, couponIDs []int) (outJxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, err error) { db := dao.GetDB() if jxOrder.StoreID == 0 { return nil, nil, fmt.Errorf("没有指定门店信息") } // 配送范围检查 - storeDetail, err := dao.GetStoreDetail(db, jxOrder.StoreID, model.VendorIDJX) + storeDetail, err := dao.GetStoreDetail(db, jxOrder.StoreID, model.VendorIDJX, "") if err != nil { return nil, nil, err } @@ -443,7 +629,7 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 if userID == "" { addressList, _, err = dao.QueryUserDeliveryAddress(db, addressID, nil, 0, 0) } else { - addressList, _, err = dao.QueryUserDeliveryAddress(db, addressID, []string{userID}, 0, 0) + addressList, _, err = dao.QueryUserDeliveryAddress(db, addressID, nil, 0, 0) } if err != nil { return nil, nil, err @@ -455,6 +641,12 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 if distance := jxutils.Point2StoreDistance(deliveryAddress.Lng, deliveryAddress.Lat, storeDetail.Lng, storeDetail.Lat, storeDetail.DeliveryRangeType, storeDetail.DeliveryRange); distance == 0 { return nil, nil, fmt.Errorf("当前送货地址不在门店%s的配送范围", storeDetail.Name) } + //结算类型 + if storeDetail.PayPercentage < 50 { + jxOrder.EarningType = model.EarningTypePoints + } else { + jxOrder.EarningType = model.EarningTypeQuote + } // 营业状态及时间检查 if storeDetail.Status != model.StoreStatusOpened { // model.StoreStatusDisabled { @@ -474,17 +666,12 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 return nil, nil, fmt.Errorf("预订单只能预定当天或第二天") } } - // if !isTimeInOpTime(storeDetail.OpenTime1, storeDetail.CloseTime1, storeDetail.OpenTime2, storeDetail.CloseTime2, checkTime) { - // return nil, nil, fmt.Errorf("门店:%s不在营业时间范围", storeDetail.Name) - // } - outJxOrder2 := *jxOrder outJxOrder2.Skus = nil outJxOrder2.OrderPrice = 0 outJxOrder2.Weight = 0 outJxOrder = &outJxOrder2 outJxOrder.StoreName = storeDetail.Name - skus := formalizeSkus(jxOrder.Skus) // 允许空商品列表(一般用于测试配送地址,门店信息是否合适) if len(skus) > 0 { @@ -514,7 +701,10 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 } skuMap := make(map[int]*model.SkuAndName) for _, v := range skuList { - if fromStoreID != 0 { + // if fromStoreID != 0 { + + // } + if jxOrder.OrderType == model.OrderTypeMatter { if v.EclpID == "" { return nil, nil, fmt.Errorf("此商品物料编码为空,请联系管理员!skuID:[%v]", v.ID) } @@ -526,7 +716,11 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 sum int //申请物料的店的最近销量,以下会根据销量计算具体袋子的价格 flag = false //新店袋子拆分当个参数 ) - if fromStoreID != 0 && fromStoreID != -1 { + // if fromStoreID != 0 && fromStoreID != -1 { + // result, _ = orderman.GetMatterStoreOrderCount(nil, fromStoreID) + // sum = result.Count + // } + if jxOrder.OrderType == model.OrderTypeMatter && fromStoreID != -1 { result, _ = orderman.GetMatterStoreOrderCount(nil, fromStoreID) sum = result.Count } @@ -538,7 +732,8 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 } for _, v := range skus { if storeSkuBind := storeSkuMap[v.SkuID]; storeSkuBind != nil { - if fromStoreID != 0 { + // if fromStoreID != 0 { + if jxOrder.OrderType == model.OrderTypeMatter { result2, _ := api.JdEclpAPI.QueryStock(storeSkuBind.EclpID) if len(result2) > 0 { if result2[0].UsableNum < v.Count { @@ -546,6 +741,7 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 } } } + // } if sku := skuMap[v.SkuID]; sku != nil { jxSku := &JxSkuInfo{ SkuID: v.SkuID, @@ -555,7 +751,7 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 Weight: sku.Weight, Name: jxutils.ComposeSkuName(sku.Prefix, sku.Name, sku.Comment, sku.Unit, sku.SpecQuality, sku.SpecUnit, 0, sku.ExPrefix, sku.ExPrefixBegin, sku.ExPrefixEnd), } - if fromStoreID != -1 { + if fromStoreID != -1 && storeSkuBind.ActType != model.ActSkuDiscount { //活动商品要拆分,一分钱的单独列一个(count为1),正常价格的列在一起(count叠加) if storeSkuBind.ActPrice != 0 && storeSkuBind.ActPrice < storeSkuBind.JxPrice { jxSku.SalePrice = int64(storeSkuBind.ActPrice) @@ -574,9 +770,12 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 jxSku = nil } } + } else if storeSkuBind.ActType == model.ActSkuDiscount && jxOrder.OrderType != model.OrderTypeDefendPrice { //守价的订单是支付原价 + jxSku.SalePrice = int64(storeSkuBind.ActPrice) } if jxSku != nil { - if fromStoreID == 0 || fromStoreID == -1 { + // if fromStoreID == 0 || fromStoreID == -1 { + if jxOrder.OrderType != model.OrderTypeMatter || (jxOrder.OrderType == model.OrderTypeMatter && fromStoreID == -1) { outJxOrder.Skus = append(outJxOrder.Skus, jxSku) outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice } else { //以下else为物料订单袋子金额和数量处理 @@ -675,47 +874,66 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 } } } - //物料订单的配送费另算,所以排除了免得多算一次 - if fromStoreID == 0 { - sort.Sort(JxSkuInfoList(outJxOrder.Skus)) - outJxOrder.FreightPrice, _, err = delivery.CalculateDeliveryFee(dao.GetDB(), jxOrder.StoreID, "", - jxutils.StandardCoordinate2Int(deliveryAddress.Lng), jxutils.StandardCoordinate2Int(deliveryAddress.Lat), - model.CoordinateTypeMars, outJxOrder.Weight, checkTime) - } - // if jxOrder.StoreID == specialStoreID { - // outJxOrder.FreightPrice = 0 + // if fromStoreID == 0 { + // sort.Sort(JxSkuInfoList(outJxOrder.Skus)) + // outJxOrder.FreightPrice, _, err = delivery.CalculateDeliveryFee(dao.GetDB(), jxOrder.StoreID, "", + // jxutils.StandardCoordinate2Int(deliveryAddress.Lng), jxutils.StandardCoordinate2Int(deliveryAddress.Lat), + // model.CoordinateTypeMars, outJxOrder.Weight, checkTime) + //TODO 2020-08-06 配送费固定5元 + outJxOrder.FreightPrice = 500 // } + //如果是守价的订单,需要查询本期中该用户是否已经守价过,如果守价过就只算一次运费 + if jxOrder.OrderType == model.OrderTypeDefendPrice { + priceDefendOrders, _ := dao.GetPriceDefendOrder(db, "", nil, nil, []int{jxutils.GetDefendPriceIssue()}, 0, -1, -1, 1, deliveryAddress.UserID, utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefendOrders) > 0 { + flag2 := false + for _, v := range priceDefendOrders { + if v.StoreID != jxOrder.StoreID { + flag2 = true + } + } + if flag2 { + return nil, nil, fmt.Errorf("同一期不允许相同用户在不同门店进行守价!") + } + outJxOrder.FreightPrice = 0 + } + } } else { outJxOrder.FreightPrice = 0 } //表示此订单为物料配送订单 - if fromStoreID != 0 { - storeDetail2, err2 := dao.GetStoreDetail(db, fromStoreID, model.VendorIDJX) + if jxOrder.OrderType != model.OrderTypeNormal { + // if fromStoreID != 0 { + storeDetail2, err2 := dao.GetStoreDetail(db, fromStoreID, model.VendorIDJX, "") if err = err2; err != nil { return nil, nil, fmt.Errorf("fromStoreID有误,[%v]", fromStoreID) } + outJxOrder.FromStoreID = fromStoreID + if jxOrder.OrderType == model.OrderTypeMatter { + //TODO 修改配送费规则,2020-04-28 + //3kg 5元,每多1kg加2元 + //配送费要按分包规则计算 + if outJxOrder.Weight <= 3000 { + outJxOrder.FreightPrice = 500 + } else if outJxOrder.Weight > 3000 && outJxOrder.Weight <= splitMatterOrderMinWeight { + outJxOrder.FreightPrice = utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(outJxOrder.Weight)-3000)/1000)*200) + } else { + _, freightPrice, _ := tryToSplitMatterOrder(jxOrder) + outJxOrder.FreightPrice = freightPrice + } + } //要求配送人姓名填门店名 if fromStoreID != -1 { deliveryAddress.ConsigneeName = storeDetail2.Name } - outJxOrder.FromStoreID = fromStoreID - //TODO 修改配送费规则,2020-04-28 - //3kg 5元,每多1kg加2元 - //配送费要按分包规则计算 - if outJxOrder.Weight <= 3000 { - outJxOrder.FreightPrice = 500 - } else if outJxOrder.Weight > 3000 && outJxOrder.Weight <= splitMatterOrderMinWeight { - outJxOrder.FreightPrice = utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(outJxOrder.Weight)-3000)/1000)*200) - } else { - _, freightPrice, _ := tryToSplitMatterOrder(jxOrder) - outJxOrder.FreightPrice = freightPrice + //内蒙古海南统一35 + //新疆西藏统一45 + if deliveryAddress.ParentCode == 150000 || deliveryAddress.ParentCode == 460000 { + outJxOrder.FreightPrice = 3500 + } + if deliveryAddress.ParentCode == 650000 || deliveryAddress.ParentCode == 540000 { + outJxOrder.FreightPrice = 4500 } - ///规则为: 配送费用规则。起价5元(含2kg),之后每kg+2元,不足1kg按1kg计算。 - // if outJxOrder.Weight <= 2000 { - // outJxOrder.FreightPrice = 500 - // } else { - // outJxOrder.FreightPrice = utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(outJxOrder.Weight)-2000)/1000)*200) - // } } else { if outJxOrder.FreightPrice > specialFreightPrice { outJxOrder.FreightPrice = specialFreightPrice @@ -726,10 +944,80 @@ func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64 outJxOrder.FreightPrice = 0 } } + if IsDeliverySelf { + outJxOrder.FreightPrice = 0 + } } if err == nil { - outJxOrder.TotalPrice = outJxOrder.OrderPrice + outJxOrder.FreightPrice - outJxOrder.ActualPayPrice = outJxOrder.TotalPrice + if jxOrder.OrderType == model.OrderTypeNormal { + outJxOrder.TotalPrice = outJxOrder.OrderPrice + outJxOrder.FreightPrice + var ( + tuserID string + dicountCards []*model.DiscountCard + ) + if userID == "" { + tuserID = deliveryAddress.UserID + } else { + tuserID = userID + } + // 1.先扣除优惠券 + if len(couponIDs) > 0 { + if userCoupons, err := dao.GetUserCoupons(db, couponIDs, []string{tuserID}, nil, model.CouponStatusNormal); err == nil { + if len(userCoupons) != len(couponIDs) { + return nil, nil, fmt.Errorf("选择的优惠券状态不正常,请刷新后重试!") + } + for _, v := range userCoupons { + coupon := &model.Coupons{} + coupon.ID = int64(v.CouponID) + if err = dao.GetEntity(db, coupon); err == nil && coupon.Name != "" { + checkPrice := func(price int64) (rPrice int64, err error) { + priceInt := int(price) + if priceInt < coupon.UpperLimit { + return 0, fmt.Errorf("抱歉,该订单价格未达到此优惠券[%v]满减额度!", coupon.Name) + } + if priceInt <= coupon.Cut { + rPrice = 0 + } else { + rPrice = int64(priceInt - coupon.Cut) + } + return rPrice, err + } + switch coupon.CouponType { + case model.CouponTypeDiscount: + outJxOrder.OrderPrice, err = checkPrice(outJxOrder.OrderPrice) + case model.CouponTypeDelivery: + outJxOrder.FreightPrice, err = checkPrice(outJxOrder.FreightPrice) + default: + return nil, nil, fmt.Errorf("暂不支持的优惠券类型![%v]", coupon.CouponType) + } + if err != nil { + return nil, nil, err + } + } + } + } else { + return nil, nil, err + } + } + // 2.判断用户是否是会员 + userMembers, _ := dao.GetUserMember(db, tuserID, "", model.MemberTypeDiscountCard, model.YES) + if len(userMembers) > 0 { + if configList, err := dao.QueryConfigs(db, "会员折扣卡", model.ConfigTypeDiscountCard, ""); err == nil { + jxutils.Strings2Objs(configList[0].Value, &dicountCards) + discountCard := findDiscountCard(dicountCards, userMembers[0].MemberTypeID) + outJxOrder.OrderPrice = utils.Float64TwoInt64(math.Round(float64(outJxOrder.OrderPrice) * float64(int64(discountCard.PicePercentage)) / float64(100))) + } + } + outJxOrder.ActualPayPrice = outJxOrder.OrderPrice + outJxOrder.FreightPrice + } else if jxOrder.OrderType == model.OrderTypeDefendPrice { + outJxOrder.Skus[0].DefendPrice = jxOrder.Skus[0].DefendPrice + } else { + outJxOrder.TotalPrice = outJxOrder.OrderPrice + outJxOrder.FreightPrice + outJxOrder.ActualPayPrice = outJxOrder.TotalPrice + } + if jxOrder.UserID != "" { + outJxOrder.UserID = jxOrder.UserID + } } else { outJxOrder = nil deliveryAddress = nil @@ -771,7 +1059,7 @@ func matterSkusLimited(skus []*JxSkuInfo, storeID int) (err error) { return err } -func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, userID string, IsDeliverySelf bool) (order *model.GoodsOrder, err error) { +func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, userID string, IsDeliverySelf bool, couponIDs []int) (order *model.GoodsOrder, err error) { order = &model.GoodsOrder{ VendorOrderID: utils.Int64ToStr(jxOrder.OrderID), VendorID: model.VendorIDJX, @@ -793,8 +1081,18 @@ func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAd OrderSeq: 0, BuyerComment: jxOrder.BuyerComment, - DeliveryType: model.OrderDeliveryTypeStoreSelf, - StatusTime: time.Now(), + DeliveryType: model.OrderDeliveryTypeStoreSelf, + StatusTime: time.Now(), + EarningType: jxOrder.EarningType, + OrderType: jxOrder.OrderType, + VendorOrderID2: jxOrder.OrderID2, + } + if len(couponIDs) > 0 { + strCounponIDs := []string{} + for _, v := range couponIDs { + strCounponIDs = append(strCounponIDs, utils.Int2Str(v)) + } + order.CouponIDs = strings.Join(strCounponIDs, ",") } if userID == "" { order.UserID = ctx.GetUserID() @@ -803,6 +1101,12 @@ func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAd } order.OrderCreatedAt = order.StatusTime order.VendorUserID = order.UserID + if order.UserID == "" && order.VendorUserID == "" { + if jxOrder.UserID != "" { + order.UserID = jxOrder.UserID + order.VendorUserID = jxOrder.UserID + } + } if jxOrder.ExpectedDeliveredTimestamp != 0 { order.ExpectedDeliveredTime = utils.Timestamp2Time(jxOrder.ExpectedDeliveredTimestamp) order.BusinessType = model.BusinessTypeDingshida @@ -822,13 +1126,16 @@ func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAd order.TotalShopMoney += int64(sku.Count) * sku.SalePrice } order.TotalShopMoney += jxOrder.FreightPrice - order.ActualPayPrice = order.TotalShopMoney + order.ActualPayPrice = jxOrder.ActualPayPrice + order.TotalShopMoney = utils.Float64TwoInt64(float64(order.TotalShopMoney) * jdshopapi.JdsPayPercentage) if jxOrder.FromStoreID != 0 { order.FromStoreID = jxOrder.FromStoreID - order.WaybillVendorID = model.VendorIDJDWL order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled - order.ConsigneeAddress = deliveryAddress.Address order.Flag = 1 + if jxOrder.OrderType == model.OrderTypeMatter { + order.WaybillVendorID = model.VendorIDJDWL + order.ConsigneeAddress = deliveryAddress.Address + } } //如果是自提单就设置 if IsDeliverySelf { @@ -854,16 +1161,20 @@ func AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList func PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { err = changeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "") //如果是物料订单则直接进行京东物流的发单,并且状态直接变为配送中 - err = orderSolutionForWuLiao(order) + //如果是进货的订单,直接变为配送中 + if order.OrderType != model.OrderTypeNormal { + err = orderSolutionForWuLiao(order) + } return err } func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) { - if order.FromStoreID != 0 { + // if order.FromStoreID != 0 { + err = changeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "") + if order.OrderType == model.OrderTypeMatter { var ( db = dao.GetDB() ) - err = changeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "") goods, err := dao.QueryOrders(db, order.VendorOrderID, -1, []int{model.VendorIDJX}, -1, utils.ZeroTimeValue, utils.ZeroTimeValue) if err != nil || len(goods) == 0 { return err @@ -876,6 +1187,7 @@ func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) { goodsNos []string prices []string quantities []string + countSum int ) for _, v := range orderSkus { skus, err := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil) @@ -885,12 +1197,35 @@ func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) { goodsNos = append(goodsNos, skus[0].EclpID) prices = append(prices, "0") quantities = append(quantities, utils.Int2Str(v.Count)) + countSum += v.Count + } + //总订单不足3kg && 商品数量不足3个 && 五香粉有库存,要送五香粉,补足3个 + stockResult, err := api.JdEclpAPI.QueryStock(jxwxfMatterEclpID) + if err == nil && len(stockResult) > 0 && stockResult[0].UsableNum > 0 { + if order.Weight < 3000 && countSum < 3 { + //要判断他本身买没买五香粉EMG4418113943423 + var index = 9999 + for k, v := range goodsNos { + if v == jxwxfMatterEclpID { + index = k + } + } + //说明他买了五香粉 + if index != 9999 { + quantities[index] = utils.Int2Str(utils.Str2Int(quantities[index]) + 3 - countSum) + } else { + goodsNos = append(goodsNos, jxwxfMatterEclpID) + prices = append(prices, "0") + quantities = append(quantities, utils.Int2Str(3-countSum)) + } + } } result, err := api.JdEclpAPI.AddOrder(&jdeclpapi.AddOrderParam{ IsvUUID: order.VendorOrderID, IsvSource: jdeclpapi.IsvSource, ShopNo: jdeclpapi.ShopNo, DepartmentNo: jdeclpapi.DepartmentNo, + ShipperNo: jdeclpapi.ShipperNo, WarehouseNo: jdeclpapi.WarehouseNo, SalesPlatformOrderNo: order.VendorOrderID, SalePlatformSource: jdeclpapi.SalePlatformSource, @@ -923,15 +1258,18 @@ func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) { outOrders, _, _ := tryToSplitMatterOrder(buildJxOrderInfo(order, orderSkus)) //以下为仿照CreateOrder,改了一些参数 for k, v := range outOrders { - outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, v, order.AddressID, order.FromStoreID, order.UserID, false) + v.OrderType = model.OrderTypeMatter + v.FromStoreID = order.FromStoreID + outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, v, order.AddressID, order.FromStoreID, order.UserID, false, nil) if err != nil { return err } //分包后的子订单ID默认是后面加两位(目前的规则),要改的话要注意取消订单那的判断 outJxOrder.OrderID = utils.Str2Int64(order.VendorOrderID)*100 + int64(k+1) checkMatterDeliveryAddress(deliveryAddress) - order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false) + order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false, nil) if err = err2; err == nil { + order2.FromStoreID = v.FromStoreID order2.AddressID = order.AddressID order2.Status = model.OrderStatusDelivering err = partner.CurOrderManager.OnOrderNew(order2, model.Order2Status(order2)) @@ -945,7 +1283,7 @@ func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) { } for _, v := range order.Skus { if bagSkuMap[v.SkuID] != 0 { - stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, nil, "") if len(stores) > 0 { store := stores[0] store.IsBoughtMatter = model.YES @@ -985,12 +1323,27 @@ func CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) errList.AddErr(err) } } else if orderPay.PayType == model.PayTypeTL { - orderPayRefund, err = refundOrderByTL(ctx, orderPay, refundID, orderPay.TotalFee, reason) + orderPayRefund, err = RefundOrderByTL(ctx, orderPay, refundID, orderPay.TotalFee, reason) if err != nil { errList.AddErr(err) } } if err == nil { + //如果用了优惠券,状态要刷回去 + if order.CouponIDs != "" { + sCouponIDs := strings.Split(order.CouponIDs, ",") + couponIDs := []int{} + for _, v := range sCouponIDs { + couponIDs = append(couponIDs, utils.Str2Int(v)) + } + if userCoupons, err := dao.GetUserCoupons(db, couponIDs, []string{order.UserID}, nil, model.CouponStatusNormal); err == nil { + for _, vv := range userCoupons { + vv.UserCouponStatus = model.CouponStatusNormal + vv.UpdatedAt = time.Now() + dao.UpdateEntity(db, vv, "UserCouponStatus", "UpdatedAt") + } + } + } MarkArrears(db, order, orderPay) err2 := CancelMatterOrder(db, order, reason) errList.AddErr(err2) @@ -1020,7 +1373,8 @@ func CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) } func CancelMatterOrder(db *dao.DaoDB, order *model.GoodsOrder, reason string) (err error) { - if order.FromStoreID != 0 { + // if order.FromStoreID != 0 { + if order.OrderType == model.OrderTypeMatter { if order.EclpOutID != "" { //表示是京西的物料订单的子订单(拆分后的订单) if len(order.VendorOrderID) == 16 && order.VendorID == model.VendorIDJX { @@ -1036,7 +1390,7 @@ func CancelMatterOrder(db *dao.DaoDB, order *model.GoodsOrder, reason string) (e } } } - stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, "") + stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, nil, "") if len(stores) > 0 { //如果这周还买过其他物料,则不刷新是否购买标志 var ( @@ -1311,6 +1665,26 @@ func GetHalfHoursList() (strs []string) { return strs } +func GetDiscountActHoursList() (str []string) { + for k := 1; k < 3; k++ { + for i := 0; i < 10; i++ { + for j := 0; j < 6; j++ { + if k == 1 && i == 0 && j == 0 { + continue + } + if k == 2 && i > 2 { + break + } + if k == 2 && i == 2 && j > 0 { + break + } + str = append(str, utils.Int2Str(k)+utils.Int2Str(i)+":"+utils.Int2Str(j)+"0"+":00") + } + } + } + return str +} + func RefreshAllMatterOrderStatus(ctx *jxcontext.Context) (err error) { var ( db = dao.GetDB() @@ -1336,7 +1710,10 @@ func RefreshAllMatterOrderStatus(ctx *jxcontext.Context) (err error) { err = dao.GetRows(db, &goodsList2, sql2, sqlParams2) for _, vv := range goodsList2 { if vv.Status < model.OrderStatusFinished { - queryOrderStatus, _ := api.JdEclpAPI.QueryOrderStatus(vv.EclpOutID) + queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(vv.EclpOutID) + if err != nil || queryOrderStatus == nil { + continue + } if len(queryOrderStatus.OrderStatusList) > 0 { if queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode == jdeclpapi.SoStatusCode10034 { dao.Begin(db) @@ -1365,26 +1742,28 @@ func RefreshAllMatterOrderStatus(ctx *jxcontext.Context) (err error) { cancelCount++ } } - dao.Begin(db) - defer func() { - if r := recover(); r != nil { - dao.Rollback(db) - panic(r) + if len(goodsList2) > 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if deliveringCount == 0 { + v.Status = model.OrderStatusFinished + } else { + if cancelCount == len(goodsList2) { + v.Status = model.OrderStatusCanceled + } } - }() - if deliveringCount == 0 { - v.Status = model.OrderStatusFinished - } else { - if cancelCount == len(goodsList2) { + if v.Status < model.OrderStatusDelivering { v.Status = model.OrderStatusCanceled } + dao.UpdateEntity(db, v, "Status") + dao.Commit(db) + changeOrderStatus(v.VendorOrderID, v.Status, "") } - if v.Status < model.OrderStatusDelivering { - v.Status = model.OrderStatusCanceled - } - dao.UpdateEntity(db, v, "Status") - dao.Commit(db) - changeOrderStatus(v.VendorOrderID, v.Status, "") } else { queryOrderStatus, _ := api.JdEclpAPI.QueryOrderStatus(v.EclpOutID) getTrackMessagePlusByOrderResult, _ := api.JdEclpAPI.GetTrackMessagePlusByOrder(v.VendorOrderID) @@ -1399,7 +1778,7 @@ func GetMatterOrderStatus(ctx *jxcontext.Context, vendorOrderID string) (result var ( db = dao.GetDB() ) - order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX) + order, err := dao.GetSimpleOrder(db, vendorOrderID) if err != nil { return nil, err } @@ -1408,17 +1787,20 @@ func GetMatterOrderStatus(ctx *jxcontext.Context, vendorOrderID string) (result } queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(order.EclpOutID) getTrackMessagePlusByOrderResult, err := api.JdEclpAPI.GetTrackMessagePlusByOrder(vendorOrderID) - if err != nil { + if err != nil || queryOrderStatus == nil { return nil, err } - for _, v := range queryOrderStatus.OrderStatusList { - matter := &MatterOrderStatus{} - matter.Time = utils.Str2Time(v.OperateTime) - matter.Status = v.SoStatusName - matter.Name = v.SoStatusName - matter.Sign = 1 - result = append(result, matter) + if len(queryOrderStatus.OrderStatusList) > 0 { + for _, v := range queryOrderStatus.OrderStatusList { + matter := &MatterOrderStatus{} + matter.Time = utils.Str2Time(v.OperateTime) + matter.Status = v.SoStatusName + matter.Name = v.SoStatusName + matter.Sign = 1 + result = append(result, matter) + } } + if len(getTrackMessagePlusByOrderResult.ResultData) > 0 { for _, vv := range getTrackMessagePlusByOrderResult.ResultData { matter := &MatterOrderStatus{} @@ -1659,55 +2041,64 @@ func SendFailedMatterOrder(ctx *jxcontext.Context, vendorOrderID string) (err er if order == nil || order.StoreID != model.MatterStoreID || order.FromStoreID == 0 { return fmt.Errorf("只允许物料店重发物料订单调用此接口!") } - queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(order.EclpOutID) - if len(queryOrderStatus.OrderStatusList) > 0 { - code := queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode - if code == jdeclpapi.SoStatusCode10022 || code == jdeclpapi.SoStatusCode10038 { //表示该订单在京东物流为暂停或已经逆向发货完成 - if len(order.VendorOrderID) == 14 && order.EclpOutID != "" { //这是不分包的订单 - _, err = createMatterOrder(buildJxOrderInfo(order, order.Skus), order, int64(00)) - err = CancelMatterOrder(db, order, cancelMatterOrderReason) - changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason) - for _, v := range order.Skus { - cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID) - } - } else if len(order.VendorOrderID) == 14 && order.EclpOutID == "" { //这是分包的主订单 - goodsList, err := dao.GetMatterChildOrders(db, order.VendorOrderID) + err = CancelMatterOrder(db, order, cancelMatterOrderReason) + // queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(order.EclpOutID) + // if len(queryOrderStatus.OrderStatusList) > 0 { + // code := queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode + // if code == jdeclpapi.SoStatusCode10022 || code == jdeclpapi.SoStatusCode10038 { //表示该订单在京东物流为暂停或已经逆向发货完成 + childs, err := dao.GetMatterChildOrders(db, vendorOrderID) + if len(childs) > 0 { + goodsList, err := dao.GetMatterChildOrders(db, order.VendorOrderID) + if err != nil { + return err + } + if len(goodsList) > 0 { + for _, v := range goodsList { + cOrder, err := partner.CurOrderManager.LoadOrder(v.VendorOrderID, model.VendorIDJX) if err != nil { return err } - if len(goodsList) > 0 { - for _, v := range goodsList { - cOrder, err := partner.CurOrderManager.LoadOrder(v.VendorOrderID, model.VendorIDJX) - if err != nil { - return err - } - suffix := utils.Str2Int64(cOrder.VendorOrderID[len(cOrder.VendorOrderID)-2:]) + int64(len(goodsList)) - _, err = createMatterOrder(buildJxOrderInfo(cOrder, cOrder.Skus), cOrder, suffix) - for _, v := range cOrder.Skus { - cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID) - } - } + suffix := utils.Str2Int64(cOrder.VendorOrderID[len(cOrder.VendorOrderID)-2:]) + int64(len(goodsList)) + _, err = createMatterOrder(buildJxOrderInfo(cOrder, cOrder.Skus), order, suffix) + for _, v := range cOrder.Skus { + cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID) } - err = CancelMatterOrder(db, order, cancelMatterOrderReason) - changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason) - } else if len(order.VendorOrderID) == 16 && order.EclpOutID != "" { // 这是分包的子订单 - return fmt.Errorf("请重发主订单!主订单号:[%v]", order.VendorOrderID[len(order.VendorOrderID)-2:]) } - } else { - return fmt.Errorf("只允许物流订单为暂停或逆向完成才能调用此接口!") + } + changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason) + } else { + _, err = createMatterOrder(buildJxOrderInfo(order, order.Skus), order, int64(01)) + if err != nil { + globals.SugarLogger.Debugf("SendFailedMatterOrder err : [%v]", err) + return err + } + changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason) + for _, v := range order.Skus { + cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID) } } + // if len(order.VendorOrderID) == 14 && order.EclpOutID != "" { //这是不分包的订单 + + // } else if len(order.VendorOrderID) == 14 && order.EclpOutID == "" { //这是分包的主订单 + + // } else if len(order.VendorOrderID) == 16 && order.EclpOutID != "" { // 这是分包的子订单 + // return fmt.Errorf("请重发主订单!主订单号:[%v]", order.VendorOrderID[len(order.VendorOrderID)-2:]) + // } + // } else { + // return fmt.Errorf("只允许物流订单为暂停或逆向完成才能调用此接口!") + // } + // } return err } func createMatterOrder(jxOrder *JxOrderInfo, order *model.GoodsOrder, newOrderIDSuffix int64) (order2 *model.GoodsOrder, err error) { - outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, jxOrder, order.AddressID, order.FromStoreID, order.UserID, false) + outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, jxOrder, order.AddressID, order.FromStoreID, order.UserID, false, nil) if err != nil { return nil, err } outJxOrder.OrderID = utils.Str2Int64(order.VendorOrderID)*100 + newOrderIDSuffix checkMatterDeliveryAddress(deliveryAddress) - order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false) + order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false, nil) if err = err2; err == nil { order2.AddressID = order.AddressID order2.Status = model.OrderStatusDelivering @@ -1734,5 +2125,359 @@ func buildJxOrderInfo(order *model.GoodsOrder, orderSkus []*model.OrderSku) (jxO } jxOrder.Skus = skus jxOrder.Weight = weight + jxOrder.OrderType = model.OrderTypeMatter return jxOrder } + +func GetSupplySupportStoreSkus(ctx *jxcontext.Context, fromDate, toDate string, fromStoreID, storeID int, percentage string) (orderSkus []*dao.GetSupplySupportStoreSkusResult, err error) { + var ( + db = dao.GetDB() + ) + orderSkus, err = dao.GetSupplySupportStoreSkus(db, utils.Str2Time(fromDate), utils.Str2Time(toDate), fromStoreID, storeID, utils.Str2Float64(percentage)) + return orderSkus, err +} + +func CreateOrderByPriceDefend(ctx *jxcontext.Context) (err error) { + var ( + db = dao.GetDB() + userOrderMap = make(map[int64][]*model.PriceDefendOrder) + ) + globals.SugarLogger.Debugf("CreateOrderByPriceDefend Begin:") + priceDefends, _ := dao.GetPriceDefendOrder(db, "", nil, nil, []int{jxutils.GetLastDefendPriceIssue()}, 0, -1, 1, 1, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefends) > 0 { + for _, v := range priceDefends { + userOrderMap[v.AddressID] = append(userOrderMap[v.AddressID], v) + } + for kk, vv := range userOrderMap { + addressList, _, _ := dao.QueryUserDeliveryAddress(db, kk, nil, 0, 0) + address := addressList[0] + if len(vv) == 1 { + jxOrder := &JxOrderInfo{ + BuyerComment: "守价订单", + StoreID: vv[0].StoreID, + Skus: []*JxSkuInfo{ + &JxSkuInfo{ + SkuID: vv[0].SkuID, + Count: vv[0].Count, + }, + }, + IsPriceDefend: model.YES, + OrderID: utils.Str2Int64(vv[0].VendorOrderID), + UserID: address.UserID, + } + if _, err := CreateOrder(ctx, jxOrder, kk, OrderCreateTypeNormal, 0, false, nil); err == nil { + err = SettleDiscountActByPriceDefend(ctx, vv[0], false) + } + } else { + var ( + skus []*JxSkuInfo + orderIDs []string + ) + jxOrder := &JxOrderInfo{ + BuyerComment: "守价订单", + StoreID: vv[0].StoreID, + IsPriceDefend: model.YES, + OrderID: jxutils.GenOrderNo(), + UserID: address.UserID, + } + for _, priceDefend := range vv { + sku := &JxSkuInfo{ + SkuID: priceDefend.SkuID, + Count: priceDefend.Count, + } + skus = append(skus, sku) + orderIDs = append(orderIDs, priceDefend.VendorOrderID) + err = SettleDiscountActByPriceDefend(ctx, priceDefend, false) + } + jxOrder.Skus = skus + jxOrder.OrderID2 = strings.Join(orderIDs, ",") + if _, err := CreateOrder(ctx, jxOrder, kk, OrderCreateTypeNormal, 0, false, nil); err == nil { + } + } + } + } + priceDefends2, _ := dao.GetPriceDefendOrder(db, "", nil, nil, []int{jxutils.GetLastDefendPriceIssue()}, 0, -1, 0, 1, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false) + if len(priceDefends2) > 0 { + for _, v := range priceDefends2 { + err = SettleDiscountActByPriceDefend(ctx, v, true) + } + } + return err +} + +//结算因京西折扣活动而参与守价的订单 +func SettleDiscountActByPriceDefend(ctx *jxcontext.Context, order *model.PriceDefendOrder, isFull bool) (err error) { + var ( + db = dao.GetDB() + ) + payList, err2 := dao.GetOrderPayList(db, order.VendorOrderID, jxutils.GetPossibleVendorIDFromVendorOrderID(order.VendorOrderID)) + if err = err2; err == nil { + for _, orderPay := range payList { + if orderPay.Status == model.PayStatusYes { + refundID := order.VendorOrderID + if orderPay.PayType == model.PayTypeTL { + if !isFull { + minusPrice := int(order.OriginPrice - order.RealPrice) + _, err = RefundOrderByTL(ctx, orderPay, refundID, order.Count*minusPrice, settleDiscountActRefundReason) + } else { + _, err = RefundOrderByTL(ctx, orderPay, refundID, int(order.ActualPayPrice), settleDiscountActRefundReason) + } + } + } else { + orderPay.Status = model.PayStatusCanceled + _, err = dao.UpdateEntity(db, orderPay) + } + } + } + return err +} + +func GetMyPriceDefendOrders(ctx *jxcontext.Context, fromTime, toTime string) (priceDefendOrders []*model.PriceDefendOrder, err error) { + var ( + db = dao.GetDB() + userID = ctx.GetUserID() + ) + priceDefendOrders, err = dao.GetPriceDefendOrder(db, "", nil, nil, nil, 0, -1, -1, -1, userID, utils.Str2Time(fromTime), utils.Str2Time(toTime), true) + return priceDefendOrders, err +} + +func GetCoupons(ctx *jxcontext.Context, couponType int, couponStatuss, storeIDs []int, keyword string) (coupons []*model.Coupons, err error) { + var ( + db = dao.GetDB() + ) + coupons, err = dao.GetCoupons(db, couponType, couponStatuss, storeIDs, "", "", keyword) + return coupons, err +} + +func AddCoupons(ctx *jxcontext.Context, coupons *model.Coupons, count int, storeIDs []int) (err error) { + var ( + db = dao.GetDB() + ) + if coupons.BeginAt == utils.ZeroTimeValue || coupons.EndAt == utils.ZeroTimeValue { + return fmt.Errorf("请输入正确的起始时间!") + } else { + if coupons.BeginAt.Sub(coupons.EndAt) > 0 { + return fmt.Errorf("请输入正确的起始时间!") + } + //优惠券还没开始生效 + if time.Now().Sub(coupons.BeginAt) < 0 { + coupons.CouponStatus = model.CouponStatusRe + } + } + if coupons.IsAll == model.NO { + if len(storeIDs) == 0 { + return fmt.Errorf("不是全国生效则必须选择生效门店!") + } + } else { + storeIDs = []int{} //全国不需要选门店 + } + if coupons.UpperLimit == 0 || coupons.Cut == 0 { + return fmt.Errorf("请输入正确的满减!") + } else { + if coupons.Cut > coupons.UpperLimit { + return fmt.Errorf("请输入正确的满减!") + } + } + if coupons.CouponType == 0 { + return fmt.Errorf("请选择一个优惠券类型!") + } + if count == 0 { + count += 1 + } + for i := 1; i < count; i++ { + dao.WrapAddIDCULDEntity(coupons, ctx.GetUserName()) + if err = dao.CreateEntity(db, coupons); err == nil { + //门店优惠券表 + if coupons.IsAll == 0 { + for _, v := range storeIDs { + storeCoupons := &model.StoreCoupons{ + CouponID: int(coupons.ID), + StoreID: v, + } + dao.WrapAddIDCULEntity(storeCoupons, ctx.GetUserName()) + dao.CreateEntity(db, v) + } + } + } + } + return err +} + +func UpdateCoupons(ctx *jxcontext.Context, payload map[string]interface{}, storeIDs []int, isDel bool) (err error) { + var ( + db = dao.GetDB() + coupons = &model.Coupons{} + ) + coupons.ID = utils.MustInterface2Int64(payload["id"]) + dao.GetEntity(db, coupons) + if isDel { + coupons.CouponStatus = model.CouponStatusDeleted + coupons.UpdatedAt = time.Now() + coupons.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, coupons, "CouponStatus", "UpdatedAt", "LastOperator") + } else { + valid := dao.StrictMakeMapByStructObject(payload, coupons, ctx.GetUserName()) + if len(valid) > 0 { + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if valid["isAll"] != nil { + if utils.MustInterface2Int64(valid["isAll"]) == model.NO && len(storeIDs) == 0 { + return fmt.Errorf("改成全国不生效要选门店!") + } + } + if _, err = dao.UpdateEntityByKV(db, coupons, valid, nil); err != nil { + dao.Rollback(db) + return err + } + if valid["isAll"] != nil { + storeCouponss, _ := dao.GetStoreCoupons(db, []int{int(coupons.ID)}, nil) + for _, v := range storeCouponss { + v.DeletedAt = time.Now() + v.LastOperator = ctx.GetUserName() + dao.UpdateEntity(db, v, "DeletoedAt", "LastOperator") + } + if utils.MustInterface2Int64(valid["isAll"]) == model.NO { + for _, v := range storeIDs { + storeCoupons := &model.StoreCoupons{ + StoreID: v, + CouponID: int(coupons.ID), + } + dao.WrapAddIDCULEntity(storeCoupons, ctx.GetUserName()) + dao.CreateEntity(db, storeCoupons) + } + } + } + dao.Commit(db) + } + } + return err +} + +func ReceiveCoupons(ctx *jxcontext.Context, couponID int) (err error) { + var ( + db = dao.GetDB() + userID = ctx.GetUserID() + coupons = &model.Coupons{} + ) + coupons.ID = int64(couponID) + dao.GetEntity(db, coupons) + if coupons == nil { + return fmt.Errorf("领取优惠券失败!") + } + if coupons.CouponStatus != model.CouponStatusNormal { + return fmt.Errorf("优惠券状态有误,领取失败!") + } + if time.Now().Sub(coupons.EndAt) > 0 { + return fmt.Errorf("优惠券已过期,领取失败!") + } + if time.Now().Sub(coupons.BeginAt) < 0 { + return fmt.Errorf("优惠券未生效,领取失败!") + } + userCoupons, _ := dao.GetUserCoupons(db, []int{couponID}, []string{userID}, nil, model.CouponStatusNormal) + if len(userCoupons) > 0 { + return fmt.Errorf("您已经领取过该优惠券了,请使用后再领取!") + } + userCoupon := &model.UserCoupons{ + CouponID: couponID, + UserID: userID, + } + dao.WrapAddIDCULEntity(userCoupon, ctx.GetUserName()) + err = dao.CreateEntity(db, userCoupon) + return err +} + +func RefreshCouponsStatus(ctx *jxcontext.Context) (err error) { + var ( + db = dao.GetDB() + ) + task := tasksch.NewParallelTask("RefreshCouponsStatus", 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: + //还没生效的弄成生效 + coupons, _ := dao.GetCoupons(db, 0, []int{model.CouponStatusRe}, nil, "", "", "") + task := tasksch.NewParallelTask("RefreshCouponsStatusRe", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + coupon := batchItemList[0].(*model.Coupons) + if time.Now().Sub(coupon.BeginAt) > 0 { + coupon.CouponStatus = model.CouponStatusNormal + coupon.UpdatedAt = time.Now() + dao.UpdateEntity(db, coupon, "CouponStatus", "UpdatedAt") + } + return retVal, err + }, coupons) + tasksch.HandleTask(task, nil, true).Run() + _, err = task.GetResult(0) + case 1: + //过期的弄成过期 + coupons, _ := dao.GetCoupons(db, 0, []int{model.CouponStatusNormal}, nil, "", "", "") + task := tasksch.NewParallelTask("RefreshCouponsStatusNormal", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, + func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + coupon := batchItemList[0].(*model.Coupons) + if time.Now().Sub(coupon.EndAt) > 0 { + coupon.CouponStatus = model.CouponStatusOverdue + coupon.UpdatedAt = time.Now() + dao.UpdateEntity(db, coupon, "CouponStatus", "UpdatedAt") + //用户手上的优惠券也要弄成过期 + if userCoupons, err := dao.GetUserCoupons(db, []int{int(coupon.ID)}, nil, nil, 0); err == nil { + for _, v := range userCoupons { + v.UserCouponStatus = model.CouponStatusOverdue + v.UpdatedAt = time.Now() + dao.UpdateEntity(db, v, "UserCouponStatus", "UpdatedAt") + } + } + } + return retVal, err + }, coupons) + tasksch.HandleTask(task, nil, true).Run() + _, err = task.GetResult(0) + } + return retVal, err + }, []int{0, 1}) + tasksch.HandleTask(task, nil, true).Run() + task.GetID() + return err +} + +func CreateStoreAcctOrder(ctx *jxcontext.Context, orderType, storeID, price int) (vendorOrderID string, err error) { + var ( + db = dao.GetDB() + storeAcct = &model.StoreAcct{ + StoreID: storeID, + } + ) + if err = dao.GetEntity(db, storeAcct, "StoreID"); err != nil && dao.IsNoRowsError(err) { + //新增门店账单 + dao.WrapAddIDCULEntity(storeAcct, ctx.GetUserName()) + dao.CreateEntity(db, storeAcct) + } + + order := &model.StoreAcctOrder{ + VendorOrderID: utils.Int64ToStr(jxutils.GenOrderNo()), + UserID: ctx.GetUserID(), + StoreID: storeID, + OrderType: orderType, + Status: model.OrderStatusWait4Pay, + ActualPayPrice: price, + VendorID: model.VendorIDJX, + } + dao.WrapAddIDCULEntity(order, ctx.GetUserName()) + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + if err = dao.CreateEntity(db, order); err != nil { + dao.Rollback(db) + } + dao.Commit(db) + return order.VendorOrderID, err +} diff --git a/business/partner/purchase/jx/localjx/tonglianpay.go b/business/partner/purchase/jx/localjx/tonglianpay.go index e7d60b769..f2344ce9e 100644 --- a/business/partner/purchase/jx/localjx/tonglianpay.go +++ b/business/partner/purchase/jx/localjx/tonglianpay.go @@ -18,7 +18,7 @@ import ( "git.rosy.net.cn/jx-callback/globals/api" ) -func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType string) (orderPay *model.OrderPay, err error) { +func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, payType int, vendorPayType, subAppID string) (orderPay *model.OrderPay, err error) { // if order.FromStoreID != 0 { // result, _ := orderman.GetMatterStoreOrderCount(nil, order.FromStoreID) // if !result.Flag { @@ -31,13 +31,14 @@ func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayTyp NotifyUrl: globals.TLPayNotifyURL, Reqsn: order.VendorOrderID, PayType: vendorPayType, + SubAppID: subAppID, } //暂时做兼容处理 if vendorPayType == "JSAPI" { param.PayType = tonglianpayapi.PayTypeWxXcx } if vendorPayType == tonglianpayapi.PayTypeWxXcx { - if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini { + if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini && authInfo.GetAuthTypeID() == subAppID { param.Acct = authInfo.GetAuthID() } } @@ -57,7 +58,7 @@ func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayTyp prePayID := result2.Package[strings.LastIndex(result2.Package, "=")+1 : len(result2.Package)] orderPay = &model.OrderPay{ PayOrderID: param.Reqsn, - PayType: model.PayTypeTL, + PayType: payType, VendorPayType: vendorPayType, TransactionID: result.TrxID, VendorOrderID: order.VendorOrderID, @@ -87,11 +88,11 @@ func OnTLPayCallback(call *tonglianpayapi.CallBackResult) (err error) { func onTLpayFinished(call *tonglianpayapi.CallBackResult) (err error) { orderPay := &model.OrderPay{ PayOrderID: call.CusorderID, - PayType: model.PayTypeTL, + // PayType: model.PayTypeTL, } orderPay.DeletedAt = utils.DefaultTimeValue db := dao.GetDB() - if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil { + if err = dao.GetEntity(db, orderPay, "PayOrderID", "DeletedAt"); err == nil { if orderPay.Status != 0 { globals.SugarLogger.Debugf("already pay msg:%s, err:%v", utils.Format4Output(call, true), err) return err @@ -147,11 +148,10 @@ func onTLpayRefund(call *tonglianpayapi.CallBackResult) (err error) { return err } -func refundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) { +func RefundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) { result, err := api.TLpayAPI.PayRefund(&tonglianpayapi.PayRefundParam{ - Trxamt: orderPay.TotalFee, - Reqsn: utils.GetUUID(), - // OldReqsn: orderPay.VendorOrderID, + Trxamt: refundFee, + Reqsn: utils.GetUUID(), Remark: refundDesc, OldTrxID: orderPay.TransactionID, }) @@ -163,7 +163,7 @@ func refundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID VendorID: orderPay.VendorID, Status: model.RefundStatusNo, TransactionID: orderPay.TransactionID, - RefundFee: orderPay.TotalFee, + RefundFee: refundFee, RefundCreatedAt: time.Now(), } dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName()) diff --git a/business/partner/purchase/jx/localjx/user.go b/business/partner/purchase/jx/localjx/user.go new file mode 100644 index 000000000..feb9d59f5 --- /dev/null +++ b/business/partner/purchase/jx/localjx/user.go @@ -0,0 +1,76 @@ +package localjx + +import ( + "git.rosy.net.cn/jx-callback/business/model/dao" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" +) + +type GetJxShopUsersResult struct { + model.User + BuyCount int `json:"buyCount"` + ActualPayPrice int `json:"actualPayPrice"` + VendorID int `orm:"column(vendor_id)" json:"vendorID"` + GoodCommentCount int `json:"goodCommentCount"` + BadCommentCount int `json:"badCommentCount"` + UserMembers []*model.UserMember `json:"userMembers"` +} + +func GetJxShopUsers(ctx *jxcontext.Context, keyword, fromTime, toTime string, vendorIDs []int, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { + var ( + requestList []*GetJxShopUsersResult + db = dao.GetDB() + fromTimeP = utils.Str2Time(fromTime) + toTimeP = utils.Str2Time(toTime) + sqlParams = []interface{}{} + ) + sql := ` + SELECT SQL_CALC_FOUND_ROWS a.*, b.name, b.created_at, b.last_login_at + FROM ( + SELECT c.vendor_user_id, IF(c.consignee_mobile2 <> '',c.consignee_mobile2,c.consignee_mobile) mobile, + c.vendor_id,COUNT(*) buy_count, SUM(c.actual_pay_price) actual_pay_price, COUNT(d.score > 3) good_comment_count, + COUNT(d.score < 3) bad_comment_count + FROM goods_order c + LEFT JOIN jx_bad_comments d ON d.order_id = c.vendor_order_id + WHERE 1 = 1 + ` + if fromTimeP != utils.ZeroTimeValue && toTimeP != utils.ZeroTimeValue { + sql += ` AND c.order_created_at >= ? AND c.order_created_at <= ?` + sqlParams = append(sqlParams, fromTimeP, toTimeP) + } + if len(vendorIDs) > 0 { + sql += ` AND c.vendor_id IN(` + dao.GenQuestionMarks(len(vendorIDs)) + `) ` + sqlParams = append(sqlParams, vendorIDs) + } + sql += ` AND c.status <> ? + GROUP BY 1,2,3)a + LEFT JOIN user b ON b.user_id = a.vendor_user_id + WHERE (b.deleted_at = ? OR b.deleted_at is null) + ` + sqlParams = append(sqlParams, model.OrderStatusCanceled, utils.DefaultTimeValue) + if keyword != "" { + sql += " AND (a.user_id LIKE ? OR b.name LIKE ? OR a.mobile LIKE ?)" + sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + } + sql += "LIMIT ? OFFSET ?" + pageSize = jxutils.FormalizePageSize(pageSize) + sqlParams = append(sqlParams, pageSize, offset) + dao.Begin(db) + defer dao.Commit(db) + if err = dao.GetRows(db, &requestList, sql, sqlParams...); err == nil { + pagedInfo = &model.PagedInfo{ + TotalCount: dao.GetLastTotalRowCount(db), + // Data: requestList, + } + for _, v := range requestList { + userMembers, _ := dao.GetUserMember(db, v.UserID, "", model.MemberTypeDiscountCard, model.YES) + v.UserMembers = userMembers + } + pagedInfo.Data = requestList + } + return pagedInfo, err +} diff --git a/business/partner/purchase/jx/order.go b/business/partner/purchase/jx/order.go index 4c36f9c25..85b9bf1c7 100644 --- a/business/partner/purchase/jx/order.go +++ b/business/partner/purchase/jx/order.go @@ -15,7 +15,7 @@ func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo return order } -func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) { +func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID, vendorStoreID string) (order *model.GoodsOrder, err error) { order, err = partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJX) return order, err } diff --git a/business/partner/purchase/jx/order_afs.go b/business/partner/purchase/jx/order_afs.go index 53319ea39..c67602161 100644 --- a/business/partner/purchase/jx/order_afs.go +++ b/business/partner/purchase/jx/order_afs.go @@ -2,11 +2,23 @@ package jx import ( "fmt" + "strings" + "time" + "git.rosy.net.cn/jx-callback/business/jxutils" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/jx-callback/business/model/dao" + + "git.rosy.net.cn/jx-callback/globals/api" + + "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx" + + "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/business/partner/purchase/jx/phpjx" ) // 审核售后单申请 @@ -17,8 +29,29 @@ func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *mod } else { status = model.AfsOrderStatusFinished } - if model.IsAfsOrderJXTemp(order) { - err = phpjx.NotifyAfsOrderStatusChanged(order, status) + orderStatus := &model.OrderStatus{ + VendorOrderID: order.AfsOrderID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 + VendorID: order.VendorID, + OrderType: model.OrderTypeAfsOrder, + RefVendorOrderID: order.VendorOrderID, + RefVendorID: order.VendorID, + VendorStatus: utils.Int2Str(status), + Status: status, + StatusTime: time.Now(), + Remark: reason, + } + if status == model.AfsOrderStatusFinished { + orderPays, err := dao.GetOrderPayList(dao.GetDB(), order.VendorOrderID, order.VendorID) + if err == nil { + _, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(order.SkuUserMoney), reason) + if err != nil { + return err + } else { + partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) + } + } + } else { + partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) } return err } @@ -31,12 +64,107 @@ func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, ord // 发起全款退款 func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { - err = fmt.Errorf("%s不支持售后全额退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDJX]) + 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) { - err = fmt.Errorf("%s不支持售后部分退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDJX]) + globals.SugarLogger.Debugf("PartRefundOrder jx, orderID :%v", order.VendorOrderID) + var ( + skuMap = make(map[int]*model.OrderSku) + appID = "" + salePrice int64 + db = dao.GetDB() + ) + if time.Now().Sub(order.OrderCreatedAt) > 24*time.Hour { + return fmt.Errorf("已超过售后申请时间,如有疑问请联系门店!") + } + referer := ctx.GetRequest().Referer() + index := strings.Index(referer, "//") + if index > 0 { + list := strings.Split(referer[index+2:], "/") + if len(list) >= 2 { + appID = list[1] + } + } + for _, sku := range order.Skus { + skuMap[sku.SkuID] = sku + } + orderStatus := buildOrderStatus(ctx, order, reason, isJxShop(appID)) + afsOrder := &model.AfsOrder{ + VendorID: order.VendorID, + AfsOrderID: orderStatus.VendorOrderID, + VendorOrderID: orderStatus.RefVendorOrderID, + VendorStoreID: order.VendorStoreID, + StoreID: order.StoreID, + 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, + } + 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) + } + + if !isJxShop(appID) { + orderPays, err := dao.GetOrderPayList(db, order.VendorOrderID, order.VendorID) + if err == nil { + _, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(salePrice), reason) + if err != nil { + return err + } else { + if afsOrder != nil { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } + } + } + } else { + err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus) + } return err } + +func buildOrderStatus(ctx *jxcontext.Context, order *model.GoodsOrder, reason string, isJxShop bool) (orderStatus *model.OrderStatus) { + orderStatus = &model.OrderStatus{ + VendorOrderID: utils.Int64ToStr(jxutils.GenAfsOrderNo()), // 是售后单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, + } + if isJxShop { + orderStatus.Status = model.AfsOrderStatusWait4Approve + } else { + orderStatus.Status = model.AfsOrderStatusFinished + } + return orderStatus +} + +func isJxShop(appID string) bool { + if appID == api.WeixinMiniAppID2 { + return true + } + return false +} diff --git a/business/partner/purchase/mtwm/callback.go b/business/partner/purchase/mtwm/callback.go index 17087b0b3..8d22c47f9 100644 --- a/business/partner/purchase/mtwm/callback.go +++ b/business/partner/purchase/mtwm/callback.go @@ -8,7 +8,7 @@ import ( func OnCallbackMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) { if CurPurchaseHandler != nil { - if msg.Cmd == mtwmapi.MsgTypeStoreStatusChanged { + if msg.Cmd == mtwmapi.MsgTypeStoreStatusChanged || msg.Cmd == mtwmapi.MsgTypeStoreAuditStatusChanged { response = CurPurchaseHandler.onStoreStatusChanged(msg) } else if msg.Cmd == mtwmapi.MsgTypePrivateNumberDowngrade { response = CurPurchaseHandler.onNumberDowngrade(msg) @@ -36,3 +36,7 @@ func OnCallbackMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse func GetOrderIDFromMsg(msg *mtwmapi.CallbackMsg) string { return msg.FormData.Get(mtwmapi.KeyOrderID) } + +func GetVendorStoreIDFromMsg(msg *mtwmapi.CallbackMsg) string { + return msg.FormData.Get(mtwmapi.KeyAppPoiCode) +} diff --git a/business/partner/purchase/mtwm/mtwm.go b/business/partner/purchase/mtwm/mtwm.go index 09bce7a52..3c2f971a2 100644 --- a/business/partner/purchase/mtwm/mtwm.go +++ b/business/partner/purchase/mtwm/mtwm.go @@ -5,6 +5,8 @@ import ( "strings" "sync" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" @@ -29,7 +31,7 @@ type PurchaseHandler struct { } func init() { - if api.MtwmAPI != nil { + if api.MtwmAPI != nil || api.Mtwm2API != nil { CurPurchaseHandler = New() partner.RegisterPurchasePlatform(CurPurchaseHandler) } @@ -223,3 +225,27 @@ func (p *PurchaseHandler) getUploadImgPoiCode() (poiCode string) { } return poiCode } + +func getAPI(appOrgCode string, storeID int, vendorStoreID string) (apiObj *mtwmapi.API) { + if appOrgCode == "" { + globals.SugarLogger.Warnf("getAPI appOrgCode is empty") + } + apiObj = partner.CurAPIManager.GetAPI(model.VendorIDMTWM, appOrgCode).(*mtwmapi.API) + if appOrgCode == globals.Mtwm2Code { + var storeDetail *dao.StoreDetail + if storeID != 0 { + storeDetail, _ = dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, appOrgCode) + } else if vendorStoreID != "" { + storeDetail, _ = dao.GetStoreDetailByVendorStoreID(dao.GetDB(), vendorStoreID, model.VendorIDMTWM, appOrgCode) + } + apiObj.SetToken(storeDetail.MtwmToken) + } + return apiObj +} + +func getAPIWithoutToken(appOrgCode string) (apiObj *mtwmapi.API) { + if appOrgCode == "" { + globals.SugarLogger.Warnf("getAPI appOrgCode is empty") + } + return partner.CurAPIManager.GetAPI(model.VendorIDMTWM, appOrgCode).(*mtwmapi.API) +} diff --git a/business/partner/purchase/mtwm/order.go b/business/partner/purchase/mtwm/order.go index 71f6e81c9..1ede690c4 100644 --- a/business/partner/purchase/mtwm/order.go +++ b/business/partner/purchase/mtwm/order.go @@ -18,7 +18,6 @@ import ( "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" ) const ( @@ -85,8 +84,8 @@ func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int { return model.OrderStatusUnknown } -func (p *PurchaseHandler) getOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) { - result, err := api.MtwmAPI.OrderGetOrderDetail(utils.Str2Int64(vendorOrderID), true) +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) @@ -94,13 +93,15 @@ func (p *PurchaseHandler) getOrder(vendorOrgCode, vendorOrderID string) (order * return order, result, err } -func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) { - order, _, err = p.getOrder(vendorOrgCode, vendorOrderID) +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) { - status, err = api.MtwmAPI.OrderViewStatus(utils.Str2Int64(vendorOrderID)) + 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)) } @@ -254,13 +255,19 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo 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 { - ignoreSkuMap[sku.SkuID] = 1 - sku.SalePrice -= jxutils.StandardPrice2Int(v.MtCharge + v.PoiCharge) + 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 // } @@ -277,11 +284,11 @@ func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *mo return order } -func getRefundSkuDetailList(msg *mtwmapi.CallbackMsg) (skuList []*mtwmapi.RefundSkuDetail, err error) { +func getRefundSkuDetailList(msg *mtwmapi.CallbackMsg, order *model.GoodsOrder) (skuList []*mtwmapi.RefundSkuDetail, err error) { if false { - skuList = api.MtwmAPI.GetRefundSkuDetailFromMsg(msg) + skuList = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").GetRefundSkuDetailFromMsg(msg) } else { - refundOrderDetailList, err2 := api.MtwmAPI.GetOrderRefundDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), mtwmapi.RefundTypePart) + 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...) @@ -316,7 +323,7 @@ func (c *PurchaseHandler) onOrderMsg(msg *mtwmapi.CallbackMsg) (response *mtwmap return nil } if msg.Cmd == mtwmapi.MsgTypeNewOrder { - order, orderMap, err2 := c.getOrder(msg.AppID, GetOrderIDFromMsg(msg)) + 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 { @@ -331,10 +338,11 @@ func (c *PurchaseHandler) onOrderMsg(msg *mtwmapi.CallbackMsg) (response *mtwmap } } else { if status != nil { - if status.Status == model.OrderStatusAdjust { - var order *model.GoodsOrder - if order, err = c.GetOrder(msg.AppID, GetOrderIDFromMsg(msg)); err == nil { - skuList, err2 := getRefundSkuDetailList(msg) + 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 { @@ -348,24 +356,24 @@ func (c *PurchaseHandler) onOrderMsg(msg *mtwmapi.CallbackMsg) (response *mtwmap jxutils.RefreshOrderSkuRelated(order) err = partner.CurOrderManager.OnOrderAdjust(order, status) } - } - } else { - if status.Status == model.OrderStatusDelivering { - // 美团订单即使时在配送状态时,如果之前没有调用过拣货完成,也会对门店指标生成影响,这里强制再调用拣货完成,且忽略错误 - utils.CallFuncAsync(func() { - if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.PreparationMealComplete(utils.Str2Int64(status.VendorOrderID)) - } - }) - } - err = partner.CurOrderManager.OnOrderStatusChanged(msg.AppID, status) - if err == nil && msg.Cmd == mtwmapi.MsgTypeOrderFinished { - utils.CallFuncAsync(func() { - orderMap, err := api.MtwmAPI.OrderGetOrderDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), true) - if err == nil && utils.MustInterface2Int64(orderMap["is_third_shipping"]) == SelfDeliveryCarrierNo { - c.OnOrderDetail(orderMap, partner.UpdatedPeration) - } - }) + } 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) + } + }) + } } } } @@ -396,14 +404,16 @@ func (c *PurchaseHandler) callbackMsg2Status(msg *mtwmapi.CallbackMsg) (orderSta if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund { if notifyType == mtwmapi.NotifyTypePartyApply { if globals.EnableMtwmStoreWrite { - goods, err := dao.GetSimpleOrder(dao.GetDB(), orderID) - if err == nil { - if goods.Status < model.OrderStatusDelivering { - api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(orderID), "自动确认退款") - } else { - api.MtwmAPI.OrderRefundReject(utils.Str2Int64(orderID), "商品配送中,请联系门店。") // todo 京东与饿百都没有售前用户提出订单调整的,自动拒绝调整单 - } + if order, _ := partner.CurOrderManager.LoadOrder(orderID, model.VendorIDMTWM); order != nil { + getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderRefundAgree(utils.Str2Int64(orderID), "自动确认退款") } + // goods, err := dao.GetSimpleOrder(dao.GetDB(), orderID) + // if err == nil { + // if goods.Status < model.OrderStatusDelivering { + // } else { + // api.MtwmAPI.OrderRefundReject(utils.Str2Int64(orderID), "商品配送中,请联系门店。") // todo 京东与饿百都没有售前用户提出订单调整的,自动拒绝调整单 + // } + // } } } else if notifyType == mtwmapi.NotifyTypeSuccess { vendorStatus = fakeOrderAdjustFinished @@ -459,7 +469,7 @@ func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI if isAcceptIt { if globals.EnableMtwmStoreWrite { // err = api.MtwmAPI.OrderReceived(utils.Str2Int64(order.VendorOrderID)) - err = api.MtwmAPI.OrderConfirm(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{ "订单已经确认过了", @@ -486,7 +496,7 @@ func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bo if !isSelfDelivery { if globals.EnableMtwmStoreWrite { // err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID)) - err = api.MtwmAPI.PreparationMealComplete(utils.Str2Int64(order.VendorOrderID)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").PreparationMealComplete(utils.Str2Int64(order.VendorOrderID)) } } if err == nil { @@ -515,7 +525,7 @@ func (c *PurchaseHandler) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Debugf("mtwm Swtich2SelfDeliver orderID:%s", order.VendorOrderID) if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderLogisticsChange2Self(utils.Str2Int64(order.VendorOrderID)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderLogisticsChange2Self(utils.Str2Int64(order.VendorOrderID)) } return err } @@ -533,7 +543,7 @@ func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Debugf("mtwm SelfDeliverDelivering orderID:%s", order.VendorOrderID) if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderDelivering(utils.Str2Int64(order.VendorOrderID)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderDelivering(utils.Str2Int64(order.VendorOrderID)) } return err } @@ -541,7 +551,7 @@ func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userNam func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Debugf("mtwm SelfDeliverDelivered orderID:%s", order.VendorOrderID) if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderArrived(utils.Str2Int64(order.VendorOrderID)) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderArrived(utils.Str2Int64(order.VendorOrderID)) } return err } @@ -561,9 +571,9 @@ func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *mode func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) { if globals.EnableMtwmStoreWrite { if isAgree { - err = api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) } else { - err = api.MtwmAPI.OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) } } return err @@ -571,7 +581,7 @@ func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *mod func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) { if globals.EnableMtwmStoreWrite { - if err = api.MtwmAPI.OrderCancel(utils.Str2Int64(order.VendorOrderID), reason, mtwmapi.CancelReasonOther); err == nil { + 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) } @@ -595,7 +605,7 @@ func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.Goods }) } if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderApplyPartRefund(utils.Str2Int64(order.VendorOrderID), reason, skuList) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), "").OrderApplyPartRefund(utils.Str2Int64(order.VendorOrderID), reason, skuList) } } return err @@ -627,11 +637,11 @@ func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode strin seqEnd := seqStart + batchSize - 1 var tmpOrderIDs []int64 if seqStart == seqEnd { - if vendorOderID, err2 := api.MtwmAPI.GetOrderIdByDaySeqSingle(vendorStoreID, queryDate, seqStart); err2 == nil { + if vendorOderID, err2 := getAPI(vendorOrgCode, 0, vendorStoreID).GetOrderIdByDaySeqSingle(vendorStoreID, queryDate, seqStart); err2 == nil { tmpOrderIDs = []int64{vendorOderID} } } else { - tmpOrderIDs, err = api.MtwmAPI.GetOrderIdByDaySeq(vendorStoreID, queryDate, seqStart, seqEnd) + tmpOrderIDs, err = getAPI(vendorOrgCode, 0, vendorStoreID).GetOrderIdByDaySeq(vendorStoreID, queryDate, seqStart, seqEnd) } if len(tmpOrderIDs) > 0 { for _, v := range tmpOrderIDs { @@ -669,7 +679,8 @@ func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode strin func (p *PurchaseHandler) GetOrderConsigneeNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) { offset := 0 for { - result, err2 := api.MtwmAPI.OrderBatchPullPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit) + 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{ @@ -695,7 +706,8 @@ func (p *PurchaseHandler) GetOrderConsigneeNumber(ctx *jxcontext.Context, storeI func (p *PurchaseHandler) GetOrderCourierNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) { offset := 0 for { - result, err2 := api.MtwmAPI.OrderGetRiderInfoPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit) + 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{ @@ -776,7 +788,7 @@ func (p *PurchaseHandler) onNumberDowngrade(msg *mtwmapi.CallbackMsg) (response } func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) { - orderInfo, err := api.MtwmAPI.GetDistributeOrderDetail(vendorOrderID, vendorStoreID) + orderInfo, err := getAPI(vendorOrgCode, 0, vendorStoreID).GetDistributeOrderDetail(vendorOrderID, vendorStoreID) if err == nil { tipFee = jxutils.StandardPrice2Int(orderInfo.TipAmount) } @@ -785,7 +797,7 @@ func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, v func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) { if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.OrderModityTips(vendorOrderID, vendorStoreID, jxutils.IntPrice2Standard(tipFee)) + err = getAPI(vendorOrgCode, 0, vendorStoreID).OrderModityTips(vendorOrderID, vendorStoreID, jxutils.IntPrice2Standard(tipFee)) } return err } diff --git a/business/partner/purchase/mtwm/order_afs.go b/business/partner/purchase/mtwm/order_afs.go index 0aaaaf1f0..f3a709c0f 100644 --- a/business/partner/purchase/mtwm/order_afs.go +++ b/business/partner/purchase/mtwm/order_afs.go @@ -13,7 +13,6 @@ import ( "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" ) var ( @@ -42,7 +41,8 @@ func (c *PurchaseHandler) isAfsMsg(msg *mtwmapi.CallbackMsg) bool { if msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund { // refundData := msg.Data.(*mtwmapi.CallbackRefundInfo) orderID := utils.Str2Int64(GetOrderIDFromMsg(msg)) - status, err := api.MtwmAPI.OrderViewStatus(orderID) + order, _ := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDMTWM) + status, err := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), order.VendorStoreID).OrderViewStatus(orderID) if err == nil { return utils.Int2Str(status) == mtwmapi.OrderStatusFinished } @@ -188,9 +188,9 @@ func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(resType int, notifyType s func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) { if globals.EnableMtwmStoreWrite { if approveType == partner.AfsApproveTypeRefused { - err = api.MtwmAPI.OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason) } else { - err = api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) + err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason) } } return err diff --git a/business/partner/purchase/mtwm/order_comment.go b/business/partner/purchase/mtwm/order_comment.go index 5fbc55e7e..b719fb843 100644 --- a/business/partner/purchase/mtwm/order_comment.go +++ b/business/partner/purchase/mtwm/order_comment.go @@ -14,7 +14,6 @@ import ( "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" - "git.rosy.net.cn/jx-callback/globals/api" ) const ( @@ -44,7 +43,7 @@ func formalizeTagList(mtwmTagList string) (outTagList string) { } 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, "") + storeMapList, err2 := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDMTWM}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "", "") if err = err2; err != nil { return err } @@ -53,7 +52,7 @@ func (c *PurchaseHandler) RefreshComment(fromTime, toTime time.Time) (err error) storeMap := batchItemList[0].(*model.StoreMap) endDateStr := time.Now().Add(-24 * time.Hour).Format("20060102") startDateStr := time.Now().Add(-RefreshCommentTime).Format("20060102") - commentList, err2 := api.MtwmAPI.CommentQuery(storeMap.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusAll) + commentList, err2 := getAPI(storeMap.VendorOrgCode, storeMap.StoreID, storeMap.VendorStoreID).CommentQuery(storeMap.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusAll) var orderCommentList []*model.OrderComment if err = err2; err != nil { @@ -106,7 +105,7 @@ func (c *PurchaseHandler) RefreshComment(fromTime, toTime time.Time) (err error) 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 = api.MtwmAPI.CommentAddReply(orderComment.VendorStoreID, utils.Str2Int64(orderComment.UserCommentID), replyComment) + err = getAPI(vendorOrgCode, orderComment.StoreID, orderComment.VendorStoreID).CommentAddReply(orderComment.VendorStoreID, utils.Str2Int64(orderComment.UserCommentID), replyComment) } return err } diff --git a/business/partner/purchase/mtwm/store.go b/business/partner/purchase/mtwm/store.go index c834465d2..63d0b0c26 100644 --- a/business/partner/purchase/mtwm/store.go +++ b/business/partner/purchase/mtwm/store.go @@ -1,7 +1,9 @@ package mtwm import ( + "encoding/json" "errors" + "fmt" "math" "regexp" "strings" @@ -21,7 +23,30 @@ import ( ) var ( - opTimeErrReg = regexp.MustCompile(`当前配送营业时间为:([\d:~,]*)`) + opTimeErrReg = regexp.MustCompile(`当前配送营业时间为:([\d:~,]*)`) + storeVendorOrgCodeMap = map[string]map[string]string{ + "589": map[string]string{ + "firstTag": mtwmapi.MtwmC4Tag, //经营品类 + "settlementID": "7030017", //结算ID + "poiCert": "1,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 { @@ -37,7 +62,7 @@ type tEbaiStoreInfo struct { } func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (retVal *dao.StoreDetail, err error) { - result, err := api.MtwmAPI.PoiGet(vendorStoreID) + result, err := getAPI(vendorOrgCode, 0, vendorStoreID).PoiGet(vendorStoreID) if err == nil { // globals.SugarLogger.Debug(utils.Format4Output(result, false)) retVal = &dao.StoreDetail{ @@ -73,9 +98,9 @@ func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendo retVal.ID = int(utils.Str2Int64WithDefault(poiCode, 0)) retVal.DeliveryRangeType = model.DeliveryRangeTypePolygon var deliveryRangeInfo []map[string]interface{} - deliveryRangeInfo, err = api.MtwmAPI.ShippingFetch(poiCode) + deliveryRangeInfo, err = getAPI(vendorOrgCode, 0, vendorStoreID).ShippingFetch(poiCode) if err != nil { - deliveryRangeInfo, err = api.MtwmAPI.ShippingList(poiCode) + deliveryRangeInfo, err = getAPI(vendorOrgCode, 0, vendorStoreID).ShippingList(poiCode) } if err == nil { if len(deliveryRangeInfo) > 0 { @@ -96,7 +121,104 @@ func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName strin return p.UpdateStore(db, storeID, userName) } -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { +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: 0, //创建 + 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 } @@ -109,13 +231,14 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin if db == nil { db = dao.GetDB() } - storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM) + mtapi := getAPI(getStoreVendorOrgCode(storeID), storeID, "") + storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM, "") if err != nil { return err } errList := errlist.New() - remoteStoreInfo, err := api.MtwmAPI.PoiGet(storeDetail.VendorStoreID) + remoteStoreInfo, err := mtapi.PoiGet(storeDetail.VendorStoreID) if err != nil { return err } @@ -152,7 +275,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin } // globals.SugarLogger.Debug(utils.Format4Output(params, false)) if globals.EnableMtwmStoreWrite { - errList.AddErr(api.MtwmAPI.PoiSave(storeDetail.VendorStoreID, params)) + errList.AddErr(mtapi.PoiSave(storeDetail.VendorStoreID, params)) } // PoiSave有时会报错:商家已接入美团配送,不可修改门店配送相关信息,这里放弃信息修改 // if err != nil { @@ -170,7 +293,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin 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)) + // errList.AddErr(p.UpdateStoreBoxFee(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID)) return errList.GetErrListAsOne() } @@ -180,18 +303,48 @@ func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask func (p *PurchaseHandler) onStoreStatusChanged(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) { var err error - poiStatus := int(utils.Str2Int64(msg.FormData.Get("poi_status"))) vendorStoreID := msg.FormData.Get("app_poi_code") storeStatus := 0 - 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) + 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) } @@ -200,7 +353,7 @@ func (p *PurchaseHandler) onStoreStatusChanged(msg *mtwmapi.CallbackMsg) (respon } func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) { - result, err := api.MtwmAPI.PoiGet(vendorStoreID) + result, err := getAPI(vendorOrgCode, storeID, "").PoiGet(vendorStoreID) if err == nil { return bizStatusMtwm2JX(result.OpenLevel, result.IsOnline), nil } @@ -215,18 +368,18 @@ func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCod openLevel, isOnline := bizStatusJX2Mtwm(status) if globals.EnableMtwmStoreWrite { if isOnline != mtwmapi.PoiStatusOnline { - err = api.MtwmAPI.PoiOffline(vendorStoreID) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOffline(vendorStoreID) } else { - if err = api.MtwmAPI.PoiOnline(vendorStoreID); err == nil { // 这个函数成功返回也并不表示上线成功。。。 - remoteStoreInfo, err2 := api.MtwmAPI.PoiGet(vendorStoreID) + 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 = api.MtwmAPI.PoiClose(vendorStoreID) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiClose(vendorStoreID) } else { - err = api.MtwmAPI.PoiOpen(vendorStoreID) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiOpen(vendorStoreID) } } else { err = errors.New("门店还未上线,不能修改营业状态") @@ -283,14 +436,14 @@ func constrainOpTimeList(opTimeList, validOpTimeList []int16) (newOpTimeList []i func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) { shippingTime := openTimeJX2Mtwm(opTimeList) if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.PoiShipTimeUpdate(vendorStoreID, shippingTime) + 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 = api.MtwmAPI.PoiShipTimeUpdate(vendorStoreID, shippingTime) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PoiShipTimeUpdate(vendorStoreID, shippingTime) } } } @@ -298,7 +451,7 @@ func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCod } func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) { - vendorStoreIDs, err = api.MtwmAPI.PoiGetIDs() + vendorStoreIDs, err = getAPIWithoutToken(vendorOrgCode).PoiGetIDs() return vendorStoreIDs, err } @@ -310,7 +463,7 @@ func (c *PurchaseHandler) UpdateStoreBoxFee(ctx *jxcontext.Context, vendorOrgCod boxFee, err := dao.GetSysConfigAsInt64(dao.GetDB(), model.ConfigSysMtwmBoxFee) if err == nil { if globals.EnableMtwmStoreWrite && globals.IsProductEnv() { - err = api.MtwmAPI.PackagePriceUpdate(vendorStoreID, 1, int(boxFee)) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).PackagePriceUpdate(vendorStoreID, 1, int(boxFee)) } } return err diff --git a/business/partner/purchase/mtwm/store_sku2.go b/business/partner/purchase/mtwm/store_sku2.go index a1e95fee9..36b20ecce 100644 --- a/business/partner/purchase/mtwm/store_sku2.go +++ b/business/partner/purchase/mtwm/store_sku2.go @@ -15,7 +15,6 @@ import ( "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" ) const ( @@ -55,9 +54,16 @@ func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) { 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 := api.MtwmAPI.RetailCatList(vendorStoreID) + remoteCats, err := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatList(vendorStoreID) if err == nil { cats = convertVendorCatList(remoteCats) } @@ -154,7 +160,7 @@ func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID in SecondaryCategoryName: subCatName, Sequence: storeCat.Seq, } - err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, catName, param4Update) + err = getAPI(storeCat.VendorOrgCode, storeID, vendorStoreID).RetailCatUpdate(vendorStoreID, catName, param4Update) if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 && // 修改分类名,但分类不存在 p.IsErrCategoryNotExist(err) && originName != "" { storeCat.CatSyncStatus |= model.SyncFlagNewMask @@ -175,7 +181,7 @@ func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID in func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) { if false { if globals.EnableMtwmStoreWrite { - err = api.MtwmAPI.RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID) + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID) } } else { var catCodes []string @@ -184,9 +190,9 @@ func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID in } if globals.EnableMtwmStoreWrite { if level == 1 { - err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil) + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil) } else { - err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil) + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil) } } } @@ -246,7 +252,7 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI syncType = "更新商品" } for i, storeSku := range storeSkuList { - // isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&( model.SyncFlagPriceMask| model.SyncFlagNewMask) != 0 + isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 foodData := make(map[string]interface{}) foodDataList[i] = foodData foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(storeSku.SkuID) @@ -256,15 +262,21 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI }, } foodData["skus"] = skus - foodData["name"] = utils.LimitUTF8StringLen(utils.FilterEmoji(storeSku.SkuName), mtwmapi.MaxSkuNameCharCount) + foodData["name"] = utils.LimitUTF8StringLen(storeSku.SkuName, mtwmapi.MaxSkuNameCharCount) foodData["description"] = storeSku.Comment - // if isNeedUpdatePrice { - foodData["price"] = jxutils.IntPrice2Standard(storeSku.VendorPrice) - // } - foodData["min_order_count"] = 1 + 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 - foodData["box_num"] = 1 - foodData["box_price"] = jxutils.IntPrice2Standard(storeSku.BoxFee) + attr := switchAttr(storeSku.VendorVendorCatID) + if attr != "" { + foodData["common_attr_value"] = attr + } catCode := tryCatName2Code(storeSku.VendorCatID) if catCode != "" { foodData["category_code"] = catCode @@ -277,7 +289,11 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI if img2 == "" { img2 = storeSku.Img } - foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, storeSku.Img, storeSku.Img, storeSku.Img), ",") + if storeSku.ImgMix != "" && ((storeSku.BrandID == storeSku.ExBrandID && storeSku.ExBrandID != 0) || storeSku.ExBrandID == 0) { + foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.ImgMix, img2, storeSku.ImgMix, storeSku.ImgMix, storeSku.ImgMix), ",") + } else { + foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, storeSku.Img, storeSku.Img, storeSku.Img), ",") + } } else { foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",") } @@ -291,13 +307,15 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI // foodData["tag_id"] = utils.Int64ToStr(defVendorCatID) } skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit) - // if isNeedUpdatePrice { - skus[0]["price"] = foodData["price"] - // } + 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 + skus[0]["ladder_box_price"] = jxutils.IntPrice2Standard(int64(storeSku.LadderBoxPrice)) if foodData["tag_id"] != nil { skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用 } @@ -305,10 +323,10 @@ func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeI if globals.EnableMtwmStoreWrite { if len(foodDataList) == 1 { foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"])) - err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) + err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType) } else if len(foodDataList) > 0 { - failedFoodList, err2 := api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) + 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) @@ -342,11 +360,11 @@ func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) { 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 = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID) + 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 = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList()) + 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) @@ -360,6 +378,30 @@ func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, v 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) } @@ -390,7 +432,7 @@ func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOr skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus) mtwmStatus := skuStatusJX2Mtwm(status) if globals.EnableMtwmStoreWrite { - failedFoodList, err2 := api.MtwmAPI.RetailSellStatus(ctx.GetTrackInfo(), vendorStoreID, skuList, mtwmStatus) + 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], "更新商品状态") @@ -410,7 +452,7 @@ func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOr 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 := api.MtwmAPI.RetailSkuPrice(ctx.GetTrackInfo(), vendorStoreID, priceList) + 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], "更新商品价格") @@ -429,7 +471,7 @@ func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrg 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 := api.MtwmAPI.RetailSkuStock(ctx.GetTrackInfo(), vendorStoreID, stockList) + 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], "更新商品库存") @@ -459,7 +501,7 @@ func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) { 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 := api.MtwmAPI.RetailGet(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID)) + skuInfo, err := getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).RetailGet(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID)) if err != nil { return nil, err } @@ -471,9 +513,10 @@ func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTas if storeSkuList != nil { storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList) } + mtapi := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID) for { // todo 待优化获取速度 - result, err := api.MtwmAPI.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit) + result, err := mtapi.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit) if err != nil { return nil, err } @@ -631,9 +674,9 @@ func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorO } if globals.EnableMtwmStoreWrite { if len(foodDataList) == 1 { - err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) + err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]) } else if len(foodDataList) > 0 { - _, err = api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) + _, err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList) } } return err diff --git a/business/partner/purchase/yb/order.go b/business/partner/purchase/yb/order.go index f8cace49e..59295fc58 100644 --- a/business/partner/purchase/yb/order.go +++ b/business/partner/purchase/yb/order.go @@ -12,7 +12,7 @@ func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, o func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) { return order } -func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) { +func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID, vendorStoreID string) (order *model.GoodsOrder, err error) { return order, err } func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) { diff --git a/business/partner/purchase/yb/store.go b/business/partner/purchase/yb/store.go index af4aa04a2..68818332c 100644 --- a/business/partner/purchase/yb/store.go +++ b/business/partner/purchase/yb/store.go @@ -15,7 +15,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin return err } -func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) { +func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error) { return vendorStoreID, err } diff --git a/business/partner/purchase/yb/store_sku.go b/business/partner/purchase/yb/store_sku.go index 530c8964d..9935ca26b 100644 --- a/business/partner/purchase/yb/store_sku.go +++ b/business/partner/purchase/yb/store_sku.go @@ -23,6 +23,10 @@ var ( sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`) ) +const ( + addErr1 = "商品已存在" +) + func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) { if globals.EnableYbStoreWrite { storeSku := storeSkuList[0] @@ -34,7 +38,19 @@ func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, v result, err = api.YinBaoAPI.AddProductInfo(buildProductInfoParam(storeSku)) } if err != nil { - failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") + if errExt, ok := err.(*utils.ErrorWithCode); ok { + if strings.Contains(errExt.ErrMsg(), addErr1) { + queryProductByBarcodeResult, _ := api.YinBaoAPI.QueryProductByBarcodes([]string{storeSku.YbBarCode}) + if len(queryProductByBarcodeResult) > 0 { + api.YinBaoAPI.BatchUpdateProductEnable(vendorStoreID, utils.Int64ToStr(queryProductByBarcodeResult[0].UID), model.SkuStatusNormal) + storeSku.VendorSkuID = utils.Int64ToStr(queryProductByBarcodeResult[0].UID) + } + } else { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") + } + } else { + failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDYB], "创建商品") + } } else { storeSku.VendorSkuID = utils.Int64ToStr(result.UID) err = uploadYbImage(vendorStoreID, storeSku.YbBarCode, storeSku.Img) @@ -91,7 +107,7 @@ func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, v } func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) { - storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDYB) + storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDYB, "") api.YinBaoAPI = yinbaoapi.New(storeDetail.YbAppKey, storeDetail.YbAppID) if configs, err := dao.QueryConfigs(dao.GetDB(), "yinbaoCookie", model.ConfigTypeCookie, ""); err == nil { yinbaoCookie := configs[0].Value diff --git a/conf/app.conf b/conf/app.conf index ef6f86ce8..0c0078087 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -15,6 +15,11 @@ dadaAppSecret = "7f97d8f258b70b450f04e7ab274ed8f8" mtwmAppID = "589" mtwmSecret = "a81eb3df418d83d6a1a4b7c572156d2f" mtwmCallbackURL = "http://callback.jxc4.com" + +mtwmAppID2 = "5873" +mtwmSecret2 = "41c479790a76f86326f89e8048964739" +mtwmCallbackURL2 = "http://callback.jxc4.com" + # mtwmCookieStr = "_lxsdk_cuid=16ddced5e9a95-0a65869c427a14-48714616-15f900-16ddced5e9b2b; _hc.v=cfebbfd1-79a7-9823-d8df-77e59646cb34.1571369610; _lxsdk=16ddced5e9a95-0a65869c427a14-48714616-15f900-16ddced5e9b2b; uuid_update=true; uuid=7b28e71504f5414e382b.1579155871.1.0.0; device_uuid=!64dedf83-b510-4910-8a31-b2b13d0bdd73; pushToken=00kRvxlerO15kB0dJFWDwYuctAoe04xGMNd0r3BqvLUA*; acctId=57396785; brandId=-1; wmPoiId=-1; isOfflineSelfOpen=0; city_id=0; isChain=1; existBrandPoi=true; ignore_set_router_proxy=true; region_id=; region_version=0; newCategory=false; bsid=OyqgRLyV54i9JKP0zRCI9jPyXc4UBU-6KReDAkPIwSlljhb97JPyFUIXfYQvhlJb6G1erzHQKbvtZ2pSWOYDxQ; cityId=510100; provinceId=510000; city_location_id=0; location_id=0; igateApp=shangouepc; wpush_server_url=wss://wpush.meituan.com; token=0MScAPaSa57iwRpgpCmGLf21tiA4yU4Uy-nDZlv8wNWs*; shopCategory=food; set_info=%7B%22wmPoiId%22%3A-1%2C%22ignoreSetRouterProxy%22%3Atrue%7D; JSESSIONID=105dgww27nsy6yfp68q7wmcni; LX_SC_CONSTANT=c_shangou_online_e_znrurnrc; _lxsdk_s=17041b590ac-3d-689-a8c%7C%7C15" autonaviKey = "ef64f638f31e05cb7bde28790f7309fe" @@ -55,6 +60,9 @@ weixinPageSecret = "c7a84ed3ef3ae04ac78e02fb593ffbe5" weixinMiniAppID = "wx08a5c2a8581414ff" weixinMiniSecret = "e7ec67c86cbd4dfa531af7af7533cdc9" +weixinMiniAppIDsc = "wx6be9ae15444fa83f" +weixinMiniSecretsc = "606ac9ff3e98016cee266704c933e687" + wxpayAppID = "wx4b5930c13f8b1170" wxpayAppKey = "XKJPOIHJ233adf01KJIXlIeQDSDKFJAD" wxpayAppMchID = "1390686702" @@ -123,10 +131,12 @@ getWeixinTokenKey = "c928ed0d-87a3-441a-8517-f92f0167296f" storeName = "京西菜市" storeNameMtwm = "京西菜市" storeNameEbai = "饿鲜达" +storeNameEbai2 = "好菜鲜生" smsSignName = "京西菜市" smsMobileVerifyTemplate = "SMS_175583158" smsNewOrderTemplate = "SMS_175583150" +smsNewOrderTemplateQ = "SMS_181856710" smsOrderCanceledTemplate = "SMS_175573134" smsNewUserOrderTemplate = "SMS_190284055" @@ -139,10 +149,20 @@ jdAppKey = "1dba76d40cac446ca500c0391a0b6c9d" jdSecret = "a88d031a1e7b462cb1579f12e97fe7f4" jd2OrgCode = "349454" -jd2Token = "29e0e567-c475-433a-aff0-37176ee8d8a7" +jd2Token = "c0615403-82a0-4226-acad-9f3af682399d" jd2AppKey = "7fb947624ff847ae94ff2f068cc99652" jd2Secret = "1097abd7ef09427099b4922784af123a" +jd3OrgCode = "359459" +jd3Token = "5e2c0a60-4450-40c0-a1da-b560051251ea" +jd3AppKey = "21b627c23ea04c69b64b48d0b361213e" +jd3Secret = "51cd27a748e64c829b4b7f83f4844610" + +jdcsOrgCode = "362665" +jdcsToken = "b3a64a71-90b0-4ee7-a572-80a2266a2a52" +jdcsAppKey = "9e4ebe035ba74c8f913bf51e6af3974c" +jdcsSecret = "8eb9778f1099416795c501b76dbb2e79" + elmIsProd = false elmToken = "2d2b583447b04b6bba5a6f3faed3559b" elmAppKey = "RwT214gAsS" @@ -172,15 +192,30 @@ EnableDocs = false jdOrgCode = "320406" jdLoginName = "jd_jxcs1223" -jdToken = "77e703b7-7997-441b-a12a-2e522efb117a" +jdToken = "29afd5a8-f93f-4d4c-9fce-a7297340af59" jdAppKey = "1dba76d40cac446ca500c0391a0b6c9d" jdSecret = "a88d031a1e7b462cb1579f12e97fe7f4" jd2OrgCode = "349454" -jd2Token = "29e0e567-c475-433a-aff0-37176ee8d8a7" +jd2Token = "c0615403-82a0-4226-acad-9f3af682399d" jd2AppKey = "7fb947624ff847ae94ff2f068cc99652" jd2Secret = "1097abd7ef09427099b4922784af123a" +jd3OrgCode = "359459" +jd3Token = "5e2c0a60-4450-40c0-a1da-b560051251ea" +jd3AppKey = "21b627c23ea04c69b64b48d0b361213e" +jd3Secret = "51cd27a748e64c829b4b7f83f4844610" + +jdcsOrgCode = "362665" +jdcsToken = "b3a64a71-90b0-4ee7-a572-80a2266a2a52" +jdcsAppKey = "9e4ebe035ba74c8f913bf51e6af3974c" +jdcsSecret = "8eb9778f1099416795c501b76dbb2e79" + +jdydOrgCode = "363179" +jdydToken = "5c4675f8-c635-4b78-a3a1-e2d91e33eff8" +jdydAppKey = "420624b948d9436daddf6501200f2ebf" +jdydSecret = "23064865bd3f49adaa5fc582daac1baf" + jdEclpAccessToken = "bcb6201b5b3c45a0976dcda5e2dea8aejiwm" jdEclpAppKey = "0D397F05CF11C51BCDCC81744680EBC3" jdEclpAppSecret = "f16a5e57ff4f4f428b702c40d2d4b933" @@ -190,6 +225,10 @@ jdShopAppKey = "E1D746D42474D5F1F1A10CECE75D99F6" jdShopAppSecret = "efa7e1d1a22640fa990e6cf164b28608" jdsCookie = "shshshfpa=13b38d4a-8ba0-df12-0012-82d9a37fb835-1573795914; shshshfpb=abYp8Dq5JobRtp2pkZa7MbA%3D%3D; __jdu=1142616513; pinId=WMIzMhF5BfL6nJp9AcA2-A; pin=shop_jxcs; unick=shop_jxcs; _tp=7FBEvLyPe%2FKcgxsfY5lRgA%3D%3D; _pst=shop_jxcs; areaId=22; ipLoc-djd=22-1930-50948-57092; user-key=3ec204b4-f204-4320-98e3-b2569c757800; cn=0; shshshfp=5d23828ee6ea3a33e1a58588db1713f8; 3AB9D23F7A4B3C9B=AK36FFYF5J6WMPRH7YTXMEX4CATHR6NAA3IQEESU2I33FEJRQ3DRLU4SZJYD2XGFLCFW43DHYP5HQKOMR4EFQSLKLA; navigation=[%22shop_jxcs%22]; __jdv=122270672|baidu|-|organic|not set|1589514011252; language=zh_CN; ceshi3.com=000; csrf_token=b84d0a5c-6288-4db4-84e1-cadf66be3bf7; mba_muid=1142616513; TrackID=1qvZk-6QSAOp1NmaouJGEx58_cFglCFv57HEfoHOezMrOnV3_FSK-5ExeYhHx97IltBADG3dvJqLIt3P57wyUW4Z2Q3Y8ITo8Cfdmlz3kykM; RT="z=1&dm=jd.com&si=mcot45862q&ss=kaf1rcqz&sl=2&tt=38t&ld=22qx&nu=b99e5a7f32b36f184614d34a1d926a39&cl=3clu&ul=3crs&hd=3cz3"; b-sec=S2JWP6CAFP7K4I6PXVBUVCO6YVXUX2JAPDHLX5RZUDE4YKCGOEXJIINB3Q4THCFCMVWZPFAYGLWLG; thor=80FAF09E9A09B6E618A68057BDFCFCB8C86E8252DC9F7D3B34572625904FBA0AB6BF053A5325612EC0407791BB05F5301356E71E8B282C40C06D0B5DF3439DEECB102A78FAFF7AC0FC4E2D1FA8DD8BBAE1A011E50B5C74F1870AD982D7BF453F470F31F2241B73AC4C25485025C2ABEBC8A538AF7257824D2FAEE300A1435175B0B451FB5C19B78D729FC83152CA3BAF; _vender_=TNK3O6PALVQGGA33SGBIUTOKL4OOE6DP6OMNVIPMAMULGTRFWUMTVWGFRUTYP4L4EPN3KP73P33BOBN5SNJFBNQB5OMQYSJ5MORGQLJS7QAPOMIN7AZD6B3ZLP2DV4JCXDI5P3KOXJ3PHLIIRZ2YVS4JSSA3JRSBACNLJSC24ELO46GIMRW53XGW36EBPLZMZP2MQCAMJNO44FKT46B7VDVT7KQTELESOOF6E377AYC3NWKQF6ICIYBW4BA4JL5QG2NHGNOHOUJDNUW3N22UF32DLFLEIQGVO2W55J6AKPPBT227XA5NO4S3NFVIUUUADGOYH56T72MTNXCILWVMN4RMUNVFMGL4ISGXJS7YILE7A2ESPAU43MISAOZM2BR53MGRB5OZSQZPV5DBDCN2OVVT3XT5N2VMFELARQNTMAJCDBGXFURSN2Q7SYULLKZEZHTYWWOI65LS5OIHLUZQKWFGMNSQF2UBSYV7FG46CWJGMVHOGV3FY4RUEVJK6BQ223QK3H3VMTHXCZOZV4GKR5EWGIZZDVUAK4B36BPA5HPBO7PXKBOEXEBX77IYBNQLCGMK72J4VKNOUPYKNB5JE5D5UN3R2MMFGLJARTL2QTC5ZRZ4PJCJZWWOV37VWLWFVAN5IGHPAYME73KTNFABM5W73XLOXJFQWTFRZEK3FCL3BLRV4UOXLBQGA34R4WUBYSZURMKTXXB7U; __jda=65775340.1142616513.1573036516.1589946171.1589952725.54; __jdb=65775340.147.1142616513|54.1589952725; __jdc=65775340; _base_=YKH2KDFHMOZBLCUV7NSRBWQUJPBI7JIMU5R3EFJ5UDHJ5LCU7R2NILKK5UJ6GLA2RGYT464UKXAI4Z6HPCTN4UQM3WHVQ4ENFP57OC2DC7JQLRXRUO5PW6B77O6UXAZ4TCNE6YVKRXISVLBYGYO44RCDDPWDA4AEL7ZLXI2SG4SOQWCP5WPWO6EFS7HEHMRWVKBRVHB33TFD4SMNBHRJCTDFHU6SZXCZD6RFXX2OORYGL5H2GYF2IIH2KKD4T72IR4F577G2E5II2OMMXYF2GDYNTS7WGAUXFEWRJ3CTKDBDWMHUKJQF4ZFOTNBBYBIZRXZYERXXIG6ATJFKID7XOR3NQ2CL6K7A2IEZV5HCBNYDPXFCM2ZMCS474KZ44S5F; _vender_new_=GI63BGTJFDBQ46CD7JXUX3HEPM4P5LEA3TJTFGW4ZGGIVOLTPK5T25EXTBLCENPUTR7E2I23YDFQ4ARO6JW3NHSWBDE73RTUKJTADIPFPLYFE3ARGJUBPHWUIONS72KRQOZC5P7PB4VPPLRHGEP7L3Z5K62L2E2MGTWHFJRQ3CAVBDYVW2Z4J6U73HW4BKKOCDAH5T6OJJKWKLBZFOTI7342QSL7YQ2E3I4T777RNZF23XGOTCP3D4INHNO5MNKT3XJZQBVHWUVZYQUXCK5QQTKWADKQUCYV3JRY6YAYOD7Z5IIKGNLREQTCPO7SYGSIS655JUGOUILFLXVZE6KCFG7ZTPRUD6VPE4KCIE4OUZSED6FTSEZHTM363E7XXCHB4NA7VLZHCQSBHDVGMRA7RM4RGJC3MOI4TJNGCLW6QKUCCZAY7XTGOTMC53TFUYERGNIH2RBULZ7UTZH5GU3TC6RWFI2QL4QTAIARA6GNVXENEOYIPZEHN222YDAJX5OBBEECAMAPNKZ3XNF5CNGDJ3DSU2ZLOCAKLFPCYTIIWPPJMCQ636F5464HS4OVFPFNIDW4OCE23JRPYP5FAL6TKHPAC3H3ZRU7WA5GKJJKBZUGIX7NEO4LZB7FJ3RZZZH3UHPQMNILD5DT2V7HVCUOVNOFBEOW5ID2ZMQ3XV264IU4MYHN64RA; _BELONG_CLIENT_=WPSC4XJXWK5USS4JNZY2X7VRLR5MCBKRSVHEXABGTHDGISIQK5YOLZUXYE7IOIM7MOKO74H6CRN6WHAAR4TMDV3XZWMXZRCRT5XRNE3V356BTOB2Y7LPK66VWQK6HPTGWVXIDXDCPVE3W5WMHAIO6AT2LX2XXVNUCXR34ZWFK6HY45CORGIKOSYDYZBF27WOKTUX6BS4FZMIJWNUX6CB4JAA25ZLF7ZEKYOO4QV5HTSBXGNRM3E242MBI6V5D4C5VJDQ3EOYCOW5BMTUJZACIBHXQFAVLRF76VQY5PNJGGJNBEZHSFYYJA3YORRT7FB5AHCOIFQKF3W5RWNUX6CB4JAA26JNMO7AYWNUPZF5HTSBXGNRM3E242MBI6V5D4C5VJDQ3EOYCOW5BWZDKMOJ5BS6II53ERY6ALV3ZWPF42L4CPUHEGPYIII35KDC4FCNVCORCXFD6IVNLBEDPB2GGP4UHWNRUDOQBDIW7RZJXBA2WV5ANZOTEGUCDWYRVQS2YUTIZNZ276PRYG4N56V6YTII7MBKBC7LYHO7C555HTSBXGNRM3E466AYN67DHWVM5HQFJ4NFDO5BTOKMOS5L2CXFVYDR2FCOILVYPEI; _lvtc_=5ZH3OJ7CWYNVGEKDRC32XTFXGY" +jdShopAccessToken2 = "9ad9cf5fc8b140b19a1dbbb700b47676kown" +jdShopAppKey2 = "D5E8352BE0786ED16F77B4548F62F09A" +jdShopAppSecret2 = "71e1061ac2f246f6ac27efb900edba12" + elmIsProd = true elmToken = "" elmAppKey = "KLRDcOZGrk" @@ -209,6 +248,8 @@ weixinAppID = "wx2bb99eb5d2c9b82c" weixinSecret = "6bbbed1443cc062c20a015a64c07a531" weixinMiniAppID2 = "wx4b5930c13f8b1170" weixinMiniSecret2 = "2a57228a716ce991a52739f0ff41111d" +weixinMiniAppID3 = "wx18111a41fd17f24f" +weixinMiniSecret3 = "c79ac6e1b2d6d7968e72a9658a8b6715" yinbaoAppKey = "682628966212343269" yinbaoAppID = "18C0E0867E467DBC26EFF5E957B02EC4" @@ -241,6 +282,15 @@ dingdingSecret = "LWrZAFeqUfuVv7n_tc8vPpCAx6PT4CwManx2XCVhJOqGsx2L5XCDuX1sAN_Jtv dingdingCallbackURL = "http://callback.jxc4.com/dingding/msg" +pushAppID = "5lyyrvHODG6wC8Sdr3a9h" +pushAppKey = "iFrkUDmR2g5eqQpfh2kQ57" +pushAppSecret = "WTn53qd6WAAdLMXfmXvzb7" +pushMasterSecret= "dGZcR0XGGg7H5Pd7FR3n47" + +fnAppID = "6a3e2073-1850-413b-9eb7-6c342ec36e1c" +fnAppSecret = "a8248088-a742-4c33-a0db-03aeae00ca7d" +fnCallbackURL = "http://callback.jxc4.com/fn/msg" + [jxgy] httpport = 8088 EnableDocs = false @@ -308,6 +358,7 @@ dingdingCallbackURL = "http://callback-jxgy.jxc4.com/dingding/msg" getWeixinTokenURL = "http://www.jxc4.com/v2/sys/GetWXToken" getYLYTokenURL = "http://www.jxc4.com/v2/sys/GetYLYToken" +getPushTokenURL = "http://www.jxc4.com/v2/sys/GetPushToken" jdEclpAccessToken = "bcb6201b5b3c45a0976dcda5e2dea8aejiwm" jdEclpAppKey = "0D397F05CF11C51BCDCC81744680EBC3" @@ -317,6 +368,10 @@ jdShopAccessToken = "de8157b447584885910f429011e49cb93yjq" jdShopAppKey = "E1D746D42474D5F1F1A10CECE75D99F6" jdShopAppSecret = "efa7e1d1a22640fa990e6cf164b28608" +fnAppID = "6a3e2073-1850-413b-9eb7-6c342ec36e1c" +fnAppSecret = "a8248088-a742-4c33-a0db-03aeae00ca7d" +fnCallbackURL = "http://callback-jxgy.jxc4.com/fn/msg" + storeName = "京西果园" [test] @@ -350,13 +405,13 @@ httpport = 8088 # xiaan jdOrgCode = "82029" -jdToken = "594ab45a-9a73-4a43-82b0-a64cbd55d883" +jdToken = "34eedf6f-78ab-4a3c-9415-a930d37bda6a" jdAppKey = "06692746f7224695ad4788ce340bc854" jdSecret = "d6b42a35a7414a5490d811654d745c84" jdStorePageCookie = "5EOCZRXVCRXBTYD5EPV6FOXRCQWFFQO75FRMJ3BAKZ5JXY6XTJECMWXK5OZIPLZTUWZKZKXHXA6I7G3WMIKSWOHZIHRLNE5FZY3NBD6G5IMBOYHMJSJR3RF4TMZB2JEW2DF755YPFUSA6BMWI3KNLT3I4EAP2Z4JA6ZWAA34MNQX5P6LOI4EGG76QJU3G3VW7QFE6BAVAONMKBEHKNXNZGX3RQF7PHXDXSPJSY5XQEGM7IV2L7LKIG3M2D6QVSPEGQW4NV7SZ4TX32D2XQA7PIX46M" -ebaiSource = "62289" -ebaiSecret = "d3ec2358d6a819ea" +ebaiSource = "61219" +ebaiSecret = "9ef8be6a53fb33e7" ebaiStorePageCookieWMUSS = "AHYHAAApIX5oBXUFKFsXKEdObiclRUhTFRZ1MUh7KEMiClB7MnB5G3VvIB5KN0USAABjQ4KngBfQ4Wcj9ebWYiEHBxCyNiBT1Yc111PhQ7UBluCENnCUB0HjIzfCAaHjAKEDoscT8sDL8JDDuQD81NaQ1dW3kN1MS9DeFMPgwC2YYROVy7AV3cKhMPkQrBwA" ebaiStorePageCookieWMSTOKEN = "UAABRL3ZhLykdGFQBBDxXVDBuYisaB3tQHjUmHlQ5cEAs5dxMdG0R-EwVILAy_CV1Vlw_nbQAA0ijuEe-F2xUzAQAAAdujHKzhohkrxY0c5LsAAH0CeSGnywAHBQAAMA" @@ -395,19 +450,24 @@ enableElmStoreWrite = false enableMtwmStoreWrite = false enableWscStoreWrite = false enableYbStoreWrite = false -enableJdShopWrite = true +enableJdShopWrite = false jdOrgCode = "320406" jdLoginName = "jd_jxcs1223" -jdToken = "77e703b7-7997-441b-a12a-2e522efb117a" +jdToken = "29afd5a8-f93f-4d4c-9fce-a7297340af59" jdAppKey = "1dba76d40cac446ca500c0391a0b6c9d" jdSecret = "a88d031a1e7b462cb1579f12e97fe7f4" jd2OrgCode = "349454" -jd2Token = "29e0e567-c475-433a-aff0-37176ee8d8a7" +jd2Token = "c0615403-82a0-4226-acad-9f3af682399d" jd2AppKey = "7fb947624ff847ae94ff2f068cc99652" jd2Secret = "1097abd7ef09427099b4922784af123a" +jd3OrgCode = "359459" +jd3Token = "5e2c0a60-4450-40c0-a1da-b560051251ea" +jd3AppKey = "21b627c23ea04c69b64b48d0b361213e" +jd3Secret = "51cd27a748e64c829b4b7f83f4844610" + jdEclpAccessToken = "bcb6201b5b3c45a0976dcda5e2dea8aejiwm" jdEclpAppKey = "0D397F05CF11C51BCDCC81744680EBC3" jdEclpAppSecret = "f16a5e57ff4f4f428b702c40d2d4b933" @@ -436,11 +496,14 @@ weixinAppID = "wx2bb99eb5d2c9b82c" weixinSecret = "6bbbed1443cc062c20a015a64c07a531" weixinMiniAppID2 = "wx4b5930c13f8b1170" weixinMiniSecret2 = "2a57228a716ce991a52739f0ff41111d" +weixinMiniAppID3 = "wx18111a41fd17f24f" +weixinMiniSecret3 = "c79ac6e1b2d6d7968e72a9658a8b6715" disableWeimob = false getWeixinTokenURL = "http://www.jxc4.com/v2/sys/GetWXToken" getWeixin2TokenURL = "http://www.jxc4.com/v2/sys/GetWX2Token" getWeimobTokenURL = "http://www.jxc4.com/v2/sys/GetWeimobToken" +getPushTokenURL = "http://www.jxc4.com/v2/sys/GetPushToken" dbConnectStr = "root:WebServer@1@tcp(127.0.0.1:3306)/jxd_dev_0?charset=utf8mb4&loc=Local&parseTime=true" diff --git a/controllers/act.go b/controllers/act.go index b4df2580a..89e6843a2 100644 --- a/controllers/act.go +++ b/controllers/act.go @@ -68,7 +68,7 @@ func (c *ActController) PreCreateAct() { // @Description 创建活动 // @Param token header string true "认证token" // @Param name formData string true "活动名,必须唯一(所以名子上最好带上日期)" -// @Param type formData int true "活动类型,3:直降,4:秒杀(美团当前不支持秒杀)" +// @Param type formData int true "活动类型,3:直降,4:秒杀(美团当前不支持秒杀),5:折扣(京西)" // @Param vendorIDs formData string true "厂商ID,当前只支持,京东:0,京西(用于记录活动信息):99" // @Param vendorOrgCode formData string false "厂商内组织代码" // @Param beginAt formData string true "开始日期" @@ -77,6 +77,9 @@ func (c *ActController) PreCreateAct() { // @Param advertising formData string true "广告语" // @Param actStoreSkuList formData string true "活动门店商品信息" // @Param overlapRule formData int false "活动重叠规则" +// @Param discountType formData int false "折扣类型,当活动类型是折扣的时候传入" +// @Param discountValue1 formData int false "折扣一档" +// @Param discountValue2 formData int false "折扣二档" // @Param limitDaily formData int false "是否按日0-不限,>0限购单数(秒杀需填)" // @Param limitUser formData int false "是否用户限购0-不限,1-限购" // @Param limitCount formData int false "限购件数 0-不限,如账号限购、设备限购有一个为1,则限购件数必须大于0的整数" @@ -108,6 +111,9 @@ func (c *ActController) CreateAct() { EndAt: timeList[1], Advertising: params.Advertising, Remark: params.Remark, + DiscountType: params.DiscountType, + DiscountValue1: params.DiscountValue1, + DiscountValue2: params.DiscountValue2, } retVal, err = act.CreateAct(params.Ctx, actObj, vendorIDs, params.VendorOrgCode, nil, actStoreSkuList, params.IsAsync) } @@ -183,7 +189,7 @@ func (c *ActController) CancelAct() { // @Param pageSize query int false "表页大小(缺省全部)" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult -// @router /GetActStoreSkuInfo [get] +// @router /GetActStoreSkuInfo [get,post] func (c *ActController) GetActStoreSkuInfo() { c.callGetActStoreSkuInfo(func(params *tActGetActStoreSkuInfoParams) (retVal interface{}, errCode string, err error) { var vendorIDs []int @@ -307,6 +313,27 @@ func (c *ActController) DeleteSkusFromAct() { }) } +// @Title 将门店从所有活动中删除 +// @Description 将门店从所有活动中删除 +// @Param token header string true "认证token" +// @Param storeIDs query string true "门店ID列表" +// @Param vendorID query int true "厂商ID" +// @Param types query string false "活动类型列表" +// @Param isAsync query bool false "是否异步" +// @Param isContinueWhenError query bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /DeleteStoresFromAct [delete] +func (c *ActController) DeleteStoresFromAct() { + c.callDeleteStoresFromAct(func(params *tActDeleteStoresFromActParams) (retVal interface{}, errCode string, err error) { + var storeIDs, types []int + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.Types, &types); err == nil { + retVal, err = act.DeleteStoresFromAct(params.Ctx, params.VendorID, types, storeIDs, params.IsAsync, params.IsContinueWhenError) + } + return retVal, "", err + }) +} + // @Title 强制更新商品平台价 // @Description 强制更新商品平台价 // @Param token header string true "认证token" diff --git a/controllers/cms.go b/controllers/cms.go index a323bb673..5c4294fde 100644 --- a/controllers/cms.go +++ b/controllers/cms.go @@ -139,6 +139,21 @@ func (c *CmsController) GetCoordinateDistrictCode() { }) } +// @Title 根据坐标得到城市 +// @Description 根据坐标得到城市 +// @Param token header string true "认证token" +// @Param lng query number true "经度" +// @Param lat query number true "纬度" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetCoordinateCityInfo [get] +func (c *CmsController) GetCoordinateCityInfo() { + c.callGetCoordinateCityInfo(func(params *tCmsGetCoordinateCityInfoParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetCoordinateCityInfo(params.Ctx, params.Lng, params.Lat) + return retVal, "", err + }) +} + // @Title 得到配置参数 // @Description 得到配置参数 // @Param token header string true "认证token" diff --git a/controllers/cms_msg.go b/controllers/cms_msg.go index 994581de6..e073856ee 100644 --- a/controllers/cms_msg.go +++ b/controllers/cms_msg.go @@ -21,6 +21,8 @@ type MsgController struct { // @Param storeIDs formData string true "门店 ID列表" // @Param title formData string true "消息标题" // @Param content formData string true "消息内容" +// @Param messageType formData int true "消息类型,1为普通给商家发的消息,3为活动内容通知" +// @Param actInfo formData string false "如果是活动内容通知需传" // @Param isAsync formData bool false "是否异步操作,缺省否" // @Param isContinueWhenError formData bool false "单个失败是否继续,缺省false" // @Success 200 {object} controllers.CallResult @@ -32,7 +34,29 @@ func (c *MsgController) SendStoreMessage() { if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err != nil { return retVal, "", err } - retVal, err = weixinmsg.SendStoreMessage(params.Ctx, params.Title, params.Content, storeIDs, params.IsAsync, params.IsContinueWhenError) + retVal, err = weixinmsg.SendStoreMessage(params.Ctx, params.Title, params.Content, storeIDs, params.ActInfo, params.MessageType, params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} + +// @Title 发送用户微信消息 +// @Description 发送用户微信消息 +// @Param token header string true "认证token" +// @Param userIDs formData string true "用户 ID列表" +// @Param title formData string true "消息标题" +// @Param content formData string true "消息内容" +// @Param isAsync formData bool false "是否异步操作,缺省否" +// @Param isContinueWhenError formData bool false "单个失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /SendUserMessage [post] +func (c *MsgController) SendUserMessage() { + c.callSendUserMessage(func(params *tMsgSendUserMessageParams) (retVal interface{}, errCode string, err error) { + var userIDs []string + if err = jxutils.Strings2Objs(params.UserIDs, &userIDs); err != nil { + return retVal, "", err + } + retVal, err = weixinmsg.SendUserMessage(params.Ctx, params.Title, params.Content, userIDs, params.IsAsync, params.IsContinueWhenError) return retVal, "", err }) } @@ -103,6 +127,7 @@ func (c *MsgController) GetStoreMessages() { // @Param storeIDs query string false "门店 ID列表" // @Param fromTime query string false "创建起始时间" // @Param toTime query string false "创建结束时间" +// @Param confirmStatuss query string false "确认状态,0表示没点,1表示确认,-1表示拒绝" // @Param fromReadCount query int false "已读次数开始" // @Param toReadCount query int false "已读次数结束" // @Param offset query int false "消息状态列表起始序号(以0开始,缺省为0)" @@ -112,9 +137,9 @@ func (c *MsgController) GetStoreMessages() { // @router /GetStoreMessageStatuses [get] func (c *MsgController) GetStoreMessageStatuses() { c.callGetStoreMessageStatuses(func(params *tMsgGetStoreMessageStatusesParams) (retVal interface{}, errCode string, err error) { - var msgIDs, storeIDs []int + var msgIDs, storeIDs, confirmStatuss []int var timeList []time.Time - if err = jxutils.Strings2Objs(params.MsgIDs, &msgIDs, params.StoreIDs, &storeIDs); err != nil { + if err = jxutils.Strings2Objs(params.MsgIDs, &msgIDs, params.StoreIDs, &storeIDs, params.ConfirmStatuss, &confirmStatuss); err != nil { return retVal, "", err } if timeList, err = jxutils.BatchStr2Time(params.FromTime, params.ToTime); err != nil { @@ -126,7 +151,7 @@ func (c *MsgController) GetStoreMessageStatuses() { if _, ok := params.MapData["toReadCount"]; !ok { params.ToReadCount = -1 } - retVal, err = cms.GetStoreMessageStatuses(params.Ctx, msgIDs, storeIDs, params.FromReadCount, params.ToReadCount, timeList[0], timeList[1], params.Keyword, params.Offset, params.PageSize) + retVal, err = cms.GetStoreMessageStatuses(params.Ctx, msgIDs, storeIDs, confirmStatuss, params.FromReadCount, params.ToReadCount, timeList[0], timeList[1], params.Keyword, params.Offset, params.PageSize) return retVal, "", err }) } diff --git a/controllers/cms_sku.go b/controllers/cms_sku.go index 1f5c9fe13..50fcc1674 100644 --- a/controllers/cms_sku.go +++ b/controllers/cms_sku.go @@ -7,6 +7,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals" "github.com/astaxie/beego" ) @@ -199,6 +200,8 @@ func (c *SkuController) UpdateSkuName() { delete(payload, "exPrefix") delete(payload, "exPrefixBegin") delete(payload, "exPrefixEnd") + delete(payload, "imgWaterMark") + delete(payload, "exVendorID") retVal, err = cms.UpdateSkuName(params.Ctx, params.NameID, payload, params.IsExd) } return retVal, "", err @@ -336,12 +339,13 @@ func (c *SkuController) SyncSku() { // @Title 获取敏感词列表 // @Description 获取敏感词列表 // @Param token header string true "认证token" +// @Param vendorID query int false "VendorID" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetSensitiveWordList [get] func (c *SkuController) GetSensitiveWordList() { c.callGetSensitiveWordList(func(params *tSkuGetSensitiveWordListParams) (retVal interface{}, errCode string, err error) { - sensitiveWordList, err := dao.GetSensitiveWordList() + sensitiveWordList, err := dao.GetSensitiveWordList(params.VendorID) var wordList []string for _, value := range sensitiveWordList { wordList = append(wordList, value.Word) @@ -351,6 +355,53 @@ func (c *SkuController) GetSensitiveWordList() { }) } +// @Title 插入敏感词列表 +// @Description 插入敏感词列表 +// @Param token header string true "认证token" +// @Param word formData string true "关键词名字" +// @Param vendorID formData int false "VendorID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /InsertSensitiveWord [post] +func (c *SkuController) InsertSensitiveWord() { + c.callInsertSensitiveWord(func(params *tSkuInsertSensitiveWordParams) (retVal interface{}, errCode string, err error) { + err = dao.InsertSensitiveWord(params.Word, params.VendorID, params.Ctx.GetUserName()) + return retVal, "", err + }) +} + +// @Title 修改敏感词列表 +// @Description 修改敏感词列表 +// @Param token header string true "认证token" +// @Param word formData string true "关键词名字" +// @Param vendorID formData int false "VendorID" +// @Param ID formData int false "关键词ID" +// @Param Status formData int false "状态,0为修改默认,1为删除" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateSensitiveWord [put] +func (c *SkuController) UpdateSensitiveWord() { + c.callUpdateSensitiveWord(func(params *tSkuUpdateSensitiveWordParams) (retVal interface{}, errCode string, err error) { + //word := &model.SensitiveWord{ + // VendorID: params.VendorID, + // Word: params.Word, + //} + globals.SugarLogger.Debug("UpdateSensitiveWord入参params:", params) + words, err := dao.GetSensitiveWordList(params.VendorID) + word := words[0] + word.Word = params.Word + if params.ID != 0 { + word.ModelIDCULD.ID = params.ID + } + if params.Status == 1 { + retVal, err = dao.DeleteSensitiveWord(word, params.ID, params.Ctx.GetUserName(), params.VendorID) + } else { + retVal, err = dao.UpdateSensitiveWord(word, params.VendorID, params.ID, params.Ctx.GetUserName()) + } + return retVal, "", err + }) +} + // @Title 子分类下商品的重排序 // @Description 子分类下商品的重排序 // @Param token header string true "认证token" @@ -403,9 +454,11 @@ func (c *SkuController) GetJdUpcCodeByName() { // @Description 批量设置商品额外前缀 // @Param token header string true "认证token" // @Param nameIDs formData string true "商品nameIDs" -// @Param exPrefix formData string true "商品额外前缀" +// @Param exPrefix formData string false "商品额外前缀" // @Param fromDate formData string true "生效开始时间,格式 2006-01-01 " // @Param toDate formData string true "生效结束时间,格式 2006-01-01 " +// @Param imgWaterMark formData string false "商品水印图" +// @Param vendorID formData int true "平台ID" // @Param isAsync formData bool false "是否异步" // @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" // @Success 200 {object} controllers.CallResult @@ -415,7 +468,7 @@ func (c *SkuController) UpdateSkuNamesExPrefix() { c.callUpdateSkuNamesExPrefix(func(params *tSkuUpdateSkuNamesExPrefixParams) (retVal interface{}, errCode string, err error) { var skuIDList []int if err = jxutils.Strings2Objs(params.NameIDs, &skuIDList); err == nil { - retVal, err = cms.UpdateSkuNamesExPrefix(params.Ctx, skuIDList, params.ExPrefix, params.FromDate, params.ToDate, params.IsAsync, params.IsContinueWhenError) + retVal, err = cms.UpdateSkuNamesExPrefix(params.Ctx, skuIDList, params.ImgWaterMark, params.VendorID, params.ExPrefix, params.FromDate, params.ToDate, params.IsAsync, params.IsContinueWhenError) } return retVal, "", err }) @@ -479,3 +532,154 @@ func (c *SkuController) RefreshJdDepot() { return retVal, "", err }) } + +// @Title 批量设置商品额外信息 +// @Description 批量设置商品额外信息 +// @Param token header string true "认证token" +// @Param nameIDs formData string true "商品nameIDs" +// @Param exPrefix formData string false "商品额外前缀" +// @Param fromDate formData string true "生效开始时间,格式 2006-01-01 " +// @Param toDate formData string true "生效结束时间,格式 2006-01-01 " +// @Param imgWaterMark formData string false "商品水印图" +// @Param brandID formData int false "品牌ID" +// @Param vendorID formData int true "平台ID" +// @Param vendorOrgCode formData string true "平台账号" +// @Param isAsync formData bool false "是否异步" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateSkuExinfoMap [put] +func (c *SkuController) UpdateSkuExinfoMap() { + c.callUpdateSkuExinfoMap(func(params *tSkuUpdateSkuExinfoMapParams) (retVal interface{}, errCode string, err error) { + var skuIDList []int + if err = jxutils.Strings2Objs(params.NameIDs, &skuIDList); err == nil { + retVal, err = cms.UpdateSkuExinfoMap(params.Ctx, skuIDList, params.ImgWaterMark, params.BrandID, params.VendorID, params.VendorOrgCode, params.ExPrefix, params.FromDate, params.ToDate, params.IsAsync, params.IsContinueWhenError) + } + return retVal, "", err + }) +} + +// @Title 得到平台类别 +// @Description 得到平台类别 +// @Param token header string true "认证token" +// @Param parentID query int false "父ID" +// @Param level query int false "分类等级" +// @Param vendorOrgCode query string true "账号ID" +// @Param vendorID query int true "平台ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetVendorCategoryMap [get] +func (c *SkuController) GetVendorCategoryMap() { + c.callGetVendorCategoryMap(func(params *tSkuGetVendorCategoryMapParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetVendorCategoryMap(params.Ctx, params.ParentID, params.Level, params.VendorID, params.VendorOrgCode) + return retVal, "", err + }) +} + +// @Title 新增平台类别 +// @Description 新增平台类别 +// @Param token header string true "认证token" +// @Param vendorID formData int true "平台ID" +// @Param vendorOrgCode formData string true "账号ID" +// @Param categroyID formData int false "京西分类id" +// @Param level formData int true "分类级别" +// @Param parentID formData int true "分类父ID" +// @Param vendorCategoryName formData string true "类别name" +// @Param vendorCategorySeq formData int true "类别序号" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddVendorCategoryMap [post] +func (c *SkuController) AddVendorCategoryMap() { + c.callAddVendorCategoryMap(func(params *tSkuAddVendorCategoryMapParams) (retVal interface{}, errCode string, err error) { + vendorCategoryMap := &model.VendorCategoryMap{ + VendorID: params.VendorID, + VendorOrgCode: params.VendorOrgCode, + CategoryID: params.CategroyID, + VendorCategoryName: params.VendorCategoryName, + VendorCategorySeq: params.VendorCategorySeq, + Level: params.Level, + ParentID: params.ParentID, + } + retVal, err = cms.AddVendorCategoryMap(params.Ctx, vendorCategoryMap) + return retVal, "", err + }) +} + +// @Title 修改平台类别 +// @Description 修改平台类别 +// @Param token header string true "认证token" +// @Param ID formData int true "记录ID" +// @Param categoryID formData int false "京西分类id" +// @Param vendorCategoryName formData string false "类别name" +// @Param level formData int true "分类级别" +// @Param parentID formData int true "分类父ID" +// @Param isDelete formData bool false "是否是删除操作,默认false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateVendorCategoryMap [put] +func (c *SkuController) UpdateVendorCategoryMap() { + c.callUpdateVendorCategoryMap(func(params *tSkuUpdateVendorCategoryMapParams) (retVal interface{}, errCode string, err error) { + vendorCategoryMap := &model.VendorCategoryMap{ + CategoryID: params.CategoryID, + VendorCategoryName: params.VendorCategoryName, + Level: params.Level, + ParentID: params.ParentID, + } + retVal, err = cms.UpdateVendorCategoryMap(params.Ctx, params.ID, vendorCategoryMap, params.IsDelete) + return retVal, "", err + }) +} + +// @Title 平台类别重排序 +// @Description 平台类别重排序 +// @Param token header string true "认证token" +// @Param categoryID formData int true "父ID" +// @Param vendorID formData int true "平台ID" +// @Param vendorOrgCode formData string true "账号ID" +// @Param categoryIDs formData string true "同一父类别下的所有子类别ID列表([1,2,3,4])" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /ReorderVendorCategories [put] +func (c *SkuController) ReorderVendorCategories() { + c.callReorderVendorCategories(func(params *tSkuReorderVendorCategoriesParams) (retVal interface{}, errCode string, err error) { + var idList []int + if err = utils.UnmarshalUseNumber([]byte(params.CategoryIDs), &idList); err == nil { + err = cms.ReorderVendorCategories(params.Ctx, params.CategoryID, params.VendorID, params.VendorOrgCode, idList) + } + return retVal, "", err + }) +} + +// @Title 复制平台类别 +// @Description 复制平台类别 +// @Param token header string true "认证token" +// @Param fromVendorOrgCode formData int true "源平台ID" +// @Param vendorID formData int true "平台ID" +// @Param toVendorOrgCodes formData string true "目标平台的IDs" +// @Param categoryIDs formData string false "原平台的分类IDs,不传代表整个复制" +// @Param isAsync formData bool false "是否异步操作" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CopyVendorCategories [put] +func (c *SkuController) CopyVendorCategories() { + c.callCopyVendorCategories(func(params *tSkuCopyVendorCategoriesParams) (retVal interface{}, errCode string, err error) { + return retVal, "", err + }) +} + +// @Title 平台分类读取门店分类 +// @Description 平台分类读取门店分类 +// @Param token header string true "认证token" +// @Param vendorOrgCode formData string true "账号ID" +// @Param vendorID formData int true "平台ID" +// @Param storeID formData int true "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /LoadStoreVendorCategories [post] +func (c *SkuController) LoadStoreVendorCategories() { + c.callLoadStoreVendorCategories(func(params *tSkuLoadStoreVendorCategoriesParams) (retVal interface{}, errCode string, err error) { + err = cms.LoadStoreVendorCategories(params.Ctx, params.VendorOrgCode, params.VendorID, params.StoreID) + return retVal, "", err + }) +} diff --git a/controllers/cms_store.go b/controllers/cms_store.go index c2b7bc993..acce34986 100644 --- a/controllers/cms_store.go +++ b/controllers/cms_store.go @@ -3,10 +3,12 @@ package controllers import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/jx-callback/business/jxstore/common" "git.rosy.net.cn/jx-callback/business/jxstore/misc" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/netprinter" "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego" ) @@ -41,6 +43,10 @@ type StoreController struct { // @Param orderCountTo query int false "订单量结束" // @Param marketManPhone query string false "市场负责人电话" // @Param briefLevel query int false "返回信息精简模式" +// @Param storeLevels query string false "门店等级" +// @Param brandID query int false "品牌ID" +// @Param marketManPhones query string false "市场负责人电话们" +// @Param earningType query int false "结算方式(1为报价,2为扣点)" // @Param offset query int false "门店列表起始序号(以0开始,缺省为0)" // @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" // @Success 200 {object} controllers.CallResult @@ -413,6 +419,7 @@ func (c *StoreController) BindPrinter() { // @Description 同步门店资质信息至平台(当前只支持京东) // @Param token header string true "认证token" // @Param storeIDs formData string true "京西门店ID列表,必须非空值" +// @Param vendorID formData int true "平台ID" // @Param isAsync formData bool true "是否异步操作" // @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" // @Success 200 {object} controllers.CallResult @@ -423,7 +430,7 @@ func (c *StoreController) SyncStoresQualify() { var storeIDs []int err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs) if err == nil { - retVal, err = cms.SyncStoresQualify(params.Ctx, storeIDs, params.IsAsync, params.IsContinueWhenError) + retVal, err = cms.SyncStoresQualify(params.Ctx, storeIDs, params.VendorID, params.IsAsync, params.IsContinueWhenError) } return retVal, "", err }) @@ -484,7 +491,7 @@ func (c *StoreController) GetStoreTotalScoreList() { if err == nil { var storeIDList []int if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil { - retVal, err = misc.GetStoreTotalScoreList(storeIDList, params.CityCode, params.Keyword, timeList[0], timeList[1], params.IsDesc, params.CheckScoreLow, params.CheckScoreHigh, params.Offset, params.PageSize) + retVal, err = misc.GetStoreTotalScoreList(params.Ctx, storeIDList, params.CityCode, params.Keyword, timeList[0], timeList[1], params.IsDesc, params.CheckScoreLow, params.CheckScoreHigh, params.Offset, params.PageSize) } } return retVal, "", err @@ -541,12 +548,13 @@ func (c *StoreController) SyncStoresCourierInfo() { // @Param lng query float64 true "经度" // @Param lat query float64 true "纬度" // @Param needWalkDistance query bool false "是否需要返回步行距离(且以步行距离排序)" +// @Param brandID query int false "品牌ID" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetStoreListByLocation [get] func (c *StoreController) GetStoreListByLocation() { c.callGetStoreListByLocation(func(params *tStoreGetStoreListByLocationParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.GetStoreListByLocation(params.Ctx, params.Lng, params.Lat, params.NeedWalkDistance) + retVal, err = common.GetStoreListByLocation(params.Ctx, params.Lng, params.Lat, 20000, params.NeedWalkDistance, false, params.BrandID) return retVal, "", err }) } @@ -665,3 +673,397 @@ func (c *StoreController) DeletePrinterSeq() { return retVal, "", err }) } + +// @Title 得到门店类别 +// @Description 得到门店类别 +// @Param token header string true "认证token" +// @Param parentID query int false "父ID" +// @Param level query int false "分类等级" +// @Param storeID query int true "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetStoreCategoryMap [get] +func (c *StoreController) GetStoreCategoryMap() { + c.callGetStoreCategoryMap(func(params *tStoreGetStoreCategoryMapParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetStoreCategoryMap(params.Ctx, params.ParentID, params.Level, params.StoreID) + return retVal, "", err + }) +} + +// @Title 新增门店类别 +// @Description 新增门店类别 +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Param categroyID formData int false "京西分类id" +// @Param level formData int true "分类级别" +// @Param parentID formData int true "分类父ID" +// @Param storeCategroyName formData string true "类别name" +// @Param storeCategroySeq formData int true "类别序号" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddStoreCategoryMap [post] +func (c *StoreController) AddStoreCategoryMap() { + c.callAddStoreCategoryMap(func(params *tStoreAddStoreCategoryMapParams) (retVal interface{}, errCode string, err error) { + storeCategoryMap := &model.StoreCategoryMap{ + StoreID: params.StoreID, + CategoryID: params.CategroyID, + StoreCategoryName: params.StoreCategroyName, + StoreCategorySeq: params.StoreCategroySeq, + Level: params.Level, + ParentID: params.ParentID, + } + retVal, err = cms.AddStoreCategoryMap(params.Ctx, storeCategoryMap) + return retVal, "", err + }) +} + +// @Title 修改门店类别 +// @Description 修改门店类别 +// @Param token header string true "认证token" +// @Param ID formData int true "记录ID" +// @Param categoryID formData int false "京西分类id" +// @Param storeCategroyName formData string false "类别name" +// @Param level formData int true "分类级别" +// @Param parentID formData int true "分类父ID" +// @Param isDelete formData bool false "是否是删除操作,默认false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateStoreCategoryMap [put] +func (c *StoreController) UpdateStoreCategoryMap() { + c.callUpdateStoreCategoryMap(func(params *tStoreUpdateStoreCategoryMapParams) (retVal interface{}, errCode string, err error) { + storeCategoryMap := &model.StoreCategoryMap{ + CategoryID: params.CategoryID, + StoreCategoryName: params.StoreCategroyName, + Level: params.Level, + ParentID: params.ParentID, + } + retVal, err = cms.UpdateStoreCategoryMap(params.Ctx, params.ID, storeCategoryMap, params.IsDelete) + return retVal, "", err + }) +} + +// @Title 门店类别重排序 +// @Description 门店类别重排序 +// @Param token header string true "认证token" +// @Param categoryID formData int true "父ID" +// @Param storeID formData int true "门店ID" +// @Param categoryIDs formData string true "同一父类别下的所有子类别ID列表([1,2,3,4])" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /ReorderStoreCategories [put] +func (c *SkuController) ReorderStoreCategories() { + c.callReorderStoreCategories(func(params *tSkuReorderStoreCategoriesParams) (retVal interface{}, errCode string, err error) { + var idList []int + if err = utils.UnmarshalUseNumber([]byte(params.CategoryIDs), &idList); err == nil { + err = cms.ReorderStoreCategories(params.Ctx, params.CategoryID, params.StoreID, idList) + } + return retVal, "", err + }) +} + +// @Title 复制门店类别 +// @Description 复制门店类别 +// @Param token header string true "认证token" +// @Param fromStoreID formData int true "源门店ID" +// @Param toStoreIDs formData string true "目标门店的IDs" +// @Param categoryIDs formData string false "原门店的分类IDs,不传代表整个复制" +// @Param isAsync formData bool false "是否异步操作" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CopyStoreCategories [put] +func (c *SkuController) CopyStoreCategories() { + var toStoreIDs, categoryIDs []int + c.callCopyStoreCategories(func(params *tSkuCopyStoreCategoriesParams) (retVal interface{}, errCode string, err error) { + if jxutils.Strings2Objs(params.ToStoreIDs, &toStoreIDs, params.CategoryIDs, &categoryIDs); err == nil { + retVal, err = cms.CopyStoreCategories(params.Ctx, params.FromStoreID, toStoreIDs, categoryIDs, params.IsAsync, params.IsContinueWhenError) + } + return retVal, "", err + }) +} + +// @Title 修改门店专属调价包 +// @Description 修改门店专属调价包 +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Param vendorID formData int true "平台ID" +// @Param pricePack formData string true "门店调价包" +// @Param value formData string false "调价包json串" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateStorePricePack [put] +func (c *StoreController) UpdateStorePricePack() { + c.callUpdateStorePricePack(func(params *tStoreUpdateStorePricePackParams) (retVal interface{}, errCode string, err error) { + err = cms.UpdateStorePricePack(params.Ctx, params.StoreID, params.VendorID, params.PricePack, params.Value) + return retVal, "", err + }) +} + +// @Title 根据门店获取距离最近的货源店铺 +// @Description 修根据门店获取距离最近的货源店铺 +// @Param token header string true "认证token" +// @Param storeID query int true "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetNearSupplyGoodsStoreByStoreID [get] +func (c *StoreController) GetNearSupplyGoodsStoreByStoreID() { + c.callGetNearSupplyGoodsStoreByStoreID(func(params *tStoreGetNearSupplyGoodsStoreByStoreIDParams) (retVal interface{}, errCode string, err error) { + retVal, err = common.GetNearSupplyGoodsStoreByStoreID(params.Ctx, params.StoreID) + return retVal, "", err + }) +} + +// @Title 获取京东门店手动划的配送范围面积 +// @Description 获取京东门店手动划的配送范围面积 +// @Param token header string true "认证token" +// @Param storeIDs query string true "门店IDs" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetJdDeliveryArea [get] +func (c *StoreController) GetJdDeliveryArea() { + var storeIDs []int + c.callGetJdDeliveryArea(func(params *tStoreGetJdDeliveryAreaParams) (retVal interface{}, errCode string, err error) { + if jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err == nil { + err = cms.GetJdDeliveryArea(params.Ctx, storeIDs) + } + return retVal, "", err + }) +} + +// @Title 修改门店对应Cid(个推推送uniapp消息用) +// @Description 修改门店对应Cid(个推推送uniapp消息用) +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Param clientID formData string true "cID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateStorePushClient [post] +func (c *StoreController) UpdateStorePushClient() { + c.callUpdateStorePushClient(func(params *tStoreUpdateStorePushClientParams) (retVal interface{}, errCode string, err error) { + err = cms.UpdateStorePushClient(params.Ctx, params.StoreID, params.ClientID) + return retVal, "", err + }) +} + +// @Title 用户申请门店审核 +// @Description 用户申请门店审核 +// @Param token header string true "认证token" +// @Param payload formData string true "json数据,store对象" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CreateStoreAudit [post] +func (c *StoreController) CreateStoreAudit() { + c.callCreateStoreAudit(func(params *tStoreCreateStoreAuditParams) (retVal interface{}, errCode string, err error) { + store := &model.StoreAudit{} + if err = utils.UnmarshalUseNumber([]byte(params.Payload), store); err == nil { + err = cms.CreateStoreAudit(params.Ctx, store) + } + return retVal, "", err + }) +} + +// @Title 获取用户申请门店审核 +// @Description 获取用户申请门店审核 +// @Param token header string true "认证token" +// @Param applyTimeStart query string false "申请开始时间" +// @Param applyTimeEnd query string false "申请结束时间" +// @Param auditTimeStart query string false "审核开始时间" +// @Param auditTimeEnd query string false "审核结束时间" +// @Param name query string false "审核人" +// @Param statuss query string false "审核状态" +// @Param keyword query string false "关键字" +// @Param offset query int false "门店列表起始序号(以0开始,缺省为0)" +// @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetStoreAudit [get] +func (c *StoreController) GetStoreAudit() { + c.callGetStoreAudit(func(params *tStoreGetStoreAuditParams) (retVal interface{}, errCode string, err error) { + var ( + statuss []int + ) + if err = jxutils.Strings2Objs(params.Statuss, &statuss); err != nil { + return retVal, "", err + } + retVal, err = cms.GetStoreAudit(params.Ctx, statuss, params.Keyword, params.ApplyTimeStart, params.ApplyTimeEnd, params.AuditTimeStart, params.AuditTimeEnd, params.PageSize, params.Offset) + return retVal, "", err + }) +} + +// @Title 门店审核 +// @Description 门店审核 +// @Param token header string true "认证token" +// @Param payload formData string true "json数据,storeaudit对象" +// @Param status formData int false "审核标志,1通过,-1 不通过" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /StoreAudit [post] +func (c *StoreController) StoreAudit() { + c.callStoreAudit(func(params *tStoreStoreAuditParams) (retVal interface{}, errCode string, err error) { + var stores []*model.StoreAudit + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &stores); err == nil { + retVal, err = cms.StoreAudit(params.Ctx, stores, params.Status) + } + return retVal, "", err + }) +} + +// @Title 比较美团配送门店信息 +// @Description 比较美团配送门店信息 +// @Param token header string true "认证token" +// @Param storeIDs formData string true "门店ids" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetDiffJxStoreAndMTWMStoreInfo [post] +func (c *StoreController) GetDiffJxStoreAndMTWMStoreInfo() { + c.callGetDiffJxStoreAndMTWMStoreInfo(func(params *tStoreGetDiffJxStoreAndMTWMStoreInfoParams) (retVal interface{}, errCode string, err error) { + var storeIDs []int + if err = utils.UnmarshalUseNumber([]byte(params.StoreIDs), &storeIDs); err == nil { + err = cms.GetDiffJxStoreAndMTWMStoreInfo(params.Ctx, storeIDs) + } + return retVal, "", err + }) +} + +// @Title 查询京东到家app上门店信息 +// @Description 查询京东到家app上门店信息 +// @Param token header string true "认证token" +// @Param vendorStoreID query string true "门店id" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetJddjStoreInfo [get] +func (c *StoreController) GetJddjStoreInfo() { + c.callGetJddjStoreInfo(func(params *tStoreGetJddjStoreInfoParams) (retVal interface{}, errCode string, err error) { + api.JdAPI.SetCookieWithStr(` + shshshfpa=13b38d4a-8ba0-df12-0012-82d9a37fb835-1573795914; shshshfpb=abYp8Dq5JobRtp2pkZa7MbA%3D%3D; cart_uuid=1bd562b37ef02371; track=46099cdb-39fb-abe6-579e-ea9536a8cf9c; deviceid_pdj_jd=H5_DEV_92DD6F05-B71A-43D7-9790-529335C43AAC; mba_muid=1605755815875269445822; TrackerID=E6aNCj4mNlBVkq6eyFfWLvkbWl9DhdG-pRGVaQPbvt2ewCa2n0QM-p0mViOLv_Uem9pAWgbNZEeaJuaz4gARAW9rTj8PJK-3hmcbl9N9h1qg-DMYXvdwc3Iau-AMlWin29CojqE8YnUPMtlJUf2gnA; pt_token=y2wjxzef; pwdt_id=jd_5e10f2d70fb4c; h5_coords_obj=""; o2o_m_h5_sid=5cb8b4db-feaa-4b25-aa96-df96cf9dba6d; PDJ_H5_JDPIN=jd_5e10f2d70fb4c; PDJ_H5_MOBILE=181****0913; PDJ_H5_PIN=JD_222ea79f49b3211; navigation=[%22shop_jxcs2020%22]; shshshfp=34eda22ad0af63b76392daccd2d03f2e; cid=NWtRMjE2NndZMzc4N2hWNzMyOHFBNDcwMXdTMjEwMm9BMjE4M3JPNjkwNHJQODk2; 3AB9D23F7A4B3C9B=AK36FFYF5J6WMPRH7YTXMEX4CATHR6NAA3IQEESU2I33FEJRQ3DRLU4SZJYD2XGFLCFW43DHYP5HQKOMR4EFQSLKLA; __jdu=1591327001141529223150; __jdv=27966078|direct|-|none|-|1606900892557; pt_key=app_openAAJfzzr6ADCQcdEYCKb4BH4DNh-9sVcgVB7nYveTS-J-x3tuin7otTCG7qTRTasxQdi-pr8mkFU; pt_pin=jd_5e10f2d70fb4c; sid=7fc3a18bc45c5766395cd2a8ad1c6daw; is_sz_old_version=false; language=zh_CN; TrackID=1a_Q7xLAd79K-ifyBFeTkWcSF5DEgCm9ISEjFoCF1VhbmI0XLzk-3Np5Wa0O0f0W2UZCX327iWisSzKkCasW_kqc4MqKSXDbOxk3w4AByhjM; pinId=qA40zQJfoxUJ0BznFrVelbV9-x-f3wj7; pin=jd_5e10f2d70fb4c; unick=jd_181600jgy; ceshi3.com=201; _tp=tPAwCz7dZ2wG9FcrXkvXEPcH%2FgU%2BK8r%2FxTPrJfx1wo8%3D; _pst=jd_5e10f2d70fb4c; b-sec=2GBADPFJ55VHNAQ2DUPKR7Y2CEX6NF5ABOAAZCYCWLTBU4NIRBCM7FKZVF35XOCEUIAEOLVWWE3OPD6NRWBX675VTE; thor=E6F66DF4AD3A159C1AE9872C7BB0CF4D5E2B8B9C52714A91A28E40CDCDB5FE53C00D4CD2A91B92947D52C5EE00FBE8D652EBD6251926555789988488332962E56D7343A6B07A071F9FF37C24CE28506474AD1E996F78691C9194C9B3171F9255349E4A94AE37D23F6A1BBE49880177B7E3D701F06FAEC88026BA9E09D25E789B59226B670D64ECA829E356891A1FB2E2D0036899FE49F651BBE4F7BCCE857385; __jda=191429163.1591327001141529223150.1591327001.1607907141.1607938587.81; __jdc=191429163; __jdb=191429163.4.1591327001141529223150|81.1607938587; _base_=YKH2KDFHMOZBLCUV7NSRBWQUJPBI7JIMU5R3EFJ5UDHJ5LCU7R2NILKK5UJ6GLA2RGYT464UKXAI5KK7PNC5B5UHJ2HVQ4ENFP57OC2NCIWTST4KDNCWZES6EV2TD5XDTCNE6YVKRXISVWNQHZDBO6QEKYXMXGPYGVEOCQCSG4SOQWCP5WPWO6EFS7HEHMRWVKBRVHB33TFD4AUHV3TOJD7MGBX53BNNP2E6MSSOORYGL5H2GYFRURR5ACFJ54GH7PTHFL22YL3C6ODFYFTWGV5UAWCX5C6J372TDCL6LDNEERERTGC3XZYHUWG3GYQCRBMGP7O2Q2MPVVQAQIWW3S2YBGSPJZVO3XPNMOJI6RFTJD5NXZUZMBDK4FVEVR2D + `) + retVal, err = api.JdAPI.GetJdStoreInfo(params.VendorStoreID) + return retVal, "", err + }) +} + +// @Title 查询品牌 +// @Description 查询品牌 +// @Param token header string false "认证token" +// @Param brandID query int false "品牌ID" +// @Param name query string false "品牌名" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetBrands [get] +func (c *StoreController) GetBrands() { + c.callGetBrands(func(params *tStoreGetBrandsParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetBrands(params.Ctx, params.Name, params.BrandID) + return retVal, "", err + }) +} + +// @Title 新增品牌 +// @Description 新增品牌 +// @Param token header string true "认证token" +// @Param payload formData string true "brand payload" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddBrand [post] +func (c *StoreController) AddBrand() { + c.callAddBrand(func(params *tStoreAddBrandParams) (retVal interface{}, errCode string, err error) { + var brand = &model.Brand{} + if err = utils.UnmarshalUseNumber([]byte(params.Payload), brand); err == nil { + err = cms.AddBrand(params.Ctx, brand) + } + return retVal, "", err + }) +} + +// @Title 修改品牌 +// @Description 修改品牌 +// @Param token header string true "认证token" +// @Param payload formData string true "brand payload" +// @Param isDel formData bool false "是否是删除" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateBrand [post] +func (c *StoreController) UpdateBrand() { + c.callUpdateBrand(func(params *tStoreUpdateBrandParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + err = cms.UpdateBrand(params.Ctx, payload, params.IsDel) + } + return retVal, "", err + }) +} + +// @Title 修改门店分类为京西分类 +// @Description 修改门店分类为京西分类 +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /InsertStoreCategories [post] +func (c *StoreController) InsertStoreCategories() { + c.callInsertStoreCategories(func(params *tStoreInsertStoreCategoriesParams) (retVal interface{}, errCode string, err error) { + err = cms.InsertStoreCategories(params.Ctx, nil, params.StoreID) + return retVal, "", err + }) +} + +// @Title 创建平台门店 +// @Description 创建平台门店 +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Param vendorID formData int true "平台ID" +// @Param payload formData string true "json数据,store对象" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CreateVendorStore [post] +func (c *StoreController) CreateVendorStore() { + c.callCreateVendorStore(func(params *tStoreCreateVendorStoreParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + err = cms.CreateVendorStore(params.Ctx, params.StoreID, params.VendorID, payload) + } + return retVal, "", err + }) +} + +// @Title 查询品牌店铺 +// @Description 查询品牌店铺 +// @Param token header string false "认证token" +// @Param name query string true "品牌名" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetBrandStore [get] +func (c *StoreController) GetBrandStore() { + c.callGetBrandStore(func(params *tStoreGetBrandStoreParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetBrandStore(params.Ctx, params.Name) + return retVal, "", err + }) +} + +// @Title 商家确认参与活动 +// @Description 商家确认参与活动 +// @Param token header string false "认证token" +// @Param status formData int true "确认或取消,确认1,取消-1" +// @Param msgStatusID formData int true "消息状态ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /StoreConfirmAct [post] +func (c *StoreController) StoreConfirmAct() { + c.callStoreConfirmAct(func(params *tStoreStoreConfirmActParams) (retVal interface{}, errCode string, err error) { + err = cms.StoreConfirmAct(params.Ctx, params.Status, params.MsgStatusID) + return retVal, "", err + }) +} + +// @Title 查询门店账户余额 +// @Description 查询门店账户余额 +// @Param token header string true "认证token" +// @Param storeID formData int true "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetStoreAcctBalance [get] +func (c *StoreController) GetStoreAcctBalance() { + c.callGetStoreAcctBalance(func(params *tStoreGetStoreAcctBalanceParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetStoreAcctBalance(params.Ctx, params.StoreID) + return retVal, "", err + }) +} diff --git a/controllers/cms_store_sku.go b/controllers/cms_store_sku.go index 1adad8330..2d96c4ebe 100644 --- a/controllers/cms_store_sku.go +++ b/controllers/cms_store_sku.go @@ -4,6 +4,8 @@ import ( "math" "time" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/jx-callback/business/jxstore/cms" @@ -89,6 +91,8 @@ func (c *StoreSkuController) GetStoreSkus() { // @Param lockTime query string false "价格锁定时间" // @Param isHighPrice query bool false "是否查过高价格商品,0是忽略,1是高价,-1是低价" // @Param priceType query int false "是否查过高价格商品,0是忽略,1是高价,-1是低价" +// @Param highestPrice query string false "查询最高价" +// @Param minimumPrice query string false "查询最低价" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetStoresSkus [get,post] @@ -214,6 +218,7 @@ func (c *StoreSkuController) SyncStoresSkus() { // @Param payload formData string true "json数据,StoreSkuBindInfo对象数组" // @Param isScale formData bool false "是否按门店结算比例缩放" // @Param causeFlag formData int false "操作类型" +// @Param isRefreshHigh formData bool false "是否只刷门店价高于给的价" // @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" // @Param isAsync formData bool false "是否异步操作" // @Success 200 {object} controllers.CallResult @@ -226,7 +231,28 @@ func (c *StoreSkuController) UpdateStoresSkus() { if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.Payload, &skuBindInfos); err != nil { return retVal, "", err } - retVal, err = cms.UpdateStoresSkus(params.Ctx, params.CauseFlag, storeIDs, skuBindInfos, params.IsScale, params.IsAsync, params.IsContinueWhenError) + retVal, err = cms.UpdateStoresSkus(params.Ctx, params.CauseFlag, storeIDs, skuBindInfos, params.IsScale, params.IsRefreshHigh, params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} + +// @Title 批量修改多商家商品绑定(不同步) +// @Description 批量修改多商家商品绑定(不同步) +// @Param token header string true "认证token" +// @Param storeIDs formData string false "门店ID列表" +// @Param payload formData string true "json数据,StoreSkuBindInfo对象数组" +// @Param isRefreshHigh formData bool true "是否只刷门店价高于给的价" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateStoresSkusWithoutSync [put] +func (c *StoreSkuController) UpdateStoresSkusWithoutSync() { + c.callUpdateStoresSkusWithoutSync(func(params *tStoreSkuUpdateStoresSkusWithoutSyncParams) (retVal interface{}, errCode string, err error) { + var storeIDs []int + var skuBindInfos []*cms.StoreSkuBindInfo + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.Payload, &skuBindInfos); err != nil { + return retVal, "", err + } + err = cms.UpdateStoresSkusWithoutSync(params.Ctx, storeIDs, skuBindInfos, params.IsRefreshHigh) return retVal, "", err }) } @@ -475,7 +501,7 @@ func (c *StoreSkuController) GetTopSkusByStoreIDs() { // @Title 根据城市信息查找推荐商品(按销量) // @Description 根据城市信息查找推荐商品(按销量) // @Param token header string true "认证token" -// @Param cityCode query int true "城市id" +// @Param cityCode query int false "城市id" // @Param storeID query int false "门店id" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult @@ -556,6 +582,12 @@ func (c *StoreSkuController) FocusStoreSkusByExcel() { r := c.Ctx.Request files := r.MultipartForm.File["userfiles"] retVal, err = cms.FocusStoreSkusByExcel(params.Ctx, files, params.IsAsync, params.IsContinueWhenError) + // file, head, err := c.GetFile("userfiles") + // defer file.Close() + // if path.Ext(head.Filename) != ".jpg" && path.Ext(head.Filename) != ".png" { + // err = fmt.Errorf("文件格式不对!") + // } + // c.SaveToFile("userfiles", "./"+head.Filename) return retVal, "", err }) } @@ -811,3 +843,83 @@ func (c *StoreSkuController) SyncMatterC4ToGy() { return retVal, "", err }) } + +// @Title 查询商品审核信息 +// @Description 查询商品审核信息 +// @Param token header string true "认证token" +// @Param applyTimeStart query string false "申请开始时间" +// @Param applyTimeEnd query string false "申请结束时间" +// @Param auditTimeStart query string false "审核开始时间" +// @Param auditTimeEnd query string false "审核结束时间" +// @Param name query string false "审核人" +// @Param remark query string false "不通过原因" +// @Param storeIDs query string false "门店ID列表" +// @Param nameIDs query string false "id列表对象,当前指skuname id" +// @Param statuss query string false "审核状态" +// @Param types query string false "改价类型,1是普通改价,2是关注" +// @Param keyword query string false "关键字" +// @Param marketManPhone query string false "市场负责人电话" +// @Param cityName query string false "城市名" +// @Param offset query int false "门店列表起始序号(以0开始,缺省为0)" +// @Param pageSize query int false "门店列表页大小(缺省为50,-1表示全部)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetStoreSkuAudit [get] +func (c *StoreSkuController) GetStoreSkuAudit() { + c.callGetStoreSkuAudit(func(params *tStoreSkuGetStoreSkuAuditParams) (retVal interface{}, errCode string, err error) { + var ( + storeIDs, nameIDs, statuss, types []int + ) + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.NameIDs, &nameIDs, params.Statuss, &statuss, params.Types, &types); err != nil { + return retVal, "", err + } + retVal, err = cms.GetStoreSkuAudit(params.Ctx, storeIDs, nameIDs, nil, statuss, types, params.Name, params.Remark, params.Keyword, params.MarketManPhone, params.CityName, params.ApplyTimeStart, params.ApplyTimeEnd, params.AuditTimeStart, params.AuditTimeEnd, params.PageSize, params.Offset) + return retVal, "", err + }) +} + +// @Title 审核商品 +// @Description 审核商品 +// @Param token header string true "认证token" +// @Param payload formData string true "json数据,storeskuaudit对象" +// @Param status formData int false "审核标志,1通过,-1 不通过,2 预审核" +// @Param isAsync formData bool false "是否异步,缺省是同步" +// @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /StoreSkuPriceAudit [post] +func (c *StoreSkuController) StoreSkuPriceAudit() { + c.callStoreSkuPriceAudit(func(params *tStoreSkuStoreSkuPriceAuditParams) (retVal interface{}, errCode string, err error) { + var storeSkuAudits []*model.StoreSkuAudit + if err = jxutils.Strings2Objs(params.Payload, &storeSkuAudits); err != nil { + return retVal, "", err + } + retVal, hint, err := cms.StoreSkuPriceAudit(params.Ctx, storeSkuAudits, params.Status, params.IsAsync, params.IsContinueWhenError) + if hint != "" { + return hint, "", err + } else { + return retVal, "", err + } + }) +} + +// @Title 查看美团力荐或京东置顶商品 +// @Description 查看美团力荐或京东置顶商品 +// @Param token header string true "认证token" +// @Param vendorIDs formData string true "平台ids" +// @Param storeIDs formData string true "门店IDs" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetSpecialtyStoreSkus [post] +func (c *StoreSkuController) GetSpecialtyStoreSkus() { + c.callGetSpecialtyStoreSkus(func(params *tStoreSkuGetSpecialtyStoreSkusParams) (retVal interface{}, errCode string, err error) { + var ( + storeIDs, vendorIDs []int + ) + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs, params.VendorIDs, &vendorIDs); err != nil { + return retVal, "", err + } + err = cms.GetSpecialtyStoreSkus(params.Ctx, storeIDs, vendorIDs) + return retVal, "", err + }) +} diff --git a/controllers/cms_sync.go b/controllers/cms_sync.go index 3b15447e4..cc79a9c47 100644 --- a/controllers/cms_sync.go +++ b/controllers/cms_sync.go @@ -296,6 +296,7 @@ func (c *SyncController) AmendAndPruneStoreStuff() { // @Param token header string true "认证token" // @Param vendorID formData int true "平台ID(京东0 美团1 饿百3)" // @Param vendorOrgCode formData string true "平台账号" +// @Param storeID formData int false "门店ID" // @Param isAsync formData bool false "是否异步操作" // @Param isContinueWhenError formData bool false "单个同步失败是否继续,缺省false" // @Success 200 {object} controllers.CallResult @@ -303,7 +304,7 @@ func (c *SyncController) AmendAndPruneStoreStuff() { // @router /FullSyncVendorStuff [post] func (c *SyncController) FullSyncVendorStuff() { c.callFullSyncVendorStuff(func(params *tSyncFullSyncVendorStuffParams) (retVal interface{}, errCode string, err error) { - retVal, err = cms.FullSyncVendorStuff(params.Ctx, nil, params.VendorID, params.VendorOrgCode, params.IsAsync, params.IsContinueWhenError) + retVal, err = cms.FullSyncVendorStuff(params.Ctx, nil, params.StoreID, params.VendorID, params.VendorOrgCode, params.IsAsync, params.IsContinueWhenError) return retVal, "", err }) } diff --git a/controllers/cms_user2.go b/controllers/cms_user2.go index a52dbf392..db960f0db 100644 --- a/controllers/cms_user2.go +++ b/controllers/cms_user2.go @@ -12,6 +12,7 @@ import ( "git.rosy.net.cn/jx-callback/business/jxutils/jsonerr" "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/purchase/jx/localjx" "github.com/astaxie/beego" ) @@ -533,3 +534,40 @@ func (c *User2Controller) GetUserAgreement() { return retVal, "", err }) } + +// @Title 查询京西商城用户信息 +// @Description 查询京西商城用户信息 +// @Param token header string true "认证token" +// @Param keyword query string false "关键字" +// @Param fromTime query string false "开始时间" +// @Param toTime query string false "结束时间" +// @Param vendorIDs query string false "平台号" +// @Param offset query int false "结果起始序号(以0开始,缺省为0)" +// @Param pageSize query int false "结果页大小(缺省为50,-1表示全部)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetJxShopUsers [get] +func (c *User2Controller) GetJxShopUsers() { + c.callGetJxShopUsers(func(params *tUser2GetJxShopUsersParams) (retVal interface{}, errCode string, err error) { + var vendorIDs []int + if err = jxutils.Strings2Objs(params.VendorIDs, &vendorIDs); err == nil { + retVal, err = localjx.GetJxShopUsers(params.Ctx, params.Keyword, params.FromTime, params.ToTime, vendorIDs, params.Offset, params.PageSize) + } + return retVal, "", err + }) +} + +// @Title 更新用户上次浏览门店和品牌 +// @Description 更新用户上次浏览门店和品牌 +// @Param token header string true "认证token" +// @Param storeID formData int false "门店ID" +// @Param brandID formData int false "品牌ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateUserLastInfo [post] +func (c *User2Controller) UpdateUserLastInfo() { + c.callUpdateUserLastInfo(func(params *tUser2UpdateUserLastInfoParams) (retVal interface{}, errCode string, err error) { + err = cms.UpdateUserLastInfo(params.Ctx, params.StoreID, params.BrandID) + return retVal, "", err + }) +} diff --git a/controllers/event.go b/controllers/event.go index 4b7df673c..ce8349a14 100644 --- a/controllers/event.go +++ b/controllers/event.go @@ -1,8 +1,20 @@ package controllers import ( + "log" + "net/http" "time" + "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/jx-callback/business/model/dao" + + "git.rosy.net.cn/jx-callback/business/model" + + "github.com/gorilla/websocket" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxstore/event" @@ -16,6 +28,20 @@ type EventController struct { beego.Controller } +//连接的客户端,吧每个客户端都放进来 +var clients = make(map[string][]*websocket.Conn) + +//广播频道(通道) +var broadcast = make(chan map[string]*model.ImMessageRecord) + +// 配置升级程序(升级为websocket) +var upgrader = websocket.Upgrader{} + +// 定义我们的消息对象 +type Message struct { + Data interface{} `json:"data"` +} + // @Title 查询操作日志事件明细 // @Description 查询操作日志事件明细 // @Param token header string true "认证token" @@ -82,3 +108,123 @@ func (c *EventController) GetWeixinUnlimited() { return retVal, "", err }) } + +// @Title 测试websocket +// @Description 测试websocket +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /TestWebsocket [get] +func (c *EventController) TestWebsocket() { + // 解决跨域问题(微信小程序) + upgrader.CheckOrigin = func(r *http.Request) bool { + return true + } + //升级将HTTP服务器连接升级到WebSocket协议。 + //responseHeader包含在对客户端升级的响应中 + //请求。使用responseHeader指定Cookie(设置Cookie)和 + //应用程序协商的子目录(Sec WebSocket协议)。 + //如果升级失败,则升级将向客户端答复一个HTTP错误 + ws, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil) + if err != nil { + log.Fatal(err) + } + defer ws.Close() + var ( + vendorOrderID = c.GetString("vendorOrderID") + msgMap = make(map[string]*model.ImMessageRecord) + ) + //将当前客户端放入map中 + clients[vendorOrderID] = append(clients[vendorOrderID], ws) + + db := dao.GetDB() + if globals.IsProductEnv() { + _, _, err = jxcontext.New(nil, c.GetString("token"), c.Ctx.ResponseWriter, c.Ctx.Request) + if err != nil { + msg := &CallResult{ + Code: model.ErrCodeGeneralFailed, + Desc: err.Error(), + } + ws.WriteJSON(&msg) + } + } + + c.EnableRender = false //Beego不启用渲染 + + var s *model.ImMessageRecord + for { + //接收客户端的消息 + err := ws.ReadJSON(&s) + if err != nil { + globals.SugarLogger.Debugf("页面可能断开啦 ws.ReadJSON error: %v", err.Error()) + index := 0 + for k, v := range clients[vendorOrderID] { + if v == ws { + index = k + } + } + wsList := clients[vendorOrderID] + clients[vendorOrderID] = clients[vendorOrderID][0:0] + clients[vendorOrderID] = append(clients[vendorOrderID], wsList[0:index]...) + clients[vendorOrderID] = append(clients[vendorOrderID], wsList[index+1:len(wsList)]...) + // delete(clients, ws) //删除map中的客户端 + break //结束循环 + } else { + //接受消息 业务逻辑 + msgMap[vendorOrderID] = s + broadcast <- msgMap + dao.WrapAddIDCULDEntity(s, "") + dao.CreateEntity(db, s) + // fmt.Println("接受到从页面上反馈回来的信息 ", utils.Format4Output(s, false)) + } + } +} + +func init() { + go handleMessages() +} + +//广播推送消息 +func handleMessages() { + for { + //读取通道中的消息 + msg := <-broadcast + globals.SugarLogger.Debugf("clients len %v", len(clients)) + //循环map客户端 + for vendorOrderID, mmsg := range msg { + for _, client := range clients[vendorOrderID] { + //把通道中的消息发送给客户端 + globals.SugarLogger.Debugf("msg %v", utils.Format4Output(mmsg, false)) + err := client.WriteJSON(mmsg) + if err != nil { + globals.SugarLogger.Debugf("client.WriteJSON error: %v", err) + client.Close() //关闭 + index := 0 + for k, v := range clients[vendorOrderID] { + if v == client { + index = k + } + } + wsList := clients[vendorOrderID] + clients[vendorOrderID] = clients[vendorOrderID][0:0] + clients[vendorOrderID] = append(clients[vendorOrderID], wsList[0:index]...) + clients[vendorOrderID] = append(clients[vendorOrderID], wsList[index+1:len(wsList)]...) + // delete(clients, client) //删除map中的客户端 + } + } + } + } +} + +// @Title 查询聊天记录 +// @Description 查询聊天记录 +// @Param token header string true "认证token" +// @Param vendorOrderID query string true "订单号" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetImMessageRecord [get] +func (c *EventController) GetImMessageRecord() { + c.callGetImMessageRecord(func(params *tEventGetImMessageRecordParams) (retVal interface{}, errCode string, err error) { + retVal, err = dao.GetImMessageRecord(dao.GetDB(), params.VendorOrderID, "", 0, -1) + return retVal, "", err + }) +} diff --git a/controllers/fn_callback.go b/controllers/fn_callback.go new file mode 100644 index 000000000..f669ef187 --- /dev/null +++ b/controllers/fn_callback.go @@ -0,0 +1,33 @@ +package controllers + +import ( + "net/http" + + "git.rosy.net.cn/baseapi/utils" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/jx-callback/business/partner/delivery/fn" + + "git.rosy.net.cn/jx-callback/globals/api" + + "github.com/astaxie/beego" +) + +type FnController struct { + beego.Controller +} + +func (c *FnController) Msg() { + if c.Ctx.Input.Method() == http.MethodPost { + msg := api.FnAPI.GetOrderCallbackMsg(c.Ctx.Input.RequestBody) + if msg != nil { + globals.SugarLogger.Debugf("%v", string(utils.MustMarshal(msg))) + fn.OnWaybillMsg(msg) + } + c.Data["json"] = "" + c.ServeJSON() + } else { + c.Abort("404") + } +} diff --git a/controllers/jd_callback.go b/controllers/jd_callback.go index c230f927f..e2d1894ae 100644 --- a/controllers/jd_callback.go +++ b/controllers/jd_callback.go @@ -216,7 +216,6 @@ func (c *DjswController) UpdateSku() { func (c *DjswController) OrderAddTips() { c.orderStatus() } - func (c *DjswController) OrderInfoChange() { if c.Ctx.Input.Method() == http.MethodPost { callbackResponse := c.handleMsg(func(a *jdapi.API, obj interface{}) (callbackResponse *jdapi.CallbackResponse) { diff --git a/controllers/jds_callback.go b/controllers/jds_callback.go index af05c996d..35bfb65b3 100644 --- a/controllers/jds_callback.go +++ b/controllers/jds_callback.go @@ -2,7 +2,6 @@ package controllers import ( "bytes" - "fmt" "io/ioutil" "net/http" @@ -19,7 +18,6 @@ type JdsController struct { } func (c *JdsController) Msg() { - fmt.Println("testjdscll") if c.Ctx.Input.Method() == http.MethodPost { ctx := c.Ctx ctx.Request.Body = ioutil.NopCloser(bytes.NewReader(ctx.Input.RequestBody)) diff --git a/controllers/jx_order.go b/controllers/jx_order.go index 271794378..322370ded 100644 --- a/controllers/jx_order.go +++ b/controllers/jx_order.go @@ -172,13 +172,14 @@ func (c *OrderController) CancelWaybill() { // @Param token header string true "认证token" // @Param storeID query int true "京西门店ID" // @Param lastHours query int false "最近多少小时的信息(缺省为两天)" +// @Param lastMinutes query int false "最近多少分钟的信息(缺省为不传)" // @Param isIncludeFake query bool false "是否包括假订单" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetStoreOrderCountInfo [get] func (c *OrderController) GetStoreOrderCountInfo() { c.callGetStoreOrderCountInfo(func(params *tOrderGetStoreOrderCountInfoParams) (retVal interface{}, errCode string, err error) { - retVal, err = orderman.FixedOrderManager.GetStoreOrderCountInfo(params.Ctx, params.StoreID, params.LastHours, params.IsIncludeFake) + retVal, err = orderman.FixedOrderManager.GetStoreOrderCountInfo(params.Ctx, params.StoreID, params.LastHours, params.LastMinutes, params.IsIncludeFake) return retVal, "", err }) } @@ -295,6 +296,7 @@ func (c *OrderController) ExportMTWaybills() { // @Param skuIDs query string false "包含的skuID列表,或的关系" // @Param isJxFirst query bool false "排序是否京西订单优先(缺省为否)" // @Param adjustCount query int false "最小调整次数" +// @Param brandID query int false "品牌ID" // @Param mustInvoice query bool false "是否必须要求开发票" // @Param offset query int false "结果起始序号(以0开始,缺省为0)" // @Param pageSize query int false "结果页大小(缺省为50,-1表示全部)" @@ -373,14 +375,15 @@ func (c *OrderController) GetAfsOrders() { // @Description 得到售后单SKU信息(订单与售后单必填一项) // @Param token header string true "认证token" // @Param vendorID query int true "售后单所属的厂商ID" -// @Param vendorOrderID query string faslse "订单ID" -// @Param afsOrderID query string faslse "售后单ID" +// @Param vendorOrderID query string false "订单ID" +// @Param afsOrderID query string false "售后单ID" +// @Param isNotFaild query bool false "是否查非失败的" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetAfsOrderSkuInfo [get] func (c *OrderController) GetAfsOrderSkuInfo() { c.callGetAfsOrderSkuInfo(func(params *tOrderGetAfsOrderSkuInfoParams) (retVal interface{}, errCode string, err error) { - retVal, err = dao.GetAfsOrderSkuInfo(dao.GetDB(), params.VendorOrderID, params.AfsOrderID, params.VendorID) + retVal, err = dao.GetAfsOrderSkuInfo(dao.GetDB(), params.VendorOrderID, params.AfsOrderID, params.VendorID, params.IsNotFaild) return retVal, "", err }) } @@ -856,7 +859,7 @@ func (c *OrderController) RefundOrder() { if err != nil { return nil, "", err } - afsSkuList, err := dao.GetAfsOrderSkuInfo(dao.GetDB(), params.VendorOrderID, "", params.VendorID) + afsSkuList, err := dao.GetAfsOrderSkuInfo(dao.GetDB(), params.VendorOrderID, "", params.VendorID, false) if err != nil { return nil, "", err } @@ -1024,7 +1027,7 @@ func (c *OrderController) GetMatterStoreOrderCount() { // @Param toTime formData string true "订单结束时间" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult -// @router /RefreshJdShopOrdersEarningPrice [put] +// @router /RefreshJdShopOrdersEarningPrice [post] func (c *OrderController) RefreshJdShopOrdersEarningPrice() { c.callRefreshJdShopOrdersEarningPrice(func(params *tOrderRefreshJdShopOrdersEarningPriceParams) (retVal interface{}, errCode string, err error) { err = orderman.RefreshJdShopOrdersEarningPrice(params.Ctx, params.FromTime, params.ToTime) @@ -1059,3 +1062,159 @@ func (c *OrderController) GetOrderUserBuyFirst() { return retVal, "", err }) } + +// @Title 京东商城订单转移 +// @Description 京东商城订单转移 +// @Param token header string true "认证token" +// @Param storeID formData int true "转移的门店ID" +// @Param vendorOrderID formData string true "转移的订单号" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /TransferJdsOrder [post] +func (c *OrderController) TransferJdsOrder() { + c.callTransferJdsOrder(func(params *tOrderTransferJdsOrderParams) (retVal interface{}, errCode string, err error) { + retVal, err = orderman.TransferJdsOrder(params.Ctx, params.VendorOrderID, params.StoreID) + return retVal, "", err + }) +} + +// @Title 合并订单(京东商城用) +// @Description 合并订单(京东商城用) +// @Param token header string true "认证token" +// @Param vendorOrderIDs formData string true "订单号s" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /MergeJdsOrders [post] +func (c *OrderController) MergeJdsOrders() { + c.callMergeJdsOrders(func(params *tOrderMergeJdsOrdersParams) (retVal interface{}, errCode string, err error) { + var vendorOrderIDs []string + if err = jxutils.Strings2Objs(params.VendorOrderIDs, &vendorOrderIDs); err == nil { + retVal, err = orderman.MergeJdsOrders(params.Ctx, vendorOrderIDs) + } + return retVal, "", err + }) +} + +// @Title 京东商城订单发送京东物流 +// @Description 京东商城订单发送京东物流 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单号" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /SendJdwlForJdsOrder [post] +func (c *OrderController) SendJdwlForJdsOrder() { + c.callSendJdwlForJdsOrder(func(params *tOrderSendJdwlForJdsOrderParams) (retVal interface{}, errCode string, err error) { + err = orderman.SendJdwlForJdsOrder(params.Ctx, params.VendorOrderID) + return retVal, "", err + }) +} + +// @Title 手动拉取京东商城订单 +// @Description 手动拉取京东商城订单 +// @Param token header string true "认证token" +// @Param fromTime formData string true "订单起始时间" +// @Param toTime formData string true "订单结束时间" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /SaveJdsOrders [post] +func (c *OrderController) SaveJdsOrders() { + c.callSaveJdsOrders(func(params *tOrderSaveJdsOrdersParams) (retVal interface{}, errCode string, err error) { + err = orderman.SaveJdsOrders(params.Ctx, utils.Str2Time(params.FromTime), utils.Str2Time(params.ToTime)) + return retVal, "", err + }) +} + +// @Title 针对京东商城进行简单的售前删除操作 +// @Description 针对京东商城进行简单的售前删除操作 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单号" +// @Param skuID formData int true "商品ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AdjustJdsOrderSimple [post] +func (c *OrderController) AdjustJdsOrderSimple() { + c.callAdjustJdsOrderSimple(func(params *tOrderAdjustJdsOrderSimpleParams) (retVal interface{}, errCode string, err error) { + err = orderman.AdjustJdsOrderSimple(params.Ctx, params.VendorOrderID, params.SkuID) + return retVal, "", err + }) +} + +// @Title 修改订单运费 +// @Description 修改订单运费 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单号" +// @Param desiredFee formData int true "运费" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateWaybillDesiredFee [put] +func (c *OrderController) UpdateWaybillDesiredFee() { + c.callUpdateWaybillDesiredFee(func(params *tOrderUpdateWaybillDesiredFeeParams) (retVal interface{}, errCode string, err error) { + err = orderman.UpdateWaybillDesiredFee(params.Ctx, params.VendorOrderID, params.DesiredFee) + return retVal, "", err + }) +} + +// @Title 接单或拒单 +// @Description 接单或拒单 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单ID" +// @Param vendorID formData int true "订单平台ID" +// @Param isAccept formData bool true "接单或者拒单" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AcceptOrRefuseOrder [post] +func (c *OrderController) AcceptOrRefuseOrder() { + c.callAcceptOrRefuseOrder(func(params *tOrderAcceptOrRefuseOrderParams) (retVal interface{}, errCode string, err error) { + err = orderman.AcceptOrRefuseOrder(params.Ctx, params.VendorOrderID, params.VendorID, params.IsAccept) + return retVal, "", err + }) +} + +// @Title 刷新京东商城订单收货人信息 +// @Description 刷新京东商城订单收货人信息 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /RefreshJdsOrderConsigneeInfo [put] +func (c *OrderController) RefreshJdsOrderConsigneeInfo() { + c.callRefreshJdsOrderConsigneeInfo(func(params *tOrderRefreshJdsOrderConsigneeInfoParams) (retVal interface{}, errCode string, err error) { + err = orderman.RefreshJdsOrderConsigneeInfo(params.Ctx, params.VendorOrderID) + return retVal, "", err + }) +} + +// @Title 修改订单信息 +// @Description 修改订单信息 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单号" +// @Param vendorID formData int true "平台ID" +// @Param payload formData string true "json数据,格式为goodsOrder" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateOrderInfo [put] +func (c *OrderController) UpdateOrderInfo() { + c.callUpdateOrderInfo(func(params *tOrderUpdateOrderInfoParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + retVal, err = orderman.UpdateOrderInfo(params.Ctx, params.VendorOrderID, params.VendorID, payload) + } + return retVal, "", err + }) +} + +// @Title 刷新报价订单的订单商品价 +// @Description 刷新报价订单的订单商品价 +// @Param token header string true "认证token" +// @Param vendorOrderID formData string true "订单ID" +// @Param vendorID formData int true "平台ID" +// @Param skuID formData int true "商品ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /RefreshOrderSkuInfo [put] +func (c *OrderController) RefreshOrderSkuInfo() { + c.callRefreshOrderSkuInfo(func(params *tOrderRefreshOrderSkuInfoParams) (retVal interface{}, errCode string, err error) { + retVal, err = orderman.RefreshOrderSkuInfo(params.Ctx, params.VendorOrderID, params.VendorID, params.SkuID) + return retVal, "", err + }) +} diff --git a/controllers/jx_order2.go b/controllers/jx_order2.go index 2b5c561f0..be591f7a2 100644 --- a/controllers/jx_order2.go +++ b/controllers/jx_order2.go @@ -3,6 +3,7 @@ package controllers import ( "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx" "github.com/astaxie/beego" ) @@ -17,6 +18,7 @@ type JxOrderController struct { // @Param jxOrder formData string true "订单信息" // @Param addressID formData int64 true "配送地址ID" // @Param fromStoreID formData int fasle "物料配送门店" +// @Param couponIDs formData string fasle "优惠券IDs" // @Param createType formData int false "创建类型, 0:预创建, 1:创建" // @Param isDeliverySelf formData bool false "是否是自提单" // @Success 200 {object} controllers.CallResult @@ -26,7 +28,10 @@ func (c *JxOrderController) CreateOrder() { c.callCreateOrder(func(params *tJxorderCreateOrderParams) (retVal interface{}, errCode string, err error) { var jxOrder *localjx.JxOrderInfo if err = utils.UnmarshalUseNumber([]byte(params.JxOrder), &jxOrder); err == nil { - retVal, err = localjx.CreateOrder(params.Ctx, jxOrder, int64(params.AddressID), params.CreateType, params.FromStoreID, params.IsDeliverySelf) + var couponIDs []int + if err = jxutils.Strings2Objs(params.CouponIDs, &couponIDs); err == nil { + retVal, err = localjx.CreateOrder(params.Ctx, jxOrder, int64(params.AddressID), params.CreateType, params.FromStoreID, params.IsDeliverySelf, couponIDs) + } } return retVal, "", err }) @@ -35,6 +40,7 @@ func (c *JxOrderController) CreateOrder() { // @Title 请求支付京西商城订单 // @Description 请求支付京西商城订单 // @Param token header string true "认证token" +// @Param subAppID formData string true "appID" // @Param vendorOrderID formData string true "订单ID" // @Param payType formData int true "支付类型" // @Param vendorPayType formData string true "平台支付类型" @@ -43,7 +49,25 @@ func (c *JxOrderController) CreateOrder() { // @router /Pay4Order [post] func (c *JxOrderController) Pay4Order() { c.callPay4Order(func(params *tJxorderPay4OrderParams) (retVal interface{}, errCode string, err error) { - retVal, err = localjx.Pay4Order(params.Ctx, utils.Str2Int64(params.VendorOrderID), params.PayType, params.VendorPayType) + retVal, err = localjx.Pay4Order(params.Ctx, utils.Str2Int64(params.VendorOrderID), params.PayType, params.VendorPayType, params.SubAppID) + return retVal, "", err + }) +} + +// @Title 请求支付京西商城相关用户支付项目 +// @Description 请求支付京西商城相关用户支付项目 +// @Param token header string true "认证token" +// @Param thingID formData int fasle "项目ID" +// @Param subAppID formData string true "appID" +// @Param vendorOrderID formData string fasle "订单ID" +// @Param payType formData int true "支付类型" +// @Param vendorPayType formData string true "平台支付类型" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /Pay4User [post] +func (c *JxOrderController) Pay4User() { + c.callPay4User(func(params *tJxorderPay4UserParams) (retVal interface{}, errCode string, err error) { + retVal, err = localjx.Pay4User(params.Ctx, params.ThingID, params.VendorOrderID, params.PayType, params.VendorPayType, params.SubAppID) return retVal, "", err }) } @@ -111,6 +135,26 @@ func (c *JxOrderController) GetMyOrders() { }) } +// @Title 查询自己的售后单 +// @Description 查询自己的售后单 +// @Param token header string true "认证token" +// @Param vendorOrderID query string false "订单号,如果此项不为空,忽略其它所有查询条件" +// @Param afsOrderID query string false "售后单号" +// @Param userID query string false "用户ID" +// @Param fromTime query string false "开始日期(包含),格式(2006-01-02),如果订单号为空此项必须要求" +// @Param toTime query string false "结束日期(包含),格式(2006-01-02),如果订单号为空此项必须要求" +// @Param offset query int false "结果起始序号(以0开始,缺省为0)" +// @Param pageSize query int false "结果页大小(缺省为50,-1表示全部)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetMyAfsOrders [get] +func (c *JxOrderController) GetMyAfsOrders() { + c.callGetMyAfsOrders(func(params *tJxorderGetMyAfsOrdersParams) (retVal interface{}, errCode string, err error) { + retVal, err = localjx.GetMyAfsOrders(params.Ctx, params.VendorOrderID, params.AfsOrderID, params.UserID, params.FromTime, params.ToTime, params.Offset, params.PageSize) + return retVal, "", err + }) +} + // @Title 查询自己的订单状态数量信息 // @Description 查询自己的订单状态数量信息 // @Param token header string true "认证token" @@ -202,3 +246,143 @@ func (c *JxOrderController) SendFailedMatterOrder() { return retVal, "", err }) } + +// @Title 根据时间获取进货辅助工具里的商品,用于加入购物车 +// @Description 根据时间获取进货辅助工具里的商品,用于加入购物车 +// @Param token header string true "认证token" +// @Param fromDate query string false "开始日期(包含),格式(2006-01-02),如果订单号为空此项必须要求" +// @Param toDate query string false "结束日期(包含),格式(2006-01-02),如果订单号为空此项必须要求" +// @Param fromStoreID query int false "进货门店ID" +// @Param storeID query int false "货源门店ID" +// @Param percentage query string false "销量比例,1,1.05,1.1" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetSupplySupportStoreSkus [get] +func (c *JxOrderController) GetSupplySupportStoreSkus() { + c.callGetSupplySupportStoreSkus(func(params *tJxorderGetSupplySupportStoreSkusParams) (retVal interface{}, errCode string, err error) { + retVal, err = localjx.GetSupplySupportStoreSkus(params.Ctx, params.FromDate, params.ToDate, params.FromStoreID, params.StoreID, params.Percentage) + return retVal, "", err + }) +} + +// @Title 得到自己的守价订单列表 +// @Description 得到自己的守价订单列表 +// @Param token header string true "认证token" +// @Param fromTime query string false "开始日期(包含),格式(2006-01-02 00:00:00)" +// @Param toTime query string false "结束日期(包含),格式(2006-01-02 00:00:00)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetMyPriceDefendOrders [get] +func (c *JxOrderController) GetMyPriceDefendOrders() { + c.callGetMyPriceDefendOrders(func(params *tJxorderGetMyPriceDefendOrdersParams) (retVal interface{}, errCode string, err error) { + retVal, err = localjx.GetMyPriceDefendOrders(params.Ctx, params.FromTime, params.ToTime) + return retVal, "", err + }) +} + +// @Title 测试立马生成守价订单 +// @Description 测试立马生成守价订单 +// @Param token header string true "认证token" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /TestDefend [get] +func (c *JxOrderController) TestDefend() { + c.callTestDefend(func(params *tJxorderTestDefendParams) (retVal interface{}, errCode string, err error) { + err = localjx.CreateOrderByPriceDefend(params.Ctx) + return retVal, "", err + }) +} + +// @Title 查询优惠券 +// @Description 查询优惠券 +// @Param token header string true "认证token" +// @Param couponType query int false "优惠券类型,1为商品总额满减,2为运费优惠" +// @Param couponStatuss query string false "优惠券状态,0为正常可使用,-1为已过期, -2为还没开始" +// @Param storeIDs query string false "门店IDs" +// @Param keyword query string false "关键字" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetCoupons [get] +func (c *JxOrderController) GetCoupons() { + c.callGetCoupons(func(params *tJxorderGetCouponsParams) (retVal interface{}, errCode string, err error) { + var statuss, storeIDs []int + if err = jxutils.Strings2Objs(params.CouponStatuss, &statuss, params.StoreIDs, &storeIDs); err == nil { + retVal, err = localjx.GetCoupons(params.Ctx, params.CouponType, statuss, storeIDs, params.Keyword) + } + return retVal, "", err + }) +} + +// @Title 添加优惠券 +// @Description 添加优惠券 +// @Param token header string true "认证token" +// @Param payload formData string true "优惠券类型 payload" +// @Param storeIDs formData string false "门店IDs" +// @Param count formData int false "优惠券数量,默认1" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddCoupons [post] +func (c *JxOrderController) AddCoupons() { + c.callAddCoupons(func(params *tJxorderAddCouponsParams) (retVal interface{}, errCode string, err error) { + coupons := &model.Coupons{} + var storeIDs []int + if err = utils.UnmarshalUseNumber([]byte(params.Payload), coupons); err == nil { + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err == nil { + err = localjx.AddCoupons(params.Ctx, coupons, params.Count, storeIDs) + } + } + return retVal, "", err + }) +} + +// @Title 修改优惠券 +// @Description 修改优惠券 +// @Param token header string true "认证token" +// @Param payload formData string true "优惠券类型 payload" +// @Param storeIDs formData string false "门店IDs" +// @Param isDel formData bool false "是否是删除" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateCoupons [post] +func (c *JxOrderController) UpdateCoupons() { + c.callUpdateCoupons(func(params *tJxorderUpdateCouponsParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + var storeIDs []int + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err == nil { + err = localjx.UpdateCoupons(params.Ctx, payload, storeIDs, params.IsDel) + } + } + return retVal, "", err + }) +} + +// @Title 领取优惠券 +// @Description 领取优惠券 +// @Param token header string true "认证token" +// @Param couponID formData int true "券ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /ReceiveCoupons [post] +func (c *JxOrderController) ReceiveCoupons() { + c.callReceiveCoupons(func(params *tJxorderReceiveCouponsParams) (retVal interface{}, errCode string, err error) { + err = localjx.ReceiveCoupons(params.Ctx, params.CouponID) + return retVal, "", err + }) +} + +// @Title 创建门店账户订单 +// @Description 创建门店账户订单 +// @Param token header string true "认证token" +// @Param orderType formData int true "订单类型,4为门店账户订单" +// @Param storeID formData int true "门店ID" +// @Param price formData int true "支付金额" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CreateStoreAcctOrder [post] +func (c *JxOrderController) CreateStoreAcctOrder() { + c.callCreateStoreAcctOrder(func(params *tJxorderCreateStoreAcctOrderParams) (retVal interface{}, errCode string, err error) { + retVal, err = localjx.CreateStoreAcctOrder(params.Ctx, params.OrderType, params.StoreID, params.Price) + return retVal, "", err + }) +} diff --git a/controllers/jx_report.go b/controllers/jx_report.go index 7966917de..c51c45836 100644 --- a/controllers/jx_report.go +++ b/controllers/jx_report.go @@ -96,3 +96,21 @@ func (c *ReportController) AutoFocusStoreSkus() { return retVal, "", err }) } + +// @Title 查询经营概况 +// @Description 查询经营概况 +// @Param token header string true "认证token" +// @Param cityCodes query string false "城市ID列表[1,2,3]" +// @Param vendorID query int false "vendorID 全部传-1" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetManageState [get] +func (c *ReportController) GetManageState() { + c.callGetManageState(func(params *tReportGetManageStateParams) (retVal interface{}, errCode string, err error) { + var cityCodes []int + if err = jxutils.Strings2Objs(params.CityCodes, &cityCodes); err == nil { + retVal, err = report.GetManageState(params.Ctx, cityCodes, params.VendorID) + } + return retVal, "", err + }) +} diff --git a/controllers/mtwm_callback.go b/controllers/mtwm_callback.go index 4bd0b4683..4d0c24ca4 100644 --- a/controllers/mtwm_callback.go +++ b/controllers/mtwm_callback.go @@ -75,3 +75,7 @@ func (c *MtwmController) StoreStatusChanged() { func (c *MtwmController) OrderFinishedPickup() { c.onCallbackMsg(mtwmapi.MsgTypeOrderFinishedPickup) } + +func (c *MtwmController) StoreAuditStatusChanged() { + c.onCallbackMsg(mtwmapi.MsgTypeStoreAuditStatusChanged) +} diff --git a/controllers/permission.go b/controllers/permission.go new file mode 100644 index 000000000..9979fdc73 --- /dev/null +++ b/controllers/permission.go @@ -0,0 +1,184 @@ +package controllers + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxstore/permission" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "github.com/astaxie/beego" +) + +type PowerController struct { + beego.Controller +} + +// @Title 添加功能(菜单) +// @Description 添加功能(菜单) +// @Param token header string true "认证token" +// @Param payload formData string true "Menu json实体" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddMenu [post] +func (c *PowerController) AddMenu() { + c.callAddMenu(func(params *tPowerAddMenuParams) (retVal interface{}, errCode string, err error) { + menu := &model.Menu{} + if err = utils.UnmarshalUseNumber([]byte(params.Payload), menu); err == nil { + err = permission.AddMenu(params.Ctx, menu) + } + return retVal, "", err + }) +} + +// @Title 查询功能(菜单) +// @Description 查询功能(菜单) +// @Param token header string true "认证token" +// @Param userID query string false "用户ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetMenu [get] +func (c *PowerController) GetMenu() { + c.callGetMenu(func(params *tPowerGetMenuParams) (retVal interface{}, errCode string, err error) { + retVal, err = permission.GetMenu(params.Ctx, params.UserID) + return retVal, "", err + }) +} + +// @Title 修改功能(菜单) +// @Description 修改功能(菜单) +// @Param token header string true "认证token" +// @Param payload formData string true "Menu json实体" +// @Param menuID formData int true "菜单ID" +// @Param isDelete formData bool true "是否是删除" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateMenu [put] +func (c *PowerController) UpdateMenu() { + c.callUpdateMenu(func(params *tPowerUpdateMenuParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + retVal, err = permission.UpdateMenu(params.Ctx, params.MenuID, payload, params.IsDelete) + } + return retVal, "", err + }) +} + +// @Title 添加角色 +// @Description 添加角色 +// @Param token header string true "认证token" +// @Param name formData string true "角色名" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /AddRole [post] +func (c *PowerController) AddRole() { + c.callAddRole(func(params *tPowerAddRoleParams) (retVal interface{}, errCode string, err error) { + err = permission.AddRole(params.Ctx, params.Name) + return retVal, "", err + }) +} + +// @Title 查询角色 +// @Description 查询角色 +// @Param token header string true "认证token" +// @Param name query string false "角色名" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetRole [get] +func (c *PowerController) GetRole() { + c.callGetRole(func(params *tPowerGetRoleParams) (retVal interface{}, errCode string, err error) { + retVal, err = permission.GetRole(params.Ctx, params.Name) + return retVal, "", err + }) +} + +// @Title 修改角色 +// @Description 修改角色 +// @Param token header string true "认证token" +// @Param name formData string true "角色名" +// @Param roleID formData int true "角色ID" +// @Param isDelete formData bool true "是否是删除" +// @Param brandID formData int false "品牌ID" +// @Param cityCodes formData string false "城市IDs" +// @Param storeIDs formData string false "门店IDs" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateRole [put] +func (c *PowerController) UpdateRole() { + c.callUpdateRole(func(params *tPowerUpdateRoleParams) (retVal interface{}, errCode string, err error) { + var ( + cityCodes, storeIDs []int + ) + if err = jxutils.Strings2Objs(params.CityCodes, &cityCodes, params.StoreIDs, &storeIDs); err == nil { + retVal, err = permission.UpdateRole(params.Ctx, params.RoleID, params.Name, params.IsDelete, params.BrandID, cityCodes, storeIDs) + } + return retVal, "", err + }) +} + +// @Title 查询用户角色 +// @Description查询用户角色 +// @Param token header string true "认证token" +// @Param userID query string false "用户ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetUserRole [get] +func (c *PowerController) GetUserRole() { + c.callGetUserRole(func(params *tPowerGetUserRoleParams) (retVal interface{}, errCode string, err error) { + retVal, err = permission.GetUserRole(params.Ctx, params.UserID) + return retVal, "", err + }) +} + +// @Title 修改用户角色 +// @Description 修改用户角色 +// @Param token header string true "认证token" +// @Param userIDs formData string true "用户IDs" +// @Param roleIDs formData string true "角色IDs" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateUserRole [put] +func (c *PowerController) UpdateUserRole() { + c.callUpdateUserRole(func(params *tPowerUpdateUserRoleParams) (retVal interface{}, errCode string, err error) { + var ( + userIDs []string + roleIDs []int + ) + if err = jxutils.Strings2Objs(params.UserIDs, &userIDs, params.RoleIDs, &roleIDs); err == nil { + err = permission.UpdateUserRole(params.Ctx, userIDs, roleIDs) + } + return retVal, "", err + }) +} + +// @Title 查询角色菜单 +// @Description 查询角色菜单 +// @Param token header string true "认证token" +// @Param roleID query int false "用户ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetRoleMenu [get] +func (c *PowerController) GetRoleMenu() { + c.callGetRoleMenu(func(params *tPowerGetRoleMenuParams) (retVal interface{}, errCode string, err error) { + retVal, err = permission.GetRoleMenu(params.Ctx, params.RoleID) + return retVal, "", err + }) +} + +// @Title 修改角色菜单 +// @Description 修改角色菜单 +// @Param token header string true "认证token" +// @Param roleIDs formData string true "角色IDs" +// @Param menuIDs formData string true "菜单IDs" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateRoleMenu [put] +func (c *PowerController) UpdateRoleMenu() { + c.callUpdateRoleMenu(func(params *tPowerUpdateRoleMenuParams) (retVal interface{}, errCode string, err error) { + var ( + roleIDs, menuIDs []int + ) + if err = jxutils.Strings2Objs(params.RoleIDs, &roleIDs, params.MenuIDs, &menuIDs); err == nil { + err = permission.UpdateRoleMenu(params.Ctx, roleIDs, menuIDs) + } + return retVal, "", err + }) +} diff --git a/controllers/sys.go b/controllers/sys.go index 6c7160961..adcff39d0 100644 --- a/controllers/sys.go +++ b/controllers/sys.go @@ -7,7 +7,10 @@ import ( "strings" "time" + "git.rosy.net.cn/jx-callback/business/jxstore/common" + "git.rosy.net.cn/baseapi/platformapi/ebaiapi" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" @@ -71,6 +74,23 @@ func (c *SysController) GetYLYToken() { }) } +// @Title 得到个推token +// @Description 得到个推token +// @Param accessKey query string true "假token" +// @Param oldToken query string false "之前的token" +// @Param waitSecond query int false "等待秒数" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetPushToken [get] +func (c *SysController) GetPushToken() { + c.callGetPushToken(func(params *tSysGetPushTokenParams) (retVal interface{}, errCode string, err error) { + if params.AccessKey == globals.GetWeixinTokenKey { + retVal = syseventhub.SysEventHub.GetPushToken(params.OldToken, time.Duration(params.WaitSecond)*time.Second) + } + return retVal, "", err + }) +} + // @Title 得到微盟token // @Description 得到微盟token // @Param accessKey query string true "假token" @@ -107,3 +127,37 @@ func (c *SysController) GetEbaiRTFDetail() { w.WriteHeader(http.StatusOK) io.WriteString(w, html) } + +// @Title 得到平台账号信息 +// @Description 得到平台账号信息 +// @Param token header string true "token" +// @Param vendorID query int false "平台ID" +// @Param vendorOrgCode query string false "平台账号" +// @Param vendorType query string false "平台账号类型" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetVendorOrgCode [get] +func (c *SysController) GetVendorOrgCode() { + c.callGetVendorOrgCode(func(params *tSysGetVendorOrgCodeParams) (retVal interface{}, errCode string, err error) { + retVal, err = common.GetVendorOrgCode(params.Ctx, params.VendorID, params.VendorOrgCode, params.VendorType) + return retVal, "", err + }) +} + +// @Title 修改平台账号信息 +// @Description 修改平台账号信息 +// @Param token header string true "token" +// @Param id formData int true "ID" +// @Param payload formData string true "json数据,vendorOrgCode对象()" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /UpdateVendorOrgCode [post] +func (c *SysController) UpdateVendorOrgCode() { + c.callUpdateVendorOrgCode(func(params *tSysUpdateVendorOrgCodeParams) (retVal interface{}, errCode string, err error) { + payload := make(map[string]interface{}) + if err = utils.UnmarshalUseNumber([]byte(params.Payload), &payload); err == nil { + err = common.UpdateVendorOrgCode(params.Ctx, params.Id, payload) + } + return retVal, "", err + }) +} diff --git a/controllers/temp_op.go b/controllers/temp_op.go index 82c9ba8ef..d9e55c8ab 100644 --- a/controllers/temp_op.go +++ b/controllers/temp_op.go @@ -292,6 +292,42 @@ func (c *TempOpController) CheckSkuDiffBetweenJxAndVendor() { }) } +// @Title 京西平台和其他平台商品的对比Test +// @Description 对比Test +// @Param token header string true "认证token" +// @Param vendorIDs formData string false "运营商ID列表(京东0 美团1 饿百3)" +// @Param storeIDs formData string false "京西门店ID列表" +// @Success 200 {object} controllers.CallResult +// @Failure 404 User not found +// @router /StoreSkuCheckDiff [post] +func (c *TempOpController) StoreSkuCheckDiff() { + c.callCheckSkuDiffBetweenJxAndVendor(func(params *tTempopCheckSkuDiffBetweenJxAndVendorParams) (retVal interface{}, errCode string, err error) { + var vendorIDList []int + var storeIDList []int + if err = jxutils.Strings2Objs(params.VendorIDs, &vendorIDList, params.StoreIDs, &storeIDList); err == nil { + cms.TestDiff(params.Ctx, vendorIDList, storeIDList) + } + return retVal, "", err + }) +} + +// @Title 把所有营业的门店,京西商城门店都打开,默认范围3km,默认100-100京西价格套餐 +// @Description 对比Test +// @Param token header string true "认证token" +// @Success 200 {object} controllers.CallResult +// @Failure 404 User not found +// @router /StoreOpenAll [post] +func (c *TempOpController) StoreOpenAll() { + c.callCheckSkuDiffBetweenJxAndVendor(func(params *tTempopCheckSkuDiffBetweenJxAndVendorParams) (retVal interface{}, errCode string, err error) { + var vendorIDList []int + var storeIDList []int + if err = jxutils.Strings2Objs(params.VendorIDs, &vendorIDList, params.StoreIDs, &storeIDList); err == nil { + cms.StoreOpenAll(params.Ctx) + } + return retVal, "", err + }) +} + // @Title 通过订单创建消费者用户 // @Description 通过订单创建消费者用户 // @Param token header string true "认证token" @@ -381,3 +417,17 @@ func (c *TempOpController) UploadJdsImage() { return retVal, "", err }) } + +// @Title 京西刷新调价包和门店价格 +// @Description 京西刷新调价包和门店价格 +// @Param token header string true "认证token" +// @Param storeID formData int false "门店ID" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /RefreshJXPriceChange [post] +func (c *TempOpController) RefreshJXPriceChange() { + c.callRefreshJXPriceChange(func(params *tTempopRefreshJXPriceChangeParams) (retVal interface{}, errCode string, err error) { + retVal, err = tempop.RefreshJXPriceChange(params.Ctx, params.StoreID) + return retVal, "", err + }) +} diff --git a/deploy/ansible.yml b/deploy/ansible.yml index 1eff26dd7..f9b033a69 100644 --- a/deploy/ansible.yml +++ b/deploy/ansible.yml @@ -1,7 +1,6 @@ --- - hosts: "{{ deploy_hosts }}" remote_user: ubuntu - become: True tasks: - name: copy shell copy: diff --git a/globals/api/api.go b/globals/api/api.go index 1cc86b19f..843a0ce2b 100644 --- a/globals/api/api.go +++ b/globals/api/api.go @@ -3,6 +3,10 @@ package api import ( "time" + "git.rosy.net.cn/baseapi/platformapi/fnpsapi" + + "git.rosy.net.cn/baseapi/platformapi/unipushapi" + "git.rosy.net.cn/baseapi/platformapi/jdshopapi" "git.rosy.net.cn/baseapi/platformapi/aliupcapi" @@ -45,24 +49,34 @@ var ( JdAPI *jdapi.API JdPageAPI *jdapi.API - Jd2API *jdapi.API - FakeJdAPI *jdapi.API - JdEclpAPI *jdeclpapi.API - JdShopAPI *jdshopapi.API + Jd2API *jdapi.API + Jd3API *jdapi.API + JdcsAPI *jdapi.API + JdydAPI *jdapi.API + FakeJdAPI *jdapi.API + JdEclpAPI *jdeclpapi.API + JdShopAPI *jdshopapi.API + JdShop2API *jdshopapi.API ElmAPI *elmapi.API EbaiAPI *ebaiapi.API Ebai2API *ebaiapi.API - MtwmAPI *mtwmapi.API - MtpsAPI *mtpsapi.API - DadaAPI *dadaapi.API - WeixinAPI *weixinapi.API // 微信公众号 - WeixinMiniAPI *weixinapi.API // 小程序 - WeixinMiniAPI2 *weixinapi.API // 小程序2 - WeixinMiniAppID2 string - WxpayAPI *wxpayapi.API // 微信支付API - TLpayAPI *tonglianpayapi.API //通联收银宝api + MtwmAPI *mtwmapi.API + Mtwm2API *mtwmapi.API + MtpsAPI *mtpsapi.API + DadaAPI *dadaapi.API + WeixinAPI *weixinapi.API // 微信公众号 + WeixinMiniAPI *weixinapi.API // 小程序 + WeixinMiniAPI2 *weixinapi.API // 小程序2 + WeixinMiniAPIsc *weixinapi.API //小程序商超 + WeixinApp *weixinapi.API // app微信登录 + WeixinMiniAppID2 string + WeixinMiniAppID3 string + WeixinMiniAppIDsc string + WxpayAPI *wxpayapi.API // 微信支付API + TLpayAPI *tonglianpayapi.API //通联收银宝api + FnAPI *fnpsapi.API //蜂鸟配送api YinBaoAPI *yinbaoapi.API //银豹平台api @@ -85,6 +99,8 @@ var ( YilianyunAPI2 *yilianyunapi.API ZhongwuAPI *zhongwuapi.API + PushAPI *unipushapi.API + Cacher cache.ICacher SMSClient *aliyunsmsclient.SmsClient ) @@ -109,6 +125,18 @@ func Init() { // Jd2API.SetJdCookie(beego.AppConfig.DefaultString("jd2StorePageCookie", "")) } + if globals.Jd3OrgCode != "" { + Jd3API = jdapi.New(beego.AppConfig.String("jd3Token"), beego.AppConfig.String("jd3AppKey"), beego.AppConfig.String("jd3Secret")) + } + + if globals.JdcsOrgCode != "" { + JdcsAPI = jdapi.New(beego.AppConfig.String("jdcsToken"), beego.AppConfig.String("jdcsAppKey"), beego.AppConfig.String("jdcsSecret")) + } + + if globals.JdydOrgCode != "" { + JdydAPI = jdapi.New(beego.AppConfig.String("jdydToken"), beego.AppConfig.String("jdydAppKey"), beego.AppConfig.String("jdydSecret")) + } + fakeJdToken := beego.AppConfig.DefaultString("fakeJdToken", "") if fakeJdToken != "" { FakeJdAPI = jdapi.NewFakeJD(fakeJdToken, beego.AppConfig.String("fakeJdBaseURL")) @@ -123,9 +151,7 @@ func Init() { } if !beego.AppConfig.DefaultBool("disableJdShop", false) { JdShopAPI = jdshopapi.New(beego.AppConfig.String("jdShopAccessToken"), beego.AppConfig.String("jdShopAppKey"), beego.AppConfig.String("jdShopAppSecret")) - // if jdsCookie := beego.AppConfig.DefaultString("jdsCookie", ""); jdsCookie != "" { - // JdShopAPI.SetCookieWithStr(jdsCookie) - // } + JdShop2API = jdshopapi.New(beego.AppConfig.String("jdShopAccessToken2"), beego.AppConfig.String("jdShopAppKey2"), beego.AppConfig.String("jdShopAppSecret2")) } else { JdShopAPI = nil } @@ -135,10 +161,11 @@ func Init() { ElmAPI = nil } if !beego.AppConfig.DefaultBool("disableMtwm", false) { - MtwmAPI = mtwmapi.New(beego.AppConfig.String("mtwmAppID"), beego.AppConfig.String("mtwmSecret"), beego.AppConfig.String("mtwmCallbackURL")) + MtwmAPI = mtwmapi.New(beego.AppConfig.String("mtwmAppID"), beego.AppConfig.String("mtwmSecret"), beego.AppConfig.String("mtwmCallbackURL"), "") // if mtwmCookieStr := beego.AppConfig.DefaultString("mtwmCookieStr", ""); mtwmCookieStr != "" { // MtwmAPI.SetCookieWithStr(mtwmCookieStr) // } + Mtwm2API = mtwmapi.New(beego.AppConfig.String("mtwmAppID2"), beego.AppConfig.String("mtwmSecret2"), beego.AppConfig.String("mtwmCallbackURL2"), "") } else { MtwmAPI = nil } @@ -210,6 +237,12 @@ func Init() { WeixinMiniAPI2 = weixinapi.New(WeixinMiniAppID2, beego.AppConfig.String("weixinMiniSecret2")) } WeixinPageAPI = weixinapi.New(beego.AppConfig.String("weixinPageAppID"), beego.AppConfig.String("weixinPageSecret")) + if WeixinMiniAppID3 = beego.AppConfig.String("weixinMiniAppID3"); WeixinMiniAppID3 != "" { + WeixinApp = weixinapi.New(WeixinMiniAppID3, beego.AppConfig.String("weixinMiniSecret3")) + } + if WeixinMiniAppIDsc = beego.AppConfig.String("weixinMiniAppIDsc"); WeixinMiniAppIDsc != "" { + WeixinMiniAPIsc = weixinapi.New(WeixinMiniAppIDsc, beego.AppConfig.String("weixinMiniSecretsc")) + } if globals.WxpayNotifyURL != "" { // WxpayAPI = wxpayapi.New(beego.AppConfig.String("wxpayAppID"), beego.AppConfig.String("wxpayAppKey"), beego.AppConfig.String("wxpayAppMchID")) WxpayAPI = wxpayapi.NewWithCertificate(beego.AppConfig.String("wxpayAppID"), beego.AppConfig.String("wxpayAppKey"), beego.AppConfig.String("wxpayAppMchID"), @@ -217,7 +250,7 @@ func Init() { } if globals.TLPayNotifyURL != "" { - TLpayAPI = tonglianpayapi.New(beego.AppConfig.String("tonglianPayAppID"), beego.AppConfig.String("tonglianPayKey"), beego.AppConfig.String("tonglianPayCusID"), beego.AppConfig.String("wxpayAppID")) + TLpayAPI = tonglianpayapi.New(beego.AppConfig.String("tonglianPayAppID"), beego.AppConfig.String("tonglianPayKey"), beego.AppConfig.String("tonglianPayCusID")) } AutonaviAPI = autonavi.New(beego.AppConfig.String("autonaviKey")) BaiDuNaviAPI = baidunavi.New(beego.AppConfig.String("baidunaviAK"), beego.AppConfig.String("baidunaviSK")) @@ -233,11 +266,13 @@ func Init() { AliPayAPI = alipayapi.New(alipayAppID, []byte(beego.AppConfig.String("alipayPrivateKey"))) } + FnAPI = fnpsapi.New(beego.AppConfig.DefaultString("fnAppID", ""), beego.AppConfig.DefaultString("fnAppSecret", "")) FeieAPI = feieapi.New(beego.AppConfig.DefaultString("feieUser", ""), beego.AppConfig.DefaultString("feieKey", "")) XiaoWMAPI = xiaowmapi.New(beego.AppConfig.DefaultInt("xiaoWMAppID", 0), beego.AppConfig.DefaultString("xiaoWMAppKey", "")) YilianyunAPI = yilianyunapi.New(beego.AppConfig.DefaultString("yilianyunClientID", ""), beego.AppConfig.DefaultString("yilianyunClientSecret", "")) YilianyunAPI2 = yilianyunapi.New(beego.AppConfig.DefaultString("yilianyunClientID2", ""), beego.AppConfig.DefaultString("yilianyunClientSecret2", "")) ZhongwuAPI = zhongwuapi.New(beego.AppConfig.DefaultInt("zhongwuAppID", 0), beego.AppConfig.DefaultString("zhongwuAppSecret", "")) + PushAPI = unipushapi.New(beego.AppConfig.DefaultString("pushAppID", ""), beego.AppConfig.DefaultString("pushAppKey", ""), beego.AppConfig.DefaultString("pushAppSecret", ""), beego.AppConfig.DefaultString("pushMasterSecret", "")) SMSClient = aliyunsmsclient.New("http://dysmsapi.aliyuncs.com/") } diff --git a/globals/api/apimanager/apimanager.go b/globals/api/apimanager/apimanager.go index 86ccd7f2b..21275ad6f 100644 --- a/globals/api/apimanager/apimanager.go +++ b/globals/api/apimanager/apimanager.go @@ -39,11 +39,26 @@ func (a *APIManager) GetAPI(vendorID int, appOrgCode string) (pfAPI interface{}) pfAPI = api.FakeJdAPI } else if appOrgCode != "" && appOrgCode == globals.Jd2OrgCode { pfAPI = api.Jd2API + } else if appOrgCode != "" && appOrgCode == globals.Jd3OrgCode { + pfAPI = api.Jd3API + } else if appOrgCode != "" && appOrgCode == globals.JdcsOrgCode { + pfAPI = api.JdcsAPI + } else if appOrgCode != "" && appOrgCode == globals.JdydOrgCode { + pfAPI = api.JdydAPI } case model.VendorIDMTWM: pfAPI = api.MtwmAPI + if appOrgCode == globals.Mtwm2Code { + pfAPI = api.Mtwm2API + } case model.VendorIDEBAI: pfAPI = api.EbaiAPI + case model.VendorIDJDShop: + if appOrgCode == "1" { + pfAPI = api.JdShopAPI + } else { + pfAPI = api.JdShop2API + } } return pfAPI } @@ -52,11 +67,13 @@ func (a *APIManager) GetAPI(vendorID int, appOrgCode string) (pfAPI interface{}) func (a *APIManager) GetAppOrgCodeList(vendorID int) (appOrgCodeList []string) { switch vendorID { case model.VendorIDJD: - appOrgCodeList = jxutils.BatchString2Slice(globals.JdOrgCode, globals.Jd2OrgCode) + appOrgCodeList = jxutils.BatchString2Slice(globals.JdOrgCode, globals.Jd2OrgCode, globals.Jd3OrgCode, globals.JdcsOrgCode, globals.JdydOrgCode) case model.VendorIDMTWM: - appOrgCodeList = []string{api.MtwmAPI.GetAppID()} + appOrgCodeList = []string{api.MtwmAPI.GetAppID(), api.Mtwm2API.GetAppID()} case model.VendorIDEBAI: appOrgCodeList = []string{api.EbaiAPI.GetSource()} + case model.VendorIDJDShop: + appOrgCodeList = []string{"1", "2"} } return appOrgCodeList } diff --git a/globals/beegodb/beegodb.go b/globals/beegodb/beegodb.go index a7b8caf44..0603dd35b 100644 --- a/globals/beegodb/beegodb.go +++ b/globals/beegodb/beegodb.go @@ -27,13 +27,22 @@ func Init() { orm.RegisterModel(new(model.Message)) orm.RegisterModel(new(model.MessageStatus)) + orm.RegisterModel(new(model.ImMessageRecord)) orm.RegisterModel(&model.Place{}) - orm.RegisterModel(&model.Store{}, &model.StoreSub{}, &model.StoreMap{}, &model.StoreCourierMap{}) + orm.RegisterModel(&model.Store{}, &model.StoreSub{}, &model.StoreMap{}, &model.StoreCourierMap{}, &model.StoreCategoryMap{}) orm.RegisterModel(&model.SkuVendorCategory{}, &model.StoreSkuCategoryMap{}, &model.SkuName{}, &model.Sku{}, &model.SkuNamePlaceBind{}, &model.StoreSkuBind{}) + orm.RegisterModel(&model.SkuVendorCategoryMap{}) //商品映射平台类目 + orm.RegisterModel(&model.VendorCategoryMap{}) //平台分类 orm.RegisterModel(&model.StoreSkuBindHistory{}) + orm.RegisterModel(&model.StoreSkuAudit{}) orm.RegisterModel(&model.SkuCategory{}) orm.RegisterModel(&model.ThingMap{}) + orm.RegisterModel(&model.SkuExinfoMap{}) + orm.RegisterModel(&model.StorePushClient{}) + orm.RegisterModel(&model.StoreAudit{}) + orm.RegisterModel(&model.Brand{}) + orm.RegisterModel(&model.BrandStore{}) orm.RegisterModel(&model.AuthBind{}, &model.User{}) @@ -55,6 +64,7 @@ func Init() { // 如下语句建表时要出错(INDEX名字太长了),暂时放一下,必须放最后一句 orm.RegisterModel(&model.OrderFinancial{}, &model.AfsOrder{}, &model.OrderDiscountFinancial{}, &model.OrderSkuFinancial{}) + orm.RegisterModel(&model.PriceDefendOrder{}) orm.RegisterModel(&model.Act{}, &model.ActOrderRule{}, &model.ActStoreSku{}) orm.RegisterModel(&model.ActMap{}, &model.ActStoreSkuMap{}) if globals.IsStoreSkuAct { @@ -73,11 +83,28 @@ func Init() { orm.RegisterModel(&model.UserDeliveryAddress{}) orm.RegisterModel(&model.UserCartItem{}) orm.RegisterModel(&model.UserAgreement{}) + orm.RegisterModel(&model.UserMember{}) orm.RegisterModel(&model.OrderPay{}, &model.OrderPayRefund{}) orm.RegisterModel(&model.UserOrderSms{}) - orm.RegisterModel(&model.FakeJdThingMap{}) + orm.RegisterModel(&model.VendorOrgCode{}) + //优惠券 + orm.RegisterModel(&model.Coupons{}) + orm.RegisterModel(&model.UserCoupons{}) + orm.RegisterModel(&model.StoreCoupons{}) + + //权限 + orm.RegisterModel(&model.Role{}) + orm.RegisterModel(&model.UserRole{}) + orm.RegisterModel(&model.Menu{}) + orm.RegisterModel(&model.RoleMenu{}) + + //门店账单 + orm.RegisterModel(&model.StoreAcct{}) + orm.RegisterModel(&model.StoreAcctExpend{}) + orm.RegisterModel(&model.StoreAcctIncome{}) + orm.RegisterModel(&model.StoreAcctOrder{}) // create table orm.RunSyncdb("default", false, true) } diff --git a/globals/globals.go b/globals/globals.go index 022333e7b..958eddba9 100644 --- a/globals/globals.go +++ b/globals/globals.go @@ -38,15 +38,18 @@ var ( GetWeixin2TokenURL string GetWeixinTokenKey string GetYLYTokenURL string + GetPushTokenURL string GetWeimobTokenURL string - StoreName string - StoreNameMtwm string - StoreNameEbai string + StoreName string + StoreNameMtwm string + StoreNameEbai string + StoreNameEbai2 string SMSSignName string SMSMobileVerifyTemplate string SMSNewOrderTemplate string + SMSNewOrderTemplateQ string SMSOrderCanceledTemplate string SMSNewUserOrderTemplate string @@ -55,11 +58,18 @@ var ( WxpayNotifyURL string TLPayNotifyURL string + FnNotifyURL string JdOrgCode string Jd2OrgCode string + Jd3OrgCode string + JdcsOrgCode string + JdydOrgCode string JdLoginName string + MtwmCode string + Mtwm2Code string + IsStoreSkuAct bool IsAddEvent bool @@ -111,14 +121,17 @@ func Init() { GetYLYTokenURL = beego.AppConfig.DefaultString("getYLYTokenURL", "") GetWeimobTokenURL = beego.AppConfig.DefaultString("getWeimobTokenURL", "") GetWeixinTokenKey = beego.AppConfig.DefaultString("getWeixinTokenKey", "") + GetPushTokenURL = beego.AppConfig.DefaultString("getPushTokenURL", "") StoreName = beego.AppConfig.String("storeName") StoreNameMtwm = beego.AppConfig.String("storeNameMtwm") StoreNameEbai = beego.AppConfig.String("storeNameEbai") + StoreNameEbai2 = beego.AppConfig.String("storeNameEbai2") SMSSignName = beego.AppConfig.String("smsSignName") SMSMobileVerifyTemplate = beego.AppConfig.String("smsMobileVerifyTemplate") SMSNewOrderTemplate = beego.AppConfig.String("smsNewOrderTemplate") + SMSNewOrderTemplateQ = beego.AppConfig.String("smsNewOrderTemplateQ") SMSOrderCanceledTemplate = beego.AppConfig.String("smsOrderCanceledTemplate") SMSNewUserOrderTemplate = beego.AppConfig.String("smsNewUserOrderTemplate") @@ -127,11 +140,18 @@ func Init() { WxpayNotifyURL = beego.AppConfig.DefaultString("wxpayNotifyURL", "") TLPayNotifyURL = beego.AppConfig.DefaultString("tonglianPayNotifyURL", "") + FnNotifyURL = beego.AppConfig.DefaultString("fnCallbackURL", "") JdOrgCode = beego.AppConfig.DefaultString("jdOrgCode", "") Jd2OrgCode = beego.AppConfig.DefaultString("jd2OrgCode", "") + Jd3OrgCode = beego.AppConfig.DefaultString("jd3OrgCode", "") + JdcsOrgCode = beego.AppConfig.DefaultString("jdcsOrgCode", "") + JdydOrgCode = beego.AppConfig.DefaultString("jdydOrgCode", "") JdLoginName = beego.AppConfig.DefaultString("jdLoginName", "") IsAddEvent = beego.AppConfig.DefaultBool("addEvent", false) IsStoreSkuAct = !IsProductEnv() + + MtwmCode = beego.AppConfig.DefaultString("mtwmAppID", "") + Mtwm2Code = beego.AppConfig.DefaultString("mtwmAppID2", "") } func IsCallbackAlwaysReturnSuccess() bool { diff --git a/main.go b/main.go index 59532647a..8d62a09a4 100644 --- a/main.go +++ b/main.go @@ -136,6 +136,10 @@ func main() { globals.SugarLogger.Errorf("RefreshWeixin2Token failed with error:%s", err) return } + if err := tasks.RefreshWeixin3Token(); err != nil { + globals.SugarLogger.Errorf("RefreshWeixin3Token failed with error:%s", err) + return + } // if err := tasks.RefreshWeimobToken(); err != nil { // globals.SugarLogger.Errorf("RefreshWeimobToken failed with error:%s", err) // return @@ -144,7 +148,17 @@ func main() { globals.SugarLogger.Errorf("RefreshYilianyunToken failed with error:%s", err) return } - + if err := tasks.RefreshPushToken(); err != nil { + globals.SugarLogger.Errorf("RefreshPushToken failed with error:%s", err) + return + } + if err := tasks.RefreshFnToken(); err != nil { + globals.SugarLogger.Errorf("RefreshFnToken failed with error:%s", err) + return + } + // if globals.IsProductEnv() { + // orderman.SaveJdsOrders(nil, time.Now().Add(-2*time.Hour), time.Now()) + // } orderman.LoadPendingOrders() // 延时的原因是等回调准备好 diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 86c0ff4f1..8c665f924 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -43,6 +43,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ActController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ActController"], + beego.ControllerComments{ + Method: "DeleteStoresFromAct", + Router: `/DeleteStoresFromAct`, + AllowHTTPMethods: []string{"delete"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ActController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ActController"], beego.ControllerComments{ Method: "ForceUpdateVendorPrice", @@ -56,7 +65,7 @@ func init() { beego.ControllerComments{ Method: "GetActStoreSkuInfo", Router: `/GetActStoreSkuInfo`, - AllowHTTPMethods: []string{"get"}, + AllowHTTPMethods: []string{"get","post"}, MethodParams: param.Make(), Filters: nil, Params: nil}) @@ -268,6 +277,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"], + beego.ControllerComments{ + Method: "GetCoordinateCityInfo", + Router: `/GetCoordinateCityInfo`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:CmsController"], beego.ControllerComments{ Method: "GetCoordinateDistrictCode", @@ -421,6 +439,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"], + beego.ControllerComments{ + Method: "GetImMessageRecord", + Router: `/GetImMessageRecord`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"], beego.ControllerComments{ Method: "GetOperateEvents", @@ -439,6 +466,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:EventController"], + beego.ControllerComments{ + Method: "TestWebsocket", + Router: `/TestWebsocket`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:FinancialController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:FinancialController"], beego.ControllerComments{ Method: "GetOrdersFinancial", @@ -628,6 +664,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "AddCoupons", + Router: `/AddCoupons`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "AutoPayForPopluarMan", @@ -655,6 +700,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "CreateStoreAcctOrder", + Router: `/CreateStoreAcctOrder`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "GetAvailableDeliverTime", @@ -664,6 +718,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "GetCoupons", + Router: `/GetCoupons`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "GetMatterOrderStatus", @@ -673,6 +736,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "GetMyAfsOrders", + Router: `/GetMyAfsOrders`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "GetMyOrderCountInfo", @@ -691,6 +763,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "GetMyPriceDefendOrders", + Router: `/GetMyPriceDefendOrders`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "GetOrderPay", @@ -700,6 +781,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "GetSupplySupportStoreSkus", + Router: `/GetSupplySupportStoreSkus`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "Pay4Order", @@ -709,6 +799,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "Pay4User", + Router: `/Pay4User`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "PayForPopluarMan", @@ -718,6 +817,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "ReceiveCoupons", + Router: `/ReceiveCoupons`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], beego.ControllerComments{ Method: "RefreshAllMatterOrderStatus", @@ -736,6 +844,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "TestDefend", + Router: `/TestDefend`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxOrderController"], + beego.ControllerComments{ + Method: "UpdateCoupons", + Router: `/UpdateCoupons`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxShopController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:JxShopController"], beego.ControllerComments{ Method: "JxMsg", @@ -783,6 +909,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:MsgController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:MsgController"], + beego.ControllerComments{ + Method: "SendUserMessage", + Router: `/SendUserMessage`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:NetSpiderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:NetSpiderController"], beego.ControllerComments{ Method: "GetAndStoreCitiesShops", @@ -819,6 +954,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "AcceptOrRefuseOrder", + Router: `/AcceptOrRefuseOrder`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "AddUpdateOrdersSupplement", @@ -828,6 +972,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "AdjustJdsOrderSimple", + Router: `/AdjustJdsOrderSimple`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "AdjustOrder", @@ -1134,6 +1287,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "MergeJdsOrders", + Router: `/MergeJdsOrders`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "PartRefundOrder", @@ -1174,6 +1336,15 @@ func init() { beego.ControllerComments{ Method: "RefreshJdShopOrdersEarningPrice", Router: `/RefreshJdShopOrdersEarningPrice`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "RefreshJdsOrderConsigneeInfo", + Router: `/RefreshJdsOrderConsigneeInfo`, AllowHTTPMethods: []string{"put"}, MethodParams: param.Make(), Filters: nil, @@ -1197,6 +1368,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "RefreshOrderSkuInfo", + Router: `/RefreshOrderSkuInfo`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "RefreshOrdersPriceInfo", @@ -1224,6 +1404,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "SaveJdsOrders", + Router: `/SaveJdsOrders`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "SelfDelivered", @@ -1242,6 +1431,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "SendJdwlForJdsOrder", + Router: `/SendJdwlForJdsOrder`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "SetOrderPrintStatus", @@ -1251,6 +1449,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "TransferJdsOrder", + Router: `/TransferJdsOrder`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "UpdateOrderInfo", + Router: `/UpdateOrderInfo`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], beego.ControllerComments{ Method: "UpdateOrderWaybillTip", @@ -1260,6 +1476,105 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:OrderController"], + beego.ControllerComments{ + Method: "UpdateWaybillDesiredFee", + Router: `/UpdateWaybillDesiredFee`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "AddMenu", + Router: `/AddMenu`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "AddRole", + Router: `/AddRole`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "GetMenu", + Router: `/GetMenu`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "GetRole", + Router: `/GetRole`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "GetRoleMenu", + Router: `/GetRoleMenu`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "GetUserRole", + Router: `/GetUserRole`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "UpdateMenu", + Router: `/UpdateMenu`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "UpdateRole", + Router: `/UpdateRole`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "UpdateRoleMenu", + Router: `/UpdateRoleMenu`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:PowerController"], + beego.ControllerComments{ + Method: "UpdateUserRole", + Router: `/UpdateUserRole`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"], beego.ControllerComments{ Method: "AutoFocusStoreSkus", @@ -1269,6 +1584,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"], + beego.ControllerComments{ + Method: "GetManageState", + Router: `/GetManageState`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:ReportController"], beego.ControllerComments{ Method: "PriceRefer", @@ -1341,6 +1665,33 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "AddVendorCategoryMap", + Router: `/AddVendorCategoryMap`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "CopyStoreCategories", + Router: `/CopyStoreCategories`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "CopyVendorCategories", + Router: `/CopyVendorCategories`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.ControllerComments{ Method: "CreateUpcSkuByExcel", @@ -1440,6 +1791,33 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "GetVendorCategoryMap", + Router: `/GetVendorCategoryMap`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "InsertSensitiveWord", + Router: `/InsertSensitiveWord`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "LoadStoreVendorCategories", + Router: `/LoadStoreVendorCategories`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.ControllerComments{ Method: "RefreshJdDepot", @@ -1458,6 +1836,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "ReorderStoreCategories", + Router: `/ReorderStoreCategories`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "ReorderVendorCategories", + Router: `/ReorderVendorCategories`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.ControllerComments{ Method: "SortCategorySkus", @@ -1512,6 +1908,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "UpdateSensitiveWord", + Router: `/UpdateSensitiveWord`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.ControllerComments{ Method: "UpdateSku", @@ -1521,6 +1926,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "UpdateSkuExinfoMap", + Router: `/UpdateSkuExinfoMap`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], beego.ControllerComments{ Method: "UpdateSkuName", @@ -1539,6 +1953,33 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"], + beego.ControllerComments{ + Method: "UpdateVendorCategoryMap", + Router: `/UpdateVendorCategoryMap`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "AddBrand", + Router: `/AddBrand`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "AddStoreCategoryMap", + Router: `/AddStoreCategoryMap`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "AddStoreCourierMap", @@ -1575,6 +2016,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "CreateStoreAudit", + Router: `/CreateStoreAudit`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "CreateStorePriceScore", @@ -1584,6 +2034,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "CreateVendorStore", + Router: `/CreateVendorStore`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "DeletePrinterSeq", @@ -1638,6 +2097,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetBrandStore", + Router: `/GetBrandStore`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetBrands", + Router: `/GetBrands`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "GetCorporationInfo", @@ -1647,6 +2124,51 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetDiffJxStoreAndMTWMStoreInfo", + Router: `/GetDiffJxStoreAndMTWMStoreInfo`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetJdDeliveryArea", + Router: `/GetJdDeliveryArea`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetJddjStoreInfo", + Router: `/GetJddjStoreInfo`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetNearSupplyGoodsStoreByStoreID", + Router: `/GetNearSupplyGoodsStoreByStoreID`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetStoreAcctBalance", + Router: `/GetStoreAcctBalance`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "GetStoreAlertList", @@ -1656,6 +2178,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetStoreAudit", + Router: `/GetStoreAudit`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetStoreCategoryMap", + Router: `/GetStoreCategoryMap`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "GetStoreCourierMaps", @@ -1737,6 +2277,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "InsertStoreCategories", + Router: `/InsertStoreCategories`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "JdStoreInfoCoordinateRecover", @@ -1764,6 +2313,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "StoreAudit", + Router: `/StoreAudit`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "StoreConfirmAct", + Router: `/StoreConfirmAct`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "SyncJdStore", @@ -1818,6 +2385,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "UpdateBrand", + Router: `/UpdateBrand`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "UpdateOrCreateCourierStores", @@ -1836,6 +2412,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "UpdateStoreCategoryMap", + Router: `/UpdateStoreCategoryMap`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "UpdateStoreCourierMap", @@ -1845,6 +2430,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "UpdateStorePricePack", + Router: `/UpdateStorePricePack`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "UpdateStorePushClient", + Router: `/UpdateStorePushClient`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "UpdateStoreVendorMap", @@ -1926,6 +2529,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "GetSpecialtyStoreSkus", + Router: `/GetSpecialtyStoreSkus`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], beego.ControllerComments{ Method: "GetStoreAbnormalSkuCount", @@ -1944,6 +2556,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "GetStoreSkuAudit", + Router: `/GetStoreSkuAudit`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], beego.ControllerComments{ Method: "GetStoreSkus", @@ -2088,6 +2709,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "StoreSkuPriceAudit", + Router: `/StoreSkuPriceAudit`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], beego.ControllerComments{ Method: "SyncJdStoreProducts", @@ -2169,6 +2799,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "UpdateStoresSkusWithoutSync", + Router: `/UpdateStoresSkusWithoutSync`, + AllowHTTPMethods: []string{"put"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SyncController"], beego.ControllerComments{ Method: "AddCreateFlagForJxStoreSku", @@ -2313,6 +2952,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"], + beego.ControllerComments{ + Method: "GetPushToken", + Router: `/GetPushToken`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"], + beego.ControllerComments{ + Method: "GetVendorOrgCode", + Router: `/GetVendorOrgCode`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"], beego.ControllerComments{ Method: "GetWX2Token", @@ -2349,6 +3006,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SysController"], + beego.ControllerComments{ + Method: "UpdateVendorOrgCode", + Router: `/UpdateVendorOrgCode`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TaskController"], beego.ControllerComments{ Method: "CancelTask", @@ -2430,6 +3096,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], + beego.ControllerComments{ + Method: "RefreshJXPriceChange", + Router: `/RefreshJXPriceChange`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], beego.ControllerComments{ Method: "RefreshMtpsWaybillFee", @@ -2448,6 +3123,24 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], + beego.ControllerComments{ + Method: "StoreOpenAll", + Router: `/StoreOpenAll`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], + beego.ControllerComments{ + Method: "StoreSkuCheckDiff", + Router: `/StoreSkuCheckDiff`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], beego.ControllerComments{ Method: "TestIt", @@ -2574,6 +3267,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], + beego.ControllerComments{ + Method: "GetJxShopUsers", + Router: `/GetJxShopUsers`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "GetMyJxStoreList", @@ -2709,6 +3411,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], + beego.ControllerComments{ + Method: "UpdateUserLastInfo", + Router: `/UpdateUserLastInfo`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:User2Controller"], beego.ControllerComments{ Method: "UpdateUserWxNoAndPercent", diff --git a/routers/router.go b/routers/router.go index 162e2ce63..1b54e201c 100644 --- a/routers/router.go +++ b/routers/router.go @@ -141,6 +141,11 @@ func init() { &controllers.EventController{}, ), ), + beego.NSNamespace("/power", + beego.NSInclude( + &controllers.PowerController{}, + ), + ), ) beego.AddNamespace(ns) @@ -158,6 +163,7 @@ func init() { beego.AutoRouter(&controllers.TongLianController{}) beego.AutoRouter(&controllers.EclpController{}) beego.AutoRouter(&controllers.JdsController{}) + beego.AutoRouter(&controllers.FnController{}) // 如下都是用于检测存活的空接口 beego.Any("/", func(ctx *beecontext.Context) {