Files
jx-callback/business/partner/purchase/ebai/store.go
2018-11-24 12:20:46 +08:00

371 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package ebai
import (
"fmt"
"strings"
"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"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
)
const (
VendorStorePrefix = "好菜鲜生"
)
type tEbaiStoreInfo struct {
model.Store
VendorStoreID string `orm:"column(vendor_store_id)"`
RealLastOperator string
EbaiStoreStatus int
SyncStatus int
ProvinceID int `orm:"column(province_id)"`
CityID int `orm:"column(city_id)"`
DistrictID int `orm:"column(district_id)"`
}
func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
var store tEbaiStoreInfo
sql := `
SELECT t1.*, t2.status ebai_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,
province.ebai_code province_id, city.ebai_code city_id, district.ebai_code district_id
FROM store t1
LEFT JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND t2.deleted_at = ?
JOIN place district ON t1.district_code = district.code
JOIN place city ON t1.city_code = city.code
JOIN place province ON city.parent_code = province.code
WHERE t1.id = ? AND t2.id IS NULL;
`
if err = dao.GetRow(db, &store, sql, model.VendorIDEBAI, utils.DefaultTimeValue, storeID); err == nil {
params := genStoreMapFromStore(&store)
params["shop_id"] = store.ID
params["business_form_id"] = "179"
params["service_phone"] = store.Tel1
params["invoice_support"] = 2
params["package_box_price"] = 0
params["encrypt"] = ""
params["category1"] = ""
params["category2"] = ""
params["category3"] = ""
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
intVendorStoreID, err2 := api.EbaiAPI.ShopCreate(params)
if err = err2; err == nil {
return utils.Int64ToStr(intVendorStoreID), err
}
} else {
return utils.Int64ToStr(jxutils.GenFakeID()), nil
}
}
return "", err
}
func (p *PurchaseHandler) ReadStore(vendorStoreID string) (*model.Store, error) {
baiduShopID := utils.Str2Int64(vendorStoreID)
result, err := api.EbaiAPI.ShopGet("", baiduShopID)
if err == nil {
// globals.SugarLogger.Debug(utils.Format4Output(result, false))
retVal := &model.Store{
Address: utils.Interface2String(result["address"]),
Tel1: utils.Interface2String(result["phone"]),
}
_, retVal.Name = jxutils.SplitStoreName(utils.Interface2String(result["name"]), partner.StoreNameSeparator, VendorStorePrefix)
retVal.DeliveryType = EbaiDeliveryType2Jx(utils.Interface2String(result["delivery_type"]))
businessTime := result["business_time"].([]interface{})
btime := businessTime[0].(map[string]interface{})
retVal.OpenTime1 = jxutils.StrTime2JxOperationTime(utils.Interface2String(btime["start"].(string)), 700)
retVal.CloseTime1 = jxutils.StrTime2JxOperationTime(utils.Interface2String(btime["end"].(string)), 2000)
if len(businessTime) > 1 {
btime = businessTime[1].(map[string]interface{})
retVal.OpenTime2 = jxutils.StrTime2JxOperationTime(utils.Interface2String(btime["start"].(string)), 700)
retVal.CloseTime2 = jxutils.StrTime2JxOperationTime(utils.Interface2String(btime["end"].(string)), 2000)
}
if ebaiStatus, err2 := api.EbaiAPI.ShopBusStatusGet("", baiduShopID, ebaiapi.PlatformFlagBaidu); err2 == nil {
retVal.Status = EbaiBusStatus2JxStatus(ebaiStatus)
}
tel2 := utils.Interface2String(result["ivr_phone"])
if tel2 != "" && tel2 != retVal.Tel1 {
retVal.Tel2 = tel2
}
lng := utils.MustInterface2Float64(result["longitude"])
lat := utils.MustInterface2Float64(result["latitude"])
if utils.Interface2String(result["coord_type"]) == ebaiapi.CoordTypeBaidu {
var err2 error
if lng, lat, err2 = api.AutonaviAPI.CoordinateConvert(lng, lat, autonavi.CoordSysBaidu); err2 != nil {
return nil, err2
}
}
retVal.Lng = jxutils.StandardCoordinate2Int(lng)
retVal.Lat = jxutils.StandardCoordinate2Int(lat)
db := dao.GetDB()
if city, err2 := dao.GetPlaceByName(db, utils.Interface2String(result["city"]), model.PlaceLevelCity, 0); err2 == nil {
retVal.CityCode = city.Code
districtName := utils.Interface2String(result["county"])
if retVal.CityCode != 0 && districtName != "" {
if district, err2 := dao.GetPlaceByName(db, utils.Interface2String(result["county"]), model.PlaceLevelDistrict, city.Code); err2 == nil {
retVal.DistrictCode = district.Code
}
}
if retVal.DistrictCode == 0 {
retVal.DistrictCode = api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat)
if district, err := dao.GetPlaceByCode(db, retVal.DistrictCode); err == nil {
retVal.CityCode = district.ParentCode
}
}
}
retVal.ID = int(utils.Str2Int64WithDefault(utils.Interface2String(result["shop_id"]), 0))
retVal.DeliveryRangeType = model.DeliveryRangeTypePolygon
retVal.DeliveryRange = EbaiDeliveryRegion2Jx(result["delivery_region"])
return retVal, nil
}
return nil, err
}
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
globals.SugarLogger.Debugf("ebai UpdateStore storeID:%d, userName:%s", storeID, userName)
var stores []*tEbaiStoreInfo
sql := `
SELECT t1.*, t2.status ebai_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 = ? OR t2.sync_status <> 0)
WHERE t1.id = ?
ORDER BY t2.updated_at
`
if err = dao.GetRows(db, &stores, sql, model.VendorIDEBAI, utils.DefaultTimeValue, storeID); err == nil {
for _, store := range stores {
params := genStoreMapFromStore(store)
// globals.SugarLogger.Debug(utils.Format4Output(params, false))
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
if err = api.EbaiAPI.ShopUpdate(params); err == nil {
shopID := 0
if store.SyncStatus&model.SyncFlagDeletedMask == 0 {
shopID = store.ID
}
store2, err2 := p.ReadStore(store.VendorStoreID)
if err = err2; err == nil {
if store2.ID == store.ID {
shopID = -1
}
}
if err == nil {
if shopID > 0 {
err = api.EbaiAPI.ShopIDBatchUpdate([]string{store.VendorStoreID}, []string{utils.Int2Str(shopID)})
} else if shopID == 0 {
// todo remove out shop id
}
}
if err == nil {
mergeStatus := jxutils.MergeStoreStatus(store.Status, store.EbaiStoreStatus)
if mergeStatus == model.StoreStatusOpened {
err = api.EbaiAPI.ShopOnline("", utils.Str2Int64(store.VendorStoreID))
} else if mergeStatus == model.StoreStatusClosed {
err = api.EbaiAPI.ShopOffline("", utils.Str2Int64(store.VendorStoreID))
} else if mergeStatus == model.StoreStatusClosed {
err = api.EbaiAPI.ShopClose("", utils.Str2Int64(store.VendorStoreID))
}
if err != nil {
return err
}
}
}
}
}
}
return err
}
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
globals.SugarLogger.Debugf("ebai RefreshAllStoresID")
const batchSize = 50
const stepCount = 3
var stores []*tEbaiStoreInfo
db := dao.GetDB()
rootTask := tasksch.NewSeqTask("ebai RefreshAllStoresID", ctx.GetUserName(), 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.VendorIDEBAI, utils.DefaultTimeValue)
default:
taskName := "ebai RefreshAllStoresID update to custom id"
if step != stepCount-1 {
taskName = "ebai RefreshAllStoresID update to uuid"
}
task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetBatchSize(batchSize), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
baiduShopIDs := make([]string, len(batchItemList))
shopIDs := make([]string, len(batchItemList))
for k, v := range batchItemList {
store := v.(*tEbaiStoreInfo)
baiduShopIDs[k] = store.VendorStoreID
shopIDs[k] = utils.Int2Str(store.ID)
if step != stepCount-1 {
shopIDs[k] = utils.GetUUID()
}
}
if globals.EnableStoreWrite && globals.EnableEbaiStoreWrite {
err = api.EbaiAPI.ShopIDBatchUpdate(baiduShopIDs, shopIDs)
}
return nil, err
}, stores)
task.AddChild(task1).Run()
_, err = task1.GetResult(0)
}
return nil, err
}, stepCount)
ctx.SetTaskOrAddChild(rootTask, parentTask)
rootTask.Run()
if !isAsync {
_, err = rootTask.GetResult(0)
}
return rootTask.ID, err
}
// todo 此函数只考虑了在饿了么侧开店的情况
func EbaiDeliveryType2Jx(deliveryType string) int8 {
spIndex := strings.Index(deliveryType, "|")
elmDeliveryType := utils.Str2Int64(deliveryType[:spIndex])
switch elmDeliveryType {
case ebaiapi.DeliveryTypeElmFengNiaoZS,
ebaiapi.DeliveryTypeElmFengNiaoZSKA,
ebaiapi.DeliveryTypeElmFengNiaoKS,
ebaiapi.DeliveryTypeElmNewRetail,
ebaiapi.DeliveryTypeElmEPeiSong,
ebaiapi.DeliveryTypeElmFengNiaoHybrid,
ebaiapi.DeliveryTypeElmFengNiaoNiubee:
return scheduler.StoreDeliveryTypeByPlatform
case ebaiapi.DeliveryTypeElmXingHuoZBTrial,
ebaiapi.DeliveryTypeElmXingHuoZB,
ebaiapi.DeliveryTypeElmXingHuoZBKA:
return scheduler.StoreDeliveryTypeCrowdSourcing
case ebaiapi.DeliveryTypeElmNone,
ebaiapi.DeliveryTypeElmXingHuoTrial,
ebaiapi.DeliveryTypeElmXingHuo,
ebaiapi.DeliveryTypeElmEBase,
ebaiapi.DeliveryTypeElmXingHuoKA:
return scheduler.StoreDeliveryTypeByStore
default:
return scheduler.StoreDeliveryTypeCrowdSourcing
}
}
func EbaiDeliveryRegion2Jx(deliveryRegion interface{}) string {
realDeliveryRegion := deliveryRegion.([]interface{})
if len(realDeliveryRegion) > 0 {
region := deliveryRegion.([]interface{})[0].(map[string]interface{})["region"].([]interface{})[0].([]interface{})
coords := make([]string, len(region))
for k, v := range region {
mapV := v.(map[string]interface{})
coords[k] = fmt.Sprintf("%.6f,%.6f", utils.MustInterface2Float64(mapV["longitude"]), utils.MustInterface2Float64(mapV["latitude"]))
}
return strings.Join(coords, ";")
}
return ""
}
func JxDeliveryRegion2Ebai(store *model.Store) (deliveryRegion interface{}) {
rangeStr := strings.Trim(store.DeliveryRange, ";")
if store.DeliveryRangeType == model.DeliveryRangeTypeRadius {
if utils.Str2Int64(store.DeliveryRange) > 100 { // todo 如果小于100米表示禁用不更新
rangeStr = jxutils.GetPolygonFromCircleStr(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat), utils.Str2Float64(store.DeliveryRange), 8)
} else {
rangeStr = ""
}
}
rangeStr = "" // todo 暂时禁止同步配送区域
if rangeStr != "" {
pointPairs := strings.Split(rangeStr, ";")
region := make([]map[string]interface{}, 0)
for _, v := range pointPairs {
pointPair := strings.Split(v, ",")
if len(pointPair) == 2 {
region = append(region, map[string]interface{}{
"longitude": utils.Str2Float64(pointPair[0]),
"latitude": utils.Str2Float64(pointPair[1]),
})
}
}
deliveryRegion = []interface{}{
map[string]interface{}{
"name": "主要配送区",
"delivery_fee": 600,
"delivery_time": "60",
"min_buy_free": "0",
"min_order_price": "0",
"region": []interface{}{
region,
},
},
}
}
return deliveryRegion
}
func JxBusinessTime2Ebai(store *model.Store) interface{} {
bTime := make([]map[string]interface{}, 1)
bTime[0] = map[string]interface{}{
"start": jxutils.JxOperationTime2StrTime(store.OpenTime1),
"end": jxutils.JxOperationTime2StrTime(store.CloseTime1),
}
if store.OpenTime2 != 0 {
bTime = append(bTime, map[string]interface{}{
"start": jxutils.JxOperationTime2StrTime(store.OpenTime2),
"end": jxutils.JxOperationTime2StrTime(store.CloseTime2),
})
}
return bTime
}
func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} {
params := map[string]interface{}{
"name": jxutils.ComposeStoreName(store.Name, partner.StoreNameSeparator, VendorStorePrefix),
"phone": store.Tel1,
"longitude": jxutils.IntCoordinate2Standard(store.Lng),
"latitude": jxutils.IntCoordinate2Standard(store.Lat),
"address": store.Address,
"coord_type": ebaiapi.CoordTypeAutonavi, // 一直用高德
"business_time": JxBusinessTime2Ebai(&store.Store),
}
if deliveryRegion := JxDeliveryRegion2Ebai(&store.Store); deliveryRegion != nil {
params["delivery_region"] = deliveryRegion
}
if store.VendorStoreID != "" {
params["baidu_shop_id"] = store.VendorStoreID
}
if store.Tel2 != "" {
params["ivr_phone"] = store.Tel2
}
if store.ProvinceID != 0 {
params["province"] = store.ProvinceID
}
if store.CityID != 0 {
params["city"] = store.CityID
}
if store.DistrictID != 0 {
params["county"] = store.DistrictID
}
return params
}