Merge remote-tracking branch 'origin/mark' into lcw
This commit is contained in:
@@ -49,8 +49,9 @@ func (a *Auther) SendVerifyCode(mobileNumber string) error {
|
||||
response, err := smsClient.Execute(globals.AliKey, globals.AliSecret, mobileNumber, "京西菜市", "SMS_84655036", string(utils.MustMarshal(map[string]interface{}{
|
||||
"code": code,
|
||||
})))
|
||||
a.SaveVerifyCode(mobileNumber, code)
|
||||
if err == nil && response.Code == aliyunsmsclient.ResponseCodeOk {
|
||||
a.SaveVerifyCode(mobileNumber, code)
|
||||
// a.SaveVerifyCode(mobileNumber, code)
|
||||
} else {
|
||||
if err == nil {
|
||||
if warningMap[response.Code] == 1 {
|
||||
|
||||
@@ -87,7 +87,7 @@ func GetWeiXinUserInfo(code string, state string) (userInfo *UserInfoExt, err er
|
||||
SNSUserInfo: *wxUserinfo,
|
||||
TempPassword: utils.GetUUID(),
|
||||
}
|
||||
globals.SugarLogger.Debugf("GetUserInfo code:%s, pwd:%s", code, userInfo.TempPassword)
|
||||
globals.SugarLogger.Debugf("GetUserInfo code:%s, userInfo:%s", code, utils.Format4Output(userInfo, true))
|
||||
cacheSNSInfo(wxUserinfo, userInfo.TempPassword, DefTempPasswordDuration)
|
||||
user, err2 := dao.GetWeiXinUserByIDs(dao.GetDB(), "", wxUserinfo.UnionID, wxUserinfo.OpenID, "")
|
||||
if err = err2; err == nil {
|
||||
|
||||
@@ -346,6 +346,7 @@ func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.Dao
|
||||
}
|
||||
|
||||
func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) {
|
||||
globals.SugarLogger.Debugf("addOrderStatus refOrderID:%s, orderID:%s", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID)
|
||||
if db == nil {
|
||||
db = dao.GetDB()
|
||||
}
|
||||
@@ -359,24 +360,30 @@ func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.Da
|
||||
if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) ||
|
||||
(model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
|
||||
order.VendorStatus = orderStatus.VendorStatus
|
||||
order.StatusTime = orderStatus.StatusTime
|
||||
updateFields := []string{
|
||||
"VendorStatus", "StatusTime",
|
||||
"VendorStatus",
|
||||
}
|
||||
if model.IsOrderMainStatus(orderStatus.Status) {
|
||||
order.LockStatus = model.OrderStatusUnknown
|
||||
order.Status = orderStatus.Status
|
||||
updateFields = append(updateFields, "Status", "LockStatus")
|
||||
order.StatusTime = orderStatus.StatusTime
|
||||
updateFields = append(updateFields, "Status", "StatusTime")
|
||||
if order.LockStatus != model.OrderStatusUnknown {
|
||||
order.LockStatus = model.OrderStatusUnknown
|
||||
order.LockStatusTime = orderStatus.StatusTime
|
||||
updateFields = append(updateFields, "LockStatus", "LockStatusTime")
|
||||
}
|
||||
} else {
|
||||
if model.IsOrderUnlockStatus(orderStatus.Status) {
|
||||
order.LockStatus = model.OrderStatusUnknown
|
||||
updateFields = append(updateFields, "LockStatus")
|
||||
} else if model.IsOrderLockStatus(orderStatus.Status) {
|
||||
} else {
|
||||
if order.LockStatus != model.OrderStatusUnknown {
|
||||
globals.SugarLogger.Warnf("addOrderStatus refOrderID:%s, orderID:%s, order.LockStatus:%d, status.LockStatus:%d", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, order.LockStatus, orderStatus.Status)
|
||||
}
|
||||
order.LockStatus = orderStatus.Status
|
||||
updateFields = append(updateFields, "LockStatus")
|
||||
}
|
||||
order.LockStatusTime = orderStatus.StatusTime
|
||||
updateFields = append(updateFields, "LockStatus", "LockStatusTime")
|
||||
}
|
||||
// orderStatus.LockStatus = order.LockStatus
|
||||
if model.IsOrderFinalStatus(orderStatus.Status) {
|
||||
order.OrderFinishedAt = orderStatus.StatusTime
|
||||
updateFields = append(updateFields, "OrderFinishedAt")
|
||||
|
||||
@@ -133,6 +133,13 @@ func (c *BaseScheduler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, ord
|
||||
if c.IsReallyCallPlatformAPI {
|
||||
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AcceptOrRefuseFailedGetOrder(ctx, order, isAcceptIt)
|
||||
}
|
||||
if err == nil {
|
||||
flag := int8(model.OrderFlagAgreeFailedGetGoods)
|
||||
if !isAcceptIt {
|
||||
flag = model.OrderFlagRefuseFailedGetGoods
|
||||
}
|
||||
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, flag)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -140,6 +147,9 @@ func (c *BaseScheduler) CallPMCourier(ctx *jxcontext.Context, order *model.Goods
|
||||
if c.IsReallyCallPlatformAPI {
|
||||
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).CallCourier(ctx, order)
|
||||
}
|
||||
if err == nil {
|
||||
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, model.OrderFlagMaskCallPMCourier)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -147,6 +157,9 @@ func (c *BaseScheduler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model
|
||||
if c.IsReallyCallPlatformAPI {
|
||||
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).ConfirmReceiveGoods(ctx, order)
|
||||
}
|
||||
if err == nil {
|
||||
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, model.OrderFlagMaskFailedDeliver)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -154,5 +167,12 @@ func (c *BaseScheduler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model
|
||||
if c.IsReallyCallPlatformAPI {
|
||||
err = partner.GetPurchasePlatformFromVendorID(order.VendorID).AgreeOrRefuseCancel(ctx, order, isAcceptIt, reason)
|
||||
}
|
||||
if err == nil {
|
||||
flag := int8(model.OrderFlagAgreeUserApplyCancel)
|
||||
if !isAcceptIt {
|
||||
flag = model.OrderFlagRefuseUserApplyCancel
|
||||
}
|
||||
dao.SetOrderFlag(dao.GetDB(), ctx.GetUserName(), order.VendorOrderID, order.VendorID, flag)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -113,11 +113,12 @@ func (s *WatchOrderInfo) updateOrderStoreFeature(order *model.GoodsOrder) (err e
|
||||
}
|
||||
s.autoPickupTimeoutMinute = int(storeMap.AutoPickup)
|
||||
s.storeDeliveryType = FixedScheduler.GetStoreDeliveryType(order, storeMap)
|
||||
if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && (order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 {
|
||||
order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
|
||||
err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order)
|
||||
}
|
||||
globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d, order.DeliveryFlag:%d", order.VendorOrderID, s.storeDeliveryType, order.DeliveryFlag)
|
||||
globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d", order.VendorOrderID, s.storeDeliveryType)
|
||||
// if s.storeDeliveryType == scheduler.StoreDeliveryTypeByStore && (order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled) == 0 {
|
||||
// order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
|
||||
// err = partner.CurOrderManager.UpdateOrderStatusAndFlag(order)
|
||||
// }
|
||||
// globals.SugarLogger.Debugf("updateOrderStoreFeature orderID:%s, s.storeDeliveryType:%d, order.DeliveryFlag:%d", order.VendorOrderID, s.storeDeliveryType, order.DeliveryFlag)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -409,20 +410,7 @@ func (s *DefScheduler) OnWaybillStatusChanged(bill *model.Waybill, isPending boo
|
||||
// s.ProxyCancelWaybill(order, bill, partner.CancelWaybillReasonNotAcceptIntime, partner.CancelWaybillReasonStrNotAcceptIntime)
|
||||
globals.SugarLogger.Infof("OnWaybillStatusChanged CourierArrived order(%d, %s) bill(%d, %s), bill:%v shouldn't get here", order.WaybillVendorID, order.VendorWaybillID, bill.WaybillVendorID, bill.VendorWaybillID, bill)
|
||||
}
|
||||
case model.WaybillStatusFailed: // todo WaybillStatusFailed理解成订单整个失败了,不需要再尝试创建运单了,注意这里应该加个zabbix日志的报警
|
||||
s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
|
||||
if s.isBillCandidate(order, bill) {
|
||||
s.resetTimer(savedOrderInfo, bill, isPending)
|
||||
if !isPending {
|
||||
globals.SugarLogger.Infof("OnWaybillStatusChanged WaybillStatusFailed, bill:%v", bill)
|
||||
bill.WaybillVendorID = model.VendorIDUnknown
|
||||
s.updateOrderByBill(order, bill, false)
|
||||
}
|
||||
} else {
|
||||
// 创建运单失败时,可能到这里来(比如:818874313000121)
|
||||
globals.SugarLogger.Infof("OnWaybillStatusChanged Failed bill:%v shouldn't got here, order details:%v", bill, order)
|
||||
}
|
||||
case model.WaybillStatusCanceled:
|
||||
case model.WaybillStatusCanceled, model.WaybillStatusFailed:
|
||||
s.removeWaybillFromMap(savedOrderInfo, bill.WaybillVendorID)
|
||||
if s.isBillCandidate(order, bill) || order.WaybillVendorID == model.VendorIDUnknown {
|
||||
s.resetTimer(savedOrderInfo, nil, isPending)
|
||||
|
||||
@@ -54,6 +54,7 @@ func InitServiceInfo(version string, buildTime time.Time, gitCommit string) {
|
||||
"storeMsgSendStatusName": model.StoreMsgSendStatusName,
|
||||
"shopChineseNames": model.ShopChineseNames,
|
||||
"printerVendorInfo": model.PrinterVendorInfo,
|
||||
"purchaseVendorInfo": model.PurchaseVendorInfo,
|
||||
},
|
||||
}
|
||||
Init()
|
||||
|
||||
@@ -63,7 +63,7 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int,
|
||||
}
|
||||
}()
|
||||
if storeKV != nil {
|
||||
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeKV:%d", vendorStoreID, utils.Format4Output(storeKV, true))
|
||||
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeKV:%s", vendorStoreID, utils.Format4Output(storeKV, true))
|
||||
store := &model.Store{}
|
||||
store.ID = storeDetail.Store.ID
|
||||
if err = utils.CallFuncLogError(func() error {
|
||||
@@ -74,7 +74,7 @@ func (s *StoreManager) OnStoreStatusChanged(vendorStoreID string, vendorID int,
|
||||
}
|
||||
}
|
||||
if storeMapKV != nil {
|
||||
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeMapKV:%d", vendorStoreID, utils.Format4Output(storeMapKV, true))
|
||||
globals.SugarLogger.Debugf("OnStoreStatusChanged venvendorStoreID:%s, storeMapKV:%s", vendorStoreID, utils.Format4Output(storeMapKV, true))
|
||||
if err = utils.CallFuncLogError(func() error {
|
||||
_, err = dao.UpdateEntityLogically(db, &model.StoreMap{}, storeMapKV, model.AdminName, map[string]interface{}{
|
||||
model.FieldStoreID: storeDetail.Store.ID,
|
||||
|
||||
@@ -242,13 +242,28 @@ func (v *VendorSync) SyncStore(ctx *jxcontext.Context, db *dao.DaoDB, vendorID,
|
||||
}
|
||||
|
||||
func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
|
||||
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameID:%d, skuID:%d, userName:%s", ctx.GetTrackInfo(), nameID, skuID, userName)
|
||||
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameID:%d, skuID:%d", nameID, skuID), isAsync, userName,
|
||||
var (
|
||||
nameIDs []int
|
||||
skuIDs []int
|
||||
)
|
||||
if nameID != -1 {
|
||||
nameIDs = []int{nameID}
|
||||
}
|
||||
if skuID != -1 {
|
||||
skuIDs = []int{skuID}
|
||||
}
|
||||
return v.SyncSkus(ctx, db, nameIDs, skuIDs, isAsync, isContinueWhenError, userName)
|
||||
}
|
||||
|
||||
func (v *VendorSync) SyncSkus(ctx *jxcontext.Context, db *dao.DaoDB, nameIDs []int, skuIDs []int, isAsync, isContinueWhenError bool, userName string) (hint string, err error) {
|
||||
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, nameIDs:%v, skuIDs:%v, userName:%s", ctx.GetTrackInfo(), nameIDs, skuIDs, userName)
|
||||
return v.LoopMultiStoresVendors(ctx, db, fmt.Sprintf("同步商品信息, nameIDs:%v, skuIDs:%v", nameIDs, skuIDs), isAsync, userName,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (interface{}, error) {
|
||||
vendorID := batchItemList[0].(int)
|
||||
multiStoresHandler := v.GetMultiStoreHandler(vendorID)
|
||||
syncStatusFieldName := dao.GetSyncStatusStructField(model.VendorNames[multiStoresHandler.GetVendorID()])
|
||||
dbField := dao.ConvertDBFieldPrefix(model.VendorNames[multiStoresHandler.GetVendorID()])
|
||||
skuMap := make(map[int]bool)
|
||||
sql := fmt.Sprintf(`
|
||||
SELECT DISTINCT t2.*
|
||||
FROM sku t1
|
||||
@@ -256,14 +271,23 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
|
||||
WHERE t1.%s_sync_status <> 0
|
||||
`, dbField)
|
||||
sqlParams := []interface{}{}
|
||||
if nameID != -1 {
|
||||
sql += " AND t1.name_id = ?"
|
||||
sqlParams = append(sqlParams, nameID)
|
||||
if len(nameIDs) > 1 {
|
||||
sql += " AND t1.name_id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")"
|
||||
sqlParams = append(sqlParams, nameIDs)
|
||||
} else if len(nameIDs) == 1 {
|
||||
sql += " AND t1.name_id = ? "
|
||||
sqlParams = append(sqlParams, nameIDs[0])
|
||||
}
|
||||
if skuID != -1 {
|
||||
sql += " AND t1.id = ?"
|
||||
sqlParams = append(sqlParams, skuID)
|
||||
if len(skuIDs) > 0 {
|
||||
sql += " AND t1.id IN(" + dao.GenQuestionMarks(len(skuIDs)) + ")"
|
||||
sqlParams = append(sqlParams, skuIDs)
|
||||
|
||||
} else if len(skuIDs) == 1 {
|
||||
sql += " AND t1.id = ? "
|
||||
sqlParams = append(sqlParams, skuIDs[0])
|
||||
}
|
||||
for _, v := range skuIDs {
|
||||
skuMap[v] = true
|
||||
}
|
||||
sql += " ORDER BY t2.id"
|
||||
|
||||
@@ -284,7 +308,7 @@ func (v *VendorSync) SyncSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuI
|
||||
for _, sku := range skuList {
|
||||
syncStatus := refutil.GetObjFieldByName(sku, syncStatusFieldName).(int8)
|
||||
globals.SugarLogger.Debugf("SyncSku trackInfo:%s, skuID:%d, syncStatus:%d", ctx.GetTrackInfo(), sku.ID, syncStatus)
|
||||
if (skuID == -1 || skuID == sku.ID) && (syncStatus != 0) {
|
||||
if (len(skuIDs) == 0 || skuMap[sku.ID]) && (syncStatus != 0) {
|
||||
updateFields := []string{syncStatusFieldName}
|
||||
if syncStatus&model.SyncFlagDeletedMask != 0 { // 删除
|
||||
if syncStatus&model.SyncFlagNewMask == 0 {
|
||||
@@ -543,3 +567,26 @@ func isSyncError(err error) bool {
|
||||
_, ok := err.(*SyncError)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (v *VendorSync) SyncSkuNames(ctx *jxcontext.Context, nameIDs []int, isForce, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
db := dao.GetDB()
|
||||
if isForce {
|
||||
sql := `
|
||||
UPDATE sku t1
|
||||
SET t1.jd_sync_status = t1.jd_sync_status | ?
|
||||
WHERE t1.deleted_at = ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
model.SyncFlagModifiedMask,
|
||||
utils.DefaultTimeValue,
|
||||
}
|
||||
if len(nameIDs) > 0 {
|
||||
sql += " AND t1.name_id IN(" + dao.GenQuestionMarks(len(nameIDs)) + ")"
|
||||
sqlParams = append(sqlParams, nameIDs)
|
||||
}
|
||||
if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return v.SyncSkus(ctx, db, nameIDs, nil, isAsync, isContinueWhenError, ctx.GetUserName())
|
||||
}
|
||||
|
||||
@@ -46,7 +46,9 @@ func GetStoreUsers(ctx *jxcontext.Context, storeID int) (storeUserInfos []*dao.S
|
||||
}
|
||||
|
||||
func GetUserInfo(ctx *jxcontext.Context, mobile string) (storeUserInfo *dao.StoreUserInfo, err error) {
|
||||
return dao.GetUserStoreInfo(dao.GetDB(), "tel", mobile)
|
||||
storeUserInfo, err = dao.GetUserStoreInfo(dao.GetDB(), "tel", mobile)
|
||||
globals.SugarLogger.Debugf("GetUserInfo:%s, token:%s, mobile:%s, storeUserInfo:%s, err:%v", ctx.GetTrackInfo(), ctx.GetToken(), mobile, utils.Format4Output(storeUserInfo, true), err)
|
||||
return storeUserInfo, err
|
||||
}
|
||||
|
||||
func GetSelfInfo(ctx *jxcontext.Context) (storeUserInfo *dao.StoreUserInfo, err error) {
|
||||
@@ -58,7 +60,9 @@ func GetSelfInfo(ctx *jxcontext.Context) (storeUserInfo *dao.StoreUserInfo, err
|
||||
if fieldName == "" {
|
||||
return nil, auth.ErrIllegalLoginType
|
||||
}
|
||||
return dao.GetUserStoreInfo(dao.GetDB(), fieldName, loginInfo.GetAuthID())
|
||||
storeUserInfo, err = dao.GetUserStoreInfo(dao.GetDB(), fieldName, loginInfo.GetAuthID())
|
||||
globals.SugarLogger.Debugf("GetSelfInfo:%s, token:%s, storeUserInfo:%s, err:%v", ctx.GetTrackInfo(), ctx.GetToken(), utils.Format4Output(storeUserInfo, true), err)
|
||||
return storeUserInfo, err
|
||||
}
|
||||
|
||||
func UnbindMobile(ctx *jxcontext.Context, mobile string) (num int64, err error) {
|
||||
|
||||
@@ -73,14 +73,14 @@ func SendFilesToStores(ctx *jxcontext.Context, files []*multipart.FileHeader, ti
|
||||
db := dao.GetDB()
|
||||
billRec := &legacymodel.StoreBill{
|
||||
Date: time.Now(),
|
||||
Url: jxutils.ComposeQiniuResURL(ret.Key),
|
||||
Url: jxutils.ComposeQiniuResURL(strings.Replace(ret.Key, "http://", "https://", -1)),
|
||||
StoreId: storeID,
|
||||
BillName: fileHeader.Filename,
|
||||
ShopName: shopName,
|
||||
BillTitle: title,
|
||||
}
|
||||
if err = dao.CreateEntity(db, billRec); err == nil {
|
||||
err = weixinmsg.NotifySaleBill(storeID, title, shopName, "http://www.jxc4.com/billshow/?path="+billRec.Url)
|
||||
err = weixinmsg.NotifySaleBill(storeID, title, shopName, fmt.Sprintf("%s/billshow/?path=%s", globals.BackstageHost, billRec.Url))
|
||||
if err != nil {
|
||||
globals.SugarLogger.Infof("SendFilesToStores NotifySaleBill file:%s error:%v", fileHeader.Filename, err)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/autonavi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
@@ -153,11 +155,15 @@ func InitSkuName(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError b
|
||||
response, err := http.Get(skuName.Img)
|
||||
if err == nil {
|
||||
defer response.Body.Close()
|
||||
data, err2 := ioutil.ReadAll(response.Body)
|
||||
if err = err2; err == nil {
|
||||
skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data))
|
||||
db := dao.GetDB()
|
||||
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode")
|
||||
if response.StatusCode == http.StatusOK {
|
||||
data, err2 := ioutil.ReadAll(response.Body)
|
||||
if err = err2; err == nil {
|
||||
skuName.ImgHashCode = fmt.Sprintf("%X", md5.Sum(data))
|
||||
db := dao.GetDB()
|
||||
_, err = dao.UpdateEntity(db, skuName, "ImgHashCode")
|
||||
}
|
||||
} else {
|
||||
err = platformapi.ErrHTTPCodeIsNot200
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,7 +429,7 @@ func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, i
|
||||
err = nil
|
||||
continue
|
||||
}
|
||||
qiniuImgURL := "http://image.jxc4.com/" + key + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800"
|
||||
qiniuImgURL := jxutils.ComposeQiniuResURL(key) + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800"
|
||||
for _, sku := range skuNameExt.Skus {
|
||||
jdCatID := 22410 // 其他国产水果
|
||||
if cat.Name == "进口水果" {
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
"github.com/astaxie/beego/orm"
|
||||
)
|
||||
|
||||
var innerDataPat *regexp.Regexp
|
||||
@@ -605,8 +604,7 @@ func CreateOrderFromOriginal(ctx *jxcontext.Context, isAsync, isContinueWhenErro
|
||||
WHERE t2.id IS NULL
|
||||
LIMIT ?;
|
||||
`
|
||||
rawDB := orm.NewOrm()
|
||||
db := dao.WrapDB(rawDB)
|
||||
db := dao.GetDB()
|
||||
var orderList []*GoodsOrderOriginalEx
|
||||
if err = dao.GetRows(db, &orderList, sql, sqlBatchCount); err != nil {
|
||||
return nil, err
|
||||
|
||||
262
business/jxutils/eventhub/eventhub.go
Normal file
262
business/jxutils/eventhub/eventhub.go
Normal file
@@ -0,0 +1,262 @@
|
||||
package eventhub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdRegisterConsumer = 1
|
||||
cmdUnregisterConsumer = 2
|
||||
cmdNewEvent = 3
|
||||
)
|
||||
|
||||
const (
|
||||
maxGetOrderTimeDuration = 24 * time.Hour
|
||||
minPollingDuration = 1 * time.Minute
|
||||
defPollingDuration = 5 * time.Minute
|
||||
maxPollingDuration = 10 * time.Minute
|
||||
)
|
||||
|
||||
const (
|
||||
cmdChanLen = 100
|
||||
)
|
||||
|
||||
const (
|
||||
allEventType = ""
|
||||
)
|
||||
|
||||
type IEventProducer interface {
|
||||
IsCriteriaMatch(eventInfo *EventInfo, criteria interface{}) bool
|
||||
}
|
||||
|
||||
type EventInfo struct {
|
||||
Type string
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
type tRegisterInfo struct {
|
||||
notifyChan chan *EventInfo
|
||||
eventCategory string
|
||||
eventTypeList []string
|
||||
criteria interface{}
|
||||
}
|
||||
|
||||
type tUnregisterInfo struct {
|
||||
notifyChan chan *EventInfo
|
||||
closeChan chan struct{}
|
||||
}
|
||||
|
||||
type tCmd struct {
|
||||
cmdType int
|
||||
data interface{}
|
||||
// regisgerInfo *RegisterInfo // CmdRegisterConsumer
|
||||
// unregisterInfo *UnregisterInfo // CmdUnregisterConsumer
|
||||
// eventInfo *EventInfo // CmdNewEvent
|
||||
}
|
||||
|
||||
type EventHub struct {
|
||||
cmdChan chan *tCmd
|
||||
|
||||
chanMap map[chan *EventInfo]*tRegisterInfo
|
||||
typeChanMap map[string]map[chan *EventInfo]bool
|
||||
|
||||
eventCatMap map[string]IEventProducer
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func eventRoutine(eventHub *EventHub) {
|
||||
eventHub.eventRoutine()
|
||||
}
|
||||
|
||||
func New() (eventHub *EventHub) {
|
||||
eventHub = &EventHub{
|
||||
cmdChan: make(chan *tCmd, cmdChanLen),
|
||||
chanMap: make(map[chan *EventInfo]*tRegisterInfo),
|
||||
typeChanMap: make(map[string]map[chan *EventInfo]bool),
|
||||
eventCatMap: make(map[string]IEventProducer),
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
eventRoutine(eventHub)
|
||||
})
|
||||
return eventHub
|
||||
}
|
||||
|
||||
func (e *EventHub) eventRoutine() {
|
||||
for {
|
||||
cmd, ok := <-e.cmdChan
|
||||
if ok {
|
||||
switch cmd.cmdType {
|
||||
case cmdRegisterConsumer:
|
||||
regisgerInfo := cmd.data.(*tRegisterInfo)
|
||||
e.chanMap[regisgerInfo.notifyChan] = regisgerInfo
|
||||
for _, eventType := range regisgerInfo.eventTypeList {
|
||||
if e.typeChanMap[eventType] == nil {
|
||||
e.typeChanMap[eventType] = make(map[chan *EventInfo]bool)
|
||||
}
|
||||
e.typeChanMap[eventType][regisgerInfo.notifyChan] = true
|
||||
}
|
||||
case cmdUnregisterConsumer:
|
||||
unregisgerInfo := cmd.data.(*tUnregisterInfo)
|
||||
e.removeChan(unregisgerInfo.notifyChan)
|
||||
close(unregisgerInfo.closeChan)
|
||||
case cmdNewEvent:
|
||||
eventInfo := cmd.data.(*EventInfo)
|
||||
typeList := []string{allEventType, eventInfo.Type}
|
||||
tmpChanMap := make(map[chan *EventInfo]*tRegisterInfo)
|
||||
for _, eventType := range typeList {
|
||||
for notifyChan := range e.typeChanMap[eventType] {
|
||||
tmpChanMap[notifyChan] = e.chanMap[notifyChan]
|
||||
}
|
||||
}
|
||||
for notifyChan, registerInfo := range tmpChanMap {
|
||||
eventCategory, _ := splitEventType(eventInfo.Type)
|
||||
if eventProducer := e.getEventProducer(eventCategory); eventProducer != nil {
|
||||
if eventProducer.IsCriteriaMatch(eventInfo, registerInfo.criteria) {
|
||||
notifyChan <- eventInfo
|
||||
e.removeChan(notifyChan)
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("eventRoutine, eventCategory:%s producer is nil", eventCategory)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EventHub) removeChan(notifyChann chan *EventInfo) {
|
||||
typeList := e.chanMap[notifyChann].eventTypeList
|
||||
for _, eventType := range typeList {
|
||||
delete(e.typeChanMap[eventType], notifyChann)
|
||||
}
|
||||
delete(e.chanMap, notifyChann)
|
||||
}
|
||||
|
||||
func (e *EventHub) Close() {
|
||||
close(e.cmdChan)
|
||||
}
|
||||
|
||||
func (e *EventHub) RegisterProducer(eventCategory string, producer IEventProducer) (err error) {
|
||||
e.locker.Lock()
|
||||
if e.eventCatMap[eventCategory] != nil {
|
||||
err = fmt.Errorf("eventCategory:%s已经被注册了", eventCategory)
|
||||
} else {
|
||||
e.eventCatMap[eventCategory] = producer
|
||||
}
|
||||
e.locker.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// 正常不应该是动态的经常调用注册与反注册Producer,只是退出进程前礼貌的调用
|
||||
func (e *EventHub) UnregisterProducer(eventCategory string) (err error) {
|
||||
e.locker.Lock()
|
||||
if e.eventCatMap[eventCategory] == nil {
|
||||
err = fmt.Errorf("eventCategory:%s没有注册", eventCategory)
|
||||
} else {
|
||||
delete(e.eventCatMap, eventCategory)
|
||||
}
|
||||
e.locker.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *EventHub) registerConsumer(eventCategory string, eventTypeList []string, criteria interface{}) (notifyChan chan *EventInfo) {
|
||||
if len(eventTypeList) == 0 {
|
||||
eventTypeList = []string{allEventType}
|
||||
}
|
||||
realEventTypeList := make([]string, len(eventTypeList))
|
||||
for index, eventType := range eventTypeList {
|
||||
realEventTypeList[index] = composeEventType(eventCategory, eventType)
|
||||
}
|
||||
info := &tRegisterInfo{
|
||||
eventCategory: eventCategory,
|
||||
eventTypeList: eventTypeList,
|
||||
notifyChan: make(chan *EventInfo, 1),
|
||||
criteria: criteria,
|
||||
}
|
||||
e.cmdChan <- &tCmd{
|
||||
cmdType: cmdRegisterConsumer,
|
||||
data: info,
|
||||
}
|
||||
return info.notifyChan
|
||||
}
|
||||
|
||||
func (e *EventHub) unregisterConsumer(notifyChan chan *EventInfo) {
|
||||
info := &tUnregisterInfo{
|
||||
notifyChan: notifyChan,
|
||||
closeChan: make(chan struct{}),
|
||||
}
|
||||
e.cmdChan <- &tCmd{
|
||||
cmdType: cmdUnregisterConsumer,
|
||||
data: info,
|
||||
}
|
||||
<-info.closeChan
|
||||
}
|
||||
|
||||
func (e *EventHub) PostNewEvent(eventCategory string, event *EventInfo) {
|
||||
utils.CallFuncAsync(func() {
|
||||
newEvent := *event
|
||||
newEvent.Type = composeEventType(eventCategory, event.Type)
|
||||
e.cmdChan <- &tCmd{
|
||||
cmdType: cmdNewEvent,
|
||||
data: &newEvent,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *EventHub) GetEvent(eventCategory string, eventTypeList []string, criteria interface{}, waitTime time.Duration) (event *EventInfo, err error) {
|
||||
notifyChan := e.registerConsumer(eventCategory, eventTypeList, criteria)
|
||||
pollingDuration := defPollingDuration
|
||||
if waitTime != 0 {
|
||||
pollingDuration = waitTime
|
||||
if globals.IsProductEnv() {
|
||||
if pollingDuration > maxPollingDuration {
|
||||
pollingDuration = maxPollingDuration
|
||||
} else if pollingDuration < minPollingDuration {
|
||||
pollingDuration = minPollingDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("GetEvent pollingDuration:%d seconds", pollingDuration/time.Second)
|
||||
timer := time.NewTimer(pollingDuration)
|
||||
select {
|
||||
case tmpEvent, ok := <-notifyChan:
|
||||
timer.Stop()
|
||||
if ok {
|
||||
event = tmpEvent
|
||||
}
|
||||
case <-timer.C:
|
||||
e.unregisterConsumer(notifyChan)
|
||||
}
|
||||
close(notifyChan)
|
||||
return event, err
|
||||
}
|
||||
|
||||
func (e *EventHub) getEventProducer(eventCategory string) IEventProducer {
|
||||
e.locker.RLock()
|
||||
defer e.locker.RUnlock()
|
||||
return e.eventCatMap[eventCategory]
|
||||
}
|
||||
|
||||
func composeEventType(eventCategory, eventType string) string {
|
||||
return eventCategory + "/" + eventType
|
||||
}
|
||||
|
||||
func splitEventType(eventType string) (eventCategory, pureEventType string) {
|
||||
typeList := strings.Split(eventType, "/")
|
||||
eventCategory = typeList[0]
|
||||
if len(typeList) > 1 {
|
||||
pureEventType = typeList[1]
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("splitEventType eventType:%s", eventType)
|
||||
}
|
||||
return eventCategory, pureEventType
|
||||
}
|
||||
76
business/jxutils/eventhub/syseventhub/syseventhub.go
Normal file
76
business/jxutils/eventhub/syseventhub/syseventhub.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package syseventhub
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/eventhub"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
EventCategory = "sys"
|
||||
|
||||
EventTypeWXToken = "wxtoken"
|
||||
)
|
||||
|
||||
type Hub struct {
|
||||
eventHub *eventhub.EventHub
|
||||
}
|
||||
|
||||
type Criteria struct {
|
||||
}
|
||||
|
||||
type WXTokenInfo struct {
|
||||
IsNew bool `json:"isNew"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
var (
|
||||
SysEventHub *Hub
|
||||
)
|
||||
|
||||
func init() {
|
||||
SysEventHub = New()
|
||||
}
|
||||
|
||||
func New() (hub *Hub) {
|
||||
hub = &Hub{
|
||||
eventHub: eventhub.New(),
|
||||
}
|
||||
hub.eventHub.RegisterProducer(EventCategory, hub)
|
||||
return hub
|
||||
}
|
||||
|
||||
func (h *Hub) IsCriteriaMatch(eventInfo *eventhub.EventInfo, criteria interface{}) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *Hub) OnNewWXToken(token string) {
|
||||
h.eventHub.PostNewEvent(EventCategory, &eventhub.EventInfo{
|
||||
Type: EventTypeWXToken,
|
||||
Data: token,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Hub) GetWXToken(oldToken string, waitTime time.Duration) (tokenInfo *WXTokenInfo) {
|
||||
token := api.WeixinAPI.CBGetToken()
|
||||
if token != oldToken {
|
||||
tokenInfo = &WXTokenInfo{
|
||||
IsNew: false,
|
||||
Token: token,
|
||||
}
|
||||
} else {
|
||||
eventInfo, err := h.eventHub.GetEvent(EventCategory, []string{EventTypeWXToken}, nil, waitTime)
|
||||
if err == nil && eventInfo != nil {
|
||||
tokenInfo = &WXTokenInfo{
|
||||
IsNew: true,
|
||||
Token: eventInfo.Data.(string),
|
||||
}
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("GetWXToken tokenInfo:%s", utils.Format4Output(tokenInfo, true))
|
||||
return tokenInfo
|
||||
}
|
||||
@@ -270,9 +270,7 @@ func (s SkuList) Swap(i, j int) {
|
||||
func DownloadFileByURL(fileURL string) (bodyData []byte, fileMD5 string, err error) {
|
||||
response, err := http.Get(fileURL)
|
||||
if err == nil {
|
||||
defer func() {
|
||||
response.Body.Close()
|
||||
}()
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode == http.StatusOK {
|
||||
if bodyData, err = ioutil.ReadAll(response.Body); err == nil {
|
||||
fileMD5 = fmt.Sprintf("%X", md5.Sum(bodyData))
|
||||
|
||||
@@ -54,10 +54,12 @@ func PrintOrderByOrder(ctx *jxcontext.Context, order *model.GoodsOrder) (printRe
|
||||
return &partner.PrinterStatus{
|
||||
PrintResult: partner.PrintResultNoPrinter,
|
||||
}, nil
|
||||
} else {
|
||||
if globals.EnableStoreWrite {
|
||||
printResult, err = handler.PrintOrder(ctx, store, order)
|
||||
}
|
||||
}
|
||||
if globals.EnableStoreWrite {
|
||||
printResult, err = handler.PrintOrder(ctx, store, order)
|
||||
}
|
||||
if err == nil {
|
||||
dao.SetOrderPrintFlag(db, ctx.GetUserName(), order.VendorOrderID, order.VendorID, true)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/eventhub/syseventhub"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/model/legacymodel"
|
||||
@@ -22,8 +28,11 @@ const (
|
||||
dingdingTokenExpires = 7200 * time.Second
|
||||
elmTokenExpires = 20 * 24 * 3600 * time.Second
|
||||
weimobTokenExpires = 7200 * time.Second
|
||||
maxRefreshGap = 5 * 60 * time.Second
|
||||
yilianyunTokenExpires = 30 * 24 * 3600 * time.Second
|
||||
|
||||
maxRefreshGap = 5 * 60 * time.Second
|
||||
errRefreshGap = 10 * time.Second
|
||||
minRefreshGap = 1 * time.Second
|
||||
)
|
||||
|
||||
type ElmTokenForCompatible struct {
|
||||
@@ -36,13 +45,21 @@ type ElmTokenForCompatible struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
type CallResult struct {
|
||||
Code string `json:"code"`
|
||||
Desc string `json:"desc"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
func RefreshConfig(configKey string, expiresTime time.Duration, configGetter func() (string, string), configSetter func(value string)) error {
|
||||
sleepGap := expiresTime / 10
|
||||
needRefreshGap := expiresTime * 8 / 10
|
||||
sleepGap := expiresTime / 10
|
||||
if sleepGap > maxRefreshGap {
|
||||
sleepGap = maxRefreshGap
|
||||
}
|
||||
refreshFunc := func() (string, error) {
|
||||
|
||||
refreshFunc := func() (sleepDuration time.Duration) {
|
||||
sleepDuration = sleepGap
|
||||
curConfig := &legacymodel.Config{
|
||||
Thirdparty: configKey,
|
||||
}
|
||||
@@ -52,7 +69,7 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
|
||||
if err := db.Read(curConfig, "Thirdparty"); err != nil {
|
||||
if err != orm.ErrNoRows {
|
||||
globals.SugarLogger.Errorf("db error:%v, curConfig:%v", err, curConfig)
|
||||
return "", err
|
||||
return errRefreshGap
|
||||
}
|
||||
handleType = 2
|
||||
} else {
|
||||
@@ -65,15 +82,17 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
|
||||
if curConfig.Token, curConfig.Date = configGetter(); curConfig.Token == "" {
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
globals.SugarLogger.Errorf("RefreshConfig %s get empty token", configKey)
|
||||
sleepDuration = errRefreshGap
|
||||
} else {
|
||||
globals.SugarLogger.Infof("RefreshConfig %s get empty token", configKey)
|
||||
}
|
||||
return "", nil
|
||||
return sleepDuration
|
||||
}
|
||||
globals.SugarLogger.Debugf("RefreshConfig refresh %s, value:%s", configKey, curConfig.Token)
|
||||
|
||||
configSetter(curConfig.Token)
|
||||
if curConfig.Date == "" {
|
||||
curConfig.Date = utils.GetCurTimeStr()
|
||||
} else {
|
||||
sleepDuration = expiresTime - time.Now().Sub(utils.Str2Time(curConfig.Date))
|
||||
}
|
||||
var num int64
|
||||
var err error
|
||||
@@ -85,88 +104,103 @@ func RefreshConfig(configKey string, expiresTime time.Duration, configGetter fun
|
||||
}
|
||||
if err != nil || num == 0 {
|
||||
globals.SugarLogger.Errorf("db error:%v, num:%d, curConfig:%v", err, num, curConfig)
|
||||
return "", err
|
||||
}
|
||||
configSetter(curConfig.Token)
|
||||
}
|
||||
return curConfig.Token, nil
|
||||
if sleepDuration < minRefreshGap {
|
||||
sleepDuration = minRefreshGap
|
||||
} else if sleepDuration > maxRefreshGap {
|
||||
sleepDuration = maxRefreshGap
|
||||
}
|
||||
return sleepDuration
|
||||
}
|
||||
token, err := refreshFunc() // 这样写的目的是强制第一次调用时要刷新一次
|
||||
if err == nil {
|
||||
if token != "" {
|
||||
configSetter(token)
|
||||
utils.CallFuncAsync(func() {
|
||||
for {
|
||||
sleepGap := refreshFunc()
|
||||
time.Sleep(sleepGap)
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
for {
|
||||
time.Sleep(sleepGap)
|
||||
refreshFunc()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func RefreshWeixinToken() (err error) {
|
||||
if api.WeixinAPI != nil {
|
||||
err = RefreshConfig("wechat", weixinTokenExpires, func() (token string, expireTimeStr string) {
|
||||
globals.SugarLogger.Debugf("RefreshWeixinToken RunMode:%s", beego.BConfig.RunMode)
|
||||
if globals.IsProductEnv() {
|
||||
if globals.IsMainProductEnv() {
|
||||
if tokenInfo, err := api.WeixinAPI.CBRetrieveToken(); err == nil {
|
||||
globals.SugarLogger.Debugf("RefreshWeixinToken tokenInfo:%s", utils.Format4Output(tokenInfo, true))
|
||||
token = tokenInfo.AccessToken
|
||||
} else {
|
||||
globals.SugarLogger.Errorf("RefreshWeixinToken RefreshToken failed with error:%v", err)
|
||||
}
|
||||
} else {
|
||||
if tokenInfo := getWXTokenFromRemote(api.WeixinAPI.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.OnNewWXToken(value)
|
||||
api.WeixinAPI.CBSetToken(value)
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func RefreshElmToken() (err error) {
|
||||
if api.ElmAPI != nil {
|
||||
err = RefreshConfig("eleme", elmTokenExpires, func() (string, string) {
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
if tokenInfo, err := api.ElmAPI.RefreshTokenIndividual(); err == nil {
|
||||
tokenInfo2 := &ElmTokenForCompatible{
|
||||
Error: "",
|
||||
ErrorDescription: "",
|
||||
AccessToken: tokenInfo.AccessToken,
|
||||
TokenType: tokenInfo.TokenType,
|
||||
Expires: tokenInfo.ExpiresIn,
|
||||
RefreshToken: "",
|
||||
Success: true,
|
||||
}
|
||||
return string(utils.MustMarshal(tokenInfo2)), ""
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}, func(value string) {
|
||||
var tokenInfo ElmTokenForCompatible
|
||||
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
|
||||
if err == nil {
|
||||
api.ElmAPI.SetToken(tokenInfo.AccessToken)
|
||||
}
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func RefreshWeixinToken() error {
|
||||
return RefreshConfig("wechat", weixinTokenExpires, func() (string, string) {
|
||||
globals.SugarLogger.Debugf("RefreshWeixinToken RunMode:%s", beego.BConfig.RunMode)
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
if tokenInfo, err := api.WeixinAPI.CBRetrieveToken(); err == nil {
|
||||
globals.SugarLogger.Debugf("RefreshWeixinToken tokenInfo:%s", utils.Format4Output(tokenInfo, true))
|
||||
return tokenInfo.AccessToken, ""
|
||||
} else {
|
||||
globals.SugarLogger.Errorf("RefreshWeixinToken RefreshToken failed with error:%v", err)
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}, func(value string) {
|
||||
api.WeixinAPI.CBSetToken(value)
|
||||
})
|
||||
}
|
||||
|
||||
func RefreshElmToken() error {
|
||||
return RefreshConfig("eleme", elmTokenExpires, func() (string, string) {
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
if tokenInfo, err := api.ElmAPI.RefreshTokenIndividual(); err == nil {
|
||||
tokenInfo2 := &ElmTokenForCompatible{
|
||||
Error: "",
|
||||
ErrorDescription: "",
|
||||
AccessToken: tokenInfo.AccessToken,
|
||||
TokenType: tokenInfo.TokenType,
|
||||
Expires: tokenInfo.ExpiresIn,
|
||||
RefreshToken: "",
|
||||
Success: true,
|
||||
func RefreshWeimobToken() (err error) {
|
||||
if api.WeimobAPI != nil {
|
||||
err = RefreshConfig("weimob", weimobTokenExpires, func() (string, string) {
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
if tokenInfo, err := api.WeimobAPI.RefreshTokenByRefreshToken(); err == nil {
|
||||
return string(utils.MustMarshal(tokenInfo)), utils.Time2Str(time.Now().Add((time.Duration(tokenInfo.ExpiresIn) - weimobTokenExpires/time.Second) * time.Second))
|
||||
}
|
||||
return string(utils.MustMarshal(tokenInfo2)), ""
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}, func(value string) {
|
||||
var tokenInfo ElmTokenForCompatible
|
||||
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
|
||||
if err == nil {
|
||||
api.ElmAPI.SetToken(tokenInfo.AccessToken)
|
||||
}
|
||||
})
|
||||
return "", ""
|
||||
}, func(value string) {
|
||||
var tokenInfo *weimobapi.TokenInfo
|
||||
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
|
||||
if err == nil {
|
||||
api.WeimobAPI.SetToken(tokenInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func RefreshWeimobToken() error {
|
||||
return RefreshConfig("weimob", weimobTokenExpires, func() (string, string) {
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
if tokenInfo, err := api.WeimobAPI.RefreshTokenByRefreshToken(); err == nil {
|
||||
return string(utils.MustMarshal(tokenInfo)), utils.Time2Str(time.Now().Add((time.Duration(tokenInfo.ExpiresIn) - weimobTokenExpires/time.Second) * time.Second))
|
||||
}
|
||||
}
|
||||
return "", ""
|
||||
}, func(value string) {
|
||||
var tokenInfo *weimobapi.TokenInfo
|
||||
err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo)
|
||||
if err == nil {
|
||||
api.WeimobAPI.SetToken(tokenInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func RefreshDingDingToken() error {
|
||||
func RefreshDingDingToken() (err error) {
|
||||
api.DingDingAPI.RetrieveToken()
|
||||
return RefreshConfig("dingding", dingdingTokenExpires, func() (string, string) {
|
||||
globals.SugarLogger.Debugf("RefreshDingDingToken RunMode:%s", beego.BConfig.RunMode)
|
||||
@@ -195,7 +229,7 @@ func SaveWeimobToken(token *weimobapi.TokenInfo) (err error) {
|
||||
return dao.CreateOrUpdate(db, config)
|
||||
}
|
||||
|
||||
func RefreshYilianyunToken() error {
|
||||
func RefreshYilianyunToken() (err error) {
|
||||
return RefreshConfig("yilianyun", yilianyunTokenExpires, func() (string, string) {
|
||||
globals.SugarLogger.Debugf("RefreshYilianyunToken RunMode:%s", beego.BConfig.RunMode)
|
||||
if beego.BConfig.RunMode == "prod" {
|
||||
@@ -214,3 +248,46 @@ func RefreshYilianyunToken() error {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getWXTokenFromRemote(oldToken string) (tokenInfo *syseventhub.WXTokenInfo) {
|
||||
if IsGetWXTokenFromRemote() {
|
||||
for {
|
||||
waitSecond := 5 * 60
|
||||
globals.SugarLogger.Debugf("getWXTokenFromProd1")
|
||||
response, err := http.Get(fmt.Sprintf("%s?accessKey=%s&oldToken=%s&waitSecond=%d", globals.GetWeixinTokenURL, globals.GetWeixinTokenKey, oldToken, waitSecond))
|
||||
globals.SugarLogger.Debugf("getWXTokenFromProd2 error:%v", err)
|
||||
if err == nil {
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode == http.StatusOK {
|
||||
data, err2 := ioutil.ReadAll(response.Body)
|
||||
if err = err2; err == nil {
|
||||
var result CallResult
|
||||
if err = utils.UnmarshalUseNumber(data, &result); err == nil {
|
||||
if result.Code == "0" {
|
||||
if result.Data != "" {
|
||||
if err = utils.UnmarshalUseNumber([]byte(result.Data), &tokenInfo); err == nil && tokenInfo != nil {
|
||||
globals.SugarLogger.Debugf("getWXTokenFromProd:%s", utils.Format4Output(tokenInfo, false))
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("return code is:%s", result.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = platformapi.ErrHTTPCodeIsNot200
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Infof("getWXTokenFromProd failed with error:%v", err)
|
||||
if err != nil {
|
||||
time.Sleep(errRefreshGap)
|
||||
}
|
||||
}
|
||||
}
|
||||
return tokenInfo
|
||||
}
|
||||
|
||||
func IsGetWXTokenFromRemote() bool {
|
||||
return !globals.IsMainProductEnv() && globals.GetWeixinTokenKey != "" && globals.GetWeixinTokenURL != ""
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
MaxTaskNameLen = 30
|
||||
MaxTaskNameLen = 50
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -15,12 +15,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// WX_TO_ORDER_PAGE_URL = "http://www.jxc4.com/jx/h5/#/?jxStoreId="
|
||||
// WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://www.jxc4.com/jx/h5/#/assess-list?jxStoreId=" //展示差评详情的页面
|
||||
WX_TO_ORDER_PAGE_URL = "http://wx.jxc4.com/#/?jxStoreId="
|
||||
WX_TO_STORE_SKU_PAGE_URL = "http://wx.jxc4.com/#/shop?jxStoreId="
|
||||
WX_TO_SHOW_COMMENTS_DETAIL_URL = "http://wx.jxc4.com/#/assess-list?jxStoreId=" //展示差评详情的页面
|
||||
WX_TO_SHOW_MSG = "http://wx.jxc4.com/#/message-detail?msgID=%d&msgStatusID=%d"
|
||||
WX_TO_ORDER_PAGE_URL = "/#/?jxStoreId="
|
||||
WX_TO_STORE_SKU_PAGE_URL = "/#/shop?jxStoreId="
|
||||
WX_TO_SHOW_COMMENTS_DETAIL_URL = "/#/assess-list?jxStoreId=" //展示差评详情的页面
|
||||
WX_TO_SHOW_MSG = "/#/message-detail?msgID=%d&msgStatusID=%d"
|
||||
|
||||
WX_MINI_TO_ORDER_PAGE_URL = "pages/order-manager/main"
|
||||
WX_MINI_TO_STORE_SKU_PAGE_URL = "pages/goods-manager/main"
|
||||
@@ -205,7 +203,7 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) {
|
||||
},
|
||||
}
|
||||
storeID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
|
||||
return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
|
||||
}
|
||||
|
||||
func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlreadyCandidate bool) error {
|
||||
@@ -340,7 +338,7 @@ func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments) (err error) {
|
||||
},
|
||||
}
|
||||
storeID := int(utils.Str2Int64(comment.Jxstoreid))
|
||||
return SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data)
|
||||
return SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data)
|
||||
}
|
||||
|
||||
func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) {
|
||||
@@ -379,7 +377,7 @@ 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 := fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID)
|
||||
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
|
||||
@@ -426,7 +424,7 @@ func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName st
|
||||
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
|
||||
fileURL := fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID)
|
||||
fileURL := globals.WxBackstageHost + fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID)
|
||||
data := map[string]interface{}{
|
||||
"first": map[string]interface{}{
|
||||
"value": content,
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
)
|
||||
|
||||
// VendorIDJD, VendorIDMTWM与VendorIDELM的定义和老系统是兼容的
|
||||
const (
|
||||
VendorIDUnknown = -1
|
||||
@@ -42,6 +48,7 @@ var (
|
||||
VendorIDYiLianYun: "Yilianyun",
|
||||
VendorIDZhongWu: "ZhongWu",
|
||||
}
|
||||
|
||||
VendorChineseNames = map[int]string{
|
||||
VendorIDJD: "京东到家",
|
||||
VendorIDMTWM: "美团外卖",
|
||||
@@ -58,6 +65,21 @@ var (
|
||||
VendorIDZhongWu: "中午云",
|
||||
}
|
||||
|
||||
PurchaseVendorInfo = map[int]map[string]interface{}{
|
||||
VendorIDJD: map[string]interface{}{
|
||||
"chineseName": VendorChineseNames[VendorIDJD],
|
||||
"userApplyCancelWaitMinute": jdapi.UserApplyCancelWaitMinute,
|
||||
},
|
||||
VendorIDMTWM: map[string]interface{}{
|
||||
"chineseName": VendorChineseNames[VendorIDMTWM],
|
||||
"userApplyCancelWaitMinute": mtwmapi.UserApplyCancelWaitMinute,
|
||||
},
|
||||
VendorIDEBAI: map[string]interface{}{
|
||||
"chineseName": VendorChineseNames[VendorIDEBAI],
|
||||
"userApplyCancelWaitMinute": ebaiapi.UserApplyCancelWaitMinute,
|
||||
},
|
||||
}
|
||||
|
||||
ShopChineseNames = map[int]string{
|
||||
VendorIDJD: "京西菜市",
|
||||
VendorIDMTWM: "美好菜市",
|
||||
@@ -215,7 +237,7 @@ const (
|
||||
WaybillStatusEndBegin = 100 // 以下的状态就是结束状态
|
||||
WaybillStatusDelivered = 105 // todo 这个应该改为110,与订单对应
|
||||
WaybillStatusCanceled = 115
|
||||
WaybillStatusFailed = 120 // todo 这个应该要去掉
|
||||
WaybillStatusFailed = 120 // 这个状态存在的意义是区分于WaybillStatusCanceled,比如达达平台在这种状态下再次创建运单的方式不一样
|
||||
WaybillStatusNeverSend = 125 // 这个状态指的是平台方不愿意配送,门店自己想办法。与WaybillStatusAcceptCanceled不一样,WaybillStatusAcceptCanceled可能之后还会尝试配送
|
||||
)
|
||||
|
||||
@@ -240,8 +262,20 @@ const (
|
||||
OrderDeliveryFlagMaskScheduleDisabled = 1 // 禁止三方配送调度
|
||||
OrderDeliveryFlagMaskPurcahseDisabled = 2 // 购物平台已不配送(一般为门店配送类型本身为自配送,或已经转自配送)
|
||||
)
|
||||
|
||||
const (
|
||||
OrderFlagMaskPrinted = 1 // 已经打印
|
||||
|
||||
OrderFlagMaskUserApplyCancel = 6
|
||||
OrderFlagAgreeUserApplyCancel = 2
|
||||
OrderFlagRefuseUserApplyCancel = 6
|
||||
|
||||
OrderFlagMaskFailedGetGoods = 24
|
||||
OrderFlagAgreeFailedGetGoods = 8
|
||||
OrderFlagRefuseFailedGetGoods = 24
|
||||
|
||||
OrderFlagMaskFailedDeliver = 32
|
||||
OrderFlagMaskCallPMCourier = 64 // 取货失败后召唤平台配送
|
||||
)
|
||||
|
||||
func IsPurchaseVendorExist(vendorID int) bool {
|
||||
|
||||
@@ -59,10 +59,6 @@ func GetDB() *DaoDB {
|
||||
return &DaoDB{Db: orm.NewOrm()}
|
||||
}
|
||||
|
||||
func WrapDB(ormDb orm.Ormer) *DaoDB {
|
||||
return &DaoDB{Db: ormDb}
|
||||
}
|
||||
|
||||
func Begin(db *DaoDB) (err error) {
|
||||
if db.transactionLevel == 0 {
|
||||
err = db.Db.Begin()
|
||||
|
||||
@@ -25,27 +25,29 @@ func GetStoreOrderAfterTime(db *DaoDB, storeID int, orderTime time.Time, lastOrd
|
||||
return orderList, GetRows(db, &orderList, sql, sqlParams...)
|
||||
}
|
||||
|
||||
func SetOrderPrintFlag(db *DaoDB, vendorOrderID string, vendorID int, isPrinted bool) (err error) {
|
||||
var (
|
||||
sql string
|
||||
sqlParams []interface{}
|
||||
)
|
||||
func SetOrderPrintFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, isPrinted bool) (err error) {
|
||||
if isPrinted {
|
||||
sql = `
|
||||
UPDATE goods_order
|
||||
SET flag = flag | ?
|
||||
WHERE vendor_order_id = ? AND vendor_id = ?
|
||||
`
|
||||
sqlParams = append(sqlParams, model.OrderFlagMaskPrinted)
|
||||
err = SetOrderFlag(db, userName, vendorOrderID, vendorID, model.OrderFlagMaskPrinted)
|
||||
} else {
|
||||
sql = `
|
||||
UPDATE goods_order
|
||||
SET flag = flag & ?
|
||||
WHERE vendor_order_id = ? AND vendor_id = ?
|
||||
`
|
||||
sqlParams = append(sqlParams, ^model.OrderFlagMaskPrinted)
|
||||
err = SetOrderFlag(db, userName, vendorOrderID, vendorID, ^int8(model.OrderFlagMaskPrinted))
|
||||
}
|
||||
sqlParams = append(sqlParams, vendorOrderID, vendorID)
|
||||
_, err = ExecuteSQL(db, sql, sqlParams...)
|
||||
return err
|
||||
}
|
||||
|
||||
func SetOrderFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, flag int8) (err error) {
|
||||
_, err = ExecuteSQL(db, `
|
||||
UPDATE goods_order
|
||||
SET flag = flag | ?
|
||||
WHERE vendor_order_id = ? AND vendor_id = ?
|
||||
`, flag, vendorOrderID, vendorID)
|
||||
return err
|
||||
}
|
||||
|
||||
func ClearOrderFlag(db *DaoDB, userName string, vendorOrderID string, vendorID int, flag int8) (err error) {
|
||||
_, err = ExecuteSQL(db, `
|
||||
UPDATE goods_order
|
||||
SET flag = flag & ?
|
||||
WHERE vendor_order_id = ? AND vendor_id = ?
|
||||
`, flag, vendorOrderID, vendorID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ type GoodsOrder struct {
|
||||
Status int `json:"status"` // 参见OrderStatus*相关的常量定义
|
||||
VendorStatus string `orm:"size(255)" json:"-"`
|
||||
LockStatus int `json:"lockStatus"`
|
||||
OrderSeq int `json:"orderSeq"` // 门店订单序号
|
||||
LockStatusTime time.Time `orm:"type(datetime);null" json:"-"` // 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"` // 预期送达时间
|
||||
|
||||
@@ -67,7 +67,7 @@ func routinueFunc() {
|
||||
registerMsg := msg.MsgData.(*MsgOp)
|
||||
delete(channelMap[registerMsg.StoreID], registerMsg.Chan2Listen)
|
||||
close(registerMsg.Chan2Close)
|
||||
case ServerMsgNewOrder:
|
||||
case ServerMsgNewOrder, ServerMsgKeyOrderStatusChanged:
|
||||
globals.SugarLogger.Debugf("msghub routinueFunc, msg:%s", utils.Format4Output(msg, false))
|
||||
utils.CallFuncAsync(func() {
|
||||
for chan2Send := range channelMap[msg.StoreID] {
|
||||
@@ -125,10 +125,12 @@ func GetMsg(ctx *jxcontext.Context, storeID int, lastOrderTime time.Time, lastOr
|
||||
pollingDuration := defPollingDuration
|
||||
if waitingSecond != 0 {
|
||||
pollingDuration = time.Duration(waitingSecond) * time.Second
|
||||
if pollingDuration > maxPollingDuration {
|
||||
pollingDuration = maxPollingDuration
|
||||
} else if pollingDuration < minPollingDuration {
|
||||
pollingDuration = minPollingDuration
|
||||
if globals.IsProductEnv() {
|
||||
if pollingDuration > maxPollingDuration {
|
||||
pollingDuration = maxPollingDuration
|
||||
} else if pollingDuration < minPollingDuration {
|
||||
pollingDuration = minPollingDuration
|
||||
}
|
||||
}
|
||||
}
|
||||
timer := time.NewTimer(pollingDuration)
|
||||
@@ -171,7 +173,7 @@ func OnKeyOrderStatusChanged(order *model.GoodsOrder) {
|
||||
msgChan <- &ServerMsg{
|
||||
Type: ServerMsgKeyOrderStatusChanged,
|
||||
StoreID: jxutils.GetSaleStoreIDFromOrder(order),
|
||||
MsgData: 1,
|
||||
MsgData: order,
|
||||
// MsgData: []*model.GoodsOrderExt{
|
||||
// &model.GoodsOrderExt{
|
||||
// GoodsOrder: *order,
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/orm"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -70,9 +69,9 @@ func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaap
|
||||
order.Status = model.WaybillStatusDelivering
|
||||
case dadaapi.OrderStatusFinished:
|
||||
order.Status = model.WaybillStatusDelivered
|
||||
case dadaapi.OrderStatusCanceled:
|
||||
case dadaapi.OrderStatusCanceled, dadaapi.OrderStatusExpired:
|
||||
order.Status = model.WaybillStatusCanceled
|
||||
case dadaapi.OrderStatusExpired, dadaapi.OrderStatusAddOrderFailed:
|
||||
case dadaapi.OrderStatusAddOrderFailed:
|
||||
order.Status = model.WaybillStatusFailed
|
||||
default:
|
||||
order.Status = model.WaybillStatusUnknown
|
||||
@@ -102,7 +101,7 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *dadaapi.CallbackMsg) (retVal
|
||||
|
||||
// IDeliveryPlatformHandler
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) {
|
||||
db := orm.NewOrm()
|
||||
db := dao.GetDB()
|
||||
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,17 +132,18 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.
|
||||
|
||||
if globals.EnableStoreWrite {
|
||||
// 达达要求第二次创建运单,调用函数不同。所以查找两天内有无相同订单号的运单
|
||||
var lists []orm.ParamsList
|
||||
num, err2 := db.Raw(`
|
||||
SELECT vendor_waybill_id
|
||||
FROM waybill
|
||||
WHERE waybill_created_at > DATE_ADD(NOW(), interval -2 day)
|
||||
AND vendor_order_id = ?
|
||||
AND waybill_vendor_id = ?
|
||||
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada).ValuesList(&lists)
|
||||
var waybillList []*model.Waybill
|
||||
err2 := dao.GetRows(db, &waybillList, `
|
||||
SELECT *
|
||||
FROM waybill
|
||||
WHERE waybill_created_at > DATE_ADD(NOW(), interval -2 day)
|
||||
AND vendor_order_id = ?
|
||||
AND waybill_vendor_id = ?
|
||||
ORDER BY id DESC
|
||||
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada)
|
||||
var result *dadaapi.CreateOrderResponse
|
||||
if err = err2; err == nil && num > 0 {
|
||||
globals.SugarLogger.Debugf("CreateWaybill orderID:%s num=%d use ReaddOrder", order.VendorOrderID, num)
|
||||
if err = err2; err == nil && len(waybillList) > 0 && waybillList[0].Status != model.WaybillStatusFailed {
|
||||
globals.SugarLogger.Debugf("CreateWaybill orderID:%s len(waybillList)=%d use ReaddOrder", order.VendorOrderID, len(waybillList))
|
||||
result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
|
||||
} else {
|
||||
if err != nil {
|
||||
@@ -192,7 +192,7 @@ func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int,
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) {
|
||||
func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
|
||||
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
sql := `
|
||||
SELECT t2.tel_code
|
||||
@@ -200,11 +200,10 @@ func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db o
|
||||
JOIN place t2 on t1.city_code = t2.code
|
||||
WHERE t1.id = ?
|
||||
`
|
||||
db2 := dao.WrapDB(db)
|
||||
codeInfo := &struct {
|
||||
TelCode string
|
||||
}{}
|
||||
if err = dao.GetRow(db2, codeInfo, sql, jxStoreID); err != nil {
|
||||
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 = ErrCanNotFindDadaCityCode
|
||||
@@ -214,11 +213,10 @@ func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db o
|
||||
return codeInfo.TelCode, nil
|
||||
}
|
||||
|
||||
func (c *DeliveryHandler) getDadaShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) {
|
||||
func (c *DeliveryHandler) getDadaShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
|
||||
saleStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
db2 := dao.WrapDB(db)
|
||||
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDDada)
|
||||
if err = err2; err != nil && err != orm.ErrNoRows {
|
||||
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDDada)
|
||||
if err = err2; err != nil && !dao.IsNoRowsError(err) {
|
||||
return "", err
|
||||
}
|
||||
if len(storeCourierList) == 0 {
|
||||
|
||||
@@ -12,7 +12,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"
|
||||
"github.com/astaxie/beego/orm"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -57,10 +56,10 @@ func CallCreateWaybillPolicy(policy partner.CreateWaybillPolicy, refDeliveryFee,
|
||||
return nil
|
||||
}
|
||||
|
||||
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db orm.Ormer) (deliveryFee, addFee int64, err error) {
|
||||
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) {
|
||||
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID)
|
||||
if db == nil {
|
||||
db = orm.NewOrm()
|
||||
db = dao.GetDB()
|
||||
}
|
||||
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
var lng, lat float64
|
||||
@@ -69,8 +68,7 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db o
|
||||
Lng int
|
||||
Lat int
|
||||
}{}
|
||||
db2 := dao.WrapDB(db)
|
||||
if err = dao.GetRow(db2, priceInfo, `
|
||||
if err = dao.GetRow(db, priceInfo, `
|
||||
SELECT t2.mtps_price price, t1.lng, t1.lat
|
||||
FROM store t1
|
||||
JOIN place t2 ON t1.city_code = t2.code
|
||||
|
||||
@@ -115,7 +115,7 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) (re
|
||||
|
||||
// IDeliveryPlatformHandler
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicy) (bill *model.Waybill, err error) {
|
||||
db := orm.NewOrm()
|
||||
db := dao.GetDB()
|
||||
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
if err == nil {
|
||||
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, deliveryFee, order, model.VendorIDMTPS); err != nil {
|
||||
@@ -201,16 +201,15 @@ func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DeliveryHandler) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) (retVal int64, err error) {
|
||||
func (c *DeliveryHandler) getDeliveryID(order *model.GoodsOrder, db *dao.DaoDB) (retVal int64, err error) {
|
||||
// jxorder表当前已经有50多万条记录了,加100万避免冲突
|
||||
// 508505
|
||||
return order.ID + 1000000, nil
|
||||
}
|
||||
|
||||
func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) {
|
||||
func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db *dao.DaoDB) (retVal string, err error) {
|
||||
saleStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
db2 := dao.WrapDB(db)
|
||||
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDMTPS)
|
||||
storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db, saleStoreID, model.VendorIDMTPS)
|
||||
if err = err2; err != nil && err != orm.ErrNoRows {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName strin
|
||||
shopID = store.ID
|
||||
}
|
||||
store2, err2 := p.ReadStore(store.VendorStoreID)
|
||||
// globals.SugarLogger.Debugf("ebai UpdateStore2 store2:%s, err2:%v", utils.Format4Output(store2, true), err2)
|
||||
if err = err2; err == nil {
|
||||
if store2.ID == store.ID {
|
||||
shopID = -1
|
||||
|
||||
@@ -387,16 +387,13 @@ func (p *PurchaseHandler) RefreshStoresAllSkusID(ctx *jxcontext.Context, parentT
|
||||
func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[string]interface{}) {
|
||||
price := jxutils.CaculateSkuVendorPrice(storeSku.Price, storeSku.PricePercentage)
|
||||
params = map[string]interface{}{
|
||||
"name": jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0),
|
||||
"status": jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status)),
|
||||
"left_num": model.MaxStoreSkuStockQty,
|
||||
"sale_price": price,
|
||||
"market_price": price,
|
||||
"category_id": storeSku.CatEbaiID,
|
||||
"cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1),
|
||||
"cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2),
|
||||
"cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3),
|
||||
"weight": storeSku.Weight,
|
||||
"name": jxutils.ComposeSkuName(storeSku.Prefix, storeSku.Name, storeSku.Comment, storeSku.Unit, storeSku.SpecQuality, storeSku.SpecUnit, 0),
|
||||
"left_num": model.MaxStoreSkuStockQty,
|
||||
"category_id": storeSku.CatEbaiID,
|
||||
"cat1_id": getEbaiCat(storeSku.EbaiCat1ID, 1),
|
||||
"cat2_id": getEbaiCat(storeSku.EbaiCat2ID, 2),
|
||||
"cat3_id": getEbaiCat(storeSku.EbaiCat3ID, 3),
|
||||
"weight": storeSku.Weight,
|
||||
"photos": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"is_master": true,
|
||||
@@ -404,6 +401,13 @@ func genSkuParamsFromStoreSkuInfo(storeSku *tStoreSkuFullInfo) (params map[strin
|
||||
},
|
||||
},
|
||||
}
|
||||
if storeSku.EbaiSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0 {
|
||||
params["sale_price"] = price
|
||||
params["market_price"] = price
|
||||
}
|
||||
if storeSku.EbaiSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
|
||||
params["status"] = jxSkuStatus2Ebai(jxutils.MergeSkuStatus(storeSku.SkuStatus, storeSku.Status))
|
||||
}
|
||||
// todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄?
|
||||
if storeSku.Upc != "" {
|
||||
params["upc"] = storeSku.Upc
|
||||
|
||||
@@ -15,11 +15,14 @@ import (
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
const (
|
||||
DefBrandID = 35247
|
||||
DefJdCategoryID = 20362
|
||||
DefBrandID = 35247
|
||||
|
||||
DefJdCategoryID = 20362
|
||||
DefJdCategoryID4Jxgy = 22410 // 其他国产水果
|
||||
)
|
||||
|
||||
type tSkuInfoExt struct {
|
||||
@@ -36,6 +39,13 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func getDefJdCategoryID() int {
|
||||
if beego.BConfig.RunMode == "jxgy" {
|
||||
return DefJdCategoryID4Jxgy
|
||||
}
|
||||
return DefJdCategoryID
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
|
||||
var jdPid int64
|
||||
if cat.ParentID != 0 {
|
||||
@@ -134,7 +144,7 @@ func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuE
|
||||
// shopCategories = append(shopCategories, skuInfoExt.SkuCatID)
|
||||
// }
|
||||
if skuInfoExt.JdCategoryID == 0 {
|
||||
skuInfoExt.JdCategoryID = DefJdCategoryID
|
||||
skuInfoExt.JdCategoryID = getDefJdCategoryID()
|
||||
}
|
||||
if skuInfoExt.BrandID == 0 {
|
||||
skuInfoExt.BrandID = DefBrandID
|
||||
@@ -176,6 +186,12 @@ func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName stri
|
||||
if skuExt.IsSpu == 0 {
|
||||
if globals.EnableStoreWrite {
|
||||
vendorSkuID, err = api.JdAPI.AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, addParams)
|
||||
if err != nil {
|
||||
if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 {
|
||||
vendorSkuID = utils.Int64ToStr(jdSkuID)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
|
||||
|
||||
@@ -301,6 +301,7 @@ func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorStoreID s
|
||||
return storeStatus, err
|
||||
}
|
||||
|
||||
// 当前京东的storeCrud消息不会在门店状态改变时发送,所以意义不大,先放在这里
|
||||
func (c *PurchaseHandler) onStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jdapi.CallbackResponse) {
|
||||
var err error
|
||||
if msg.StatusID == jdapi.StatusIDUpdateStore {
|
||||
@@ -308,6 +309,11 @@ func (c *PurchaseHandler) onStoreMsg(msg *jdapi.CallbackOrderMsg) (response *jda
|
||||
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, "")
|
||||
|
||||
@@ -3,6 +3,8 @@ package wsc
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasks"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
@@ -19,7 +21,7 @@ func init() {
|
||||
}
|
||||
|
||||
func TestGetVendorCategories(t *testing.T) {
|
||||
vendorCatList, err := new(PurchaseHandler).GetVendorCategories()
|
||||
vendorCatList, err := new(PurchaseHandler).GetVendorCategories(jxcontext.AdminCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user