package jd import ( "fmt" "strings" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "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/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals/api" ) const ( VendorStorePrefix = "京西菜市" ) type tJdStoreInfo struct { model.Store JdCityCode int JdDistrictCode int JdStoreStatus int VendorStoreID string `orm:"column(vendor_store_id)"` RealLastOperator string SyncStatus int } func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorStoreID string) (*dao.StoreDetail, error) { result, err := api.JdAPI.GetStoreInfoByStationNo(vendorStoreID) if err == nil { retVal := &dao.StoreDetail{ Store: model.Store{ Address: utils.Interface2String(result["stationAddress"]), OpenTime1: JdOperationTime2JxOperationTime(result["serviceTimeStart1"]), CloseTime1: JdOperationTime2JxOperationTime(result["serviceTimeEnd1"]), OpenTime2: JdOperationTime2JxOperationTime(result["serviceTimeStart2"]), CloseTime2: JdOperationTime2JxOperationTime(result["serviceTimeEnd2"]), Status: JdStoreStatus2JxStatus(result["yn"], result["closeStatus"]), Tel1: utils.Interface2String(result["phone"]), }, } retVal.OriginalName = utils.Interface2String(result["stationName"]) _, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, VendorStorePrefix) retVal.DeliveryType = JdDeliveryType2Jx(int(utils.MustInterface2Int64(result["carrierNo"]))) tel2 := utils.Interface2String(result["mobile"]) if tel2 != "" && tel2 != retVal.Tel1 { retVal.Tel2 = tel2 } lng := utils.MustInterface2Float64(result["lng"]) lat := utils.MustInterface2Float64(result["lat"]) retVal.Lng = jxutils.StandardCoordinate2Int(lng) retVal.Lat = jxutils.StandardCoordinate2Int(lat) db := dao.GetDB() cityCode := int(utils.MustInterface2Int64(result["city"])) if cityCode != 0 { if city, err2 := dao.GetPlaceByJdCode(db, cityCode); err2 == nil { retVal.CityCode = city.Code districtName := utils.Interface2String(result["countyName"]) // 京东的市区号码与通用数据完全无法关联,只有通过名字来关联 if retVal.CityCode != 0 && districtName != "" { if district, err2 := dao.GetPlaceByName(db, districtName, 3, city.Code); err2 == nil { retVal.DistrictCode = district.Code } } } } if retVal.DistrictCode == 0 { retVal.DistrictCode = api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat) if retVal.CityCode == 0 { if district, err := dao.GetPlaceByCode(db, retVal.DistrictCode); err == nil { retVal.CityCode = district.ParentCode } } } retVal.ID = int(utils.Str2Int64WithDefault(utils.Interface2String(result["outSystemId"]), 0)) result, err2 := api.JdAPI.GetDeliveryRangeByStationNo(vendorStoreID) if err = err2; err == nil { retVal.DeliveryRangeType = int8(utils.MustInterface2Int64(result["deliveryRangeType"])) if retVal.DeliveryRangeType == model.DeliveryRangeTypePolygon { retVal.DeliveryRange = strings.Trim(utils.Interface2String(result["deliveryRange"]), ";") } else { retVal.DeliveryRange = utils.Int64ToStr(utils.MustInterface2Int64(result["deliveryRangeRadius"])) } return retVal, nil } } return nil, err } // stoerIDs为nil表示所有 func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) { var stores []*tJdStoreInfo sql := ` SELECT 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 FROM store t1 JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?) LEFT JOIN place city ON t1.city_code = city.code LEFT JOIN place district ON t1.district_code = district.code WHERE t1.id = ? ORDER BY t2.updated_at ` if err = dao.GetRows(db, &stores, sql, model.VendorIDJD, utils.DefaultTimeValue, storeID); err == nil { for _, store := range stores { outSystemID := "" if store.SyncStatus&model.SyncFlagDeletedMask == 0 { outSystemID = utils.Int2Str(int(store.ID)) } params := map[string]interface{}{ "outSystemId": outSystemID, // todo 直接修改这个字段可能会有问题 "phone": store.Tel1, "mobile": store.Tel2, } fillOpTimeParams(params, store.GetOpTimeList()) if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 { params["stationName"] = jxutils.ComposeStoreName(store.Name, model.VendorIDJD) } if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreAddress) != 0 { params["stationAddress"] = store.Address params["deliveryRangeType"] = store.DeliveryRangeType params["coordinateType"] = 3 // 一直用高德 params["lng"] = jxutils.IntCoordinate2Standard(store.Lng) params["lat"] = jxutils.IntCoordinate2Standard(store.Lat) if store.JdCityCode != 0 { params["city"] = store.JdCityCode } if store.JdDistrictCode != 0 { params["county"] = store.JdDistrictCode } if store.DeliveryRangeType == model.DeliveryRangeTypePolygon { params["coordinatePoints"] = store.DeliveryRange } else { params["deliveryRangeRadius"] = utils.Str2Int64WithDefault(store.DeliveryRange, 0) } } _, params["closeStatus"] = JxStoreStatus2JdStatus(jxutils.MergeStoreStatus(store.Status, store.JdStoreStatus)) globals.SugarLogger.Debug(utils.Format4Output(params, false)) if globals.EnableJdStoreWrite { if err = api.JdAPI.UpdateStoreInfo4Open(store.VendorStoreID, store.RealLastOperator, params); err != nil { return err } } } } return err } // 没用 // func (p *PurchaseHandler) DeleteStore(vendorStoreID, userName string) error { // params := map[string]interface{}{ // "yn": 1, // } // return api.JdAPI.UpdateStoreInfo4Open(vendorStoreID, userName, params) // } // func (p *PurchaseHandler) EnableAutoAcceptOrder(vendorStoreID string, isEnabled bool) error { // _, err := api.JdAPI.UpdateStoreConfig4Open(vendorStoreID, isEnabled) // return err // } // func (p *PurchaseHandler) OpenStore(vendorStoreID string, userName string) error { // params := map[string]interface{}{ // "closeStatus": 0, // "storeNotice": "", // } // return api.JdAPI.UpdateStoreInfo4Open(vendorStoreID, userName, params) // } // func (p *PurchaseHandler) CloseStore(vendorStoreID, closeNotice, userName string) error { // params := map[string]interface{}{ // "closeStatus": 1, // "storeNotice": closeNotice, // } // return api.JdAPI.UpdateStoreInfo4Open(vendorStoreID, userName, params) // } /////////////////////// func (p *PurchaseHandler) GetAllStoresFromRemote() ([]*model.Store, error) { ids, err := p.GetAllStoresVendorID(jxcontext.AdminCtx) if err == nil { retVal := make([]*model.Store, len(ids)) for index, id := range ids { store, err2 := p.ReadStore(jxcontext.AdminCtx, id) if err2 == nil { retVal[index] = &store.Store } else { return nil, err2 } } return retVal, nil } return nil, err } func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) { globals.SugarLogger.Debugf("jd RefreshAllStoresID") const stepCount = 3 var stores []*tJdStoreInfo db := dao.GetDB() rootTask := tasksch.NewSeqTask("jd RefreshAllStoresID", ctx, func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: err = dao.GetRows(db, &stores, ` SELECT t1.*, t2.vendor_store_id FROM store t1 JOIN store_map t2 ON t1.id = t2.store_id AND t2.deleted_at = ? AND t2.vendor_id = ? WHERE t1.deleted_at = ? `, utils.DefaultTimeValue, model.VendorIDJD, utils.DefaultTimeValue) default: taskName := "jd RefreshAllStoresID update outSystemId" if step != stepCount-1 { taskName = "jd RefreshAllStoresID update to uuid" } task1 := tasksch.NewParallelTask(taskName, nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { store := batchItemList[0].(*tJdStoreInfo) storeParams := map[string]interface{}{ "outSystemId": utils.Int2Str(int(store.ID)), } if step != stepCount-1 { storeParams["outSystemId"] = utils.GetUUID() } if globals.EnableJdStoreWrite { err = api.JdAPI.UpdateStoreInfo4Open(store.VendorStoreID, ctx.GetUserName(), storeParams) } return nil, err }, stores) task.AddChild(task1).Run() _, err = task1.GetResult(0) } return nil, err }, stepCount) tasksch.HandleTask(rootTask, parentTask, false).Run() if !isAsync { _, err = rootTask.GetResult(0) } return rootTask.ID, err } // func JdRange2JxRange(jdRanges string) (jxRanges string) { // coords := strings.Split(jdRanges, ";") // intCoords := []string{} // for _, coord := range coords { // items := strings.Split(coord, ",") // if len(items) == 2 { // lng := jxutils.StandardCoordinate2Int(utils.Str2Float64(items[0])) // lat := jxutils.StandardCoordinate2Int(utils.Str2Float64(items[1])) // intCoords = append(intCoords, fmt.Sprintf("%d,%d", lng, lat)) // } // } // return strings.Join(intCoords, ";") // } // func JxRange2JdRange(jxRanges string) (jdRanges string) { // coords := strings.Split(jxRanges, ";") // intCoords := []string{} // for _, coord := range coords { // items := strings.Split(coord, ",") // if len(items) == 2 { // lng := jxutils.IntCoordinate2Standard(int(utils.Str2Int64(items[0]))) // lat := jxutils.IntCoordinate2Standard(int(utils.Str2Int64(items[1]))) // intCoords = append(intCoords, fmt.Sprintf("%f,%f", lng, lat)) // } // } // return strings.Join(intCoords, ";") // } func JdDeliveryType2Jx(deliveryType int) int8 { if deliveryType == jdapi.CarrierNoSelfDelivery { return scheduler.StoreDeliveryTypeByStore } else if deliveryType == jdapi.CarrierNoCrowdSourcing { return scheduler.StoreDeliveryTypeCrowdSourcing } return scheduler.StoreDeliveryTypeByPlatform } func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeStatus int, err error) { result, err := api.JdAPI.GetStoreInfoByStationNo(vendorStoreID) if err == nil { storeStatus = JdStoreStatus2JxStatus(result["yn"], result["closeStatus"]) } return storeStatus, err } // 当前京东的storeCrud消息不会在门店状态改变时发送,所以意义不大,先放在这里 func (c *PurchaseHandler) OnStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jdapi.CallbackResponse) { var err error // if msg.StatusID == jdapi.StatusIDUpdateStore { // var storeStatus int // vendorStoreID := msg.BillID // if storeStatus, err = c.GetStoreStatus(jxcontext.AdminCtx, vendorStoreID); err == nil { // err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDJD, storeStatus) // } else { // // 可能在门店删除的情况下会出查不到门店的错误 // if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 4 { // err = nil // } // } // } return jdapi.Err2CallbackResponse(err, "") } func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, status int) (err error) { _, closeStatus := JxStoreStatus2JdStatus(status) if globals.EnableJdStoreWrite { err = api.JdAPI.UpdateStoreInfo4Open(vendorStoreID, ctx.GetUserName(), map[string]interface{}{ "closeStatus": closeStatus, }) } return err } func fillOpTimeParams(params map[string]interface{}, opTimeList []int16) map[string]interface{} { if params == nil { params = make(map[string]interface{}) } index := 1 opTimeListLen := len(opTimeList) if opTimeListLen > 4 { opTimeListLen = 4 } opTimeListLen = opTimeListLen / 2 * 2 for k := 0; k < len(opTimeList); k += 2 { if opTimeList[k] != 0 { params[fmt.Sprintf("serviceTimeStart%d", index)] = JxOperationTime2JdOperationTime(int16(opTimeList[k])) params[fmt.Sprintf("serviceTimeEnd%d", index)] = JxOperationTime2JdOperationTime(int16(opTimeList[k+1])) } else { break } index++ } return params } func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, storeID int, vendorStoreID string, opTimeList []int16) (err error) { params := fillOpTimeParams(nil, opTimeList) if globals.EnableJdStoreWrite { err = api.JdAPI.UpdateStoreInfo4Open(vendorStoreID, ctx.GetUserName(), params) } return err } func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context) (vendorStoreIDs []string, err error) { vendorStoreIDs, err = api.JdAPI.GetStationsByVenderId() return vendorStoreIDs, err }