Files
jx-callback/business/partner/purchase/jd/store.go

464 lines
16 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 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 := getAPI("").GetStoreInfoByStationNo2(vendorStoreID)
if err == nil {
retVal := &dao.StoreDetail{
Store: model.Store{
Address: result.StationAddress,
OpenTime1: JdOperationTime2JxOperationTime(result.ServiceTimeStart1),
CloseTime1: JdOperationTime2JxOperationTime(result.ServiceTimeEnd1),
OpenTime2: JdOperationTime2JxOperationTime(result.ServiceTimeStart2),
CloseTime2: JdOperationTime2JxOperationTime(result.ServiceTimeEnd2),
Status: JdStoreStatus2JxStatus(int(result.Yn), result.CloseStatus),
Tel1: result.Phone,
},
}
retVal.OriginalName = result.StationName
_, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, VendorStorePrefix)
retVal.DeliveryType = JdDeliveryType2Jx(result.CarrierNo)
tel2 := result.Mobile
if tel2 != "" && tel2 != retVal.Tel1 {
retVal.Tel2 = tel2
}
lng := result.Lng
lat := result.Lat
retVal.Lng = jxutils.StandardCoordinate2Int(lng)
retVal.Lat = jxutils.StandardCoordinate2Int(lat)
db := dao.GetDB()
cityCode := result.City
if cityCode != 0 {
if city, err2 := dao.GetPlaceByJdCode(db, cityCode); err2 == nil {
retVal.CityCode = city.Code
districtName := 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(result.OutSystemID, 0))
deliveryRange, err2 := getAPI("").GetDeliveryRangeByStationNo2(vendorStoreID)
if err = err2; err == nil {
retVal.DeliveryRangeType = int8(deliveryRange.DeliveryRangeType)
if retVal.DeliveryRangeType == model.DeliveryRangeTypePolygon {
retVal.DeliveryRange = strings.Trim(deliveryRange.DeliveryRange, ";")
} else {
retVal.DeliveryRange = utils.Int2Str(deliveryRange.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 {
storeParams := &jdapi.OpStoreParams{
StationNo: store.VendorStoreID,
Operator: userName,
Phone: store.Tel1,
Mobile: store.Tel2,
}
if store.SyncStatus&model.SyncFlagDeletedMask == 0 {
storeParams.OutSystemID = utils.Int2Str(int(store.ID))
} else {
storeParams.OutSystemID = store.VendorStoreID
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD)
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreAddress) != 0 {
storeParams.StationAddress = store.Address
storeParams.DeliveryRangeType = store.DeliveryRangeType
storeParams.CoordinateType = jdapi.CoordinateTypeAutonavi // 一直用高德
storeParams.Lng = jxutils.IntCoordinate2Standard(store.Lng)
storeParams.Lat = jxutils.IntCoordinate2Standard(store.Lat)
if store.JdCityCode != 0 {
storeParams.City = store.JdCityCode
}
if store.JdDistrictCode != 0 {
storeParams.County = store.JdDistrictCode
}
if store.DeliveryRangeType == model.DeliveryRangeTypePolygon {
storeParams.CoordinatePoints = store.DeliveryRange
} else {
storeParams.DeliveryRangeRadius = int(utils.Str2Int64WithDefault(store.DeliveryRange, 0))
}
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagDeletedMask|model.SyncFlagStoreStatus) != 0 {
_, storeParams.CloseStatus = JxStoreStatus2JdStatus(jxutils.MergeStoreStatus(store.Status, store.JdStoreStatus))
}
fillOpTimeParams(storeParams, store.GetOpTimeList())
globals.SugarLogger.Debug(utils.Format4Output(storeParams, false))
if globals.EnableJdStoreWrite {
if err = getAPI("").UpdateStoreInfo4Open2(storeParams); err != nil {
return err
}
}
}
}
return err
}
///////////////////////
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 := &jdapi.OpStoreParams{
StationNo: store.VendorStoreID,
Operator: ctx.GetUserName(),
OutSystemID: utils.Int2Str(int(store.ID)),
}
if step != stepCount-1 {
storeParams.OutSystemID = store.VendorStoreID
}
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateStoreInfo4Open2(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 := getAPI("").GetStoreInfoByStationNo2(vendorStoreID)
if err == nil {
storeStatus = JdStoreStatus2JxStatus(int(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 (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
_, err = getAPI("").UpdateStoreConfig4Open(vendorStoreID, isSetEnable)
return err
}
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, storeID int, vendorStoreID string, status int) (err error) {
_, closeStatus := JxStoreStatus2JdStatus(status)
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateStoreInfo4Open2(&jdapi.OpStoreParams{
StationNo: vendorStoreID,
Operator: ctx.GetUserName(),
CloseStatus: closeStatus,
})
}
return err
}
func fillOpTimeParams(params *jdapi.OpStoreParams, opTimeList []int16) {
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 {
if index == 1 {
params.ServiceTimeStart1 = int(JxOperationTime2JdOperationTime(int16(opTimeList[k])))
params.ServiceTimeEnd1 = int(JxOperationTime2JdOperationTime(int16(opTimeList[k+1])))
} else {
params.ServiceTimeStart2 = int(JxOperationTime2JdOperationTime(int16(opTimeList[k])))
params.ServiceTimeEnd2 = int(JxOperationTime2JdOperationTime(int16(opTimeList[k+1])))
}
} else {
break
}
index++
}
}
func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
params := &jdapi.OpStoreParams{
StationNo: vendorStoreID,
Operator: ctx.GetUserName(),
}
fillOpTimeParams(params, opTimeList)
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateStoreInfo4Open2(params)
}
return err
}
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context) (vendorStoreIDs []string, err error) {
vendorStoreIDs, err = getAPI("").GetStationsByVenderId()
return vendorStoreIDs, err
}
func (c *PurchaseHandler) storeUploadImgByURL(inImgURL string) (imgURL string, err error) {
if globals.EnableJdStoreWrite {
imgURL, err = api.JdPageAPI.StoreUploadImgByURL(inImgURL)
} else {
imgURL = utils.GetUUID()
}
return imgURL, err
}
func addStoreInfo2Err(err error, storeID int) error {
if err != nil {
errExt := utils.NewErrorCode(err.Error(), "999")
errExt.AddPrefixMsg(fmt.Sprintf("门店%d", storeID))
err = errExt
}
return err
}
func (c *PurchaseHandler) SyncQualify(ctx *jxcontext.Context, storeDetail *dao.StoreDetail) (err error) {
if storeDetail.LicenceCode == "" || storeDetail.Licence == "" {
return addStoreInfo2Err(fmt.Errorf("营业执照信息不全"), storeDetail.ID)
}
if storeDetail.IDCode == "" || storeDetail.IDCardFront == "" || storeDetail.IDCardBack == "" || storeDetail.IDValid == "" {
return addStoreInfo2Err(fmt.Errorf("个人信息不全"), storeDetail.ID)
}
var qualifyList []*jdapi.QualifyItem
licenceDetail, err := api.JdPageAPI.GetCorporationInfo(storeDetail.VendorStoreID, storeDetail.LicenceCode)
if err != nil {
return err
}
licenceURL, err := c.storeUploadImgByURL(storeDetail.Licence)
if err != nil {
return err
}
expireStart, err := utils.TryStr2Time(licenceDetail.StartDate)
if err != nil {
return fmt.Errorf("执照有效开始时间:%s非法请手动处理", licenceDetail.StartDate)
}
qualifyList = append(qualifyList, &jdapi.QualifyItem{
QualifyType: jdapi.QualifyTypeCompany,
QualifyURL: licenceURL,
QualifyExpireStart: utils.Time2Str(expireStart),
QualifyExpireForever: 0,
QualifyName: licenceDetail.OperName,
LicenceType: "-1",
QualifyNumber: storeDetail.LicenceCode,
QualifyAddress: licenceDetail.Address,
LicenceName: licenceDetail.Name,
EconKind: licenceDetail.EconKind,
Scope: licenceDetail.Scope,
})
idFrondURL, err := c.storeUploadImgByURL(storeDetail.IDCardFront)
if err != nil {
return addStoreInfo2Err(err, storeDetail.ID)
}
// 个体经营,个体工商户
if storeDetail.LicenceType == 0 { // 个人
personQualify := &jdapi.QualifyItem{
QualifyType: jdapi.QualifyTypePerson,
QualifyURL: idFrondURL,
QualifyExpireStart: utils.Time2Str(utils.Str2Time(storeDetail.IDValid)),
QualifyExpireForever: 0,
QualifyNumber: storeDetail.IDCode,
QualifyOwner: storeDetail.LicenceOwnerName,
}
if storeDetail.IDExpire != "" {
personQualify.QualifyExpireForever = 1
personQualify.QualifyExpireEnd = utils.Time2Str(utils.Str2Time(storeDetail.IDExpire))
}
qualifyList = append(qualifyList, personQualify)
} else {
addInfo := &jdapi.QualifyItem{
QualifyType: jdapi.QualifyTypeAddInfo,
QualifyURL: idFrondURL,
QualifyExpireStart: utils.Time2Str(utils.Str2Time(storeDetail.IDValid)),
QualifyExpireForever: 0,
}
if storeDetail.IDExpire != "" {
addInfo.QualifyExpireForever = 1
addInfo.QualifyExpireEnd = utils.Time2Str(utils.Str2Time(storeDetail.IDExpire))
}
qualifyList = append(qualifyList, addInfo)
}
if storeDetail.IDExpire == "" {
idBackURL, err := c.storeUploadImgByURL(storeDetail.IDCardBack)
if err != nil {
return addStoreInfo2Err(err, storeDetail.ID)
}
qualifyList = append(qualifyList, &jdapi.QualifyItem{
QualifyType: jdapi.QualifyTypeAddInfo,
QualifyURL: idBackURL,
QualifyExpireStart: utils.Time2Str(utils.Str2Time(storeDetail.IDValid)),
QualifyExpireForever: 0,
})
}
globals.SugarLogger.Debug(utils.Format4Output(qualifyList, false))
if globals.EnableJdStoreWrite {
err = api.JdPageAPI.SaveQualify(storeDetail.VendorStoreID, jdapi.SaveQualifyActionTypeCommit, qualifyList)
// err = api.JdPageAPI.SaveQualify(storeDetail.VendorStoreID, jdapi.SaveQualifyActionTypeSave, qualifyList)
}
return addStoreInfo2Err(err, storeDetail.ID)
}
func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorStoreID string, storeID int64) (err error) {
if globals.EnableJdStoreWrite {
err = getAPI("").UpdateStoreInfo4Open2(
&jdapi.OpStoreParams{
StationNo: vendorStoreID,
Operator: ctx.GetUserName(),
OutSystemID: utils.Int2Str(int(storeID)),
})
}
return err
}