shan
This commit is contained in:
@@ -1,340 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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"
|
||||
)
|
||||
|
||||
func actType2Ebai(actType int) int {
|
||||
if actType < model.ActOrderBegin {
|
||||
return ebaiapi.ActivityTypeDirectDown
|
||||
}
|
||||
return ebaiapi.ActivityTypeFullDiscount
|
||||
}
|
||||
|
||||
func actOrderRules2Ebai(actOrderRules []*model.ActOrderRule) (ebaiRules []*ebaiapi.ActivityRule) {
|
||||
for _, v := range actOrderRules {
|
||||
ebaiRules = append(ebaiRules, &ebaiapi.ActivityRule{
|
||||
Accords: int(jxutils.IntPrice2Standard(v.SalePrice)),
|
||||
Sale: int(jxutils.IntPrice2Standard(v.DeductPrice)),
|
||||
})
|
||||
}
|
||||
return ebaiRules
|
||||
}
|
||||
|
||||
func actStoreSu2Ebai4Add(oneStoreActSku []*model.ActStoreSku2) (skus []*ebaiapi.ActivitySkuInfo4Add) {
|
||||
for _, v := range oneStoreActSku {
|
||||
if v.VendorSkuID != "" {
|
||||
if model.IsSyncStatusNeedCreate(v.SyncStatus) {
|
||||
skus = append(skus, &ebaiapi.ActivitySkuInfo4Add{
|
||||
SkuID: v.VendorSkuID,
|
||||
SpecialPrice: v.ActualActPrice,
|
||||
Stock: v.Stock,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return skus
|
||||
}
|
||||
|
||||
func actStoreSu2Ebai4Update(oneStoreActSku []*model.ActStoreSku2) (skus []*ebaiapi.ActivitySkuInfo4Update) {
|
||||
for _, v := range oneStoreActSku {
|
||||
if v.VendorSkuID != "" {
|
||||
if model.IsSyncStatusNeedUpdate(v.SyncStatus) {
|
||||
skus = append(skus, &ebaiapi.ActivitySkuInfo4Update{
|
||||
ShopID: utils.Int2Str(v.StoreID),
|
||||
SkuID: v.VendorSkuID,
|
||||
SpecialPrice: v.ActPrice,
|
||||
Stock: v.Stock,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return skus
|
||||
}
|
||||
|
||||
func actStoreSu2Ebai4Delete(oneStoreActSku []*model.ActStoreSku2) (skus []string) {
|
||||
for _, v := range oneStoreActSku {
|
||||
if v.VendorSkuID != "" {
|
||||
if model.IsSyncStatusNeedDelete(v.SyncStatus) {
|
||||
skus = append(skus, v.VendorSkuID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return skus
|
||||
}
|
||||
|
||||
func act2EbaiActivity(act *model.Act2, actOrderRules []*model.ActOrderRule) (activity *ebaiapi.ActivityInfo) {
|
||||
activity = &ebaiapi.ActivityInfo{
|
||||
ActivityName: utils.LimitMixedStringLen(act.GetRealActName(), ebaiapi.MaxActivityNameLength),
|
||||
ActivityType: actType2Ebai(act.Type),
|
||||
StartTime: act.BeginAt.Unix(),
|
||||
EndTime: act.EndAt.Unix(),
|
||||
OpenTime: "00:00",
|
||||
CloseTime: "23:59",
|
||||
WeekDay: "0,1,2,3,4,5,6",
|
||||
ActivityDesc: act.Advertising,
|
||||
ShowCategory: model.ActTypeName[act.Type],
|
||||
PromotionSkuDesc: utils.LimitMixedStringLen(act.Advertising, ebaiapi.MaxActivityDescLength),
|
||||
DayLimit: act.LimitDaily,
|
||||
ActivityPlatform: ebaiapi.ActivityPFAll,
|
||||
}
|
||||
if act.LimitCount > 0 {
|
||||
activity.OrderLimit = act.LimitCount
|
||||
}
|
||||
if activity.DayLimit == 0 {
|
||||
activity.DayLimit = 999
|
||||
}
|
||||
if actOrderRules != nil {
|
||||
activity.Rule = actOrderRules2Ebai(actOrderRules)
|
||||
}
|
||||
return activity
|
||||
}
|
||||
|
||||
func createOneShopAct(act *model.Act2, shopID string, oneStoreActSku []*model.ActStoreSku2) (ebaiActIDStr string, err error) {
|
||||
globals.SugarLogger.Debugf("ebai createOneShopAct")
|
||||
activity := act2EbaiActivity(act, nil)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
ebaiActID, err2 := api.EbaiAPI.ActivityCreate(shopID, 0, 0, activity)
|
||||
if err = err2; err == nil {
|
||||
ebaiActIDStr = utils.Int64ToStr(ebaiActID)
|
||||
if _, err = ActivitySkuAddBatch(ebaiActID, shopID, 0, activity.ActivityType, actStoreSu2Ebai4Add(oneStoreActSku), false); err != nil {
|
||||
ActivityDisable(ebaiActID, shopID, 0, 0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ebaiActIDStr = utils.Int64ToStr(jxutils.GenFakeID())
|
||||
}
|
||||
return ebaiActIDStr, err
|
||||
}
|
||||
|
||||
func ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID int64, activityType int, skuList []*ebaiapi.ActivitySkuInfo4Add, isSkuIDCustom bool) (successIDs []string, err error) {
|
||||
globals.SugarLogger.Debugf("ebai ActivitySkuAddBatch")
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
successIDs, err = api.EbaiAPI.ActivitySkuAddBatch(activityID, shopID, baiduShopID, activityType, skuList, isSkuIDCustom)
|
||||
} else {
|
||||
for _, v := range skuList {
|
||||
successIDs = append(successIDs, v.SkuID)
|
||||
}
|
||||
}
|
||||
return successIDs, err
|
||||
}
|
||||
|
||||
func ActivitySkuDeleteBatch(activityID int64, shopID string, baiduShopID int64, skuIDs []string, isSkuIDCustom bool) (successIDs []string, err error) {
|
||||
globals.SugarLogger.Debugf("ebai ActivitySkuDeleteBatch")
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
successIDs, err = api.EbaiAPI.ActivitySkuDeleteBatch(activityID, shopID, baiduShopID, skuIDs, isSkuIDCustom)
|
||||
} else {
|
||||
successIDs = append([]string{}, skuIDs...)
|
||||
}
|
||||
return successIDs, err
|
||||
}
|
||||
|
||||
func ActivitySkuUpdateBatch(activityID int64, actSkuInfoList []*ebaiapi.ActivitySkuInfo4Update) (faildInfoList []string, err error) {
|
||||
globals.SugarLogger.Debugf("ebai ActivitySkuUpdateBatch")
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
faildInfoList, err = api.EbaiAPI.ActivitySkuUpdateBatch(activityID, actSkuInfoList)
|
||||
}
|
||||
return faildInfoList, err
|
||||
}
|
||||
|
||||
func ActivityDisable(activityID int64, shopID string, baiduShopID, supplierID int64) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai ActivityDisable")
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.ActivityDisable(activityID, shopID, baiduShopID, supplierID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getActStoreSkuFromTaskResult(taskReslt []interface{}) (list []*model.ActStoreSku2) {
|
||||
for _, v := range taskReslt {
|
||||
actStoreSkuList := v.([]*model.ActStoreSku2)
|
||||
list = append(list, actStoreSkuList...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func createSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (createdList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("ebai createSkuAct")
|
||||
actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
|
||||
task := tasksch.NewParallelTask("ebai createSkuAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
list := batchItemList[0].([]*model.ActStoreSku2)
|
||||
var vendorActID string
|
||||
if vendorActID, err = createOneShopAct(act, utils.Int2Str(list[0].StoreID), list); err == nil {
|
||||
for _, v := range list {
|
||||
v.VendorActID = vendorActID
|
||||
}
|
||||
retVal = []interface{}{list}
|
||||
}
|
||||
return retVal, err
|
||||
}, actStoreSkuListList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err := task.GetResult(0)
|
||||
return getActStoreSkuFromTaskResult(result), err
|
||||
}
|
||||
|
||||
func cancelSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, actStoreSkuMap map[string][]*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("ebai cancelSkuAct")
|
||||
var vendorActIDs []string
|
||||
for k := range actStoreSkuMap {
|
||||
vendorActIDs = append(vendorActIDs, k)
|
||||
}
|
||||
task := tasksch.NewParallelTask("ebai cancelSkuAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorActID := batchItemList[0].(string)
|
||||
actStoreSkuList := actStoreSkuMap[vendorActID]
|
||||
if vendorActID != "" {
|
||||
err = ActivityDisable(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, 0)
|
||||
}
|
||||
if err == nil {
|
||||
retVal = []interface{}{actStoreSkuList}
|
||||
}
|
||||
return retVal, err
|
||||
}, vendorActIDs)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err := task.GetResult(0)
|
||||
return getActStoreSkuFromTaskResult(result), err
|
||||
}
|
||||
|
||||
func deleteSkuActSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, actStoreSkuMap, vendorActInfoMap map[string][]*model.ActStoreSku2) (deletedList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("ebai deleteSkuActSkus")
|
||||
var vendorActIDs []string
|
||||
for k := range actStoreSkuMap {
|
||||
if k != "" {
|
||||
vendorActIDs = append(vendorActIDs, k)
|
||||
}
|
||||
}
|
||||
if len(vendorActIDs) > 0 {
|
||||
task := tasksch.NewParallelTask("ebai deleteSkuAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorActID := batchItemList[0].(string)
|
||||
actStoreSkuList := actStoreSkuMap[vendorActID]
|
||||
vendorActStoreSkuList := vendorActInfoMap[vendorActID]
|
||||
if len(actStoreSkuList) < len(vendorActStoreSkuList) {
|
||||
if list := actStoreSu2Ebai4Delete(actStoreSkuList); len(list) > 0 {
|
||||
_, err = ActivitySkuDeleteBatch(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, list, false)
|
||||
}
|
||||
} else {
|
||||
err = ActivityDisable(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, 0)
|
||||
}
|
||||
if err == nil {
|
||||
retVal = []interface{}{actStoreSkuList}
|
||||
}
|
||||
return retVal, err
|
||||
}, vendorActIDs)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err2 := task.GetResult(0)
|
||||
err = err2
|
||||
deletedList = getActStoreSkuFromTaskResult(result)
|
||||
}
|
||||
return deletedList, err
|
||||
}
|
||||
|
||||
func addSkuActSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2, vendorActIDMap map[int]string) (addedList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("ebai addSkuActSkus, actID:%d", act.ID)
|
||||
actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
|
||||
if len(actStoreSkuListList) > 0 {
|
||||
task := tasksch.NewParallelTask("ebai addSkuActSkus", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
actStoreSkuList := batchItemList[0].([]*model.ActStoreSku2)
|
||||
vendorActID := vendorActIDMap[actStoreSkuList[0].StoreID]
|
||||
if vendorActID != "" {
|
||||
if list := actStoreSu2Ebai4Add(actStoreSkuList); len(list) > 0 {
|
||||
_, err = ActivitySkuAddBatch(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, actType2Ebai(act.Type), list, false)
|
||||
}
|
||||
} else {
|
||||
vendorActID, err = createOneShopAct(act, utils.Int2Str(actStoreSkuList[0].StoreID), actStoreSkuList)
|
||||
}
|
||||
if err == nil {
|
||||
for _, v := range actStoreSkuList {
|
||||
v.VendorActID = vendorActID
|
||||
}
|
||||
retVal = []interface{}{actStoreSkuList}
|
||||
}
|
||||
return retVal, err
|
||||
}, actStoreSkuListList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err2 := task.GetResult(0)
|
||||
err = err2
|
||||
addedList = getActStoreSkuFromTaskResult(result)
|
||||
}
|
||||
return addedList, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai SyncAct, actID:%d", act.ID)
|
||||
vendorActInfoMap := make(map[string][]*model.ActStoreSku2)
|
||||
deleteActInfoMap := make(map[string][]*model.ActStoreSku2)
|
||||
vendorActIDMap := make(map[int]string)
|
||||
var actStoreSkuList4Create []*model.ActStoreSku2
|
||||
var updateItems []*dao.KVUpdateItem
|
||||
|
||||
actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuList)
|
||||
for storeID := range actStoreSkuMap {
|
||||
for _, actStoreSku := range actStoreSkuMap[storeID] {
|
||||
vendorActInfoMap[actStoreSku.VendorActID] = append(vendorActInfoMap[actStoreSku.VendorActID], actStoreSku)
|
||||
if vendorActIDMap[storeID] == "" && actStoreSku.VendorActID != "" {
|
||||
vendorActIDMap[storeID] = actStoreSku.VendorActID
|
||||
}
|
||||
if model.IsSyncStatusDelete(actStoreSku.SyncStatus) {
|
||||
vendorActID := actStoreSku.VendorActID
|
||||
if vendorActID == "" {
|
||||
vendorActID = act.VendorActID
|
||||
}
|
||||
deleteActInfoMap[vendorActID] = append(deleteActInfoMap[vendorActID], actStoreSku)
|
||||
} else if model.IsSyncStatusNew(actStoreSku.SyncStatus) {
|
||||
actStoreSkuList4Create = append(actStoreSkuList4Create, actStoreSku)
|
||||
}
|
||||
}
|
||||
}
|
||||
err = func() (err error) {
|
||||
if model.IsSyncStatusDelete(act.SyncStatus) {
|
||||
canceledList, err2 := cancelSkuAct(ctx, nil, vendorActInfoMap)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, canceledList, model.SyncFlagModifiedMask)...)
|
||||
if err = err2; err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
} else if model.IsSyncStatusNew(act.SyncStatus) {
|
||||
createdList, err2 := createSkuAct(ctx, nil, act, actStoreSkuList4Create)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, createdList, model.SyncFlagNewMask)...)
|
||||
if err = err2; err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagNewMask))
|
||||
}
|
||||
} else if model.IsSyncStatusUpdate(act.SyncStatus) {
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(updateItems, false))
|
||||
if len(actStoreSkuList4Create) > 0 {
|
||||
addedList, err2 := addSkuActSkus(ctx, nil, act, actStoreSkuList4Create, vendorActIDMap)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, addedList, model.SyncFlagNewMask)...)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(deleteActInfoMap) > 0 {
|
||||
deletedList, err2 := deleteSkuActSkus(ctx, nil, deleteActInfoMap, vendorActInfoMap)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deletedList, model.SyncFlagDeletedMask)...)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}()
|
||||
db := dao.GetDB()
|
||||
_, err2 := dao.BatchUpdateActEntity(db, model.IsSyncStatusDelete(act.SyncStatus), updateItems)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"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/globals/api"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
type tShowStatusAndTypeInfo struct {
|
||||
ShowStatus int
|
||||
ActivityType int
|
||||
}
|
||||
|
||||
func ebaiPageActType2Jx(activityType int) int {
|
||||
if activityType == ebaiapi.PageActivityTypeSkuDiscount || activityType == ebaiapi.PageActivityTypeSkuDirectDown {
|
||||
return model.ActSkuDirectDown
|
||||
} else if activityType == ebaiapi.PageActivityTypeSkuSpecialPrice {
|
||||
return model.ActSkuSecKill
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func ebaiPageActStatus2Jx(status int) int {
|
||||
if status == ebaiapi.PageActivityStatusWaiting || status == ebaiapi.PageActivityStatusOnGoing {
|
||||
return model.ActStatusCreated
|
||||
} else if status == ebaiapi.PageActivityStatusEnded {
|
||||
return model.ActStatusEnded
|
||||
}
|
||||
return model.ActStatusNA
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetPageActList(ctx *jxcontext.Context, createdFrom time.Time) (actList []*model.Act2, err error) {
|
||||
var typeAndStatusList []*tShowStatusAndTypeInfo
|
||||
for _, showStatus := range []int{
|
||||
ebaiapi.PageActivityShowStatusWaiting,
|
||||
ebaiapi.PageActivityShowStatusOnGoing,
|
||||
// ebaiapi.PageActivityStatusEnded,
|
||||
} {
|
||||
for _, activityType := range []int{
|
||||
ebaiapi.PageActivityTypeSkuDiscount,
|
||||
ebaiapi.PageActivityTypeSkuSpecialPrice,
|
||||
ebaiapi.PageActivityTypeSkuDirectDown,
|
||||
} {
|
||||
typeAndStatusList = append(typeAndStatusList, &tShowStatusAndTypeInfo{
|
||||
ShowStatus: showStatus,
|
||||
ActivityType: activityType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
task := tasksch.NewParallelTask("ebai GetPageActList", tasksch.NewParallelConfig().SetParallelCount(10), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
info := batchItemList[0].(*tShowStatusAndTypeInfo)
|
||||
list, err := api.EbaiAPI.BegetActivityList(info.ShowStatus, info.ActivityType, 0, api.EbaiAPI.GetSupplierID())
|
||||
if err == nil {
|
||||
retVal = list
|
||||
}
|
||||
return retVal, err
|
||||
}, typeAndStatusList)
|
||||
task.Run()
|
||||
list, err := task.GetResult(0)
|
||||
if len(list) > 0 {
|
||||
for _, v := range list {
|
||||
ebaiAct := v.(*ebaiapi.PageActItem)
|
||||
if utils.Timestamp2Time(ebaiAct.CreateTime).Sub(createdFrom) > 0 {
|
||||
act := &model.Act2{
|
||||
Act: model.Act{
|
||||
Name: fmt.Sprintf("%s-%s", ebaiAct.ActivityName, ebaiAct.ActivityID),
|
||||
Type: ebaiPageActType2Jx(ebaiAct.ActivityType),
|
||||
Status: ebaiPageActStatus2Jx(ebaiAct.Status),
|
||||
Source: ebaiAct.User,
|
||||
CreateType: model.ActCreateTypeSpider,
|
||||
BeginAt: utils.Timestamp2Time(ebaiAct.StartTime),
|
||||
EndAt: utils.Timestamp2Time(ebaiAct.EndTime),
|
||||
VendorMask: model.GetVendorMask(model.VendorIDEBAI),
|
||||
LimitCount: 1,
|
||||
},
|
||||
VendorID: model.VendorIDEBAI,
|
||||
VendorOrgCode: api.EbaiAPI.GetSource(),
|
||||
VendorActID: ebaiAct.ActivityID,
|
||||
}
|
||||
actList = append(actList, act)
|
||||
}
|
||||
}
|
||||
}
|
||||
return actList, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetPageActSkuList(ctx *jxcontext.Context, vendorPageActID string) (actStoreSkuList []*model.ActStoreSku2, err error) {
|
||||
skus, err := api.EbaiAPI.BegetActSkuList(utils.Str2Int64(vendorPageActID), 0, api.EbaiAPI.GetSupplierID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range skus {
|
||||
actStoreSku := &model.ActStoreSku2{
|
||||
ActStoreSku: model.ActStoreSku{
|
||||
Stock: v.Stock,
|
||||
OriginalPrice: jxutils.StandardPrice2Int(v.OriginalPrice),
|
||||
},
|
||||
VendorStoreID: utils.Int64ToStr(v.Wid),
|
||||
VendorSkuID: v.SkuID,
|
||||
VendorActID: v.ActivityID,
|
||||
ActualActPrice: jxutils.StandardPrice2Int(v.PromotionPrice),
|
||||
}
|
||||
actStoreSkuList = append(actStoreSkuList, actStoreSku)
|
||||
}
|
||||
return actStoreSkuList, nil
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch"
|
||||
)
|
||||
|
||||
func TestGetPageActList(t *testing.T) {
|
||||
actList, err := new(PurchaseHandler).GetPageActList(jxcontext.AdminCtx, utils.DefaultTimeValue)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(actList, false))
|
||||
t.Log(len(actList))
|
||||
}
|
||||
|
||||
func TestGetPageActSkuList(t *testing.T) {
|
||||
actList, err := new(PurchaseHandler).GetPageActSkuList(jxcontext.AdminCtx, "3000000001477429")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(actList, false))
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
func OnCallbackMsg(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) {
|
||||
globals.SugarLogger.Debugf("ebai OnCallbackMsg msg:%s", utils.Format4Output(msg, true))
|
||||
if CurPurchaseHandler != nil {
|
||||
if orderID := GetOrderIDFromMsg(msg); orderID != "" {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
switch msg.Cmd {
|
||||
case ebaiapi.CmdOrderCreate, ebaiapi.CmdOrderStatus, ebaiapi.CmdOrderUserCancel, ebaiapi.CmdOrderPartRefund:
|
||||
response = CurPurchaseHandler.onOrderMsg(msg)
|
||||
case ebaiapi.CmdOrderDeliveryStatus:
|
||||
response = CurPurchaseHandler.onWaybillMsg(msg)
|
||||
}
|
||||
}, jxutils.ComposeUniversalOrderID(orderID, model.VendorIDEBAI))
|
||||
}
|
||||
if /*msg.Cmd == ebaiapi.CmdOrderPartRefund || msg.Cmd == ebaiapi.CmdOrderUserCancel || */ msg.Cmd == ebaiapi.CmdOrderDeliveryStatus {
|
||||
response = CurPurchaseHandler.OnFinancialMsg(msg)
|
||||
} else if msg.Cmd == ebaiapi.CmdShopMsgPush {
|
||||
response = CurPurchaseHandler.onShopMsgPush(msg)
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func GetOrderIDFromMsg(msg *ebaiapi.CallbackMsg) string {
|
||||
return GetOrderIDFromMap(msg.Body)
|
||||
}
|
||||
|
||||
func GetOrderIDFromMap(orderMap map[string]interface{}) string {
|
||||
if orderID := orderMap["order_id"]; orderID != nil {
|
||||
if tryOrderID, ok := orderID.(string); ok {
|
||||
return tryOrderID
|
||||
}
|
||||
return utils.Int64ToStr(utils.MustInterface2Int64(orderID))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) UpdatePlaces() (err error) {
|
||||
provinces, err := api.EbaiAPI.CommonShopCities(0)
|
||||
if err == nil {
|
||||
task := tasksch.NewParallelTask("UpdatePlaces", nil, jxcontext.AdminCtx,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
province := batchItemList[0].(*ebaiapi.CityInfo)
|
||||
retSlice := make([]*ebaiapi.CityInfo, 0)
|
||||
if province.IsOpen != 0 {
|
||||
retSlice = append(retSlice, province)
|
||||
cities, err := api.EbaiAPI.CommonShopCities(province.ID)
|
||||
for _, city := range cities {
|
||||
if city.IsOpen != 0 {
|
||||
retSlice = append(retSlice, city)
|
||||
districts, err2 := api.EbaiAPI.CommonShopCities(city.ID)
|
||||
if err = err2; err == nil {
|
||||
for _, district := range districts {
|
||||
if district.IsOpen != 0 {
|
||||
retSlice = append(retSlice, district)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retSlice, err
|
||||
}, provinces)
|
||||
task.Run()
|
||||
places, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
globals.SugarLogger.Debug(utils.Format4Output(places, false))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUpdatePlacese(t *testing.T) {
|
||||
err := new(PurchaseHandler).UpdatePlaces()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
CurPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
putils.DefSingleStorePlatform
|
||||
|
||||
shopList []*ebaiapi.ShopInfo
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func init() {
|
||||
if api.EbaiAPI != nil {
|
||||
CurPurchaseHandler = New()
|
||||
partner.RegisterPurchasePlatform(CurPurchaseHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func New() (obj *PurchaseHandler) {
|
||||
obj = new(PurchaseHandler)
|
||||
obj.ISingleStoreStoreSkuHandler = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func EbaiBusStatus2JxStatus(ebaiStatus int) int {
|
||||
if ebaiStatus == ebaiapi.ShopBusStatusHaveRest {
|
||||
return model.StoreStatusClosed
|
||||
}
|
||||
if ebaiStatus == ebaiapi.ShopBusStatusSuspended {
|
||||
return model.StoreStatusDisabled
|
||||
}
|
||||
return model.StoreStatusOpened
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDEBAI
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
globals.SugarLogger.Debugf("ebai UploadImg imgURL:%s, imgName:%s, imgType:%d", imgURL, imgName, imgType)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if imgType == model.ImgTypeMain {
|
||||
imgHint, err = api.EbaiAPI.PictureUpload(imgURL, imgData)
|
||||
} else if imgType == model.ImgTypeDesc {
|
||||
imgHint, err = api.EbaiAPI.SkuUploadRTF(p.getShopID4UploadRTF(), ebaiapi.BuildRFTFromImgs(imgURL))
|
||||
}
|
||||
} else {
|
||||
imgHint = imgURL + ".ebai"
|
||||
}
|
||||
return imgHint, err
|
||||
}
|
||||
|
||||
func getShopIDFromList(shopList []*ebaiapi.ShopInfo) (shopID string) {
|
||||
if len(shopList) > 0 {
|
||||
shopID = shopList[0].ShopID
|
||||
}
|
||||
return shopID
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getShopID4UploadRTF() (shopID string) {
|
||||
var shopList []*ebaiapi.ShopInfo
|
||||
p.locker.RLock()
|
||||
shopList = p.shopList
|
||||
p.locker.RUnlock()
|
||||
if len(shopList) > 0 {
|
||||
return getShopIDFromList(shopList)
|
||||
}
|
||||
|
||||
p.locker.Lock()
|
||||
shopList = p.shopList
|
||||
if len(shopList) > 0 {
|
||||
p.locker.Unlock()
|
||||
return getShopIDFromList(shopList)
|
||||
}
|
||||
|
||||
defer p.locker.Unlock()
|
||||
shopList, err := api.EbaiAPI.ShopList(ebaiapi.SysStatusAll)
|
||||
if err == nil {
|
||||
if len(shopList) > 0 {
|
||||
p.shopList = shopList
|
||||
shopID = getShopIDFromList(shopList)
|
||||
} else {
|
||||
// p.shopList = []*ebaiapi.ShopInfo{
|
||||
// &ebaiapi.ShopInfo{
|
||||
// ShopID: "",
|
||||
// },
|
||||
// }
|
||||
}
|
||||
}
|
||||
return shopID
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getVendorCategories(level int, pid int64) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
cats, err := api.EbaiAPI.SkuCategoryList("", level, pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range cats {
|
||||
cat := &model.SkuVendorCategory{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
Name: v.CatName,
|
||||
Level: level,
|
||||
VendorCategoryID: v.CatID,
|
||||
}
|
||||
if level > 1 {
|
||||
cat.ParentID = v.ParentID
|
||||
if level == 3 {
|
||||
cat.IsLeaf = 1
|
||||
}
|
||||
}
|
||||
vendorCats = append(vendorCats, cat)
|
||||
if level < 3 {
|
||||
childVendorCats, err2 := p.getVendorCategories(level+1, utils.Str2Int64(v.CatID))
|
||||
if err2 == nil && len(childVendorCats) > 0 {
|
||||
vendorCats = append(vendorCats, childVendorCats...)
|
||||
} else {
|
||||
cat.IsLeaf = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return vendorCats, nil
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
vendorCats, err = p.getVendorCategories(1, 0)
|
||||
return vendorCats, err
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
const (
|
||||
// testShopBaiduID = "2233976901"
|
||||
// testShopID = 100077
|
||||
|
||||
testShopBaiduID = "2267254343"
|
||||
testShopID = 2
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestGetVendorCategories(t *testing.T) {
|
||||
catList, err := new(PurchaseHandler).GetVendorCategories(jxcontext.AdminCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(catList, false))
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) OnFinancialMsg(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) {
|
||||
utils.CallFuncAsync(func() {
|
||||
response = p.onFinancialMsg(msg)
|
||||
})
|
||||
return response
|
||||
}
|
||||
|
||||
// 存储饿百退款订单结账信息
|
||||
func (p *PurchaseHandler) onFinancialMsg(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) {
|
||||
var err error
|
||||
if msg.Cmd == ebaiapi.CmdOrderPartRefund { // 部分退款处理
|
||||
if int(utils.MustInterface2Int64(msg.Body["status"])) == ebaiapi.OrderPartRefundSuccess {
|
||||
// 获取到部分退款订单id
|
||||
afsOrderID := GetOrderIDFromMsg(msg)
|
||||
// 处理部分退款信息
|
||||
orderData, err2 := api.EbaiAPI.OrderPartRefundGet(afsOrderID)
|
||||
if err = err2; err == nil {
|
||||
afsOrder := CurPurchaseHandler.AfsOrderDetail2Financial(orderData)
|
||||
err = partner.CurOrderManager.SaveAfsOrderFinancialInfo(afsOrder)
|
||||
}
|
||||
}
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderUserCancel { // 全额退款处理
|
||||
messageType := int(utils.MustInterface2Int64(msg.Body["type"]))
|
||||
if int(utils.MustInterface2Int64(msg.Body["cancel_type"])) == ebaiapi.OrderUserCancelTypeAfterSale &&
|
||||
(messageType == ebaiapi.OrderUserCancelCSAgreed || messageType == ebaiapi.OrderUserCancelMerchantAgreed) {
|
||||
afsOrderID := GetOrderIDFromMsg(msg)
|
||||
// 获得退款订单ID,去本地数据库拿?饿百消息推送只给了订单号,但是没有查询全额退款的接口,只有部分退款才可以查询
|
||||
orderFinancial, err := partner.CurOrderManager.LoadOrderFinancial(afsOrderID, model.VendorIDEBAI)
|
||||
if err == nil {
|
||||
globals.SugarLogger.Debug(utils.Format4Output(orderFinancial, false))
|
||||
err = partner.CurOrderManager.SaveAfsOrderFinancialInfo(CurPurchaseHandler.OrderFinancialDetail2Refund(orderFinancial, msg))
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai OnFinancialMsg, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrderFinancial", afsOrderID)
|
||||
}
|
||||
}
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderDeliveryStatus { // 转自送调整
|
||||
if utils.Int64ToStr(utils.MustInterface2Int64(msg.Body["status"])) == ebaiapi.WaybillStatusSelfDelivery {
|
||||
vendorOrderID := GetOrderIDFromMsg(msg)
|
||||
orderMap, err := api.EbaiAPI.OrderGet(vendorOrderID)
|
||||
if err == nil {
|
||||
err = CurPurchaseHandler.OnOrderDetail(orderMap, partner.UpdatedPeration)
|
||||
}
|
||||
}
|
||||
}
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, msg.Cmd)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OrderFinancialDetail2Refund(orderFinancial *model.OrderFinancial, msg *ebaiapi.CallbackMsg) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
AfsOrderID: GetOrderIDFromMsg(msg),
|
||||
VendorOrderID: GetOrderIDFromMsg(msg),
|
||||
AfsCreatedAt: utils.Timestamp2Time(msg.Timestamp),
|
||||
// BoxMoney: orderFinancial.BoxMoney, // 饿百的餐盒费已经拆分到单条Sku里面,退款时直接计算用户支付sku金额就好了
|
||||
// SkuBoxMoney: orderFinancial.SkuBoxMoney,
|
||||
FreightUserMoney: orderFinancial.FreightMoney,
|
||||
SkuUserMoney: orderFinancial.ActualPayMoney - orderFinancial.FreightMoney,
|
||||
PmSubsidyMoney: orderFinancial.PmSubsidyMoney,
|
||||
}
|
||||
// if msg.Body["timestamp"] != nil {
|
||||
// afsOrder.AfsCreateAt = utils.Timestamp2Time(utils.Str2Int64(utils.Interface2String(msg.Body["timestamp"])))
|
||||
// } else {
|
||||
// globals.SugarLogger.Warnf("ebai OrderFinancialDetail2Refund timestamp is not found in afsOrder:%s", afsOrder.AfsOrderID)
|
||||
// afsOrder.AfsCreateAt = time.Now()
|
||||
// }
|
||||
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
|
||||
globals.SugarLogger.Debug(utils.Format4Output(order, false))
|
||||
if err == nil {
|
||||
afsOrder.JxStoreID = order.JxStoreID
|
||||
afsOrder.VendorStoreID = order.VendorStoreID
|
||||
afsOrder.StoreID = order.StoreID
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
for _, sku := range orderFinancial.Skus {
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: sku.VendorID,
|
||||
VendorOrderID: sku.VendorOrderID,
|
||||
AfsOrderID: sku.VendorOrderID,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorStoreID: afsOrder.VendorStoreID,
|
||||
StoreID: afsOrder.StoreID,
|
||||
JxStoreID: afsOrder.JxStoreID,
|
||||
VendorSkuID: sku.VendorSkuID,
|
||||
SkuID: sku.SkuID,
|
||||
PromotionType: sku.PromotionType,
|
||||
Name: sku.Name,
|
||||
ShopPrice: sku.ShopPrice,
|
||||
SalePrice: sku.SalePrice,
|
||||
Count: sku.Count,
|
||||
SkuBoxMoney: sku.SkuBoxMoney,
|
||||
UserMoney: sku.UserMoney,
|
||||
PmSubsidyMoney: sku.PmSubsidyMoney,
|
||||
IsAfsOrder: 1,
|
||||
}
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSkuFinancial)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AfsOrderDetail2Financial(orderData map[string]interface{}) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
AfsOrderID: GetOrderIDFromMap(orderData),
|
||||
VendorOrderID: GetOrderIDFromMap(orderData),
|
||||
}
|
||||
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
|
||||
if err == nil {
|
||||
afsOrder.JxStoreID = order.JxStoreID
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
// 部分退款订单,第三方平台佣金会变化,金额为 orderData["commission"],是否将该字段更新到正向订单结算表中
|
||||
// 不作更新的话,商户可以得到的钱会少几毛钱,最终京西受益
|
||||
// 如果要更新,总佣金,京西佣金是否都要更新,而其它一系列连锁反应,是否需要考虑更新
|
||||
// 或者换个思路,不考虑变更之前的正向订单,在佣金上入手,退款金额减去佣金减少的部分
|
||||
orderFinancial, err := partner.CurOrderManager.LoadOrderFinancial(afsOrder.VendorOrderID, model.VendorIDEBAI)
|
||||
if err == nil {
|
||||
afsOrder.PmRefundMoney = orderFinancial.PmMoney - utils.MustInterface2Int64(orderData["commission"])
|
||||
} else {
|
||||
// 此处应该报错
|
||||
// globals.SugarLogger.Warnf("ebai AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrderFinancial", afsOrder.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
if orderData["refund_detail"] != nil {
|
||||
refundDetail := orderData["refund_detail"].([]interface{})
|
||||
for _, refundInfo := range refundDetail {
|
||||
xMap := refundInfo.(map[string]interface{})
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
AfsOrderID: afsOrder.AfsOrderID,
|
||||
VendorOrderID: afsOrder.VendorOrderID,
|
||||
// ConfirmTime: getTimeFromInterface(xMap["apply_time"]),
|
||||
VendorSkuID: utils.Interface2String(xMap["sku_id"]),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(xMap["custom_sku_id"]), 0)),
|
||||
Name: utils.Interface2String(xMap["name"]),
|
||||
UserMoney: utils.MustInterface2Int64(xMap["total_refund"]),
|
||||
PmSubsidyMoney: utils.MustInterface2Int64(xMap["shop_ele_refund"]),
|
||||
IsAfsOrder: 1,
|
||||
}
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSkuFinancial)
|
||||
afsOrder.SkuUserMoney += orderSkuFinancial.UserMoney
|
||||
afsOrder.PmSubsidyMoney += orderSkuFinancial.PmSubsidyMoney
|
||||
}
|
||||
if len(refundDetail) > 0 {
|
||||
afsOrder.AfsCreatedAt = getTimeFromInterface(refundDetail[0].(map[string]interface{})["apply_time"])
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai AfsOrderDetail2Financial, orderID:%s have no refund_detail", afsOrder.VendorOrderID)
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai AfsOrderDetail2Financial, orderID:% refund_detail is nil", afsOrder.VendorOrderID)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
// 存储饿百正向订单结账信息
|
||||
func (p *PurchaseHandler) OnOrderDetail(result map[string]interface{}, operation string) (err error) {
|
||||
err = partner.CurOrderManager.SaveOrderFinancialInfo(p.OrderDetail2Financial(result), operation)
|
||||
return err
|
||||
}
|
||||
|
||||
// func (p *PurchaseHandler) GetTrueEbaiOrder(result1 map[string]interface{}) (result2 map[string]interface{}) {
|
||||
// order := result1["order"].(map[string]interface{})
|
||||
// if utils.MustInterface2Int64(order["down_flag"]) == 1 {
|
||||
// result, err := api.EbaiAPI.OrderGet(GetOrderIDFromMap(order))
|
||||
// if err == nil {
|
||||
// return p.GetTrueEbaiOrder(result)
|
||||
// }
|
||||
// }
|
||||
// return result1
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) OrderDetail2Financial(result map[string]interface{}) (orderFinancial *model.OrderFinancial) {
|
||||
orderFinancial = &model.OrderFinancial{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
}
|
||||
order1 := result["order"].(map[string]interface{})
|
||||
orderFinancial.VendorOrderID = GetOrderIDFromMap(order1)
|
||||
orderFinancial.VendorOrderID2 = utils.Interface2String(order1["eleme_order_id"])
|
||||
// orderFinancial.DeliveryConfirmTime = getTimeFromInterface(order1["finished_time"])
|
||||
orderFinancial.TotalDiscountMoney = utils.MustInterface2Int64(order1["discount_fee"])
|
||||
orderFinancial.ReceivableFreight = utils.MustInterface2Int64(order1["send_fee"])
|
||||
orderFinancial.DownFlag = int8(utils.MustInterface2Int64(order1["down_flag"]))
|
||||
|
||||
if int(getInt64FromInterface(order1["delivery_party"])) == ebaiapi.DeliveryPartyFengElmSelf {
|
||||
orderFinancial.SelfDeliveryDiscountMoney = orderFinancial.ReceivableFreight
|
||||
orderFinancial.DistanceFreightMoney = 0
|
||||
// 通过本地数据库去取是否转美团/达达,并计算运费
|
||||
// wayBill, err := partner.CurOrderManager.LoadWaybill(orderFinancial.VendorOrderID, orderFinancial.VendorID)
|
||||
// if err == nil {
|
||||
// orderFinancial.JxFreightMoney = wayBill.DesiredFee
|
||||
// }
|
||||
}
|
||||
orderFinancial.BoxMoney = utils.ForceInterface2Int64(order1["package_fee"])
|
||||
orderFinancial.ActualPayMoney = utils.ForceInterface2Int64(order1["user_fee"])
|
||||
orderFinancial.PmMoney = utils.ForceInterface2Int64(order1["commission"])
|
||||
orderFinancial.ShopMoney = utils.ForceInterface2Int64(order1["shop_fee"])
|
||||
order, err := partner.CurOrderManager.LoadOrder(orderFinancial.VendorOrderID, orderFinancial.VendorID)
|
||||
storeID := 0
|
||||
jxStoreID := 0
|
||||
if err == nil {
|
||||
storeID = order.StoreID
|
||||
jxStoreID = order.JxStoreID
|
||||
skus := order.Skus
|
||||
if skus != nil {
|
||||
for _, x := range skus {
|
||||
orderFinancial.ShopPriceMoney += x.ShopPrice * int64(x.Count)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("ebai OrderDetail2Financial, orderID:%s is not found from partner.CurOrderManager.LoadOrder", orderFinancial.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
shop := result["shop"].(map[string]interface{})
|
||||
if result["products"] != nil {
|
||||
products := result["products"].([]interface{})
|
||||
for _, x := range products {
|
||||
for _, y := range x.([]interface{}) {
|
||||
product := y.(map[string]interface{})
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
// OrderFinancialID: orderFinancial.VendorOrderID,
|
||||
// ConfirmTime: getTimeFromInterface(order1["create_time"]),
|
||||
VendorStoreID: utils.Interface2String(shop["baidu_shop_id"]),
|
||||
StoreID: storeID,
|
||||
JxStoreID: jxStoreID,
|
||||
VendorSkuID: utils.Interface2String(product["baidu_product_id"]),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product["custom_sku_id"]), 0)),
|
||||
Name: utils.Interface2String(product["product_name"]),
|
||||
SalePrice: utils.MustInterface2Int64(product["product_price"]),
|
||||
Count: int(utils.MustInterface2Int64(product["product_amount"])),
|
||||
SkuBoxMoney: utils.MustInterface2Int64(product["package_fee"]),
|
||||
IsAfsOrder: 0,
|
||||
}
|
||||
orderFinancial.Skus = append(orderFinancial.Skus, orderSkuFinancial)
|
||||
orderFinancial.SalePriceMoney += orderSkuFinancial.SalePrice * int64(orderSkuFinancial.Count)
|
||||
orderFinancial.SkuBoxMoney += orderSkuFinancial.SkuBoxMoney
|
||||
orderFinancial.BoxMoney -= orderSkuFinancial.SkuBoxMoney
|
||||
}
|
||||
}
|
||||
}
|
||||
if result["discount"] != nil {
|
||||
discount := result["discount"].([]interface{})
|
||||
for _, x := range discount {
|
||||
xMap := x.(map[string]interface{})
|
||||
discountPrice := utils.MustInterface2Int64(xMap["fee"])
|
||||
orderFinancial.DiscountMoney += discountPrice
|
||||
orderFinancial.PmSubsidyMoney += utils.MustInterface2Int64(xMap["baidu_rate"]) // 平台承担补贴
|
||||
activity := &model.OrderDiscountFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
// ActivityName: utils.Interface2String(xMap["desc"]),
|
||||
// ActivityMoney: discountPrice,
|
||||
VendorActivityID: utils.Interface2String(xMap["activity_id"]),
|
||||
Type: utils.Interface2String(xMap["type"]),
|
||||
}
|
||||
orderFinancial.Discounts = append(orderFinancial.Discounts, activity)
|
||||
// 通过活动Id去取,京西活动补贴
|
||||
// orderFinancial.JxSubsidyMoney +=
|
||||
}
|
||||
}
|
||||
orderFinancial.FreightDiscountMoney = orderFinancial.TotalDiscountMoney - orderFinancial.DiscountMoney
|
||||
return orderFinancial
|
||||
}
|
||||
|
||||
func getInt64FromInterface(strOrNum interface{}) int64 {
|
||||
var resultNum int64
|
||||
if resultStr, ok := strOrNum.(string); ok {
|
||||
resultNum = utils.Str2Int64WithDefault(resultStr, 0)
|
||||
} else {
|
||||
resultNum = utils.Interface2Int64WithDefault(strOrNum, 0)
|
||||
}
|
||||
return resultNum
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func TestOnFinancialMsg(t *testing.T) {
|
||||
msg := &ebaiapi.CallbackMsg{
|
||||
Timestamp: time.Now().Unix(),
|
||||
Body: make(map[string]interface{}),
|
||||
}
|
||||
msg.Body["order_id"] = "1554939646172038357"
|
||||
|
||||
// 部分退款
|
||||
msg.Cmd = "order.partrefund.push"
|
||||
msg.Body["status"] = json.Number("20")
|
||||
|
||||
// 全单退款
|
||||
// msg.Cmd = "order.user.cancel"
|
||||
// msg.Body["type"] = json.Number("40")
|
||||
// msg.Body["cancel_type"] = json.Number("2")
|
||||
|
||||
res := CurPurchaseHandler.onAfsOrderMsg(msg)
|
||||
fmt.Println(res)
|
||||
}
|
||||
|
||||
func TestOnOrderDetail(t *testing.T) {
|
||||
orderID := "1554939646172038357"
|
||||
result, err := api.EbaiAPI.OrderGet(orderID)
|
||||
if err == nil {
|
||||
new(PurchaseHandler).OnOrderDetail(result, partner.CreatedPeration)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package ebai
|
||||
@@ -1,722 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
|
||||
"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/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 (
|
||||
// acceptOrderDelay = 180 * time.Second
|
||||
// pickupOrderDelay = 260 * time.Second
|
||||
pickupOrderDelay = 1 * time.Minute
|
||||
|
||||
callDeliveryDelay = 10 * time.Minute
|
||||
callDeliveryDelayGap = 30
|
||||
|
||||
fakeAcceptOrder = "fake_accept_order"
|
||||
fakeOrderAdjustFinished = "fake_order_adjust_finished"
|
||||
fakeOrderCanceled = "fake_order_canceled"
|
||||
)
|
||||
|
||||
// 饿百的接单会直接召唤配送,为了统一将饿百的接单影射成拣货完成,然后模拟一个接单消息
|
||||
|
||||
var (
|
||||
VendorStatus2StatusMap = map[string]int{
|
||||
ebaiapi.CmdOrderCreate: model.OrderStatusWaitAccepted,
|
||||
ebaiapi.OrderStatusNew: model.OrderStatusWaitAccepted,
|
||||
fakeAcceptOrder: model.OrderStatusAccepted,
|
||||
ebaiapi.OrderStatusAccepted: model.OrderStatusFinishedPickup,
|
||||
ebaiapi.OrderStatusCourierAccepted: model.OrderStatusDelivering,
|
||||
ebaiapi.OrderStatusCourierPickedup: model.OrderStatusDelivering,
|
||||
ebaiapi.OrderStatusFinished: model.OrderStatusFinished,
|
||||
ebaiapi.OrderStatusCanceled: model.OrderStatusCanceled,
|
||||
|
||||
fakeOrderAdjustFinished: model.OrderStatusAdjust,
|
||||
fakeOrderCanceled: model.OrderStatusCanceled,
|
||||
}
|
||||
|
||||
skuActTypeMap = map[string]int{
|
||||
ebaiapi.OrderSkuDiscountTypeZhe: 1,
|
||||
ebaiapi.OrderSkuDiscountTypeReduce: 1,
|
||||
ebaiapi.OrderSkuDiscountTypeTe: 1,
|
||||
}
|
||||
deliveryTypeMap = map[int]string{
|
||||
ebaiapi.DeliveryPartyFengElmSelf: model.OrderDeliveryTypeStoreSelf,
|
||||
}
|
||||
)
|
||||
|
||||
func mapDeliveryType(ebaiDeliveryParty int, businessType int) (deliveryType string) {
|
||||
if businessType == ebaiapi.DeliveryBusinessTypeZT {
|
||||
return model.OrderDeliveryTypeSelfTake
|
||||
} else {
|
||||
deliveryType = deliveryTypeMap[ebaiDeliveryParty]
|
||||
if deliveryType == "" {
|
||||
deliveryType = model.OrderDeliveryTypePlatform
|
||||
}
|
||||
}
|
||||
return deliveryType
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) {
|
||||
order, _, err = p.getOrder(vendorOrderID)
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
status, err = api.EbaiAPI.OrderStatusGet(vendorOrderID)
|
||||
if err == nil {
|
||||
status = p.getStatusFromVendorStatus(utils.Int2Str(status))
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getOrder(vendorOrderID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) {
|
||||
for i := 0; i < 2; i++ {
|
||||
orderMap, err = api.EbaiAPI.OrderGet(vendorOrderID)
|
||||
if err == nil {
|
||||
order = p.Map2Order(orderMap)
|
||||
// 饿百订单有时会出现取不到baidu_shop_id的情况,重试
|
||||
if order.VendorStoreID != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
return order, orderMap, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrder4PartRefund(vendorOrderID string) (order *model.GoodsOrder, err error) {
|
||||
taskIDs := []int{1, 2}
|
||||
var (
|
||||
err1, err2 error
|
||||
result1, result2 map[string]interface{}
|
||||
)
|
||||
task := tasksch.NewParallelTask("GetOrder4PartRefund", nil, jxcontext.AdminCtx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
taskID := batchItemList[0].(int)
|
||||
if taskID == 1 {
|
||||
result1, err1 = api.EbaiAPI.OrderGet(vendorOrderID)
|
||||
} else if taskID == 2 {
|
||||
result2, err2 = api.EbaiAPI.OrderPartRefundGet(vendorOrderID)
|
||||
}
|
||||
return nil, nil
|
||||
}, taskIDs)
|
||||
task.Run()
|
||||
task.GetResult(0)
|
||||
if err1 == nil {
|
||||
order = p.Map2Order(result1)
|
||||
if err2 == nil {
|
||||
order.Skus = p.partRefund2OrderDetailSkuList(utils.Interface2String(result2["order_id"]), result2["order_detail"])
|
||||
giftSkus, discountMoney := getZengSkus(vendorOrderID, result1)
|
||||
order.DiscountMoney = discountMoney
|
||||
order.Skus = append(order.Skus, giftSkus...)
|
||||
order.ActualPayPrice = utils.MustInterface2Int64(result2["user_fee"])
|
||||
order.TotalShopMoney = utils.MustInterface2Int64(result2["shop_fee"])
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
} else if err2Ext, ok := err2.(*utils.ErrorWithCode); !ok || err2Ext.IntCode() != ebaiapi.ErrOrderIsNotPartRefund {
|
||||
err = err2
|
||||
}
|
||||
} else {
|
||||
err = err1
|
||||
}
|
||||
return order, err
|
||||
}
|
||||
|
||||
func getZengSkus(orderID string, orderMan map[string]interface{}) (skus []*model.OrderSku, discountMoney int64) {
|
||||
discounts, _ := orderMan["discount"].([]interface{})
|
||||
for _, v := range discounts {
|
||||
discount := v.(map[string]interface{})
|
||||
discountType := utils.Interface2String(discount["type"])
|
||||
if discountType == ebaiapi.OrderSkuDiscountTypeZeng {
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDEBAI,
|
||||
Count: 1,
|
||||
SkuID: 0,
|
||||
VendorSkuID: "",
|
||||
SkuName: utils.Interface2String(discount["desc"]),
|
||||
VendorPrice: 0,
|
||||
}
|
||||
skus = append(skus, sku)
|
||||
}
|
||||
discountMoney += utils.Interface2Int64WithDefault(discount["fee"], 0)
|
||||
}
|
||||
return skus, discountMoney
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) partRefund2OrderDetailSkuList(orderID string, orderDetail2 interface{}) (skuList []*model.OrderSku) {
|
||||
orderDetail := orderDetail2.([]interface{})
|
||||
for _, product2 := range orderDetail {
|
||||
product := product2.(map[string]interface{})
|
||||
skuName := product["name"].(string)
|
||||
_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(skuName)
|
||||
number := int(utils.MustInterface2Int64(product["number"]))
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDEBAI,
|
||||
Count: number,
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product[ebaiapi.KeyCustomSkuID]), 0)),
|
||||
VendorSkuID: utils.Interface2String(product[ebaiapi.KeySkuID]),
|
||||
SkuName: skuName,
|
||||
// Weight: int(utils.Interface2Int64WithDefault(product["total_weight"], 0)) / number, // 退单这里的total_weight有BUG,这里的total_weight还是没有退单时的值
|
||||
VendorPrice: utils.MustInterface2Int64(product["product_price"]),
|
||||
}
|
||||
sku.SalePrice, _, sku.StoreSubName = getSkuSalePrice(product)
|
||||
if sku.Weight == 0 {
|
||||
sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit) // 订单信息里没有重量,只有名字里尝试找
|
||||
}
|
||||
skuList = append(skuList, sku)
|
||||
}
|
||||
return skuList
|
||||
}
|
||||
|
||||
func getExpectedDeliveredTime(orderMap map[string]interface{}) (expectedTime time.Time) {
|
||||
expectedTime = getTimeFromInterface(orderMap["latest_send_time"])
|
||||
if utils.IsTimeZero(expectedTime) {
|
||||
expectedTime = getTimeFromInterface(orderMap["send_time"])
|
||||
}
|
||||
return expectedTime
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := orderData
|
||||
shopMap := result["shop"].(map[string]interface{})
|
||||
orderMap := result["order"].(map[string]interface{})
|
||||
userMap := result["user"].(map[string]interface{})
|
||||
vendorOrderID := orderMap["order_id"].(string)
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: vendorOrderID,
|
||||
VendorOrderID2: utils.Interface2String(orderMap["eleme_order_id"]),
|
||||
VendorID: model.VendorIDEBAI,
|
||||
VendorStoreID: utils.Interface2String(shopMap["baidu_shop_id"]),
|
||||
StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(shopMap["id"]), 0)),
|
||||
StoreName: utils.Interface2String(shopMap["name"]),
|
||||
VendorUserID: utils.Interface2String(userMap["user_id"]),
|
||||
ConsigneeName: utils.Interface2String(userMap["name"]),
|
||||
ConsigneeMobile: jxutils.FormalizeMobile(utils.Interface2String(userMap["phone"])),
|
||||
ConsigneeAddress: utils.Interface2String(userMap["address"]),
|
||||
CoordinateType: model.CoordinateTypeMars,
|
||||
BuyerComment: utils.TrimBlankChar(utils.Interface2String(orderMap["remark"])),
|
||||
ExpectedDeliveredTime: getExpectedDeliveredTime(orderMap),
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(orderMap["status"])),
|
||||
OrderSeq: int(utils.ForceInterface2Int64(orderMap["order_index"])),
|
||||
StatusTime: getTimeFromInterface(orderMap["create_time"]),
|
||||
OrderCreatedAt: getTimeFromInterface(orderMap["create_time"]),
|
||||
// OrderFinishedAt: getTimeFromInterface(orderMap["finished_time"]),
|
||||
OriginalData: string(utils.MustMarshal(result)),
|
||||
ActualPayPrice: utils.ForceInterface2Int64(orderMap["user_fee"]),
|
||||
BaseFreightMoney: utils.ForceInterface2Int64(orderMap["send_fee"]),
|
||||
TotalShopMoney: utils.ForceInterface2Int64(orderMap["shop_fee"]),
|
||||
DeliveryType: mapDeliveryType(int(utils.ForceInterface2Int64(orderMap["delivery_party"])), int(utils.ForceInterface2Int64(orderMap["business_type"]))),
|
||||
|
||||
InvoiceTitle: utils.Interface2String(orderMap["invoice_title"]),
|
||||
InvoiceTaxerID: utils.Interface2String(orderMap["taxer_id"]),
|
||||
InvoiceEmail: jxutils.GetOneEmailFromStr(utils.Interface2String(orderMap["remark"])),
|
||||
|
||||
VendorOrgCode: utils.Interface2String(result["source"]),
|
||||
}
|
||||
finishTime := getTimeFromInterface(orderMap["finished_time"])
|
||||
if finishTime == utils.ZeroTimeValue {
|
||||
order.OrderFinishedAt = utils.DefaultTimeValue
|
||||
} else {
|
||||
order.OrderFinishedAt = finishTime
|
||||
}
|
||||
if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) {
|
||||
order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 饿百要求在5分钟内拣货,不然订单会被取消
|
||||
}
|
||||
if order.ConsigneeMobile == "" {
|
||||
if mobileInfo, err := api.EbaiAPI.OrderPrivateInfo(vendorOrderID); err == nil {
|
||||
order.ConsigneeMobile = jxutils.FormalizeMobile(mobileInfo.ShortNumber)
|
||||
}
|
||||
}
|
||||
if order.StoreID > math.MaxInt32 {
|
||||
order.StoreID = 0
|
||||
}
|
||||
order.Status = p.getStatusFromVendorStatus(order.VendorStatus)
|
||||
if utils.MustInterface2Int64(orderMap["send_immediately"]) == 1 {
|
||||
order.BusinessType = model.BusinessTypeImmediate
|
||||
} else {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
if utils.IsTimeZero(order.ExpectedDeliveredTime) {
|
||||
order.ExpectedDeliveredTime = getTimeFromInterface(orderMap["latest_send_time"])
|
||||
}
|
||||
}
|
||||
|
||||
deliveryGeo := userMap["coord_amap"].(map[string]interface{})
|
||||
originalLng := utils.Interface2Float64WithDefault(deliveryGeo["longitude"], 0.0) // 饿百的订单在过一段时间后,经纬度信息会变成字符串"**"
|
||||
originalLat := utils.Interface2Float64WithDefault(deliveryGeo["latitude"], 0.0)
|
||||
// lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysBaidu)
|
||||
// if err2 == nil {
|
||||
// originalLng = lng
|
||||
// originalLat = lat
|
||||
// order.CoordinateType = model.CoordinateTypeMars
|
||||
// }
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng)
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat)
|
||||
|
||||
products := result["products"].([]interface{})[0].([]interface{})
|
||||
for _, product2 := range products {
|
||||
product := product2.(map[string]interface{})
|
||||
skuName := product["product_name"].(string)
|
||||
_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(skuName)
|
||||
productAmount := int(utils.MustInterface2Int64(product["product_amount"]))
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: model.VendorIDEBAI,
|
||||
Count: productAmount,
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product[ebaiapi.KeyCustomSkuID]), 0)),
|
||||
VendorSkuID: utils.Interface2String(product["baidu_product_id"]),
|
||||
SkuName: skuName,
|
||||
Weight: int(utils.Interface2Int64WithDefault(product["total_weight"], 0)) / productAmount,
|
||||
VendorPrice: utils.MustInterface2Int64(product["product_price"]),
|
||||
}
|
||||
var baiduRate int64
|
||||
sku.SalePrice, baiduRate, sku.StoreSubName = getSkuSalePrice(product)
|
||||
order.PmSubsidyMoney += baiduRate
|
||||
if sku.Weight == 0 {
|
||||
sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit) // 订单信息里没有重量,只有名字里尝试找
|
||||
}
|
||||
// if product["isGift"].(bool) {
|
||||
// sku.SkuType = 1
|
||||
// }
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
giftSkus, discountMoney := getZengSkus(vendorOrderID, orderData)
|
||||
order.DiscountMoney = discountMoney
|
||||
order.Skus = append(order.Skus, giftSkus...)
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
return order
|
||||
}
|
||||
|
||||
func getSkuSalePrice(product map[string]interface{}) (salePrice, baiduRate int64, vendorActType string) {
|
||||
var product2 *ebaiapi.OrderProductInfo
|
||||
if err := utils.Map2StructByJson(product, &product2, true); err != nil {
|
||||
return utils.MustInterface2Int64(product["product_price"]), 0, ""
|
||||
}
|
||||
return getSkuSalePrice2(product2)
|
||||
}
|
||||
|
||||
func getSkuSalePrice2(product *ebaiapi.OrderProductInfo) (salePrice, baiduRate int64, vendorActType string) {
|
||||
salePrice = int64(product.ProductPrice)
|
||||
if product.ProductSubsidy != nil {
|
||||
for _, v := range product.ProductSubsidy.DiscountDetail {
|
||||
if skuActTypeMap[v.Type] == 1 {
|
||||
skuCount := product.ProductAmount
|
||||
if skuCount == 0 {
|
||||
skuCount = product.Number
|
||||
}
|
||||
salePrice -= int64(math.Round(float64(v.BaiduRate+v.ShopRate) / float64(skuCount))) // 饿百同一SKU的优惠与非优惠没有拆开,平均摊销处理
|
||||
vendorActType = v.Type
|
||||
}
|
||||
baiduRate += int64(v.BaiduRate)
|
||||
}
|
||||
}
|
||||
return salePrice, baiduRate, vendorActType
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
|
||||
if isAcceptIt {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderConfirm(order.VendorOrderID)
|
||||
utils.AfterFuncWithRecover(time.Minute, func() {
|
||||
err = api.EbaiAPI.OrderPickComplete(order.VendorOrderID)
|
||||
})
|
||||
}
|
||||
p.postFakeMsg(order.VendorOrderID, fakeAcceptOrder)
|
||||
} else {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderCancel(order.VendorOrderID, ebaiapi.CancelTypeCustom, "bu")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
// err = api.EbaiAPI.OrderPickComplete(order.VendorOrderID)
|
||||
}
|
||||
if err == nil {
|
||||
p.postFakeMsg(order.VendorOrderID, ebaiapi.OrderStatusAccepted)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
return err
|
||||
}
|
||||
|
||||
// 将订单从购物平台配送转为自送
|
||||
func (p *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if err = api.EbaiAPI.OrderSwitchselfdelivery(order.VendorOrderID); err != nil {
|
||||
if utils.IsErrMatch(err, "301251", nil) {
|
||||
if deliveryStatus, err2 := api.EbaiAPI.OrderDeliveryGet(order.VendorOrderID); err2 == nil {
|
||||
deliveryStatus := utils.Int64ToStr(utils.MustInterface2Int64(deliveryStatus["status"]))
|
||||
if deliveryStatus == ebaiapi.WaybillStatusSelfDelivery {
|
||||
err = nil
|
||||
} else if deliveryStatus == ebaiapi.WaybillStatusDeliveryCancled {
|
||||
p.trySyncCancelStatus(order.VendorOrderID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
// 饿百不会发送配送中,模拟发送
|
||||
p.postFakeMsg(order.VendorOrderID, ebaiapi.OrderStatusCourierAccepted)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) trySyncCancelStatus(vendorOrderID string) (err error) {
|
||||
orderInfo, err := api.EbaiAPI.OrderGet2(vendorOrderID)
|
||||
if err == nil {
|
||||
if utils.Int2Str(orderInfo.Order.Status) == ebaiapi.OrderStatusCanceled {
|
||||
p.postFakeMsg(vendorOrderID, fakeOrderCanceled)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 将订单从购物平台配送转为自送后又送达
|
||||
func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
|
||||
// todo 饿百转商家自送后,没有确认送达的概念,空操作
|
||||
return err
|
||||
}
|
||||
|
||||
// 完全自送的门店表示开始配送
|
||||
func (p *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai SelfDeliverDelivering orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderSendOut(order.VendorOrderID, userName)
|
||||
}
|
||||
if err == nil {
|
||||
// 饿百不会发送配送中,模拟发送
|
||||
p.postFakeMsg(order.VendorOrderID, ebaiapi.OrderStatusCourierAccepted)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 完全自送的门店表示配送完成
|
||||
func (p *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("ebai SelfDeliverDelivered orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderComplete(order.VendorOrderID, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//
|
||||
func (c *PurchaseHandler) onOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
|
||||
if c.isAfsMsg(msg) {
|
||||
retVal = c.onAfsOrderMsg(msg)
|
||||
} else {
|
||||
status := c.callbackMsg2Status(msg)
|
||||
if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 {
|
||||
return nil
|
||||
}
|
||||
if ebaiapi.CmdOrderCreate == msg.Cmd {
|
||||
retVal = c.onOrderNew(msg, status)
|
||||
} else {
|
||||
var err error
|
||||
if status != nil {
|
||||
if status.Status == model.OrderStatusAdjust {
|
||||
var order *model.GoodsOrder
|
||||
if order, err = c.GetOrder4PartRefund(GetOrderIDFromMsg(msg)); err == nil {
|
||||
err = partner.CurOrderManager.OnOrderAdjust(order, status)
|
||||
}
|
||||
} else {
|
||||
// 处理饿百降级订单的情况
|
||||
// 是否降级;1:是,0:否;极少数订单因网络或信息交互异常,导致订单部分字段(如订单金额)生成延迟,此时订单会被标记为“已降级”状态,需开发者重新调用查看订单详情接口获取完整订单数据。
|
||||
// toto sku是否也需要处理?
|
||||
if status.Status == model.OrderStatusDelivering || status.Status == model.OrderStatusFinished {
|
||||
if order, err2 := partner.CurOrderManager.LoadOrder(status.VendorOrderID, status.VendorID); err2 == nil {
|
||||
if order.TotalShopMoney == 0 {
|
||||
if order2, err2 := c.GetOrder(msg.Source, status.VendorOrderID); err2 == nil {
|
||||
order.TotalShopMoney = order2.TotalShopMoney
|
||||
order.PmSubsidyMoney = order2.PmSubsidyMoney
|
||||
partner.CurOrderManager.UpdateOrderFields(order, []string{"TotalShopMoney", "PmSubsidyMoney"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged(msg.Source, status)
|
||||
}
|
||||
}
|
||||
retVal = api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil)
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderNew(msg *ebaiapi.CallbackMsg, orderStatus *model.OrderStatus) (response *ebaiapi.CallbackResponse) {
|
||||
vendorOrderID := GetOrderIDFromMsg(msg)
|
||||
order, orderMap, err := c.getOrder(vendorOrderID)
|
||||
if err == nil {
|
||||
// 饿百订单有时会出现取不到baidu_shop_id的情况,返回错误让服务器重试
|
||||
if order.VendorStoreID == "" {
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, fmt.Errorf("订单%s的baidu_shop_id为空", order.VendorOrderID), "")
|
||||
}
|
||||
if err = partner.CurOrderManager.OnOrderNew(order, orderStatus); err == nil {
|
||||
utils.CallFuncAsync(func() {
|
||||
c.OnOrderDetail(orderMap, partner.CreatedPeration)
|
||||
})
|
||||
}
|
||||
}
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, map[string]interface{}{
|
||||
"source_order_id": vendorOrderID,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Status(msg *ebaiapi.CallbackMsg) (orderStatus *model.OrderStatus) {
|
||||
orderID := GetOrderIDFromMsg(msg)
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDEBAI,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: orderID,
|
||||
RefVendorID: model.VendorIDEBAI,
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
VendorStatus: msg.Cmd,
|
||||
}
|
||||
if msg.Cmd == ebaiapi.CmdOrderUserCancel {
|
||||
msgType := int(utils.MustInterface2Int64(msg.Body["type"]))
|
||||
cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"]))
|
||||
orderStatus.Remark = buildFullReason(utils.Interface2String(msg.Body["cancel_reason"]), utils.Interface2String(msg.Body["addition_reason"]))
|
||||
orderStatus.VendorStatus = msg.Cmd + "-" + utils.Int2Str(msgType)
|
||||
if cancelType == ebaiapi.OrderUserCancelTypeBeforeSale {
|
||||
if msgType == ebaiapi.OrderUserCancelApply /* || msgType == ebaiapi.OrderUserCancelCSIntervene */ {
|
||||
orderStatus.Status = model.OrderStatusApplyCancel
|
||||
} else if msgType == ebaiapi.OrderUserCancelCSRefused ||
|
||||
msgType == ebaiapi.OrderUserCancelMerchantRefused {
|
||||
orderStatus.Status = model.OrderStatusVendorRejectCancel
|
||||
} else if msgType == ebaiapi.OrderUserCancelInvalid {
|
||||
orderStatus.Status = model.OrderStatusUndoApplyCancel
|
||||
} else if msgType == ebaiapi.OrderUserCancelCSAgreed ||
|
||||
msgType == ebaiapi.OrderUserCancelMerchantAgreed {
|
||||
orderStatus.Status = model.OrderStatusVendorAgreeCancel
|
||||
}
|
||||
}
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderPartRefund {
|
||||
msgType := int(utils.MustInterface2Int64(msg.Body["type"]))
|
||||
status := int(utils.MustInterface2Int64(msg.Body["status"]))
|
||||
orderStatus.Remark = buildFullReason(utils.Interface2String(msg.Body["reason"]), utils.Interface2String(msg.Body["addition_reason"]))
|
||||
if msgType == ebaiapi.OrderPartRefuncTypeMerchant && status == ebaiapi.OrderPartRefundSuccess {
|
||||
orderStatus.VendorStatus = fakeOrderAdjustFinished
|
||||
}
|
||||
} else if status, ok := msg.Body["status"]; ok {
|
||||
if vendorStatus, ok := status.(string); ok {
|
||||
orderStatus.VendorStatus = vendorStatus
|
||||
} else {
|
||||
orderStatus.VendorStatus = utils.Int64ToStr(utils.MustInterface2Int64(status))
|
||||
}
|
||||
orderStatus.Remark = utils.Interface2String(msg.Body["reason"])
|
||||
}
|
||||
if orderStatus.Status == 0 {
|
||||
orderStatus.Status = c.getStatusFromVendorStatus(orderStatus.VendorStatus)
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func buildFullReason(reason, addReason string) (fullReason string) {
|
||||
fullReason = reason
|
||||
if addReason != "" {
|
||||
fullReason += ",额外原因:" + addReason
|
||||
}
|
||||
return fullReason
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) {
|
||||
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusAccepted {
|
||||
params = &partner.StatusActionParams{ // PickDeadline没有设置时才有效,饿百要求在5分钟内拣货,不然订单会被取消
|
||||
Timeout: pickupOrderDelay,
|
||||
}
|
||||
} else if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusFinishedPickup {
|
||||
params = &partner.StatusActionParams{ // 立即达订单有效,自配送延时召唤配送
|
||||
Timeout: callDeliveryDelay,
|
||||
TimeoutGap: callDeliveryDelayGap,
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) getOrderStoreDeliveryType(order *model.GoodsOrder) (deliveryType int) {
|
||||
sql := `
|
||||
SELECT *
|
||||
FROM store_map t1
|
||||
WHERE t1.vendor_store_id = ?
|
||||
AND t1.vendor_id = ?
|
||||
AND t1.deleted_at = ?
|
||||
`
|
||||
db := dao.GetDB()
|
||||
var storeMap *model.StoreMap
|
||||
if err := dao.GetRow(db, &storeMap, sql, order.VendorStoreID, model.VendorIDEBAI, utils.DefaultTimeValue); err == nil {
|
||||
return int(storeMap.DeliveryType)
|
||||
} else if !dao.IsNoRowsError(err) {
|
||||
globals.SugarLogger.Warnf("getOrderStoreDeliveryType orderID:%s failed with error:%v", order.VendorOrderID, err)
|
||||
}
|
||||
return scheduler.StoreDeliveryTypeByPlatform
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) postFakeMsg(vendorOrderID, vendorStatus string) {
|
||||
msg := &ebaiapi.CallbackMsg{
|
||||
Cmd: ebaiapi.CmdOrderStatus,
|
||||
Timestamp: time.Now().Unix(),
|
||||
Body: map[string]interface{}{
|
||||
"status": vendorStatus,
|
||||
"order_id": vendorOrderID,
|
||||
},
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
OnCallbackMsg(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func getTimeFromInterface(timeValue interface{}) time.Time {
|
||||
var timeStamp int64
|
||||
if timeStr, ok := timeValue.(string); ok {
|
||||
timeStamp = utils.Str2Int64WithDefault(timeStr, 0)
|
||||
} else {
|
||||
timeStamp = utils.Interface2Int64WithDefault(timeValue, 0)
|
||||
}
|
||||
if timeStamp < 1538103149 { // 立即达订单给的是1(而不是空,0),1538103149不是特殊值,只是一个任意之前的时间,这样写可以处理
|
||||
return utils.DefaultTimeValue
|
||||
}
|
||||
return utils.Timestamp2Time(timeStamp)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
mobile, err = api.EbaiAPI.GetRealMobile4Order(order.VendorOrderID)
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if isAgree {
|
||||
err = api.EbaiAPI.OrderAgreeRefund(order.VendorOrderID)
|
||||
} else {
|
||||
err = api.EbaiAPI.OrderDisagreeRefund(order.VendorOrderID, reason)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderCancel(order.VendorOrderID, ebaiapi.CancelTypeCustom, reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
// 饿百必须要确认订单后才能调整单
|
||||
if order.Status < model.OrderStatusFinishedPickup {
|
||||
err = c.PickupGoods(order, false, ctx.GetUserName())
|
||||
}
|
||||
if err == nil {
|
||||
var skuList []*ebaiapi.RefundSku
|
||||
for _, sku := range removedSkuList {
|
||||
skuList = append(skuList, &ebaiapi.RefundSku{
|
||||
CustomeSkuID: utils.Int2Str(jxutils.GetSkuIDFromOrderSku(sku)),
|
||||
Number: utils.Int2Str(sku.Count),
|
||||
})
|
||||
}
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderPartRefund(order.VendorOrderID, skuList)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) {
|
||||
if utils.IsTimeZero(queryDate) {
|
||||
return nil, fmt.Errorf("queryDate必须指定")
|
||||
}
|
||||
fromDate := utils.Time2Date(queryDate)
|
||||
toDate := fromDate.Add(24*time.Hour - 1)
|
||||
var vendorStoreIDs []string
|
||||
if vendorStoreID == "" {
|
||||
vendorStoreIDs, err = c.GetAllStoresVendorID(ctx, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
vendorStoreIDs = []string{vendorStoreID}
|
||||
}
|
||||
task := tasksch.NewParallelTask("ebai ListOrders", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorStoreID := batchItemList[0].(string)
|
||||
orderList, err := api.EbaiAPI.OrderListAll("", utils.Str2Int64(vendorStoreID), fromDate.Unix(), toDate.Unix(), 0)
|
||||
if err == nil {
|
||||
retVal = orderList
|
||||
}
|
||||
return retVal, err
|
||||
}, vendorStoreIDs)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
orderList, err := task.GetResult(0)
|
||||
if err == nil && len(orderList) > 0 {
|
||||
vendorOrderIDs = make([]string, len(orderList))
|
||||
for k, v := range orderList {
|
||||
orderInfo := v.(*ebaiapi.ListOrderItemInfo)
|
||||
vendorOrderIDs[k] = orderInfo.OrderID
|
||||
}
|
||||
}
|
||||
return vendorOrderIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
|
||||
orderInfo, err := api.EbaiAPI.GetStoreOrderInfo(vendorOrderID)
|
||||
if err == nil {
|
||||
if orderBasic, _ := orderInfo["order_basic"].(map[string]interface{}); orderBasic != nil {
|
||||
tipFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(orderBasic["delivery_tip_amount"], 0))
|
||||
}
|
||||
}
|
||||
return tipFee, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.ModifyTip4OrderWaybill(vendorOrderID, "", jxutils.IntPrice2Standard(tipFee), 0)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "HTTP code is not 200") {
|
||||
return fmt.Errorf("饿百此订单暂不支持加小费!")
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
AfsVendorStatus2Status4PartRefundMap = map[int]int{
|
||||
ebaiapi.OrderPartRefundApply: model.AfsOrderStatusWait4Approve,
|
||||
ebaiapi.OrderPartRefundSuccess: model.AfsOrderStatusFinished,
|
||||
ebaiapi.OrderPartRefundUserApplyArbitration: model.OrderStatusUnknown, // 是否是中间状态
|
||||
ebaiapi.OrderPartRefundFailed: model.AfsOrderStatusFailed,
|
||||
ebaiapi.OrderPartRefundMerchantRefused: model.AfsOrderStatusFailed, // 是否是中间状态
|
||||
}
|
||||
AfsVendorStatus2Status4UserCancel = map[int]int{
|
||||
ebaiapi.OrderUserCancelApply: model.AfsOrderStatusWait4Approve,
|
||||
ebaiapi.OrderUserCancelCSIntervene: model.OrderStatusUnknown,
|
||||
ebaiapi.OrderUserCancelCSRefused: model.AfsOrderStatusFailed,
|
||||
ebaiapi.OrderUserCancelCSAgreed: model.AfsOrderStatusFinished,
|
||||
ebaiapi.OrderUserCancelMerchantRefused: model.AfsOrderStatusFailed,
|
||||
ebaiapi.OrderUserCancelMerchantAgreed: model.AfsOrderStatusFinished,
|
||||
ebaiapi.OrderUserCancelInvalid: model.AfsOrderStatusFailed,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) isAfsMsg(msg *ebaiapi.CallbackMsg) bool {
|
||||
if msg.Cmd == ebaiapi.CmdOrderPartRefund {
|
||||
msgType := int(utils.MustInterface2Int64(msg.Body["type"]))
|
||||
return msgType == ebaiapi.OrderPartRefuncTypeCustomer
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
|
||||
cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"]))
|
||||
return cancelType == ebaiapi.OrderUserCancelTypeAfterSale
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandlerAsync(func() {
|
||||
retVal = c.onAfsOrderMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(GetOrderIDFromMsg(msg), model.VendorIDEBAI))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
|
||||
if orderStatus := c.callbackAfsMsg2Status(msg); orderStatus != nil {
|
||||
var err error
|
||||
if orderStatus.Status == model.AfsOrderStatusWait4Approve || orderStatus.Status == model.AfsOrderStatusNew {
|
||||
var afsOrder *model.AfsOrder
|
||||
if msg.Cmd == ebaiapi.CmdOrderPartRefund {
|
||||
partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo)
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDEBAI,
|
||||
AfsOrderID: orderStatus.VendorOrderID,
|
||||
VendorOrderID: orderStatus.RefVendorOrderID,
|
||||
VendorStoreID: "",
|
||||
StoreID: 0,
|
||||
AfsCreatedAt: utils.Timestamp2Time(msg.Timestamp),
|
||||
VendorAppealType: "",
|
||||
AppealType: model.AfsAppealTypeRefund,
|
||||
VendorReasonType: partRefundData.ReasonType,
|
||||
ReasonType: c.convertAfsReasonType(partRefundData.ReasonType),
|
||||
ReasonDesc: utils.LimitUTF8StringLen(buildFullReason(partRefundData.Reason, partRefundData.AdditionReason), 1024),
|
||||
ReasonImgList: utils.LimitUTF8StringLen(strings.Join(partRefundData.Photos, ","), 1024),
|
||||
RefundType: model.AfsTypePartRefund,
|
||||
|
||||
VendorOrgCode: msg.Source,
|
||||
// FreightUserMoney: afsInfo.OrderFreightMoney,
|
||||
// AfsFreightMoney: afsInfo.AfsFreight,
|
||||
// BoxMoney: afsInfo.PackagingMoney,
|
||||
// TongchengFreightMoney: afsInfo.TongchengFreightMoney,
|
||||
// SkuBoxMoney: afsInfo.MealBoxMoney,
|
||||
}
|
||||
for _, sku := range partRefundData.RefundProducts {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
// VendorID: model.VendorIDEBAI,
|
||||
// AfsOrderID: afsOrder.AfsOrderID,
|
||||
// VendorOrderID: afsOrder.VendorOrderID,
|
||||
// VendorStoreID: afsOrder.VendorStoreID,
|
||||
// StoreID: afsOrder.StoreID,
|
||||
// IsAfsOrder: 1,
|
||||
|
||||
Count: sku.Number,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorSkuID: sku.SkuID,
|
||||
SkuID: int(utils.Str2Int64WithDefault(sku.CustomSkuID, 0)),
|
||||
Name: sku.Name,
|
||||
UserMoney: sku.TotalRefund,
|
||||
PmSkuSubsidyMoney: sku.ShopEleRefund,
|
||||
}
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
|
||||
if afsOrder = c.createAfsOrder(msg); afsOrder != nil {
|
||||
// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDEBAI); err2 == nil {
|
||||
// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg)
|
||||
cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
|
||||
afsOrder.AfsOrderID = orderStatus.VendorOrderID
|
||||
afsOrder.RefundType = model.AfsTypeFullRefund
|
||||
afsOrder.AppealType = model.AfsAppealTypeRefund
|
||||
afsOrder.VendorReasonType = ""
|
||||
afsOrder.ReasonType = model.AfsReasonNotOthers
|
||||
afsOrder.ReasonDesc = utils.LimitUTF8StringLen(buildFullReason(cancelData.CancelReason, cancelData.AdditionReason), 1024)
|
||||
afsOrder.ReasonImgList = utils.LimitUTF8StringLen(strings.Join(cancelData.Pictures, ","), 1024)
|
||||
}
|
||||
}
|
||||
if afsOrder != nil {
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
|
||||
}
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
|
||||
}
|
||||
retVal = api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) createAfsOrder(msg *ebaiapi.CallbackMsg) (afsOrder *model.AfsOrder) {
|
||||
cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
|
||||
afsOrder, err := partner.CurOrderManager.CreateAfsOrderFromOrder(utils.Int64ToStr(cancelData.OrderID), model.VendorIDEBAI)
|
||||
if err == nil {
|
||||
afsOrder.AfsOrderID = afsOrder.VendorOrderID
|
||||
afsOrder.AfsCreatedAt = utils.Timestamp2Time(msg.Timestamp)
|
||||
} else {
|
||||
afsOrder = nil
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) convertAfsReasonType(vendorReasonType string) int8 {
|
||||
return model.AfsReasonNotOthers
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAfsStatusFromVendorStatus4PartRefund(vendorStatus int) int {
|
||||
return AfsVendorStatus2Status4PartRefundMap[vendorStatus]
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAfsStatusFromVendorStatus4UserCancel(vendorStatus int) int {
|
||||
return AfsVendorStatus2Status4UserCancel[vendorStatus]
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackAfsMsg2Status(msg *ebaiapi.CallbackMsg) (orderStatus *model.OrderStatus) {
|
||||
if msg.Cmd == ebaiapi.CmdOrderPartRefund {
|
||||
partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo)
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: partRefundData.RefundID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: model.VendorIDEBAI,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: utils.Int64ToStr(partRefundData.OrderID),
|
||||
RefVendorID: model.VendorIDEBAI,
|
||||
VendorStatus: utils.Int2Str(partRefundData.Status),
|
||||
Status: c.GetAfsStatusFromVendorStatus4PartRefund(partRefundData.Status),
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
Remark: buildFullReason(partRefundData.Reason, partRefundData.AdditionReason),
|
||||
}
|
||||
if orderStatus.Status == model.AfsOrderStatusWait4Approve && partRefundData.Type != ebaiapi.OrderPartRefuncTypeCustomer {
|
||||
orderStatus.Status = model.AfsOrderStatusNew
|
||||
}
|
||||
} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
|
||||
cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: utils.Int64ToStr(cancelData.OrderID), // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: model.VendorIDEBAI,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: utils.Int64ToStr(cancelData.OrderID),
|
||||
RefVendorID: model.VendorIDEBAI,
|
||||
VendorStatus: utils.Int2Str(cancelData.Type),
|
||||
Status: c.GetAfsStatusFromVendorStatus4UserCancel(cancelData.Type),
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
Remark: buildFullReason(cancelData.CancelReason, cancelData.AdditionReason),
|
||||
}
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if approveType == partner.AfsApproveTypeRefused {
|
||||
err = api.EbaiAPI.OrderDisagreeRefund(order.VendorOrderID, reason)
|
||||
} else {
|
||||
err = api.EbaiAPI.OrderAgreeRefund(order.VendorOrderID)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
err = fmt.Errorf("内部错误,饿百平台不支持确认收到退货操作")
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return c.PartRefundOrder(ctx, order, order.Skus, reason)
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderPartRefund(order.VendorOrderID, orderSkus2AfsSkus(refundSkuList))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func orderSkus2AfsSkus(refundSkuList []*model.OrderSku) (removeSkuList []*ebaiapi.RefundSku) {
|
||||
for _, v := range refundSkuList {
|
||||
refundSku := &ebaiapi.RefundSku{
|
||||
CustomeSkuID: utils.Int2Str(v.SkuID),
|
||||
Number: utils.Int2Str(v.Count),
|
||||
}
|
||||
removeSkuList = append(removeSkuList, refundSku)
|
||||
}
|
||||
return removeSkuList
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
// 饿百的评价不是一点一点出来的,而是一下把前一天的全部崩出来。。。
|
||||
|
||||
const (
|
||||
RefreshCommentTime = 84 * time.Hour
|
||||
RefreshCommentTimeInterval = 60 * time.Minute
|
||||
EBAI_BAD_COMMENTS_MAX_MODIFY_TIME = 24 // 小时
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) StartRefreshComment() {
|
||||
utils.AfterFuncWithRecover(5*time.Second, func() {
|
||||
c.refreshCommentOnce()
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) refreshCommentOnce() {
|
||||
c.RefreshComment(time.Now().Add(-RefreshCommentTime), time.Now())
|
||||
utils.AfterFuncWithRecover(RefreshCommentTimeInterval, func() {
|
||||
c.refreshCommentOnce()
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) RefreshComment(fromTime, toTime time.Time) (err error) {
|
||||
globals.SugarLogger.Debugf("RefreshComment fromTime:%s, toTime:%s", utils.Time2Str(fromTime), utils.Time2Str(toTime))
|
||||
var orderCommentList []*model.OrderComment
|
||||
stepGap := 24 * time.Hour
|
||||
stepFromTime := fromTime
|
||||
for {
|
||||
stepToTime := stepFromTime.Add(stepGap - time.Second)
|
||||
if stepToTime.Sub(toTime) > 0 {
|
||||
stepToTime = toTime
|
||||
}
|
||||
if stepToTime.Sub(stepFromTime) == 0 {
|
||||
break
|
||||
}
|
||||
resultList, err2 := api.EbaiAPI.GetEleCommentList(stepFromTime, stepToTime, "", "", ebaiapi.ReplyStatusAll, ebaiapi.CommentLevelAll, ebaiapi.CommentContentAll)
|
||||
if err = err2; err == nil {
|
||||
for _, result := range resultList {
|
||||
orderComment := &model.OrderComment{
|
||||
VendorOrderID: utils.Interface2String(result["order_id"]),
|
||||
VendorID: model.VendorIDELM,
|
||||
UserCommentID: utils.Int64ToStr(utils.MustInterface2Int64(result["comment_id"])),
|
||||
// VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["shop_id"])), // 这个shop_id是饿了么ID,不是饿百ID
|
||||
TagList: "",
|
||||
Score: int8(utils.MustInterface2Int64(result["service_rating"])),
|
||||
Content: utils.Interface2String(result["content"]),
|
||||
CommentCreatedAt: utils.Str2Time(utils.Interface2String(result["create_time"])),
|
||||
IsReplied: int8(1 - utils.MustInterface2Int64(result["can_reply"])),
|
||||
ModifyDuration: EBAI_BAD_COMMENTS_MAX_MODIFY_TIME,
|
||||
OriginalMsg: string(utils.MustMarshal(result)),
|
||||
}
|
||||
// 直接得到的订单是饿了么的,尝试统一成饿百
|
||||
if order, err := partner.CurOrderManager.LoadOrder2(orderComment.VendorOrderID, model.VendorIDEBAI); err == nil {
|
||||
orderComment.VendorOrderID = order.VendorOrderID
|
||||
orderComment.VendorOrderID2 = order.VendorOrderID2
|
||||
orderComment.VendorID = model.VendorIDEBAI
|
||||
|
||||
orderComment.VendorStoreID = order.VendorStoreID
|
||||
orderComment.StoreID = jxutils.GetSaleStoreIDFromOrder(order)
|
||||
orderComment.ConsigneeMobile = order.ConsigneeMobile
|
||||
} else {
|
||||
globals.SugarLogger.Infof("RefreshComment, load orderID:%s failed", orderComment.VendorOrderID)
|
||||
}
|
||||
orderCommentList = append(orderCommentList, orderComment)
|
||||
}
|
||||
} else {
|
||||
// globals.SugarLogger.Warnf("RefreshComment stepFromTime:%s, stepToTime:%s failed with error:%v", utils.Time2Str(stepFromTime), utils.Time2Str(stepToTime), err)
|
||||
// break //?
|
||||
}
|
||||
if stepToTime.Sub(toTime) == 0 {
|
||||
break
|
||||
}
|
||||
stepFromTime = stepToTime.Add(time.Second)
|
||||
}
|
||||
if err == nil && len(orderCommentList) > 0 {
|
||||
err = partner.CurOrderManager.OnOrderComments(orderCommentList)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string,orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
if orderComment.VendorStoreID != "" && orderComment.UserCommentID != "" {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.OrderRatesReply("", utils.Str2Int64(orderComment.VendorStoreID), orderComment.UserCommentID, replyComment)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestGetOrder4PartRefund(t *testing.T) {
|
||||
order, err := CurPurchaseHandler.GetOrder4PartRefund("1556529608021993938")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
} else {
|
||||
t.Log(utils.Format4Output(order, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestListOrders(t *testing.T) {
|
||||
order, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "", nil, utils.GetCurDate(), "")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
} else {
|
||||
t.Log(utils.Format4Output(order, false))
|
||||
}
|
||||
}
|
||||
@@ -1,552 +0,0 @@
|
||||
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"
|
||||
)
|
||||
|
||||
type tEbaiStoreInfo struct {
|
||||
model.Store
|
||||
VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空
|
||||
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)"`
|
||||
VendorStoreName string
|
||||
}
|
||||
|
||||
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.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
|
||||
}
|
||||
|
||||
// 2019-07-26 疑似饿百将门店返回的坐标类型从float64改为string了
|
||||
func getCoordintate(data interface{}) float64 {
|
||||
if str, ok := data.(string); ok {
|
||||
return utils.Str2Float64WithDefault(str, 0)
|
||||
}
|
||||
return utils.MustInterface2Float64(data)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (*dao.StoreDetail, error) {
|
||||
baiduShopID := utils.Str2Int64WithDefault(vendorStoreID, 0)
|
||||
if baiduShopID == 0 {
|
||||
return nil, fmt.Errorf("饿百门店ID:%s非法,应该是一个整数", vendorStoreID)
|
||||
}
|
||||
result, err := api.EbaiAPI.ShopGet("", baiduShopID)
|
||||
if err == nil {
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
retVal := &dao.StoreDetail{
|
||||
Store: model.Store{
|
||||
Address: utils.Interface2String(result["address"]),
|
||||
Tel1: utils.Interface2String(result["phone"]),
|
||||
},
|
||||
}
|
||||
retVal.OriginalName = utils.Interface2String(result["name"])
|
||||
_, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, globals.StoreNameEbai)
|
||||
retVal.DeliveryType = EbaiDeliveryType2Jx(utils.Interface2String(result["delivery_type"]))
|
||||
|
||||
retVal.SetOpTime(ebaiOpTime2Jx(result["business_time"]))
|
||||
retVal.Status, _ = p.GetStoreStatus(ctx, vendorOrgCode, 0, vendorStoreID)
|
||||
|
||||
tel2 := utils.Interface2String(result["ivr_phone"])
|
||||
if tel2 != "" && tel2 != retVal.Tel1 {
|
||||
retVal.Tel2 = tel2
|
||||
}
|
||||
|
||||
lng := getCoordintate(result["longitude"])
|
||||
lat := getCoordintate(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
|
||||
retVal.CityName = utils.Interface2String(result["city"])
|
||||
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 retVal.CityCode == 0 {
|
||||
if district, err := dao.GetPlaceByCode(db, retVal.DistrictCode); err == nil {
|
||||
retVal.CityCode = district.ParentCode
|
||||
}
|
||||
}
|
||||
}
|
||||
retVal.VendorStoreID = vendorStoreID
|
||||
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, t2.vendor_org_code,
|
||||
IF(t1.updated_at > t2.updated_at, t1.last_operator, t2.last_operator) real_last_operator, t2.sync_status, t2.vendor_store_name
|
||||
FROM store t1
|
||||
JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ? AND (t2.deleted_at = ?)
|
||||
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 {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
shopID := 0
|
||||
if store.SyncStatus&model.SyncFlagDeletedMask == 0 {
|
||||
shopID = store.ID
|
||||
}
|
||||
store2, err2 := p.ReadStore(jxcontext.AdminCtx, store.VendorOrgCode, 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
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if shopID > 0 {
|
||||
err = p.UpdateStoreCustomID(jxcontext.AdminCtx, "", store.VendorStoreID, int64(shopID))
|
||||
} else if shopID == 0 {
|
||||
// todo remove out shop id
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 {
|
||||
mergeStatus := jxutils.MergeStoreStatus(store.Status, store.EbaiStoreStatus)
|
||||
if err = p.UpdateStoreStatus(jxcontext.AdminCtx, store.VendorOrgCode, storeID, store.VendorStoreID, mergeStatus); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
params := genStoreMapFromStore(store)
|
||||
if err = api.EbaiAPI.ShopUpdate(params); err == nil {
|
||||
if store.PromoteInfo != "" {
|
||||
err = api.EbaiAPI.ShopAnnouncementSet("", utils.Str2Int64(store.VendorStoreID), store.PromoteInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func isStoreStatusSame(status1, status2 int) bool {
|
||||
if status1 == model.StoreStatusHaveRest {
|
||||
status1 = model.StoreStatusClosed
|
||||
}
|
||||
if status2 == model.StoreStatusHaveRest {
|
||||
status2 = model.StoreStatusClosed
|
||||
}
|
||||
return status1 == status2
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
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.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.ShopIDBatchUpdate(baiduShopIDs, shopIDs)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// 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.Str2Int64WithDefault(store.DeliveryRange, 0) > 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 fillOpTimeParams(params map[string]interface{}, opTimeList []int16) map[string]interface{} {
|
||||
if params == nil {
|
||||
params = make(map[string]interface{})
|
||||
}
|
||||
var pairList []map[string]string
|
||||
opTimeListLen := len(opTimeList)
|
||||
if opTimeListLen > 4 {
|
||||
opTimeListLen = 4
|
||||
}
|
||||
opTimeListLen = opTimeListLen / 2 * 2
|
||||
for k := 0; k < len(opTimeList); k += 2 {
|
||||
if opTimeList[k] != 0 {
|
||||
pairList = append(pairList, map[string]string{
|
||||
"start": jxutils.JxOperationTime2StrTime(opTimeList[k]),
|
||||
"end": jxutils.JxOperationTime2StrTime(opTimeList[k+1]),
|
||||
})
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
params["business_time"] = pairList
|
||||
return params
|
||||
}
|
||||
|
||||
func ebaiOpTime2Jx(businessTime interface{}) (opTimeList []int16) {
|
||||
businessTimeList, _ := businessTime.([]interface{})
|
||||
for _, v := range businessTimeList {
|
||||
vMap := v.(map[string]interface{})
|
||||
opTimeList = append(opTimeList, jxutils.StrTime2JxOperationTime(utils.Interface2String(vMap["start"])+":00", 700),
|
||||
jxutils.StrTime2JxOperationTime(utils.Interface2String(vMap["end"])+":00", 2000))
|
||||
}
|
||||
return opTimeList
|
||||
}
|
||||
|
||||
func genStoreMapFromStore(store *tEbaiStoreInfo) map[string]interface{} {
|
||||
params := fillOpTimeParams(nil, store.GetOpTimeList())
|
||||
// tel := store.Tel1
|
||||
// if tel == "" {
|
||||
// tel = store.Tel2
|
||||
// }
|
||||
// if tel != "" {
|
||||
// // params["phone"] = tel // 外卖客服联系电话,这个有时能修改,有时不能修改,暂时统一不改
|
||||
// params["ivr_phone"] = tel // 订单提醒电话
|
||||
// }
|
||||
phone := ""
|
||||
if store.MarketManPhone != "" {
|
||||
phone = store.MarketManPhone
|
||||
} else {
|
||||
phone = model.VendorStoreTel
|
||||
}
|
||||
params["ivr_phone"] = phone //统一改为这个电话
|
||||
|
||||
if store.VendorStoreID != "" {
|
||||
params["baidu_shop_id"] = store.VendorStoreID
|
||||
}
|
||||
if false { //store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
|
||||
if store.VendorStoreName != "" {
|
||||
params["name"] = store.VendorStoreName
|
||||
} else {
|
||||
params["name"] = jxutils.ComposeStoreName(store.Name, model.VendorIDEBAI)
|
||||
}
|
||||
}
|
||||
boxFee, _ := dao.GetSysConfigAsInt64(dao.GetDB(), model.ConfigSysEbaiBoxFee)
|
||||
params["package_box_price"] = jxutils.IntPrice2Standard(boxFee)
|
||||
params["service_phone"] = store.Tel1
|
||||
params["address"] = store.Address
|
||||
// todo 饿百 开店审核通过后不允许修改商户信息
|
||||
if store.SyncStatus&(model.SyncFlagNewMask /*|model.SyncFlagStoreAddress*/) != 0 {
|
||||
// todo 这里应该要做坐标转换吧
|
||||
params["longitude"] = jxutils.IntCoordinate2Standard(store.Lng)
|
||||
params["latitude"] = jxutils.IntCoordinate2Standard(store.Lat)
|
||||
params["coord_type"] = ebaiapi.CoordTypeAutonavi
|
||||
// if deliveryRegion := JxDeliveryRegion2Ebai(&store.Store); deliveryRegion != nil {
|
||||
// params["delivery_region"] = deliveryRegion
|
||||
// }
|
||||
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
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
ebaiStatus, err := api.EbaiAPI.ShopBusStatusGet("", utils.Str2Int64(vendorStoreID), ebaiapi.PlatformFlagElm)
|
||||
if err == nil {
|
||||
storeStatus = EbaiBusStatus2JxStatus(ebaiStatus)
|
||||
}
|
||||
return storeStatus, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onShopMsgPush(msg *ebaiapi.CallbackMsg) (response *ebaiapi.CallbackResponse) {
|
||||
var err error
|
||||
vendorStoreID := utils.Interface2String(msg.Body["baidu_shop_id"])
|
||||
storeID := int(utils.Interface2Int64WithDefault(msg.Body["shop_id"], 0))
|
||||
storeStatus := model.StoreStatusOpened
|
||||
switch utils.Interface2String(msg.Body["msg_type"]) {
|
||||
case "online", "offline":
|
||||
storeStatus, err = c.GetStoreStatus(jxcontext.AdminCtx, "", storeID, vendorStoreID)
|
||||
case "shop_open", "shop_pause", "shop_close":
|
||||
if int(utils.ForceInterface2Int64(msg.Body["business_ele"])) == 1 {
|
||||
storeStatus = model.StoreStatusOpened
|
||||
} else {
|
||||
storeStatus = model.StoreStatusClosed
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDEBAI, storeStatus)
|
||||
}
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetShopHealthInfo(vendorShopID string) (shopHealthInfo map[string]interface{}, err error) {
|
||||
result, err := api.EbaiAPI.GetShopHealthByDetail(utils.Str2Int64(vendorShopID))
|
||||
if err == nil {
|
||||
shopHealthInfo = utils.Struct2FlatMap(result)
|
||||
}
|
||||
return shopHealthInfo, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if status == model.StoreStatusOpened {
|
||||
err = api.EbaiAPI.ShopOpen("", utils.Str2Int64(vendorStoreID))
|
||||
} else if status == model.StoreStatusHaveRest || status == model.StoreStatusClosed {
|
||||
err = api.EbaiAPI.ShopClose("", utils.Str2Int64(vendorStoreID))
|
||||
} else if status == model.StoreStatusDisabled {
|
||||
err = api.EbaiAPI.ShopClose("", utils.Str2Int64(vendorStoreID))
|
||||
// err = api.EbaiAPI.ShopOffline("", utils.Str2Int64(vendorStoreID))
|
||||
}
|
||||
if err != nil {
|
||||
if remoteStatus, err2 := c.GetStoreStatus(ctx, vendorOrgCode, storeID, vendorStoreID); err2 == nil && remoteStatus == status {
|
||||
err = nil
|
||||
} else if intErr, ok := err.(*utils.ErrorWithCode); ok && intErr.IntCode() == 201100 || intErr.IntCode() == 201101 { // 兼容假错误:商户开业饿了么侧成功
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
|
||||
params := map[string]interface{}{
|
||||
ebaiapi.KeyBaiduShopID: vendorStoreID,
|
||||
}
|
||||
fillOpTimeParams(params, opTimeList)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
api.EbaiAPI.ShopUpdate(params)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) {
|
||||
shopList, err := api.EbaiAPI.ShopList(ebaiapi.SysStatusAll)
|
||||
if err == nil && len(shopList) > 0 {
|
||||
vendorStoreIDs = make([]string, len(shopList))
|
||||
for k, v := range shopList {
|
||||
vendorStoreIDs[k] = utils.Int64ToStr(v.BaiduShopID)
|
||||
}
|
||||
}
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode string, vendorStoreID string, storeID int64) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = api.EbaiAPI.ShopIDBatchUpdate([]string{vendorStoreID}, []string{utils.Int64ToStr(storeID)})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetShopListByPage(status, proxy_business_state int) (shopList []*ebaiapi.ShopList, err error) {
|
||||
var (
|
||||
pageCount = 500
|
||||
pageNum = 1
|
||||
)
|
||||
for {
|
||||
shopListPage, _, err2 := api.EbaiAPI.GetShopListByPage(status, proxy_business_state, pageCount, pageNum)
|
||||
err = err2
|
||||
shopList = append(shopList, shopListPage...)
|
||||
if len(shopList) < pageCount {
|
||||
break
|
||||
}
|
||||
pageNum++
|
||||
}
|
||||
return shopList, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetShopIDsByPage() (vendorStoreIDs []string, err error) {
|
||||
shopList, err := c.GetShopListByPage(ebaiapi.ShopStatusOnLine, ebaiapi.ProxyBusinessState)
|
||||
for _, v := range shopList {
|
||||
vendorStoreIDs = append(vendorStoreIDs, v.Wid)
|
||||
}
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
|
||||
return vendorStoreID, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,596 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
defVendorCatID = 201222934 // 其他蔬菜
|
||||
)
|
||||
|
||||
var (
|
||||
sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`)
|
||||
categoryCheck = map[int]string{
|
||||
175: "赠品专区",
|
||||
18: "烧烤吧台",
|
||||
}
|
||||
|
||||
//果园果切的饿百分类ID
|
||||
gygqVendorCatID = map[int]int{
|
||||
201227732: 1,
|
||||
201220933: 1,
|
||||
201223525: 1,
|
||||
201220334: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
|
||||
switch funcID {
|
||||
case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice, partner.FuncDeleteStoreSkus:
|
||||
batchSize = ebaiapi.MaxStoreSkuBatchSize
|
||||
case partner.FuncCreateStoreSkus, partner.FuncUpdateStoreSkus:
|
||||
batchSize = 1
|
||||
case partner.FuncGetStoreSkusFullInfo:
|
||||
batchSize = 1
|
||||
case partner.FuncCreateActs, partner.FuncCancelActs:
|
||||
batchSize = 1
|
||||
}
|
||||
return batchSize
|
||||
}
|
||||
|
||||
// 门店分类
|
||||
func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) {
|
||||
remoteCats, err := api.EbaiAPI.ShopCategoryGet(utils.Int2Str(storeID))
|
||||
if err == nil {
|
||||
cats = convertVendorCatList(remoteCats)
|
||||
}
|
||||
return cats, err
|
||||
}
|
||||
|
||||
func convertVendorCatList(remoteCats []*ebaiapi.CategoryInfo) (cats []*partner.BareCategoryInfo) {
|
||||
for _, rCat := range remoteCats {
|
||||
cat := &partner.BareCategoryInfo{
|
||||
VendorCatID: utils.Int64ToStr(rCat.CategoryID),
|
||||
Name: rCat.Name,
|
||||
Level: rCat.Level,
|
||||
Seq: jxCatSeq2Ebai(rCat.Rank),
|
||||
Children: convertVendorCatList(rCat.Children),
|
||||
}
|
||||
cats = append(cats, cat)
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) {
|
||||
return ebaiapi.IsErrCategoryExist(err)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) {
|
||||
return ebaiapi.IsErrCategoryNotExist(err)
|
||||
}
|
||||
|
||||
func getCheckExdStoreNameAndSeq(storeID int, storeCat *dao.SkuStoreCatInfo) (name string, seq int, isCheck bool) {
|
||||
store, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDEBAI)
|
||||
if err != nil || store == nil {
|
||||
return storeCat.Name, storeCat.Seq, false
|
||||
}
|
||||
if strings.Contains(store.Name, model.ExdStoreName) {
|
||||
if categoryCheck[storeCat.ID] != "" {
|
||||
return storeCat.ExdName, storeCat.ExdSeq, true
|
||||
} else {
|
||||
return storeCat.ExdName, storeCat.ExdSeq, false
|
||||
}
|
||||
} else {
|
||||
return storeCat.Name, storeCat.Seq, false
|
||||
}
|
||||
return name, seq, false
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
var vendorCatID int64
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if catName, catSeq, isCheck := getCheckExdStoreNameAndSeq(storeID, storeCat); !isCheck {
|
||||
vendorCatID, err = api.EbaiAPI.ShopCategoryCreate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.ParentVendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
|
||||
}
|
||||
} else {
|
||||
vendorCatID = jxutils.GenFakeID()
|
||||
}
|
||||
storeCat.VendorCatID = utils.Int64ToStr(vendorCatID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if catName, catSeq, isCheck := getCheckExdStoreNameAndSeq(storeID, storeCat); !isCheck {
|
||||
err = api.EbaiAPI.ShopCategoryUpdate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.VendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
|
||||
}
|
||||
// todo, 饿百将一个分类重复改名,也会报分类名重复错,特殊处理一下,不过因为GetStoreCategory其实会拉取所有的门店分类,是比较耗时的操作
|
||||
if utils.IsErrMatch(err, "1", []string{"分类名称已经存在"}) {
|
||||
if cat, err2 := p.GetStoreCategory(ctx, storeID, vendorStoreID, storeCat.Name); err2 == nil {
|
||||
if cat.VendorCatID == storeCat.VendorCatID {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
err = api.EbaiAPI.ShopCategoryDelete(utils.Int2Str(storeID), utils.Str2Int64WithDefault(vendorCatID, 0))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 门店商品
|
||||
|
||||
// 多门店平台不需要实现这个接口
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) {
|
||||
return ebaiapi.IsErrSkuExist(err)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
|
||||
return ebaiapi.IsErrSkuNotExist(err)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) updateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isNeedMapCat bool) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
storeSku := storeSkuList[0]
|
||||
strStoreID := utils.Int2Str(storeID)
|
||||
isExd := false
|
||||
if strings.Contains(storeSku.StoreName, model.ExdStoreName) {
|
||||
isExd = true
|
||||
}
|
||||
params := genSkuParamsFromStoreSkuInfo2(storeSku, false, isExd)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
_, err = api.EbaiAPI.SkuUpdate(ctx.GetTrackInfo(), strStoreID, utils.Str2Int64(storeSku.VendorSkuID), params)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品基础信息")
|
||||
}
|
||||
if isNeedMapCat && !isExd {
|
||||
utils.CallFuncAsync(func() {
|
||||
api.EbaiAPI.SkuShopCategoryMap(strStoreID, utils.Str2Int64(storeSku.VendorSkuID), "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku))
|
||||
})
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
return p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
|
||||
}
|
||||
|
||||
// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义
|
||||
func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
storeSku := storeSkuList[0]
|
||||
var (
|
||||
vendorSkuID int64
|
||||
isExd bool = false
|
||||
customSkuID int64
|
||||
)
|
||||
if strings.Contains(storeSku.StoreName, model.ExdStoreName) {
|
||||
isExd = true
|
||||
if storeSku.ExdSkuID == "" {
|
||||
customSkuID = 0
|
||||
} else {
|
||||
customSkuID = utils.Str2Int64(storeSku.ExdSkuID)
|
||||
}
|
||||
} else {
|
||||
isExd = false
|
||||
customSkuID = int64(storeSku.SkuID)
|
||||
}
|
||||
params := genSkuParamsFromStoreSkuInfo2(storeSku, true, isExd)
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
strStoreID := utils.Int2Str(storeID)
|
||||
if vendorSkuID, err = api.EbaiAPI.SkuCreate(ctx.GetTrackInfo(), strStoreID, customSkuID, params); err == nil && !isExd {
|
||||
utils.AfterFuncWithRecover(5*time.Second, func() {
|
||||
api.EbaiAPI.SkuShopCategoryMap(strStoreID, vendorSkuID, "", utils.Str2Int64(storeSku.VendorCatID), genSkuCatRank(storeSku))
|
||||
// 饿百平台有BUG,会导致新建一个之前删除的商品时,信息不会及时更新,强制刷新一下
|
||||
// 比如门店:100887, skuID:33805,订单:1577176719141226065
|
||||
p.updateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
|
||||
})
|
||||
} else {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "创建商品")
|
||||
}
|
||||
} else {
|
||||
vendorSkuID = jxutils.GenFakeID()
|
||||
}
|
||||
err = nil
|
||||
storeSku.VendorSkuID = utils.Int64ToStr(vendorSkuID)
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func getFailedVendorSkuIDsFromOpResult(opResult *ebaiapi.BatchOpResult) (skuIDs []string) {
|
||||
if opResult != nil {
|
||||
for _, v := range opResult.FailedList {
|
||||
skuIDs = append(skuIDs, utils.Int64ToStr(v.SkuID))
|
||||
}
|
||||
}
|
||||
return skuIDs
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
opResult, err2 := api.EbaiAPI.SkuDelete(ctx.GetTrackInfo(), utils.Int2Str(storeID), partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList(), nil)
|
||||
if err = err2; err2 != nil && opResult != nil {
|
||||
// if len(storeSkuList) > len(opResult.FailedList) {
|
||||
failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorChineseNames[model.VendorIDEBAI], "删除商品")
|
||||
// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult))
|
||||
// }
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
vendorSkuIDs := partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDIntList()
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
var opResult *ebaiapi.BatchOpResult
|
||||
if status == model.SkuStatusNormal {
|
||||
if len(vendorSkuIDs) > 1 {
|
||||
opResult, err = api.EbaiAPI.SkuOnline(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs, nil, nil)
|
||||
} else if len(vendorSkuIDs) == 1 {
|
||||
err = api.EbaiAPI.SkuOnlineOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs[0], "", "")
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品状态")
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
} else {
|
||||
if len(vendorSkuIDs) > 1 {
|
||||
opResult, err = api.EbaiAPI.SkuOffline(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs, nil, nil)
|
||||
} else if len(vendorSkuIDs) == 1 {
|
||||
err = api.EbaiAPI.SkuOfflineOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), vendorSkuIDs[0], "", "")
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品状态")
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
}
|
||||
if err != nil && opResult != nil {
|
||||
failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品状态")
|
||||
// failedList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult))
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func StoreSkuInfoList2Ebai(storeSkuList []*partner.StoreSkuInfo) (outList ebaiapi.ShopSkuInfoList) {
|
||||
outList = make(ebaiapi.ShopSkuInfoList, len(storeSkuList))
|
||||
for k, v := range storeSkuList {
|
||||
outList[k] = &ebaiapi.ShopSkuInfo{
|
||||
SkuID: utils.Str2Int64WithDefault(v.VendorSkuID, 0),
|
||||
// CustomSkuID: utils.Int2Str(v.SkuID),
|
||||
SalePrice: v.VendorPrice,
|
||||
Stock: v.Stock,
|
||||
}
|
||||
}
|
||||
return outList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if len(storeSkuList) > 1 {
|
||||
opResult, err2 := api.EbaiAPI.SkuPriceUpdateBatch(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID)
|
||||
if err = err2; err != nil && opResult != nil {
|
||||
failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品价格")
|
||||
}
|
||||
} else if len(storeSkuList) == 1 {
|
||||
_, err := api.EbaiAPI.SkuPriceUpdateOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0])
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品价格")
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableEbaiStoreWrite {
|
||||
if len(storeSkuList) > 1 {
|
||||
opResult, err2 := api.EbaiAPI.SkuStockUpdateBatch(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList), ebaiapi.SkuIDTypeSkuID)
|
||||
if err = err2; err != nil && opResult != nil {
|
||||
failedList = SelectStoreSkuListByOpResult(storeSkuList, opResult, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品库存")
|
||||
// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getFailedVendorSkuIDsFromOpResult(opResult))
|
||||
}
|
||||
} else if len(storeSkuList) == 1 {
|
||||
err = api.EbaiAPI.SkuStockUpdateOne(ctx.GetTrackInfo(), utils.Int2Str(storeID), StoreSkuInfoList2Ebai(storeSkuList)[0])
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDEBAI], "更新商品库存")
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate, isExd bool) (params map[string]interface{}) {
|
||||
var img string
|
||||
if storeSku.ImgMix != "" {
|
||||
img = storeSku.ImgMix
|
||||
} else {
|
||||
img = storeSku.Img
|
||||
}
|
||||
photos := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"is_master": true,
|
||||
"url": img,
|
||||
},
|
||||
}
|
||||
if storeSku.Img2 != "" {
|
||||
photos = append(photos, map[string]interface{}{
|
||||
"is_master": false,
|
||||
"url": storeSku.Img2,
|
||||
})
|
||||
}
|
||||
if storeSku.Img3 != "" {
|
||||
photos = append(photos, map[string]interface{}{
|
||||
"is_master": false,
|
||||
"url": storeSku.Img3,
|
||||
})
|
||||
}
|
||||
params = map[string]interface{}{
|
||||
// "name": utils.LimitMixedStringLen(storeSku.SkuName, ebaiapi.MaxSkuNameByteCount),
|
||||
"left_num": model.MaxStoreSkuStockQty,
|
||||
// "category_id": utils.Str2Int64(storeSku.VendorCatID),
|
||||
"predict_cat": 0, // 不使用推荐类目
|
||||
// "cat3_id": getEbaiCat(storeSku.VendorVendorCatID),
|
||||
"weight": storeSku.Weight,
|
||||
"photos": photos,
|
||||
"preparation_time": storeSku.PreparationTime,
|
||||
}
|
||||
if !isExd {
|
||||
params["category_id"] = utils.Str2Int64(storeSku.VendorCatID)
|
||||
params["name"] = utils.LimitMixedStringLen(storeSku.SkuName, ebaiapi.MaxSkuNameByteCount)
|
||||
params["cat3_id"] = getEbaiCat(storeSku.VendorVendorCatID)
|
||||
} else {
|
||||
params["upc"] = storeSku.Upc
|
||||
params["name"] = storeSku.Name
|
||||
params["cat3_id"] = storeSku.ExdCategoryThirdID
|
||||
params["category_id"] = utils.Str2Int64WithDefault(storeSku.VendorCatID, 0)
|
||||
}
|
||||
//证明是果园的几个果切分类,需要填加工服务
|
||||
if gygqVendorCatID[int(storeSku.VendorVendorCatID)] == 1 {
|
||||
params["process_type"] = model.YES
|
||||
processDetail := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"type": "去皮",
|
||||
"time": 2,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "不加工",
|
||||
"time": 0,
|
||||
},
|
||||
}
|
||||
params["process_detail"] = processDetail
|
||||
}
|
||||
if storeSku.DescImg != "" {
|
||||
params["rtf"] = storeSku.DescImg
|
||||
}
|
||||
if isCreate /*storeSku.SkuSyncStatus&(model.SyncFlagPriceMask| model.SyncFlagNewMask) != 0 */ {
|
||||
params["sale_price"] = storeSku.VendorPrice
|
||||
}
|
||||
if storeSku.SkuSyncStatus&(model.SyncFlagSaleMask|model.SyncFlagNewMask) != 0 {
|
||||
params["status"] = jxSkuStatus2Ebai(storeSku.MergedStatus)
|
||||
}
|
||||
// todo 饿百如果给的UPC是空要报错,但如果我要删除UPC怎么弄?
|
||||
// if storeSku.Upc != "" {
|
||||
// params["upc"] = storeSku.Upc
|
||||
// }
|
||||
return params
|
||||
}
|
||||
|
||||
func ebaiSkuStatus2Jx(ebaiSkuStatus int) (jxSkuStatus int) {
|
||||
if ebaiSkuStatus == ebaiapi.SkuStatusOnline {
|
||||
jxSkuStatus = model.SkuStatusNormal
|
||||
} else if ebaiSkuStatus == ebaiapi.SkuStatusOffline {
|
||||
jxSkuStatus = model.SkuStatusDontSale
|
||||
} else if ebaiSkuStatus == ebaiapi.SkuStatusOnline {
|
||||
jxSkuStatus = model.SkuStatusDeleted
|
||||
}
|
||||
return jxSkuStatus
|
||||
}
|
||||
|
||||
func jxSkuStatus2Ebai(status int) int {
|
||||
if status <= 0 {
|
||||
return ebaiapi.SkuStatusOffline
|
||||
}
|
||||
return ebaiapi.SkuStatusOnline
|
||||
}
|
||||
|
||||
func getEbaiCat(catID int64) int64 {
|
||||
if catID == 0 {
|
||||
return defVendorCatID
|
||||
}
|
||||
return catID
|
||||
}
|
||||
|
||||
// 饿百的排序是从大到小
|
||||
func genSkuCatRank(storeSku *dao.StoreSkuSyncInfo) int {
|
||||
return int(ebaiapi.MaxSkuCatRank - storeSku.GetSeq())
|
||||
}
|
||||
|
||||
// 饿百的排序是从大到小
|
||||
func jxCatSeq2Ebai(seq int) int {
|
||||
return ebaiapi.MaxCatCatRank - seq
|
||||
}
|
||||
|
||||
func formatCatName(name string) string {
|
||||
return utils.LimitUTF8StringLen(name, ebaiapi.MaxCategoryNameLen)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) {
|
||||
params := &ebaiapi.SkuListParams{
|
||||
PageSize: ebaiapi.MaxSkuListPageSize,
|
||||
}
|
||||
if len(storeSkuList) == 1 {
|
||||
if storeSkuList[0].SkuID > 0 {
|
||||
params.CustomSkuID = utils.Int2Str(storeSkuList[0].SkuID)
|
||||
}
|
||||
if storeSkuList[0].VendorSkuID != "" {
|
||||
params.SkuID = utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0)
|
||||
}
|
||||
}
|
||||
page1, err := api.EbaiAPI.SkuList(utils.Int2Str(storeID), params)
|
||||
if err == nil {
|
||||
skuNameList = append(skuNameList, vendorSkuList2Jx(page1.List)...)
|
||||
if page1.Pages > 1 {
|
||||
pages := make([]int, page1.Pages-1)
|
||||
for i := 2; i <= page1.Pages; i++ {
|
||||
pages[i-2] = i
|
||||
}
|
||||
task := tasksch.NewParallelTask("ebai GetStoreSkusFullInfo", nil, ctx,
|
||||
func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
callParams := &ebaiapi.SkuListParams{
|
||||
PageSize: ebaiapi.MaxSkuListPageSize,
|
||||
Page: batchItemList[0].(int),
|
||||
}
|
||||
pageSku, err2 := api.EbaiAPI.SkuList(utils.Int2Str(storeID), callParams)
|
||||
if err2 == nil {
|
||||
return pageSku.List, err2
|
||||
}
|
||||
return nil, err2
|
||||
}, pages)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
for _, v := range result {
|
||||
skuNameList = append(skuNameList, vendorSku2Jx(v.(*ebaiapi.SkuInfo)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return skuNameList, err
|
||||
}
|
||||
|
||||
func vendorSku2Jx(vendorSku *ebaiapi.SkuInfo) (skuName *partner.SkuNameInfo) {
|
||||
prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(vendorSku.Name)
|
||||
weight := vendorSku.Weight
|
||||
if weight <= 0 {
|
||||
weight = jxutils.FormatSkuWeight(specQuality, specUnit)
|
||||
}
|
||||
skuID := int(utils.Str2Int64WithDefault(vendorSku.CustomSkuID, 0))
|
||||
vendorSkuID := utils.Int64ToStr(vendorSku.SkuID)
|
||||
skuName = &partner.SkuNameInfo{
|
||||
NameID: skuID,
|
||||
VendorNameID: vendorSkuID,
|
||||
|
||||
Prefix: prefix,
|
||||
Name: name,
|
||||
Unit: unit,
|
||||
SkuList: []*partner.SkuInfo{
|
||||
&partner.SkuInfo{
|
||||
StoreSkuInfo: partner.StoreSkuInfo{
|
||||
VendorSkuID: vendorSkuID,
|
||||
SkuID: skuID,
|
||||
|
||||
Stock: vendorSku.LeftNum,
|
||||
VendorPrice: vendorSku.SalePrice,
|
||||
Status: ebaiSkuStatus2Jx(vendorSku.Status),
|
||||
},
|
||||
SkuName: vendorSku.Name,
|
||||
Comment: comment,
|
||||
SpecQuality: float64(specQuality),
|
||||
SpecUnit: specUnit,
|
||||
Weight: weight,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, v := range vendorSku.Photos {
|
||||
skuName.PictureList = append(skuName.PictureList, v.URL)
|
||||
}
|
||||
// todo, 看起来饿百只返回了最低一级的商家分类信息
|
||||
for _, v := range vendorSku.CustomCatList {
|
||||
skuName.VendorCatIDList = append(skuName.VendorCatIDList, v.CustomCatID)
|
||||
}
|
||||
return skuName
|
||||
}
|
||||
|
||||
func vendorSkuList2Jx(vendorSkuList []*ebaiapi.SkuInfo) (skuNameList []*partner.SkuNameInfo) {
|
||||
for _, vendorSku := range vendorSkuList {
|
||||
skuNameList = append(skuNameList, vendorSku2Jx(vendorSku))
|
||||
}
|
||||
return skuNameList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp {
|
||||
return sensitiveWordRegexp
|
||||
}
|
||||
|
||||
//饿百api返回
|
||||
func SelectStoreSkuListByOpResult(storeSkuList []*partner.StoreSkuInfo, opResult *ebaiapi.BatchOpResult, storeID int, vendorName string, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) {
|
||||
opResultMap := make(map[int64]string)
|
||||
if len(opResult.FailedList) > 0 {
|
||||
for _, v := range opResult.FailedList {
|
||||
if !(syncType == "删除商品" && ebaiapi.IsMsgSkuNotExist(v.ErrorMsg)) {
|
||||
opResultMap[v.SkuID] = v.ErrorMsg
|
||||
}
|
||||
}
|
||||
for _, v := range storeSkuList {
|
||||
if opResultMap[utils.Str2Int64(v.VendorSkuID)] != "" {
|
||||
opFailed := &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
ErrMsg: opResultMap[utils.Str2Int64(v.VendorSkuID)],
|
||||
StoreID: storeID,
|
||||
VendoreName: vendorName,
|
||||
SyncType: syncType,
|
||||
}
|
||||
selectedStoreSkuList = append(selectedStoreSkuList, opFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedStoreSkuList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
for _, v := range storeSkuList {
|
||||
if vendorActID, err2 := createOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, v.SkuID), utils.Int2Str(storeID), putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, []*partner.StoreSkuInfo{v})); err2 != nil {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
VendoreID: model.VendorIDEBAI,
|
||||
StoreID: storeID,
|
||||
ErrMsg: err2.Error(),
|
||||
})
|
||||
} else {
|
||||
v.VendorActID = vendorActID
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
for _, v := range storeSkuList {
|
||||
if err2 := ActivityDisable(utils.Str2Int64(v.VendorActID), utils.Int2Str(storeID), 0, 0); err2 != nil {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
VendoreID: model.VendorIDJD,
|
||||
StoreID: storeID,
|
||||
ErrMsg: err2.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
)
|
||||
|
||||
func TestGetStoreSkusFullInfo(t *testing.T) {
|
||||
skuNameList, err := CurPurchaseHandler.GetStoreSkusFullInfo(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, []*partner.StoreSkuInfo{
|
||||
&partner.StoreSkuInfo{
|
||||
SkuID: 4256,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(skuNameList, false))
|
||||
t.Log(len(skuNameList))
|
||||
}
|
||||
|
||||
func TestGetStoreSkusBareInfo(t *testing.T) {
|
||||
storeSkuList, err := CurPurchaseHandler.GetStoreSkusBareInfo(jxcontext.AdminCtx, "", nil, testShopID, testShopBaiduID, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(storeSkuList, false))
|
||||
t.Log(len(storeSkuList))
|
||||
}
|
||||
|
||||
func TestDeleteStoreAllSkus(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteStoreAllCategories(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllCategories(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
)
|
||||
|
||||
// func TestSyncStoresSkus(t *testing.T) {
|
||||
// skus := make([]int, 100)
|
||||
// for i := 0; i < 100; i++ {
|
||||
// skus[i] = i + 1
|
||||
// }
|
||||
// _, err := CurPurchaseHandler.SyncStoreSkus(jxcontext.AdminCtx, nil, testShopID, skus, false, false)
|
||||
// if err != nil {
|
||||
// t.Fatal(err.Error())
|
||||
// }
|
||||
// time.Sleep(4 * time.Second)
|
||||
// }
|
||||
|
||||
// func TestSyncOneStoreCategoriesFromRemote2Local(t *testing.T) {
|
||||
// db := dao.GetDB()
|
||||
// err := CurPurchaseHandler.SyncLocalStoreCategory(db, testShopID, "autotest")
|
||||
// if err != nil {
|
||||
// t.Fatal(err.Error())
|
||||
// }
|
||||
// }
|
||||
|
||||
// func TestSyncOneStoreCategoriesFromLocal2Remote(t *testing.T) {
|
||||
// _, err := CurPurchaseHandler.SyncStoreCategory(jxcontext.AdminCtx, nil, testShopID, false)
|
||||
// if err != nil {
|
||||
// t.Fatal(err.Error())
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestGetAllRemoteSkus(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.GetStoreSkusFullInfo(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
} else {
|
||||
t.Log(len(result))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteRemoteSkus(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteRemoteCategories(t *testing.T) {
|
||||
err := new(PurchaseHandler).DeleteStoreAllCategories(jxcontext.AdminCtx, nil, testShopID, testShopBaiduID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
)
|
||||
|
||||
func TestReadStore(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.ReadStore(jxcontext.AdminCtx, "", testShopBaiduID)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestUpdateStore(t *testing.T) {
|
||||
db := dao.GetDB()
|
||||
err := CurPurchaseHandler.UpdateStore(db, testShopID, "autotest")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateStore(t *testing.T) {
|
||||
db := dao.GetDB()
|
||||
_, err := CurPurchaseHandler.CreateStore(db, 1, "autotest")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package ebai
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
timeout4WaybillCancel = 10 * time.Minute // 饿百发送运单取消消息10分钟后,如果没有转自送,就要取消订单,且不再发送订单取消消息
|
||||
)
|
||||
|
||||
var (
|
||||
VendorWaybillStatus2StatusMap = map[string]int{
|
||||
ebaiapi.WaybillStatusNew: model.WaybillStatusUnknown,
|
||||
ebaiapi.WaybillStatusRequestDelivery: model.WaybillStatusUnknown,
|
||||
ebaiapi.WaybillStatusWait4Courier: model.WaybillStatusNew,
|
||||
ebaiapi.WaybillStatusCourierAccepted: model.WaybillStatusAccepted,
|
||||
ebaiapi.WaybillStatusCourierPickedup: model.WaybillStatusDelivering,
|
||||
ebaiapi.WaybillStatusDeliveryCancled: model.WaybillStatusCanceled,
|
||||
ebaiapi.WaybillStatusFinished: model.WaybillStatusDelivered,
|
||||
// ebaiapi.WaybillStatusExceptional: model.WaybillStatusCanceled, // 饿百的配送异常不应该当成取消来处理,比如:1568651453228834871
|
||||
ebaiapi.WaybillStatusSelfDelivery: model.WaybillStatusUnknown,
|
||||
ebaiapi.WaybillStatusDontDeliver: model.WaybillStatusCanceled,
|
||||
ebaiapi.WaybillStatusDeliveryRejected: model.WaybillStatusCanceled,
|
||||
ebaiapi.WaybillStatusCourierArrived: model.WaybillStatusCourierArrived,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetWaybillStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorWaybillStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.WaybillStatusUnknown
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onWaybillMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
|
||||
order := c.callbackMsg2Waybill(msg)
|
||||
globals.SugarLogger.Debugf("ebai onWaybillMsg orderID:%s", order.VendorOrderID)
|
||||
if order.Status == model.WaybillStatusNew || order.Status == model.WaybillStatusAccepted { // 饿百新运单事件要查询快递员信息,因为可能事件错序
|
||||
if result, err := api.EbaiAPI.OrderDeliveryGet(order.VendorOrderID); err != nil {
|
||||
globals.SugarLogger.Warnf("ebai onWaybillMsg orderID:%s OrderDeliveryGet failed with error:%v", order.VendorOrderID, err)
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, order.VendorOrderID)
|
||||
} else {
|
||||
order.CourierName = utils.Interface2String(result["name"])
|
||||
order.CourierMobile = utils.Interface2String(result["phone"])
|
||||
}
|
||||
if order.Status == model.WaybillStatusNew {
|
||||
order2, _ := partner.CurOrderManager.LoadOrder(order.VendorOrderID, order.WaybillVendorID)
|
||||
if order2.Status == model.OrderStatusWaitAccepted {
|
||||
order2.Status = model.OrderStatusNew
|
||||
scheduler.CurrentScheduler.OnOrderNew(order2, false)
|
||||
}
|
||||
}
|
||||
} else if order.Status == model.WaybillStatusCanceled {
|
||||
utils.AfterFuncWithRecover(timeout4WaybillCancel, func() {
|
||||
if localOrder, err2 := partner.CurOrderManager.LoadOrder(order.VendorOrderID, model.VendorIDEBAI); err2 == nil {
|
||||
if localOrder.Status < model.OrderStatusEndBegin {
|
||||
c.trySyncCancelStatus(order.VendorOrderID)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, partner.CurOrderManager.OnWaybillStatusChanged(order), order.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Waybill(msg *ebaiapi.CallbackMsg) (retVal *model.Waybill) {
|
||||
vendorStatus := utils.Int64ToStr(utils.MustInterface2Int64(msg.Body["status"]))
|
||||
orderID := GetOrderIDFromMsg(msg)
|
||||
retVal = &model.Waybill{
|
||||
VendorOrderID: orderID,
|
||||
OrderVendorID: model.VendorIDEBAI,
|
||||
VendorWaybillID: orderID,
|
||||
WaybillVendorID: model.VendorIDEBAI,
|
||||
Status: c.GetWaybillStatusFromVendorStatus(vendorStatus),
|
||||
VendorStatus: vendorStatus,
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
|
||||
VendorOrgCode: msg.Source,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
return nil
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/elmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
curPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
}
|
||||
|
||||
func init() {
|
||||
if api.ElmAPI != nil {
|
||||
curPurchaseHandler = new(PurchaseHandler)
|
||||
// partner.RegisterPurchasePlatform(curPurchaseHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDELM
|
||||
}
|
||||
|
||||
func OnCallbackMsg(msg *elmapi.CallbackMsg) (retVal *elmapi.CallbackResponse) {
|
||||
if curPurchaseHandler != nil {
|
||||
retVal = curPurchaseHandler.OnCallbackMsg(msg)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnCallbackMsg(msg *elmapi.CallbackMsg) (retVal *elmapi.CallbackResponse) {
|
||||
if msg.Type == elmapi.MsgTypeOrderValid {
|
||||
innerMsg := make(map[string]interface{})
|
||||
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
|
||||
if err != nil {
|
||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||
} else {
|
||||
innerMsg["msgType"] = msg.Type
|
||||
retVal = c.OnOrderNewMsg(innerMsg)
|
||||
}
|
||||
} else if msg.Type > elmapi.MsgTypeOrderValid && msg.Type < elmapi.MsgTypeUserApplyCancel {
|
||||
var innerMsg elmapi.CallbackOrderStatusMsg
|
||||
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
|
||||
if err != nil {
|
||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||
} else {
|
||||
innerMsg.MsgType = msg.Type
|
||||
retVal = c.OnOrderStatusMsg(&innerMsg)
|
||||
}
|
||||
} else if msg.Type >= elmapi.MsgTypeUserApplyCancel && msg.Type < elmapi.MsgTypeUserUrgeOrder {
|
||||
var innerMsg elmapi.CallbackOrderCancelRefundMsg
|
||||
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
|
||||
if err != nil {
|
||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||
} else {
|
||||
innerMsg.MsgType = msg.Type
|
||||
retVal = c.OnOrderCancelRefundMsg(&innerMsg)
|
||||
}
|
||||
} else if msg.Type == elmapi.MsgTypeUserUrgeOrder {
|
||||
var innerMsg elmapi.CallbackOrderUrgeMsg
|
||||
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
|
||||
if err != nil {
|
||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||
} else {
|
||||
innerMsg.MsgType = msg.Type
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderUserUrgeOrder(&innerMsg)
|
||||
}, jxutils.ComposeUniversalOrderID(innerMsg.OrderID, model.VendorIDELM))
|
||||
}
|
||||
} else if msg.Type >= elmapi.MsgTypeWaybillWait4DeliveryVendor && msg.Type <= elmapi.MsgTypeRejectedSystemError {
|
||||
var innerMsg elmapi.CallbackWaybillStatusMsg
|
||||
err := utils.UnmarshalUseNumber([]byte(msg.Message), &innerMsg)
|
||||
if err != nil {
|
||||
retVal = elmapi.Err2CallbackResponse(err, "")
|
||||
} else {
|
||||
innerMsg.MsgType = msg.Type
|
||||
retVal = c.OnWaybillStatusMsg(&innerMsg)
|
||||
}
|
||||
} else {
|
||||
retVal = elmapi.SuccessResponse
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
return imgHint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
return nil, fmt.Errorf("平台%s不支持此操作", jxutils.GetVendorName(model.VendorIDELM))
|
||||
}
|
||||
@@ -1,334 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/elmapi"
|
||||
"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/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
const (
|
||||
acceptOrderDelay = 270 * time.Second
|
||||
fakePickedUp = "fakefinishedpickup"
|
||||
)
|
||||
|
||||
var (
|
||||
VendorStatus2StatusMap = map[string]int{
|
||||
elmapi.OrderStatusUnprocessed: model.OrderStatusNew,
|
||||
elmapi.OrderStatusValid: model.OrderStatusAccepted,
|
||||
elmapi.OrderStatusPending: model.OrderStatusNew,
|
||||
// elmapi.OrderStatusRefunding: model.OrderStatusApplyRefund,
|
||||
elmapi.OrderStatusInvalid: model.OrderStatusCanceled,
|
||||
elmapi.OrderStatusSettled: model.OrderStatusFinished,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) OnOrderStatusMsg(msg *elmapi.CallbackOrderStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderStatusMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnOrderNewMsg(msg map[string]interface{}) (retVal *elmapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderNew(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg["orderId"].(string), model.VendorIDELM))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancelRefundMsg) (retVal *elmapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderCancelRefundMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) orderStatusMsg2Status(msg *elmapi.CallbackOrderStatusMsg) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.OrderID,
|
||||
VendorID: model.VendorIDELM,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: msg.OrderID,
|
||||
RefVendorID: model.VendorIDELM,
|
||||
VendorStatus: c.stateAndType2Str(msg.State, msg.MsgType),
|
||||
StatusTime: utils.Timestamp2Time(msg.UpdateTime),
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) cancelRefundMsg2Status(msg *elmapi.CallbackOrderCancelRefundMsg) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.OrderID,
|
||||
VendorID: model.VendorIDELM,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: msg.OrderID,
|
||||
RefVendorID: model.VendorIDELM,
|
||||
VendorStatus: c.stateAndType2Str(msg.RefundStatus, msg.MsgType),
|
||||
StatusTime: utils.Timestamp2Time(msg.UpdateTime),
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderStatusMsg(msg *elmapi.CallbackOrderStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||
status := c.orderStatusMsg2Status(msg)
|
||||
switch msg.MsgType {
|
||||
case elmapi.MsgTypeOrderAccepted:
|
||||
status.Status = model.OrderStatusAccepted
|
||||
case elmapi.MsgTypeOrderCanceled, elmapi.MsgTypeOrderInvalid, elmapi.MsgTypeOrderForceInvalid:
|
||||
status.Status = model.OrderStatusCanceled
|
||||
case elmapi.MsgTypeOrderFinished:
|
||||
status.Status = model.OrderStatusFinished
|
||||
default:
|
||||
globals.SugarLogger.Warnf("onOrderStatusMsg elm msg:%v not handled", msg)
|
||||
return elmapi.SuccessResponse
|
||||
}
|
||||
err := partner.CurOrderManager.OnOrderStatusChanged("", status)
|
||||
|
||||
// 直接跳到拣货完成
|
||||
if msg.MsgType == elmapi.MsgTypeOrderAccepted {
|
||||
status.Status = model.OrderStatusFinishedPickup
|
||||
status.VendorStatus = fakePickedUp
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged("", status)
|
||||
}
|
||||
// if globals.HandleLegacyJxOrder && err == nil {
|
||||
// c.legacyElmOrderStatusChanged(status)
|
||||
// }
|
||||
return elmapi.Err2CallbackResponse(err, status.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancelRefundMsg) (retVal *elmapi.CallbackResponse) {
|
||||
status := c.cancelRefundMsg2Status(msg)
|
||||
switch msg.MsgType {
|
||||
case elmapi.MsgTypeUserApplyCancel:
|
||||
status.Status = model.OrderStatusApplyCancel
|
||||
case elmapi.MsgTypeUserApplyRefund:
|
||||
// status.Status = model.OrderStatusApplyRefund
|
||||
default:
|
||||
status.Status = model.OrderStatusUnknown
|
||||
}
|
||||
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged("", status), status.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) {
|
||||
result, err := api.ElmAPI.GetOrder(orderID)
|
||||
if err == nil {
|
||||
order = c.Map2Order(result)
|
||||
}
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := orderData
|
||||
orderID := result["id"].(string)
|
||||
phoneList := result["phoneList"].([]interface{})
|
||||
consigneeMobile := ""
|
||||
if len(phoneList) > 0 {
|
||||
consigneeMobile = utils.Interface2String(phoneList[0])
|
||||
}
|
||||
|
||||
// globals.SugarLogger.Debug(result)
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDELM,
|
||||
VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["shopId"])),
|
||||
StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["openId"]), 0)),
|
||||
StoreName: result["shopName"].(string),
|
||||
ConsigneeName: result["consignee"].(string),
|
||||
ConsigneeMobile: jxutils.FormalizeMobile(consigneeMobile),
|
||||
ConsigneeAddress: result["address"].(string),
|
||||
BuyerComment: utils.TrimBlankChar(utils.Interface2String(result["description"])),
|
||||
ExpectedDeliveredTime: utils.Str2TimeWithDefault(utils.Interface2String(result["deliverTime"]), utils.DefaultTimeValue),
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
VendorStatus: utils.Interface2String(result["status"]), // 取订单的原始status,不合并消息类型(因为当前消息类型没有意义)
|
||||
OrderSeq: int(utils.MustInterface2Int64(result["daySn"])),
|
||||
StatusTime: utils.Str2Time(result["activeAt"].(string)),
|
||||
OriginalData: string(utils.MustMarshal(result)),
|
||||
ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["totalPrice"])),
|
||||
Skus: []*model.OrderSku{},
|
||||
}
|
||||
order.Status = c.getStatusFromVendorStatus(order.VendorStatus)
|
||||
if result["book"].(bool) {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
} else {
|
||||
order.BusinessType = model.BusinessTypeImmediate
|
||||
}
|
||||
deliveryGeo := strings.Split(utils.Interface2String(result["deliveryGeo"]), ",")
|
||||
if len(deliveryGeo) == 2 {
|
||||
order.CoordinateType = model.CoordinateTypeMars
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(utils.Str2Float64(deliveryGeo[0]))
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(utils.Str2Float64(deliveryGeo[1]))
|
||||
}
|
||||
|
||||
for _, group2 := range result["groups"].([]interface{}) {
|
||||
group := group2.(map[string]interface{})
|
||||
for _, product2 := range group["items"].([]interface{}) {
|
||||
product := product2.(map[string]interface{})
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDELM,
|
||||
Count: int(utils.MustInterface2Int64(product["quantity"])),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product["extendCode"]), 0)),
|
||||
VendorSkuID: utils.Int64ToStr(utils.Interface2Int64WithDefault(product["vfoodId"], 0)),
|
||||
SkuName: product["name"].(string),
|
||||
SalePrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])),
|
||||
Weight: int(math.Round(utils.Interface2Float64WithDefault(product["weight"], 0.0))),
|
||||
}
|
||||
if dao.IsVendorThingIDEmpty(sku.VendorSkuID) {
|
||||
sku.VendorSkuID = utils.Int64ToStr(utils.MustInterface2Int64(product["id"])) // 2018-09-28日,饿了么迁移到饿百后,这个字段发生了变化
|
||||
}
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
}
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
return order
|
||||
}
|
||||
|
||||
//
|
||||
func (c *PurchaseHandler) onOrderNew(msg map[string]interface{}) (response *elmapi.CallbackResponse) {
|
||||
// todo 这里应该可以直接用msg里的内容,而不用再次去查
|
||||
order, err := c.GetOrder("", msg["orderId"].(string))
|
||||
if err == nil {
|
||||
order.VendorStatus = c.stateAndType2Str(order.VendorStatus, elmapi.MsgTypeOrderValid)
|
||||
err = partner.CurOrderManager.OnOrderNew(order, nil)
|
||||
// if globals.HandleLegacyJxOrder && err == nil {
|
||||
// c.legacyWriteElmOrder(order)
|
||||
// }
|
||||
}
|
||||
return elmapi.Err2CallbackResponse(err, "elm onOrderNew")
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderUserUrgeOrder(msg *elmapi.CallbackOrderUrgeMsg) *elmapi.CallbackResponse {
|
||||
status := &model.OrderStatus{
|
||||
VendorOrderID: msg.OrderID,
|
||||
VendorID: model.VendorIDELM,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: msg.OrderID,
|
||||
RefVendorID: model.VendorIDELM,
|
||||
Status: model.OrderStatusApplyUrgeOrder,
|
||||
VendorStatus: utils.Int2Str(msg.MsgType),
|
||||
StatusTime: utils.Timestamp2Time(msg.UpdateTime),
|
||||
}
|
||||
c.ClientUrgeOrder(msg.OrderID)
|
||||
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnOrderStatusChanged("", status), status.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) stateAndType2Str(state string, msgType int) string {
|
||||
return fmt.Sprintf("%s-%d", state, msgType)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) spliltCompositeState(compositeState string) (state string, msgType int) {
|
||||
index := strings.Index(compositeState, "-")
|
||||
if index >= 0 {
|
||||
msgType = int(utils.Str2Int64(compositeState[index+1:]))
|
||||
if msgType == 0 {
|
||||
globals.SugarLogger.Debug(compositeState)
|
||||
}
|
||||
return compositeState[:index], msgType
|
||||
}
|
||||
return compositeState, 0
|
||||
}
|
||||
|
||||
// IPurchasePlatformHandler
|
||||
func (c *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int {
|
||||
state, _ := c.spliltCompositeState(vendorStatus)
|
||||
if status, ok := VendorStatus2StatusMap[state]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("elm AcceptOrRefuseOrder orderID:%s", order.VendorOrderID)
|
||||
// if globals.EnableElmStoreWrite {
|
||||
// if isAcceptIt {
|
||||
// err = api.ElmAPI.ConfirmOrder(order.VendorOrderID)
|
||||
// } else {
|
||||
// err = api.ElmAPI.CancelOrder(order.VendorOrderID, elmapi.CancelOrderTypeOthers, "")
|
||||
// }
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
// 饿了么没有拣货这个状态,直接返回成功
|
||||
// 真实流程中也不会调用这个方法,因为接收订单后状态会直接转移到已拣货
|
||||
func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
// if globals.EnableElmStoreWrite {
|
||||
// err = api.ElmAPI.DeliveryBySelfLite(order.VendorOrderID)
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
// 饿了么转商家自送后,没有确认送达的概念,空操作
|
||||
func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
// if globals.EnableElmStoreWrite {
|
||||
// err = api.ElmAPI.StartDeliveryBySelf(order.VendorOrderID, order.ConsigneeMobile)
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
// if globals.EnableElmStoreWrite {
|
||||
// err = api.ElmAPI.CompleteDeliveryBySelf(order.VendorOrderID, order.ConsigneeMobile)
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *partner.StatusActionParams) {
|
||||
if statusType == scheduler.TimerStatusTypeOrder && status == model.OrderStatusNew {
|
||||
params = &partner.StatusActionParams{ // 饿了么开了专送店的订单没有拣货状态,接单后就为拣货完成,所以要延迟接单,否则门店来不及备货
|
||||
Timeout: acceptOrderDelay,
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
err = errors.New("饿了么还未实现GetOrderRealMobile")
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return fmt.Errorf("饿了么不支持全款退款")
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
return fmt.Errorf("饿了么不支持部分退款")
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
aliyunsmsclient "github.com/KenmyZhang/aliyun-communicate"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
const (
|
||||
ELM_SMS_REMINDERS_DAIPEISHONG_TEMPLATECODE = "SMS_175573181" //饿了么待配送模板ID
|
||||
ELM_SMS_REMINDERS_PEISHOGNZHONG_TEMPLATECODE = "SMS_175583155" //饿了么配送中模板ID
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) ClientUrgeOrder(orderID string) (err error) {
|
||||
utils.CallFuncAsync(func() {
|
||||
var err error
|
||||
globals.SugarLogger.Debugf("ClientUrgeOrder orderID:%s", orderID)
|
||||
order, err2 := partner.CurOrderManager.LoadOrder(orderID, model.VendorIDELM)
|
||||
if err = err2; err == nil {
|
||||
templateCode := ""
|
||||
var templateParams map[string]interface{}
|
||||
if order.Status == model.OrderStatusFinishedPickup {
|
||||
templateCode = ELM_SMS_REMINDERS_DAIPEISHONG_TEMPLATECODE
|
||||
templateParams = map[string]interface{}{
|
||||
"name": order.ConsigneeName,
|
||||
}
|
||||
} else if order.Status == model.OrderStatusDelivering {
|
||||
bill, err2 := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
|
||||
if err = err2; err == nil {
|
||||
templateCode = ELM_SMS_REMINDERS_PEISHOGNZHONG_TEMPLATECODE
|
||||
templateParams = map[string]interface{}{
|
||||
"name": order.ConsigneeName,
|
||||
"number": bill.CourierMobile,
|
||||
}
|
||||
}
|
||||
}
|
||||
if templateCode != "" {
|
||||
smsClient := aliyunsmsclient.New("http://dysmsapi.aliyuncs.com/")
|
||||
if globals.ReallyCallPlatformAPI {
|
||||
_, err = smsClient.Execute(globals.AliKey, globals.AliSecret, order.ConsigneeMobile, globals.SMSSignName, templateCode, string(utils.MustMarshal(templateParams)))
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
globals.SugarLogger.Warnf("ClientUrgeOrder orderID:%s failed with error:%v", orderID, err)
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
orderID := "3025427524410871880"
|
||||
order, err := new(PurchaseHandler).GetOrder("", orderID)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if order.VendorOrderID != orderID {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode string, vendorStoreID string) (*dao.StoreDetail, error) {
|
||||
return nil, errors.New("饿了么还没实现")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
return storeStatus, err
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package elm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/elmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) OnWaybillStatusMsg(msg *elmapi.CallbackWaybillStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onWaybillStatusMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDELM))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onWaybillStatusMsg(msg *elmapi.CallbackWaybillStatusMsg) (retVal *elmapi.CallbackResponse) {
|
||||
order := c.callbackMsg2Waybill(msg)
|
||||
if msg.MsgType == elmapi.MsgTypeWaybillWait4Courier { //MsgTypeWaybillWait4Courier事件与JD的新运单事件的时间机制更相似
|
||||
order.Status = model.WaybillStatusNew
|
||||
} else if msg.MsgType == elmapi.MsgTypeWaybillPickingUp {
|
||||
if result, err := api.ElmAPI.GetOrder(msg.OrderID); err == nil {
|
||||
order.DesiredFee = jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["deliverFee"], 0.0) +
|
||||
utils.Interface2Float64WithDefault(result["vipDeliveryFeeDiscount"], 0.0))
|
||||
}
|
||||
order.Status = model.WaybillStatusAccepted
|
||||
} else if msg.MsgType == elmapi.MsgTypeWaybillCourierArrived {
|
||||
order.Status = model.WaybillStatusCourierArrived
|
||||
} else if msg.MsgType == elmapi.MsgTypeWaybillDelivering {
|
||||
order.Status = model.WaybillStatusDelivering
|
||||
} else if msg.MsgType == elmapi.MsgTypeWaybillDelivered {
|
||||
order.Status = model.WaybillStatusDelivered
|
||||
} else if msg.MsgType >= elmapi.MsgTypeWaybillCanceledByMerchant && msg.MsgType <= elmapi.MsgTypeWaybillCanceledBySystem {
|
||||
order.Status = model.WaybillStatusCanceled
|
||||
} else if msg.MsgType >= elmapi.MsgTypeWaybillFailedCallLate &&
|
||||
msg.MsgType <= elmapi.MsgTypeRejectedSystemError &&
|
||||
msg.MsgType != elmapi.MsgTypeDeiverBySelf {
|
||||
order.Status = model.WaybillStatusFailed
|
||||
} else {
|
||||
// MsgTypeWaybillWait4DeliveryVendor
|
||||
// MsgTypeDeiverBySelf
|
||||
order.Status = model.WaybillStatusUnknown
|
||||
}
|
||||
return elmapi.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order), order.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Waybill(msg *elmapi.CallbackWaybillStatusMsg) (retVal *model.Waybill) {
|
||||
retVal = &model.Waybill{
|
||||
VendorOrderID: msg.OrderID,
|
||||
OrderVendorID: model.VendorIDELM,
|
||||
VendorWaybillID: msg.OrderID,
|
||||
WaybillVendorID: model.VendorIDELM,
|
||||
CourierName: msg.Name,
|
||||
CourierMobile: msg.Phone,
|
||||
VendorStatus: c.composeState(msg.State, msg.SubState, msg.MsgType),
|
||||
StatusTime: utils.Timestamp2Time(msg.UpdateAt / 1000),
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) composeState(state, subState string, msgType int) string {
|
||||
return fmt.Sprintf("%s-%d", state, msgType)
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/baseapi/utils/errlist"
|
||||
"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"
|
||||
)
|
||||
|
||||
const (
|
||||
actMapDuration = 2 * time.Hour
|
||||
)
|
||||
|
||||
type LogicUpdateInfo struct {
|
||||
Item interface{}
|
||||
KVs map[string]interface{}
|
||||
Condition map[string]interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
jdSkuActStatusMap = map[int]int{
|
||||
jdapi.PromotionStateNotConfirm: model.ActStatusNA,
|
||||
jdapi.PromotionStateConfirmed: model.ActStatusCreated,
|
||||
jdapi.PromotionStateCanceled: model.ActStatusCanceled,
|
||||
jdapi.PromotionStateEnded: model.ActStatusEnded,
|
||||
}
|
||||
|
||||
actMap jxutils.SyncMapWithTimeout
|
||||
)
|
||||
|
||||
// 是否按单一门店商品维度创建活动
|
||||
func isCreateTypeSingleStoreSku() bool {
|
||||
return false
|
||||
// return !globals.IsProductEnv()
|
||||
}
|
||||
|
||||
func splitPromotionSku(skus []*jdapi.PromotionSku, maxCount int) (skusList [][]*jdapi.PromotionSku) {
|
||||
for {
|
||||
skusLen := len(skus)
|
||||
if skusLen <= maxCount {
|
||||
skusList = append(skusList, skus)
|
||||
break
|
||||
}
|
||||
skusList = append(skusList, skus[:maxCount])
|
||||
skus = skus[maxCount:]
|
||||
}
|
||||
return skusList
|
||||
}
|
||||
|
||||
func jdSkuActType2Jx(actType int) int {
|
||||
if actType == jdapi.PromotionTypeDirectDown {
|
||||
return model.ActSkuDirectDown
|
||||
} else if actType == jdapi.PromotionTypeSeckill || actType == jdapi.PromotionTypeLimitedTime {
|
||||
return model.ActSkuSecKill
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func jdSkuActStatus2Jx(jdActState int) int {
|
||||
return jdSkuActStatusMap[jdActState]
|
||||
}
|
||||
|
||||
func CreatePromotionInfos(vendorOrgCode string, promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
infoId, err = getAPI(vendorOrgCode).CreatePromotionInfosSingle(name, beginDate, endDate, outInfoId, advertising, traceId)
|
||||
} else {
|
||||
infoId, err = getAPI(vendorOrgCode).CreatePromotionInfosLimitTime(name, beginDate, endDate, outInfoId, advertising, traceId)
|
||||
}
|
||||
} else {
|
||||
infoId = jxutils.GenFakeID()
|
||||
}
|
||||
if err == nil {
|
||||
actMap.StoreWithTimeout(infoId, 1, actMapDuration)
|
||||
}
|
||||
return infoId, err
|
||||
}
|
||||
|
||||
func CreatePromotionRules(vendorOrgCode string, promotionType int, infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
err = getAPI(vendorOrgCode).CreatePromotionRulesSingle(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
|
||||
} else {
|
||||
err = getAPI(vendorOrgCode).CreatePromotionRulesLimitTime(infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func CreatePromotionSku(vendorOrgCode string, promotionType int, infoId int64, outInfoId string, skus []*jdapi.PromotionSku, traceId string) (skusResult []*jdapi.PromotionSku, err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
for _, batchSkus := range splitPromotionSku(skus, jdapi.MaxPromotionSkuCount) {
|
||||
var tmpSkusResult []*jdapi.PromotionSku
|
||||
var tmpErr error
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
tmpSkusResult, tmpErr = getAPI(vendorOrgCode).CreatePromotionSkuSingle(infoId, outInfoId, batchSkus, traceId)
|
||||
} else {
|
||||
tmpSkusResult, tmpErr = getAPI(vendorOrgCode).CreatePromotionSkuLimitTime(infoId, outInfoId, batchSkus, traceId)
|
||||
}
|
||||
if err = tmpErr; err != nil {
|
||||
break
|
||||
}
|
||||
skusResult = append(skusResult, tmpSkusResult...)
|
||||
}
|
||||
}
|
||||
return skusResult, err
|
||||
}
|
||||
|
||||
func CancelPromotionSku(vendorOrgCode string, promotionType int, infoId int64, outInfoId string, skus []*jdapi.PromotionSku, traceId string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
for _, batchSkus := range splitPromotionSku(skus, jdapi.MaxPromotionSkuCount) {
|
||||
var tmpErr error
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
tmpErr = getAPI(vendorOrgCode).CancelPromotionSkuSingle(infoId, outInfoId, batchSkus, traceId)
|
||||
} else {
|
||||
tmpErr = getAPI(vendorOrgCode).CancelPromotionSkuLimitTime(infoId, outInfoId, batchSkus, traceId)
|
||||
}
|
||||
if err = tmpErr; err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func ConfirmPromotion(vendorOrgCode string, promotionType int, infoId int64, outInfoId, traceId string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
return getAPI(vendorOrgCode).ConfirmPromotionSingle(infoId, outInfoId, traceId)
|
||||
} else {
|
||||
return getAPI(vendorOrgCode).ConfirmPromotionLimitTime(infoId, outInfoId, traceId)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func CancelPromotion(vendorOrgCode string, promotionType int, infoId int64, outInfoId, traceId string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
err = getAPI(vendorOrgCode).CancelPromotionSingle(infoId, outInfoId, traceId)
|
||||
} else {
|
||||
err = getAPI(vendorOrgCode).CancelPromotionLimitTime(infoId, outInfoId, traceId)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func AdjustPromotionTime(vendorOrgCode string, promotionType int, infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
err = getAPI(vendorOrgCode).AdjustPromotionTimeSingle(infoId, outInfoId, endDate, traceId)
|
||||
} else {
|
||||
err = getAPI(vendorOrgCode).AdjustPromotionTimeLimitTime(infoId, outInfoId, endDate, traceId)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func AdjustPromotionSku(vendorOrgCode string, promotionType int, infoId int64, outInfoId string, skus []*jdapi.PromotionSku, traceId string) (skusResult []*jdapi.PromotionSku, err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if promotionType == model.ActSkuDirectDown {
|
||||
skusResult, err = getAPI(vendorOrgCode).AdjustPromotionSkuSingle(infoId, outInfoId, skus, traceId)
|
||||
} else {
|
||||
skusResult, err = getAPI(vendorOrgCode).AdjustPromotionSkuLimitTime(infoId, outInfoId, skus, traceId)
|
||||
}
|
||||
}
|
||||
return skusResult, err
|
||||
}
|
||||
|
||||
func storeSku2Jd(actStoreSku []*model.ActStoreSku2, handler func(syncStatus int8) bool) (jdActStoreSku []*jdapi.PromotionSku) {
|
||||
for _, v := range actStoreSku {
|
||||
if handler(v.SyncStatus) {
|
||||
if v.VendorStoreID != "" && v.VendorSkuID != "" {
|
||||
jdActStoreSku = append(jdActStoreSku, &jdapi.PromotionSku{
|
||||
StationNo: utils.Str2Int64(v.VendorStoreID),
|
||||
SkuID: utils.Str2Int64(v.VendorSkuID),
|
||||
PromotionPrice: v.ActualActPrice,
|
||||
LimitSkuCount: v.Stock,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return jdActStoreSku
|
||||
}
|
||||
|
||||
func createSkuAct(ctx *jxcontext.Context, act *model.Act2, actStoreSku []*model.ActStoreSku2) (vendorActID string, err error) {
|
||||
traceInfo := ctx.GetTrackInfo()
|
||||
outInfoID := ""
|
||||
if act.VendorActID == "" {
|
||||
outInfoID = utils.Int2Str(act.ID)
|
||||
}
|
||||
infoID, err2 := CreatePromotionInfos(act.VendorOrgCode, act.Type, act.GetRealActName(), act.BeginAt, act.EndAt, outInfoID, act.Advertising, traceInfo)
|
||||
if err = err2; err == nil {
|
||||
vendorActID = utils.Int64ToStr(infoID)
|
||||
if err = CreatePromotionRules(act.VendorOrgCode, act.Type, infoID, "", act.LimitUser, act.LimitUser, act.LimitCount, 1, traceInfo); err == nil {
|
||||
if _, err = CreatePromotionSku(act.VendorOrgCode, act.Type, infoID, utils.Int2Str(act.ID), storeSku2Jd(actStoreSku, model.IsSyncStatusNeedCreate), traceInfo); err == nil {
|
||||
if err = ConfirmPromotion(act.VendorOrgCode, act.Type, infoID, "", traceInfo); err == nil {
|
||||
for _, v := range actStoreSku {
|
||||
v.VendorActID = vendorActID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
CancelPromotion(act.VendorOrgCode, act.Type, infoID, "", traceInfo)
|
||||
}
|
||||
}
|
||||
return vendorActID, err
|
||||
}
|
||||
|
||||
func proxyCreateSkuAct(ctx *jxcontext.Context, act *model.Act2, actStoreSku []*model.ActStoreSku2) (vendorActID string, err error) {
|
||||
if isCreateTypeSingleStoreSku() && len(actStoreSku) > 1 {
|
||||
errList := errlist.New()
|
||||
vendorActID := act.VendorActID
|
||||
act.VendorActID = "placeholder"
|
||||
for _, v := range actStoreSku {
|
||||
_, err := createSkuAct(ctx, act, []*model.ActStoreSku2{v})
|
||||
errList.AddErr(err)
|
||||
}
|
||||
act.VendorActID = vendorActID
|
||||
err = errList.GetErrListAsOne()
|
||||
} else {
|
||||
vendorActID, err = createSkuAct(ctx, act, actStoreSku)
|
||||
}
|
||||
return vendorActID, err
|
||||
}
|
||||
|
||||
func cancelSkuActSkus(ctx *jxcontext.Context, act *model.Act2, vendorActID string, actStoreSku []*model.ActStoreSku2) (err error) {
|
||||
if vendorActID != "" {
|
||||
if skuList := storeSku2Jd(actStoreSku, model.IsSyncStatusNeedDelete); len(skuList) > 0 {
|
||||
err = CancelPromotionSku(act.VendorOrgCode, act.Type, utils.Str2Int64(vendorActID), "", skuList, ctx.GetTrackInfo())
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func cancelSkuAct(ctx *jxcontext.Context, act *model.Act2, vendorActID string) (err error) {
|
||||
if vendorActID != "" {
|
||||
err = CancelPromotion(act.VendorOrgCode, act.Type, utils.Str2Int64(vendorActID), "", ctx.GetTrackInfo())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
globals.SugarLogger.Debugf("jd SyncAct, actID:%d", act.ID)
|
||||
vendorActInfoMap := make(map[string][]*model.ActStoreSku2)
|
||||
deleteActInfoMap := make(map[string][]*model.ActStoreSku2)
|
||||
var actStoreSkuList4Create []*model.ActStoreSku2
|
||||
var updateItems []*dao.KVUpdateItem
|
||||
|
||||
actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuList)
|
||||
actSkuCount := 0
|
||||
toDelActSkuCount := 0
|
||||
for storeID := range actStoreSkuMap {
|
||||
for _, actStoreSku := range actStoreSkuMap[storeID] {
|
||||
vendorActID := actStoreSku.VendorActID
|
||||
if vendorActID == "" {
|
||||
vendorActID = act.VendorActID
|
||||
}
|
||||
actSkuCount++
|
||||
vendorActInfoMap[vendorActID] = append(vendorActInfoMap[vendorActID], actStoreSku)
|
||||
if model.IsSyncStatusDelete(actStoreSku.SyncStatus) {
|
||||
toDelActSkuCount++
|
||||
deleteActInfoMap[vendorActID] = append(deleteActInfoMap[vendorActID], actStoreSku)
|
||||
} else if model.IsSyncStatusNew(actStoreSku.SyncStatus) {
|
||||
actStoreSkuList4Create = append(actStoreSkuList4Create, actStoreSku)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果是全删,直接添加删除(即取消)标志
|
||||
if actSkuCount == toDelActSkuCount {
|
||||
act.SyncStatus |= model.SyncFlagDeletedMask
|
||||
}
|
||||
db := dao.GetDB()
|
||||
err = func() (err error) {
|
||||
if model.IsSyncStatusDelete(act.SyncStatus) {
|
||||
errList := errlist.New()
|
||||
for vendorActID := range vendorActInfoMap {
|
||||
if vendorActID != "" {
|
||||
if err = cancelSkuAct(ctx, act, vendorActID); err == nil {
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, vendorActInfoMap[vendorActID], model.SyncFlagModifiedMask)...)
|
||||
} else {
|
||||
errList.AddErr(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = errList.GetErrListAsOne(); err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
} else if model.IsSyncStatusNew(act.SyncStatus) {
|
||||
if act.VendorActID, err = proxyCreateSkuAct(ctx, act, actStoreSkuList4Create); err == nil {
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, actStoreSkuList4Create, model.SyncFlagNewMask)...)
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagNewMask))
|
||||
} else {
|
||||
if act.VendorActID != "" {
|
||||
actMap := partner.Act2ActMap(act)
|
||||
dao.UpdateEntity(db, actMap, model.FieldVendorActID)
|
||||
}
|
||||
}
|
||||
} else if model.IsSyncStatusUpdate(act.SyncStatus) {
|
||||
errList := errlist.New()
|
||||
if len(actStoreSkuList4Create) > 0 {
|
||||
if _, err = proxyCreateSkuAct(ctx, act, actStoreSkuList4Create); err == nil {
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, actStoreSkuList4Create, model.SyncFlagNewMask)...)
|
||||
} else {
|
||||
errList.AddErr(err)
|
||||
}
|
||||
}
|
||||
for vendorActID := range deleteActInfoMap {
|
||||
if vendorActID != "" {
|
||||
if len(vendorActInfoMap[vendorActID]) == len(deleteActInfoMap[vendorActID]) {
|
||||
err = cancelSkuAct(ctx, act, vendorActID)
|
||||
} else {
|
||||
err = cancelSkuActSkus(ctx, act, vendorActID, deleteActInfoMap[vendorActID])
|
||||
}
|
||||
if err == nil {
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deleteActInfoMap[vendorActID], model.SyncFlagDeletedMask)...)
|
||||
} else {
|
||||
errList.AddErr(err)
|
||||
}
|
||||
} else {
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deleteActInfoMap[vendorActID], model.SyncFlagDeletedMask)...)
|
||||
}
|
||||
}
|
||||
if err = errList.GetErrListAsOne(); err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}()
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(updateItems, false))
|
||||
_, err2 := dao.BatchUpdateActEntity(db, model.IsSyncStatusDelete(act.SyncStatus), updateItems)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func OnActMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = CurPurchaseHandler.onActMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onActMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
if msg.StatusID == jdapi.PromotionStatusSingleOK || msg.StatusID == jdapi.PromotionStatusLimitTimeOK {
|
||||
promotionID := msg.BillID
|
||||
intPromotionID := utils.Str2Int64(promotionID)
|
||||
if _, ok := actMap.Load(intPromotionID); !ok {
|
||||
utils.CallFuncAsync(func() {
|
||||
if !partner.CurActManager.IsVendorActExist(jxcontext.AdminCtx, promotionID, model.VendorIDJD) {
|
||||
act, actStoreSkuList, err := getActFromJD(AppKey2OrgCode(msg.AppKey), promotionID)
|
||||
if err == nil && len(actStoreSkuList) > 0 {
|
||||
_, err = partner.CurActManager.CreateActFromVendor(jxcontext.AdminCtx, act, actStoreSkuList)
|
||||
}
|
||||
if err != nil {
|
||||
retVal = jdapi.Err2CallbackResponse(err, promotionID)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
actMap.Delete(intPromotionID)
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func getActFromJD(vendorOrgCode, promotionID string) (act *model.Act2, actStoreSkuList []*model.ActStoreSku2, err error) {
|
||||
result, err := getAPI(vendorOrgCode).QueryPromotionInfo(utils.Str2Int64(promotionID))
|
||||
if err == nil && len(result.SkuResultList) > 0 {
|
||||
act = &model.Act2{
|
||||
Act: model.Act{
|
||||
Name: fmt.Sprintf("%s-%d", result.Source, result.PromotionInfoID),
|
||||
Type: jdSkuActType2Jx(result.PromotionType),
|
||||
Status: jdSkuActStatus2Jx(result.PromotionState),
|
||||
BeginAt: result.SkuResultList[0].BeginTime.GoTime(),
|
||||
EndAt: result.SkuResultList[0].EndTime.GoTime(),
|
||||
Source: result.Source,
|
||||
CreateType: model.ActCreateTypeCallback,
|
||||
PricePercentage: 0,
|
||||
LimitDaily: result.SkuResultList[0].LimitDaily,
|
||||
LimitCount: 1,
|
||||
},
|
||||
VendorID: model.VendorIDJD,
|
||||
VendorOrgCode: vendorOrgCode,
|
||||
VendorActID: promotionID,
|
||||
}
|
||||
if utils.IsTimeZero(act.BeginAt) {
|
||||
act.BeginAt = result.BeginTime.GoTime()
|
||||
}
|
||||
if utils.IsTimeZero(act.EndAt) {
|
||||
act.EndAt = result.EndTime.GoTime().Add(24*time.Hour - 1*time.Second)
|
||||
}
|
||||
if result.SkuResultList[0].LimitPin == 1 || result.SkuResultList[0].LimitDevice == 1 {
|
||||
act.LimitUser = 1
|
||||
}
|
||||
|
||||
for _, v := range result.SkuResultList {
|
||||
if v.PromotionState != jdapi.PromotionStateCanceled {
|
||||
actStoreSkuList = append(actStoreSkuList, &model.ActStoreSku2{
|
||||
VendorStoreID: utils.Int64ToStr(v.StationNo),
|
||||
VendorSkuID: utils.Int64ToStr(v.SkuID),
|
||||
ActualActPrice: int64(v.PromotionPrice),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return act, actStoreSkuList, err
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
)
|
||||
|
||||
func OnOrderMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
if CurPurchaseHandler != nil {
|
||||
retVal = CurPurchaseHandler.OnOrderMsg(AppKey2OrgCode(msg.AppKey), msg)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func OnWaybillMsg(msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
|
||||
if CurPurchaseHandler != nil {
|
||||
retVal = CurPurchaseHandler.OnWaybillMsg(AppKey2OrgCode(msg.AppKey), msg)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func OnStoreMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
if CurPurchaseHandler != nil {
|
||||
retVal = CurPurchaseHandler.OnStoreMsg(AppKey2OrgCode(msg.AppKey), msg)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func OnOrderInfoChangeMsg(msg *jdapi.CallbackOrderInfoChangeMsg) (retVal *jdapi.CallbackResponse) {
|
||||
if CurPurchaseHandler != nil {
|
||||
retVal = CurPurchaseHandler.OnOrderInfoChangeMsg(AppKey2OrgCode(msg.AppKey), msg)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"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/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) OnFinancialMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
utils.CallFuncAsync(func() {
|
||||
retVal = p.onFinancialMsg(msg)
|
||||
})
|
||||
return retVal
|
||||
}
|
||||
|
||||
// 京东正向/退款订单类型处理--存储
|
||||
func (p *PurchaseHandler) onFinancialMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
var err error
|
||||
a := getAPI(AppKey2OrgCode(msg.AppKey))
|
||||
// if msg.StatusID == jdapi.OrderStatusPayFinishedSettle || msg.StatusID == jdapi.OrderStatusTipChanged || msg.StatusID == jdapi.OrderStatusSwitch2SelfSettle { // 如果是正向单
|
||||
if msg.StatusID == jdapi.OrderStatusPayFinishedSettle || msg.StatusID == jdapi.OrderStatusTipChanged || msg.StatusID == jdapi.OrderStatusAdjustSettle || msg.StatusID == jdapi.OrderStatusSwitch2SelfSettle { // 如果是正向单
|
||||
order, err2 := partner.CurOrderManager.LoadOrder(msg.BillID, model.VendorIDJD)
|
||||
if err = err2; err == nil {
|
||||
orderData, err2 := a.QuerySingleOrder(msg.BillID)
|
||||
if err = err2; err == nil {
|
||||
orderFinancial, err2 := CurPurchaseHandler.OrderDetail2Financial(a, orderData, false, order)
|
||||
if err = err2; err == nil {
|
||||
if msg.StatusID == jdapi.OrderStatusPayFinishedSettle {
|
||||
err = partner.CurOrderManager.SaveOrderFinancialInfo(orderFinancial, partner.CreatedPeration)
|
||||
} else {
|
||||
err = partner.CurOrderManager.SaveOrderFinancialInfo(orderFinancial, partner.UpdatedPeration)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
} else if msg.StatusID == jdapi.AfsServiceStateRefundSuccess || msg.StatusID == jdapi.AfsServiceStateReturnGoodsSuccess { // 如果是退款单
|
||||
orderData, err2 := a.GetAfsService(msg.BillID)
|
||||
if err = err2; err == nil {
|
||||
err = partner.CurOrderManager.SaveAfsOrderFinancialInfo(CurPurchaseHandler.AfsOrderDetail2Financial(orderData))
|
||||
}
|
||||
}
|
||||
return jdapi.Err2CallbackResponse(nil, "jd OnFinancialMsg") // todo 强制返回成功
|
||||
}
|
||||
|
||||
// 处理京东正向订单信息
|
||||
func (p *PurchaseHandler) OrderDetail2Financial(a *jdapi.API, orderData map[string]interface{}, isFromOrderDetail bool, order *model.GoodsOrder) (orderFinancial *model.OrderFinancial, err error) {
|
||||
orderFinancial = &model.OrderFinancial{
|
||||
VendorID: model.VendorIDJD,
|
||||
VendorOrderID: utils.Int64ToStr(utils.MustInterface2Int64(orderData["orderId"])),
|
||||
ReceivableFreight: utils.MustInterface2Int64(orderData["orderReceivableFreight"]),
|
||||
FreightMoney: utils.MustInterface2Int64(orderData["orderFreightMoney"]),
|
||||
ActualPayMoney: utils.MustInterface2Int64(orderData["orderBuyerPayableMoney"]),
|
||||
DiscountMoney: utils.MustInterface2Int64(orderData["orderDiscountMoney"]),
|
||||
DistanceFreightMoney: utils.MustInterface2Int64(orderData["merchantPaymentDistanceFreightMoney"]),
|
||||
FreightTipsMoney: utils.MustInterface2Int64(orderData["tips"]),
|
||||
PointsDeductionMoney: utils.MustInterface2Int64(orderData["platformPointsDeductionMoney"]),
|
||||
// BoxMoney: utils.MustInterface2Int64(orderData["packagingMoney"]), // 京东包装(塑料袋)由京东提供,相应钱款也归京东,不记录/记录之后优化算法
|
||||
}
|
||||
skus := order.Skus
|
||||
if skus != nil {
|
||||
for _, x := range skus {
|
||||
orderFinancial.ShopPriceMoney += x.ShopPrice * int64(x.Count)
|
||||
}
|
||||
}
|
||||
if orderData["product"] != nil {
|
||||
product := orderData["product"].([]interface{})
|
||||
for _, x := range product {
|
||||
xMap := x.(map[string]interface{})
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
// OrderFinancialID: orderFinancial.VendorOrderID,
|
||||
// ConfirmTime: utils.Str2Time(utils.Interface2String(orderData["orderStartTime"])),
|
||||
VendorStoreID: utils.Interface2String(orderData["deliveryStationNo"]),
|
||||
StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(orderData["deliveryStationNoIsv"]), 0)),
|
||||
JxStoreID: order.JxStoreID,
|
||||
VendorSkuID: utils.Int64ToStr(utils.MustInterface2Int64(xMap["skuId"])),
|
||||
// SkuID: int(utils.Str2Int64(utils.Interface2String(xMap["skuIdIsv"]))),
|
||||
PromotionType: int(utils.MustInterface2Int64(xMap["promotionType"])),
|
||||
Name: utils.Interface2String(xMap["skuName"]),
|
||||
ShopPrice: utils.MustInterface2Int64(xMap["skuStorePrice"]),
|
||||
SalePrice: utils.MustInterface2Int64(xMap["skuJdPrice"]),
|
||||
Count: int(utils.MustInterface2Int64(xMap["skuCount"])),
|
||||
IsAfsOrder: 0,
|
||||
// MealBoxMoney: utils.MustInterface2Int64(xMap["canteenMoney"]), // 京东的目前不考虑结算餐盒费,因为都归京东所有
|
||||
}
|
||||
|
||||
// PromotionType 是一个关键数据,可能某商品活动限购,用户超出限购数量,超出部分不享受优惠,那么除了要在活动表根据skuId,活动起止日期,活动城市来查询,还需要判断活动类型PromotionType
|
||||
// 平台/京西单条sku补贴金额,应该去京西后台活动库去取,活动里针对单条SKU,如果京东/京西有补贴,应该有记录
|
||||
// orderSkuFinancial.PmSubsidyMoneyForSku =
|
||||
// orderSkuFinancial.JxSubsidyMoneyForSku =
|
||||
// orderFinancial.JxSubsidyMoneyToSku += orderSkuFinancial.JxSubsidyMoneyForSku
|
||||
// orderFinancial.JxSubsidyMoney += orderSkuFinancial.JxSubsidyMoneyForSku
|
||||
orderFinancial.SalePriceMoney += orderSkuFinancial.SalePrice * int64(orderSkuFinancial.Count)
|
||||
orderSkuFinancial.SkuID = int(utils.Str2Int64WithDefault(utils.Interface2String(xMap["skuIdIsv"]), 0))
|
||||
if orderSkuFinancial.SkuID > math.MaxInt32 {
|
||||
orderSkuFinancial.SkuID = orderSkuFinancial.JxSkuID
|
||||
}
|
||||
orderFinancial.Skus = append(orderFinancial.Skus, orderSkuFinancial)
|
||||
}
|
||||
}
|
||||
// orderFinancial.DeliveryConfirmTime = utils.Str2TimeWithDefault(utils.Interface2String(orderData["deliveryConfirmTime"]), utils.DefaultTimeValue)
|
||||
if int(utils.Str2Int64WithDefault(utils.Interface2String(orderData["deliveryCarrierNo"]), 0)) == jdapi.CarrierNoSelfDelivery {
|
||||
// 如果为自配送,自配送补贴=订单初始运费,远距离费=0
|
||||
orderFinancial.SelfDeliveryDiscountMoney = utils.MustInterface2Int64(orderData["orderReceivableFreight"])
|
||||
orderFinancial.DistanceFreightMoney = 0
|
||||
orderFinancial.FreightTipsMoney = 0
|
||||
// 通过本地数据库去取是否转美团/达达,并计算运费
|
||||
// wayBill, err2 := partner.CurOrderManager.LoadWaybill(orderFinancial.VendorOrderID, orderFinancial.VendorID)
|
||||
// if err = err2; err == nil {
|
||||
// orderFinancial.JxFreightMoney = wayBill.DesiredFee
|
||||
// }
|
||||
}
|
||||
if orderData["discount"] != nil {
|
||||
discount := orderData["discount"].([]interface{})
|
||||
for _, x := range discount {
|
||||
xMap := x.(map[string]interface{})
|
||||
discountPrice := utils.MustInterface2Int64(xMap["discountPrice"])
|
||||
discountType := int(utils.MustInterface2Int64(xMap["discountType"]))
|
||||
if discountType == jdapi.FreightDiscountTypeByShop {
|
||||
orderFinancial.FreightDiscountMoney = discountPrice
|
||||
} else if discountType == jdapi.FreightDiscountTypeByVip || discountType == jdapi.FreightDiscountTypeByActivity {
|
||||
orderFinancial.PmFreightDiscountMoney = discountPrice
|
||||
} else if discountType == jdapi.FreightDiscountTypeByCoupons {
|
||||
if xMap["platPayMoney"] == nil {
|
||||
orderFinancial.PmFreightDiscountMoney = discountPrice
|
||||
} else {
|
||||
orderFinancial.PmFreightDiscountMoney = int64(utils.MustInterface2Float64(xMap["platPayMoney"]))
|
||||
orderFinancial.FreightDiscountMoney = discountPrice - orderFinancial.PmFreightDiscountMoney
|
||||
}
|
||||
}
|
||||
orderFinancial.TotalDiscountMoney += discountPrice
|
||||
if xMap["orderShareRatioData"] != nil {
|
||||
orderShareRatioData, _ := utils.HTTPBody2Values([]byte(utils.Interface2String(xMap["orderShareRatioData"])), false)
|
||||
if promotionID := orderShareRatioData.Get("promotionId"); promotionID != "" {
|
||||
activity := &model.OrderDiscountFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
VendorActivityID: promotionID, // utils.Interface2String(orderShareRatioData["promotionId"][0]),
|
||||
Type: utils.Int64ToStr(int64(discountType)),
|
||||
// ActivityName: utils.Interface2String(xMap["discountName"]),
|
||||
// ActivityMoney: discountPrice,
|
||||
// Remark: utils.Interface2String(xMap["orderShareRatioData"]),
|
||||
}
|
||||
orderFinancial.Discounts = append(orderFinancial.Discounts, activity)
|
||||
// 通过活动Id去取,京西活动补贴
|
||||
// orderFinancial.JxSubsidyMoney +=
|
||||
}
|
||||
}
|
||||
}
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(orderFinancial.Discounts, false))
|
||||
}
|
||||
order1, err2 := a.OrderShoudSettlementService(orderFinancial.VendorOrderID)
|
||||
if err = err2; err == nil {
|
||||
orderFinancial.ShopMoney = utils.Interface2Int64WithDefault(order1["settlementAmount"], 0)
|
||||
orderFinancial.PmMoney += utils.Interface2Int64WithDefault(order1["goodsCommission"], 0)
|
||||
orderFinancial.PmMoney += utils.Interface2Int64WithDefault(order1["freightCommission"], 0)
|
||||
orderFinancial.PmMoney += utils.Interface2Int64WithDefault(order1["packageCommission"], 0)
|
||||
orderFinancial.PmMoney += utils.Interface2Int64WithDefault(order1["guaranteedCommission"], 0)
|
||||
orderFinancial.PmSkuSubsidyMoney = utils.Interface2Int64WithDefault(order1["platSkuGoodsDiscountMoney"], 0)
|
||||
orderFinancial.PmSubsidyMoney = utils.Interface2Int64WithDefault(order1["platOrderGoodsDiscountMoney"], 0) + orderFinancial.PmSkuSubsidyMoney
|
||||
}
|
||||
return orderFinancial, err
|
||||
}
|
||||
|
||||
// 处理京东售后订单结账信息
|
||||
func (p *PurchaseHandler) AfsOrderDetail2Financial(orderData map[string]interface{}) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDJD,
|
||||
AfsOrderID: utils.Interface2String(orderData["afsServiceOrder"]),
|
||||
VendorOrderID: utils.Interface2String(orderData["orderId"]),
|
||||
VendorStoreID: utils.Interface2String(orderData["stationId"]),
|
||||
StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(orderData["stationNumOutSystem"]), 0)),
|
||||
AfsCreatedAt: utils.Timestamp2Time(utils.MustInterface2Int64(orderData["updateTime"].(map[string]interface{})["time"]) / 1000),
|
||||
FreightUserMoney: utils.MustInterface2Int64(orderData["orderFreightMoney"]),
|
||||
AfsFreightMoney: utils.MustInterface2Int64(orderData["afsFreight"]),
|
||||
BoxMoney: utils.MustInterface2Int64(orderData["packagingMoney"]),
|
||||
TongchengFreightMoney: utils.MustInterface2Int64(orderData["tongchengFreightMoney"]),
|
||||
SkuBoxMoney: utils.MustInterface2Int64(orderData["mealBoxMoney"]),
|
||||
VendorOrgCode: utils.Interface2String(orderData["venderId"]),
|
||||
}
|
||||
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
|
||||
if err == nil {
|
||||
afsOrder.JxStoreID = order.JxStoreID
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("jd AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
|
||||
}
|
||||
if orderData["afsDetailList"] != nil {
|
||||
refundDetail := orderData["afsDetailList"].([]interface{})
|
||||
for _, x := range refundDetail {
|
||||
xMap := x.(map[string]interface{})
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
VendorID: model.VendorIDJD,
|
||||
AfsOrderID: afsOrder.AfsOrderID,
|
||||
VendorOrderID: afsOrder.VendorOrderID,
|
||||
VendorStoreID: afsOrder.VendorStoreID,
|
||||
StoreID: afsOrder.StoreID,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorSkuID: utils.Int64ToStr(utils.MustInterface2Int64(xMap["wareId"])),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(xMap["skuIdIsv"]), 0)),
|
||||
Name: utils.Interface2String(xMap["wareName"]),
|
||||
UserMoney: utils.MustInterface2Int64(xMap["afsMoney"]),
|
||||
PmSkuSubsidyMoney: utils.MustInterface2Int64(xMap["platPayMoney"]),
|
||||
IsAfsOrder: 1,
|
||||
}
|
||||
afsOrder.PmSkuSubsidyMoney += orderSku.PmSkuSubsidyMoney
|
||||
orderSku.PmSubsidyMoney += orderSku.PmSkuSubsidyMoney
|
||||
|
||||
if xMap["afsSkuDiscountList"] != nil {
|
||||
afsSkuDiscountList := xMap["afsSkuDiscountList"].([]interface{})
|
||||
for _, y := range afsSkuDiscountList {
|
||||
orderSku.PmSubsidyMoney += utils.MustInterface2Int64(y.(map[string]interface{})["platPayMoney"])
|
||||
}
|
||||
}
|
||||
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
if len(refundDetail) <= 0 {
|
||||
globals.SugarLogger.Warnf("jd AfsOrderDetail2Financial, orderID:%s have no refund_detail", afsOrder.VendorOrderID)
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("jd AfsOrderDetail2Financial, orderID:% refund_detail is nil", afsOrder.VendorOrderID)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OnOrderDetail(a *jdapi.API, orderDetail map[string]interface{}, peration string) (err error) {
|
||||
order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(utils.MustInterface2Int64(orderDetail["orderId"])), model.VendorIDJD)
|
||||
if err == nil {
|
||||
orderFinancial, err2 := CurPurchaseHandler.OrderDetail2Financial(a, orderDetail, true, order)
|
||||
if err = err2; err == nil {
|
||||
err = partner.CurOrderManager.SaveOrderFinancialInfo(orderFinancial, peration)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
)
|
||||
|
||||
func TestOnFinancialMsg(t *testing.T) {
|
||||
msg := &jdapi.CallbackOrderMsg{
|
||||
BillID: "907315020000322",
|
||||
StatusID: "330902",
|
||||
}
|
||||
res := CurPurchaseHandler.onFinancialMsg(msg)
|
||||
fmt.Println(res)
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
}
|
||||
|
||||
var (
|
||||
CurPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
func init() {
|
||||
globals.SugarLogger.Debug("init jd")
|
||||
CurPurchaseHandler = new(PurchaseHandler)
|
||||
partner.RegisterPurchasePlatform(CurPurchaseHandler)
|
||||
}
|
||||
|
||||
func getAPI(appOrgCode string) (apiObj *jdapi.API) {
|
||||
if appOrgCode == "" {
|
||||
globals.SugarLogger.Warnf("getAPI appOrgCode is empty")
|
||||
}
|
||||
return partner.CurAPIManager.GetAPI(model.VendorIDJD, appOrgCode).(*jdapi.API)
|
||||
}
|
||||
|
||||
func GetAPI(appOrgCode string) (apiObj *jdapi.API) {
|
||||
return getAPI(appOrgCode)
|
||||
}
|
||||
|
||||
func AppKey2OrgCode(appKey string) (vendorOrgCode string) {
|
||||
apiList := partner.CurAPIManager.GetAppOrgCodeList(model.VendorIDJD)
|
||||
for _, v := range apiList {
|
||||
jdAPI := partner.CurAPIManager.GetAPI(model.VendorIDJD, v).(*jdapi.API)
|
||||
if jdAPI.GetAppKey() == appKey {
|
||||
vendorOrgCode = v
|
||||
break
|
||||
}
|
||||
}
|
||||
if vendorOrgCode == "" {
|
||||
globals.SugarLogger.Warnf("AppKey2OrgCode appKey:%s get empty vendorOrgCode", appKey)
|
||||
}
|
||||
return vendorOrgCode
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDJD
|
||||
}
|
||||
|
||||
func JdOperationTime2JxOperationTime(value1 int) int16 {
|
||||
value := int16(value1)
|
||||
return (value/2)*100 + (value%2)*30
|
||||
}
|
||||
|
||||
func JxOperationTime2JdOperationTime(value int16) int16 {
|
||||
return (value/100)*2 + (value%100)/30
|
||||
}
|
||||
|
||||
func JdStoreStatus2JxStatus(yn, closeStatus int) int {
|
||||
if yn == 1 {
|
||||
return model.StoreStatusDisabled
|
||||
} else if closeStatus == 1 {
|
||||
return model.StoreStatusClosed
|
||||
}
|
||||
return model.StoreStatusOpened
|
||||
}
|
||||
|
||||
func JxStoreStatus2JdStatus(status int) (yn, closeStatus int) {
|
||||
switch status {
|
||||
case model.StoreStatusDisabled:
|
||||
return 1, 1
|
||||
case model.StoreStatusHaveRest, model.StoreStatusClosed:
|
||||
return 0, 1
|
||||
default:
|
||||
return 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
return imgHint, err
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
_ "git.rosy.net.cn/jx-callback/globals/api/apimanager"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package jd
|
||||
@@ -1,617 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/autonavi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
VendorStatus2StatusMap = map[string]int{
|
||||
jdapi.OrderStatusPurchased: model.OrderStatusNew,
|
||||
jdapi.OrderStatusWaitOutStore: model.OrderStatusAccepted,
|
||||
jdapi.StatusIDWaitOutStore: model.OrderStatusAccepted,
|
||||
jdapi.OrderStatusFinishedPickup: model.OrderStatusFinishedPickup,
|
||||
jdapi.OrderStatusDelivering: model.OrderStatusDelivering,
|
||||
jdapi.OrderStatusDelivered: model.OrderStatusFinished,
|
||||
jdapi.OrderStatusFinished: model.OrderStatusFinished, // todo 这个状态不是真正都完成的意思?
|
||||
jdapi.OrderStatusCanceled: model.OrderStatusCanceled,
|
||||
|
||||
jdapi.OrderStatusAdjust: model.OrderStatusAdjust,
|
||||
jdapi.OrderStatusUserApplyCancel: model.OrderStatusApplyCancel,
|
||||
jdapi.OrderStatusLocked: model.OrderStatusLocked,
|
||||
jdapi.OrderStatusUnlocked: model.OrderStatusUnlocked,
|
||||
|
||||
jdapi.OrderStatusVenderAgreeCancel: model.OrderStatusVendorAgreeCancel,
|
||||
jdapi.OrderStatusVenderRejectCancel: model.OrderStatusVendorRejectCancel,
|
||||
jdapi.CallbackMsgOrderAddTips: model.OrderStatusWaybillTipChanged,
|
||||
}
|
||||
deliveryTypeMap = map[int]string{
|
||||
jdapi.CarrierNoCrowdSourcing: model.OrderDeliveryTypePlatform,
|
||||
jdapi.CarrierNoSelfDelivery: model.OrderDeliveryTypeStoreSelf,
|
||||
jdapi.CarrierNoSelfTake: model.OrderDeliveryTypeSelfTake,
|
||||
}
|
||||
|
||||
selfTakeCodeReg = regexp.MustCompile(`等待用户凭提货码(\d+)于`)
|
||||
|
||||
afsMsgMap = map[string]bool{
|
||||
jdapi.CallbackMsgNewApplyAfterSaleBill: true,
|
||||
jdapi.CallbackMsgUpdateApplyAfterSaleBill: true,
|
||||
jdapi.CallbackMsgNewAfterSaleBill: true,
|
||||
jdapi.CallbackMsgAfterSaleBillStatus: true,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) OnOrderMsg(vendorOrgCode string, msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderMsg(vendorOrgCode, msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) updateOrderFinancialInfo(a *jdapi.API, orderID string) (err error) {
|
||||
order := &model.GoodsOrder{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDJD,
|
||||
}
|
||||
orderSettlement, err := a.OrderShoudSettlementService2(orderID)
|
||||
if err == nil {
|
||||
if orderSettlement != nil {
|
||||
updateOrderBySettleMent(order, orderSettlement)
|
||||
globals.SugarLogger.Debugf("updateOrderBySettleMent: %v , %v", order.NewEarningPrice, order.TotalShopMoney)
|
||||
err = partner.CurOrderManager.UpdateOrderFields(order, []string{ /*"WaybillTipMoney", */ "TotalShopMoney", "PmSubsidyMoney", "NewEarningPrice"})
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderMsg(vendorOrgCode string, msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
a := getAPI(vendorOrgCode)
|
||||
if afsMsgMap[msg.MsgURL] {
|
||||
retVal = c.OnAfsOrderMsg(a, msg)
|
||||
} else {
|
||||
status := c.callbackMsg2Status(msg)
|
||||
if jdapi.StatusIDNewOrder == msg.StatusID {
|
||||
status.Status = model.OrderStatusNew // 因为京东将事件32000与状态32000混用,事件32000可能是新订单,也可能是已接单,统一当成新订单处理
|
||||
}
|
||||
if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 {
|
||||
return nil
|
||||
}
|
||||
if msg.MsgURL == jdapi.CallbackMsgOrderAccounting {
|
||||
retVal = c.OnFinancialMsg(msg)
|
||||
retVal = jdapi.Err2CallbackResponse(c.updateOrderFinancialInfo(a, msg.BillID), status.VendorStatus)
|
||||
} else {
|
||||
// 新订单事件,与订单状态有点冲突
|
||||
if jdapi.StatusIDNewOrder == msg.StatusID {
|
||||
retVal = c.onOrderNew(a, msg, status)
|
||||
} else if jdapi.OrderStatusAdjust == msg.StatusID {
|
||||
retVal = c.onOrderAdjust(a, msg, status)
|
||||
} else {
|
||||
if msg.StatusID == jdapi.OrderStatusAddComment || msg.StatusID == jdapi.OrderStatusModifyComment {
|
||||
utils.CallFuncAsync(func() {
|
||||
c.onOrderComment2(a, msg)
|
||||
})
|
||||
}
|
||||
// if msg.StatusID == jdapi.OrderStatusVenderAgreeCancel {
|
||||
// order := &model.GoodsOrder{
|
||||
// VendorOrgCode: vendorOrgCode,
|
||||
// VendorOrderID: msg.BillID,
|
||||
// }
|
||||
// err2 := c.PickupGoods(order, false, jxcontext.AdminCtx.GetUserName())
|
||||
// if err2 != nil {
|
||||
// globals.SugarLogger.Warnf("京东取消拣货:%v", err2)
|
||||
// }
|
||||
// }
|
||||
err := partner.CurOrderManager.OnOrderStatusChanged(vendorOrgCode, status)
|
||||
retVal = jdapi.Err2CallbackResponse(err, status.VendorStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnOrderInfoChangeMsg(vendorOrgCode string, msg *jdapi.CallbackOrderInfoChangeMsg) (retVal *jdapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onOrderInfoChangeMsg(vendorOrgCode, msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderInfoChangeMsg(vendorOrgCode string, msg *jdapi.CallbackOrderInfoChangeMsg) (retVal *jdapi.CallbackResponse) {
|
||||
db := dao.GetDB()
|
||||
order, err := dao.GetSimpleOrder(db, msg.BillID)
|
||||
if err == nil {
|
||||
globals.SugarLogger.Debugf("onOrderInfoChangeMsg msg:%v", utils.Format4Output(msg, false))
|
||||
if msg.BuyerFullAddress != "" {
|
||||
order.ConsigneeAddress = msg.BuyerFullAddress
|
||||
}
|
||||
if msg.BuyerFullName != "" {
|
||||
order.ConsigneeName = msg.BuyerFullName
|
||||
}
|
||||
if msg.BuyerMobile != "" {
|
||||
order.ConsigneeMobile = msg.BuyerMobile
|
||||
}
|
||||
if msg.BuyerLat != "" {
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(utils.Str2Float64(msg.BuyerLat))
|
||||
}
|
||||
if msg.BuyerLng != "" {
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(utils.Str2Float64(msg.BuyerLng))
|
||||
}
|
||||
if msg.OrderBuyerRemark != "" {
|
||||
order.BuyerComment = msg.OrderBuyerRemark
|
||||
}
|
||||
_, err = dao.UpdateEntity(db, order, "ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeLat", "ConsigneeLng", "BuyerComment")
|
||||
weixinmsg.NotifyOrderChanged(order)
|
||||
}
|
||||
return jdapi.SuccessResponse
|
||||
}
|
||||
|
||||
func updateOrderBySettleMent(order *model.GoodsOrder, orderSettlement *jdapi.OrderSettlementInfo) {
|
||||
if orderSettlement != nil {
|
||||
order.TotalShopMoney = orderSettlement.SettlementAmount
|
||||
order.PmSubsidyMoney = orderSettlement.PlatOrderGoodsDiscountMoney + orderSettlement.PlatSkuGoodsDiscountMoney
|
||||
if order.TotalShopMoney > 0 {
|
||||
if jxutils.GetSaleStoreIDFromOrder(order) != 0 {
|
||||
storeDetail, err := partner.CurOrderManager.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID)
|
||||
if storeDetail != nil && err == nil {
|
||||
jxutils.RefreshOrderEarningPrice2(order, storeDetail.PayPercentage)
|
||||
}
|
||||
} else {
|
||||
order2, err := partner.CurOrderManager.LoadOrder(order.VendorOrderID, order.VendorID)
|
||||
if order2 != nil && err == nil {
|
||||
storeDetail, err := partner.CurOrderManager.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order2), order.VendorID)
|
||||
if storeDetail != nil && err == nil {
|
||||
jxutils.RefreshOrderEarningPrice2(order, storeDetail.PayPercentage)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
order.NewEarningPrice = order.EarningPrice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) getOrder(a *jdapi.API, orderID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) {
|
||||
globals.SugarLogger.Debugf("jd getOrder orderID:%s", orderID)
|
||||
var (
|
||||
realMobile string
|
||||
orderSettlement *jdapi.OrderSettlementInfo
|
||||
)
|
||||
task := tasksch.NewParallelTask("jd getOrder", tasksch.NewParallelConfig().SetIsContinueWhenError(true), jxcontext.AdminCtx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
taskIndex := batchItemList[0].(int)
|
||||
switch taskIndex {
|
||||
case 0:
|
||||
orderMap, err = a.QuerySingleOrder(orderID)
|
||||
if err == nil {
|
||||
order = c.Map2Order(orderMap)
|
||||
realMobile, _ = a.GetRealMobile4Order(orderID, order.VendorStoreID)
|
||||
if realMobile != "" {
|
||||
order.ConsigneeMobile2 = jxutils.FormalizeMobile(realMobile)
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
orderSettlement, _ = a.OrderShoudSettlementService2(orderID)
|
||||
}
|
||||
return nil, err
|
||||
}, []int{0, 1})
|
||||
task.Run()
|
||||
_, err = task.GetResult(0)
|
||||
if order != nil && orderSettlement != nil {
|
||||
updateOrderBySettleMent(order, orderSettlement)
|
||||
err = partner.CurOrderManager.UpdateOrderFields(order, []string{"NewEarningPrice"})
|
||||
}
|
||||
return order, orderMap, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) {
|
||||
order, _, err = c.getOrder(getAPI(vendorOrgCode), orderID)
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
order, err := getAPI(vendorOrgCode).QuerySingleOrder2(vendorOrderID)
|
||||
if err == nil {
|
||||
status = getStatusFromVendorStatus(utils.Int2Str(order.OrderStatus))
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
return Map2Order(orderData)
|
||||
}
|
||||
|
||||
func Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := orderData
|
||||
orderID := utils.Int64ToStr(utils.MustInterface2Int64(result["orderId"]))
|
||||
globals.SugarLogger.Debugf("jd Map2Order orderID:%s", orderID)
|
||||
|
||||
const defaultStatusTimeField = "orderPurchaseTime"
|
||||
statusTimeField := defaultStatusTimeField
|
||||
if result[statusTimeField] == nil { // 814560888003021 orderPurchaseTime为空
|
||||
statusTimeField = "orderStartTime"
|
||||
}
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDJD,
|
||||
VendorStoreID: utils.Interface2String(result["produceStationNo"]),
|
||||
StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["produceStationNoIsv"]), 0)),
|
||||
StoreName: utils.Interface2String(result["produceStationName"]),
|
||||
VendorUserID: utils.Interface2String(result["buyerPin"]),
|
||||
ConsigneeName: utils.Interface2String(result["buyerFullName"]),
|
||||
ConsigneeMobile: jxutils.FormalizeMobile(utils.Interface2String(result["buyerMobile"])),
|
||||
ConsigneeAddress: utils.Interface2String(result["buyerFullAddress"]),
|
||||
CoordinateType: model.CoordinateTypeMars,
|
||||
BuyerComment: utils.TrimBlankChar(utils.Interface2String(result["orderBuyerRemark"])),
|
||||
ExpectedDeliveredTime: utils.Str2TimeWithDefault(utils.Interface2String(result["orderPreEndDeliveryTime"]), utils.DefaultTimeValue),
|
||||
PickDeadline: utils.Str2TimeWithDefault(utils.Interface2String(result["pickDeadline"]), utils.DefaultTimeValue), // 813951615000022 pickDeadline为空
|
||||
VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(result["orderStatus"])),
|
||||
OrderSeq: int(utils.MustInterface2Int64(result["orderNum"])),
|
||||
StatusTime: utils.Str2Time(result[statusTimeField].(string)),
|
||||
OrderCreatedAt: utils.Str2Time(result[statusTimeField].(string)),
|
||||
// OrderFinishedAt: utils.Str2Time(result["orderStatusTime"].(string)),
|
||||
OriginalData: string(utils.MustMarshal(result)),
|
||||
ActualPayPrice: utils.MustInterface2Int64(result["orderBuyerPayableMoney"]),
|
||||
BaseFreightMoney: utils.Interface2Int64WithDefault(result["orderBaseFreightMoney"], 0),
|
||||
DistanceFreightMoney: utils.Interface2Int64WithDefault(result["merchantPaymentDistanceFreightMoney"], 0),
|
||||
DeliveryType: deliveryTypeMap[int(utils.Str2Int64WithDefault(utils.Interface2String(result["deliveryCarrierNo"]), 0))],
|
||||
VendorOrgCode: utils.Interface2String(result["orgCode"]),
|
||||
}
|
||||
if orderInvoice, ok := result["orderInvoice"].(map[string]interface{}); ok && orderInvoice != nil {
|
||||
order.InvoiceTitle = utils.Interface2String(orderInvoice["invoiceTitle"])
|
||||
order.InvoiceTaxerID = utils.Interface2String(orderInvoice["invoiceDutyNo"])
|
||||
order.InvoiceEmail = utils.Interface2String(orderInvoice["invoiceMail"])
|
||||
}
|
||||
order.Status = getStatusFromVendorStatus(order.VendorStatus)
|
||||
businessTage := utils.Interface2String(result["businessTag"])
|
||||
if strings.Index(businessTage, "dj_aging_immediately") >= 0 {
|
||||
order.BusinessType = model.BusinessTypeImmediate
|
||||
} else {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
}
|
||||
coordinateType := utils.Interface2Int64WithDefault(result["buyerCoordType"], 1)
|
||||
originalLng := utils.MustInterface2Float64(result["buyerLng"])
|
||||
originalLat := utils.MustInterface2Float64(result["buyerLat"])
|
||||
if coordinateType == 1 {
|
||||
lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysGPS)
|
||||
if err2 == nil {
|
||||
originalLng = lng
|
||||
originalLat = lat
|
||||
} else {
|
||||
// 如果没有转成功,保留原始数据
|
||||
order.CoordinateType = model.CoordinateTypeGPS
|
||||
}
|
||||
}
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng)
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat)
|
||||
discounts, _ := result["discount"].([]interface{})
|
||||
for _, v := range discounts {
|
||||
discount := v.(map[string]interface{})
|
||||
order.DiscountMoney += utils.Interface2Int64WithDefault(discount["discountPrice"], 0)
|
||||
}
|
||||
for _, product2 := range result["product"].([]interface{}) {
|
||||
product := product2.(map[string]interface{})
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDJD,
|
||||
Count: int(utils.MustInterface2Int64(product["skuCount"])),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product["skuIdIsv"]), 0)),
|
||||
VendorSkuID: utils.Int64ToStr(utils.MustInterface2Int64(product["skuId"])),
|
||||
SkuName: product["skuName"].(string),
|
||||
Weight: jxutils.FloatWeight2Int(float32(utils.MustInterface2Float64(product["skuWeight"]))),
|
||||
VendorPrice: utils.MustInterface2Int64(product["skuStorePrice"]),
|
||||
SalePrice: utils.MustInterface2Int64(product["skuJdPrice"]),
|
||||
}
|
||||
if jdPromotionType := int(utils.MustInterface2Int64(product["promotionType"])); jdPromotionType != 0 && jdPromotionType != jdapi.PromotionTypeNormal {
|
||||
sku.StoreSubName = utils.Int2Str(jdPromotionType)
|
||||
}
|
||||
if skuCostumeProperty, ok := product["skuCostumeProperty"]; ok {
|
||||
sku.SkuName += skuCostumeProperty.(string)
|
||||
}
|
||||
if isGift, ok := product["isGift"].(bool); ok && isGift {
|
||||
sku.SkuType = 1
|
||||
}
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
return order
|
||||
}
|
||||
|
||||
//
|
||||
func (c *PurchaseHandler) onOrderNew(a *jdapi.API, msg *jdapi.CallbackOrderMsg, orderStatus *model.OrderStatus) (response *jdapi.CallbackResponse) {
|
||||
globals.SugarLogger.Debugf("onOrderNew orderID:%s", msg.BillID)
|
||||
order, orderMap, err := c.getOrder(a, msg.BillID)
|
||||
if err == nil {
|
||||
globals.SugarLogger.Debugf("onOrderNew2 orderID:%s", msg.BillID)
|
||||
if err = partner.CurOrderManager.OnOrderNew(order, orderStatus); err == nil {
|
||||
utils.CallFuncAsync(func() {
|
||||
c.OnOrderDetail(a, orderMap, partner.CreatedPeration)
|
||||
})
|
||||
}
|
||||
}
|
||||
return jdapi.Err2CallbackResponse(err, "jd onOrderNew")
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderAdjust(a *jdapi.API, msg *jdapi.CallbackOrderMsg, orderStatus *model.OrderStatus) *jdapi.CallbackResponse {
|
||||
order, orderMap, err := c.getOrder(a, msg.BillID)
|
||||
if err == nil {
|
||||
err = partner.CurOrderManager.OnOrderAdjust(order, orderStatus)
|
||||
if err == nil {
|
||||
utils.CallFuncAsync(func() {
|
||||
c.OnOrderDetail(a, orderMap, partner.UpdatedPeration)
|
||||
})
|
||||
}
|
||||
}
|
||||
return jdapi.Err2CallbackResponse(err, "jd onOrderAdjust")
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Status(msg *jdapi.CallbackOrderMsg) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.BillID,
|
||||
VendorID: model.VendorIDJD,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: msg.BillID,
|
||||
RefVendorID: model.VendorIDJD,
|
||||
VendorStatus: msg.StatusID,
|
||||
StatusTime: utils.Str2Time(msg.Timestamp),
|
||||
Remark: msg.Remark,
|
||||
}
|
||||
if msg.MsgURL == jdapi.CallbackMsgOrderAddTips {
|
||||
orderStatus.VendorStatus = jdapi.CallbackMsgOrderAddTips
|
||||
}
|
||||
orderStatus.Status = getStatusFromVendorStatus(orderStatus.VendorStatus)
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) postFakeMsg(vendorOrgCode, vendorOrderID, vendorStatus string) {
|
||||
msg := &jdapi.CallbackOrderMsg{
|
||||
CallbackMsg: &jdapi.CallbackMsg{
|
||||
AppKey: getAPI(vendorOrgCode).GetAppKey(),
|
||||
},
|
||||
BillID: vendorOrderID,
|
||||
StatusID: vendorStatus,
|
||||
Timestamp: utils.Time2Str(time.Now()),
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
OnOrderMsg(msg)
|
||||
})
|
||||
}
|
||||
|
||||
// IPurchasePlatformHandler
|
||||
func getStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).OrderAcceptOperate(order.VendorOrderID, isAcceptIt, userName)
|
||||
if isAcceptIt && err == nil {
|
||||
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.StatusIDWaitOutStore)
|
||||
}
|
||||
} else {
|
||||
if isAcceptIt {
|
||||
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.StatusIDWaitOutStore)
|
||||
} else {
|
||||
|
||||
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.OrderStatusCanceled)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery)
|
||||
if !isSelfDelivery && globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(order.VendorOrgCode).OrderJDZBDelivery(order.VendorOrderID, userName)
|
||||
} else {
|
||||
c.postFakeMsg(order.VendorOrgCode, order.VendorOrderID, jdapi.OrderStatusFinishedPickup)
|
||||
}
|
||||
if err == nil {
|
||||
orderSettlement, _ := getAPI(order.VendorOrgCode).OrderShoudSettlementService2(order.VendorOrderID)
|
||||
updateOrderBySettleMent(order, orderSettlement)
|
||||
globals.SugarLogger.Debugf("jd PickupGoods, %v", order.NewEarningPrice)
|
||||
err = partner.CurOrderManager.UpdateOrderFields(order, []string{"NewEarningPrice"})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).ReceiveFailedAudit(order.VendorOrderID, isAcceptIt, ctx.GetUserName(), "")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).UrgeDispatching(order.VendorOrderID, ctx.GetUserName())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).ConfirmReceiveGoods(order.VendorOrderID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(order.VendorOrgCode).ModifySellerDelivery(order.VendorOrderID, userName)
|
||||
if err != nil {
|
||||
if errWithCode, ok := err.(*utils.ErrorWithCode); ok && errWithCode.Level() == 1 {
|
||||
globals.SugarLogger.Infof("Swtich2SelfDeliver failed with error:%v try get current status", err)
|
||||
if order2, err2 := c.GetOrder(order.VendorOrgCode, order.VendorOrderID); err2 == nil {
|
||||
var mapData map[string]interface{}
|
||||
if err2 = utils.UnmarshalUseNumber([]byte(order2.OriginalData), &mapData); err2 == nil {
|
||||
if utils.Interface2String(mapData["deliveryCarrierNo"]) == "2938" { // 当前已经是自送状态了
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(order.VendorOrgCode).DeliveryEndOrder(order.VendorOrderID, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd SelfDeliverDelivering orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(order.VendorOrgCode).OrderSerllerDelivery(order.VendorOrderID, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 京东送达接口都是一样的
|
||||
func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("jd SelfDeliverDelivered orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = c.Swtich2SelfDelivered(order, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
mobile, err = getAPI(order.VendorOrgCode).GetRealMobile4Order(order.VendorOrderID, order.VendorStoreID)
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).OrderCancelOperate(order.VendorOrderID, isAgree, ctx.GetUserName(), reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err1 := c.Swtich2SelfDeliver(order, ctx.GetUserName())
|
||||
if err = getAPI(order.VendorOrgCode).CancelAndRefund(order.VendorOrderID, ctx.GetUserName(), reason); err != nil {
|
||||
if err1 != nil {
|
||||
err = fmt.Errorf("取消订单失败,京东取消订单是要先转为自送再处理,转自送失败:%v", err1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
order = jxutils.RemoveSkuFromOrder(order, removedSkuList)
|
||||
var oaosAdjustDTOList []*jdapi.OAOSAdjustDTO
|
||||
dtoMap := make(map[int]*jdapi.OAOSAdjustDTO)
|
||||
for _, sku := range order.Skus {
|
||||
skuID := jxutils.GetSkuIDFromOrderSku(sku)
|
||||
if dtoMap[skuID] == nil {
|
||||
dtoMap[skuID] = &jdapi.OAOSAdjustDTO{
|
||||
OutSkuID: utils.Int2Str(skuID),
|
||||
SkuCount: sku.Count,
|
||||
}
|
||||
oaosAdjustDTOList = append(oaosAdjustDTOList, dtoMap[skuID])
|
||||
} else {
|
||||
dtoMap[skuID].SkuCount += sku.Count
|
||||
}
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).AdjustOrder(order.VendorOrderID, ctx.GetUserName(), reason, oaosAdjustDTOList)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) {
|
||||
if utils.IsTimeZero(queryDate) {
|
||||
return nil, fmt.Errorf("queryDate必须指定")
|
||||
}
|
||||
fromDate := utils.Time2Date(queryDate)
|
||||
toDate := fromDate.Add(24*time.Hour - 1)
|
||||
queryParam := &jdapi.OrderQueryParam{
|
||||
OrderPurchaseTimeBegin: utils.Time2Str(fromDate),
|
||||
OrderPurchaseTimeEnd: utils.Time2Str(toDate),
|
||||
PageNo: jdapi.AllPage,
|
||||
}
|
||||
if vendorStoreID != "" {
|
||||
queryParam.DeliveryStationNo = vendorStoreID
|
||||
}
|
||||
orderList, _, err := getAPI(vendorOrgCode).OrderQuery2(queryParam)
|
||||
if err == nil {
|
||||
vendorOrderIDs = make([]string, len(orderList))
|
||||
for k, v := range orderList {
|
||||
vendorOrderIDs[k] = utils.Int64ToStr(v.OrderID)
|
||||
}
|
||||
}
|
||||
return vendorOrderIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
|
||||
orderInfo, err := getAPI(vendorOrgCode).QuerySingleOrder2(vendorOrderID)
|
||||
if err == nil {
|
||||
tipFee = int64(orderInfo.Tips)
|
||||
}
|
||||
return tipFee, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
|
||||
curTipFee, err := c.GetWaybillTip(ctx, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2)
|
||||
if err == nil {
|
||||
if tipFee2Add := tipFee - curTipFee; tipFee2Add > 0 {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).OrderAddTips(vendorOrderID, int(tipFee2Add), ctx.GetUserName())
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetSelfTakeCode(ctx *jxcontext.Context, order *model.GoodsOrder) (selfTakeCode string, err error) {
|
||||
orderTrackList, err := getAPI(order.VendorOrgCode).GetByOrderNoForOaos(order.VendorOrderID)
|
||||
if err == nil {
|
||||
for _, v := range orderTrackList {
|
||||
if v.TagCode == 180 {
|
||||
searchResult := selfTakeCodeReg.FindStringSubmatch(v.MsgContent)
|
||||
if searchResult != nil && len(searchResult[1]) > 0 {
|
||||
selfTakeCode = searchResult[1]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return selfTakeCode, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, order *model.GoodsOrder, selfTakeCode string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).CheckSelfPickCode(selfTakeCode, order.VendorOrderID, ctx.GetUserName())
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
var (
|
||||
AfsVendorStatus2StatusMap = map[string]int{
|
||||
jdapi.AfsServiceStateWaiting4Audit: model.AfsOrderStatusWait4Approve, // 需要审核
|
||||
|
||||
jdapi.AfsServiceStateWaiting4CSFeedback: model.AfsOrderStatusNew,
|
||||
jdapi.AfsServiceStateRefundProcessing: model.AfsOrderStatusNew,
|
||||
jdapi.AfsServiceStateWaiting4DirectCompensate: model.AfsOrderStatusNew,
|
||||
jdapi.AfsServiceStateWaiting4ReturnGoods: model.AfsOrderStatusNew,
|
||||
|
||||
jdapi.AfsServiceStateWaiting4MerchantReceiveGoods: model.AfsOrderStatusWait4ReceiveGoods,
|
||||
|
||||
jdapi.AfsServiceStateRefundSuccess: model.AfsOrderStatusFinished,
|
||||
jdapi.AfsServiceStateSolved: model.AfsOrderStatusFinished,
|
||||
jdapi.AfsServiceStateDirectCompensateSuccess: model.AfsOrderStatusFinished,
|
||||
jdapi.AfsServiceStateReturnGoodsSuccess: model.AfsOrderStatusFinished,
|
||||
|
||||
jdapi.AfsServiceStateRefundFailed: model.AfsOrderStatusFailed,
|
||||
jdapi.AfsServiceStateAuditRefused: model.AfsOrderStatusFailed,
|
||||
jdapi.AfsServiceStateUserCanceled: model.AfsOrderStatusFailed,
|
||||
jdapi.AfsServiceStateMerchantFailedReceiveGoods: model.AfsOrderStatusFailed,
|
||||
jdapi.AfsServiceStateDirectCompensateFailed: model.AfsOrderStatusFailed,
|
||||
jdapi.AfsServiceStateReturnGoodsFailed: model.AfsOrderStatusFailed,
|
||||
}
|
||||
|
||||
afsReasonTypeMap = map[int]int8{
|
||||
jdapi.AfsReasonTypeGoodsQuality: model.AfsReasonTypeGoodsQuality,
|
||||
jdapi.AfsReasonTypeWrongGoods: model.AfsReasonTypeWrongGoods,
|
||||
jdapi.AfsReasonTypeMissingGoods: model.AfsReasonTypeMissingGoods,
|
||||
jdapi.AfsReasonTypeNoGoods: model.AfsReasonTypeNoGoods,
|
||||
jdapi.AfsReasonTypeDamagedGoods: model.AfsReasonTypeDamagedGoods,
|
||||
jdapi.AfsReasonTypeGoodsQuantity: model.AfsReasonTypeGoodsQuantity,
|
||||
jdapi.AfsReasonTypeGoodsAbsent: model.AfsReasonTypeGoodsAbsent,
|
||||
jdapi.AfsReasonTypeGoodsSizeNoSame: model.AfsReasonTypeGoodsNoSame,
|
||||
jdapi.AfsReasonTypeGoodsColorNoSame: model.AfsReasonTypeGoodsNoSame,
|
||||
jdapi.AfsReasonWrongPurchase: model.AfsReasonWrongPurchase,
|
||||
jdapi.AfsReasonNotReceivedIntime: model.AfsReasonNotReceivedIntime,
|
||||
}
|
||||
afsAppealTypeMap = map[string]int8{
|
||||
jdapi.AfsDealTypeRefund: model.AfsAppealTypeRefund,
|
||||
jdapi.AfsDealTypeReturnGoodsRefund: model.AfsAppealTypeReturnAndRefund,
|
||||
jdapi.AfsDealTypeDirectCompensate: model.AfsAppealTypeNewGoods,
|
||||
}
|
||||
afsApproveTypeMap = map[int]int{
|
||||
partner.AfsApproveTypeRefund: jdapi.AfsApproveTypeRefund,
|
||||
partner.AfsApproveTypeReturnGoods: jdapi.AfsApproveTypeReturnGoods,
|
||||
partner.AfsApproveTypeRefused: jdapi.AfsApproveTypeRefused,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) OnAfsOrderMsg(a *jdapi.API, msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandlerAsync(func() {
|
||||
retVal = c.onAfsOrderMsg(a, msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.BillID, model.VendorIDJD))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onAfsOrderMsg(a *jdapi.API, msg *jdapi.CallbackOrderMsg) (retVal *jdapi.CallbackResponse) {
|
||||
afsInfo, err := a.GetAfsService2(msg.BillID)
|
||||
if err == nil {
|
||||
status := c.callbackAfsMsg2Status(msg, afsInfo)
|
||||
if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 {
|
||||
return nil
|
||||
}
|
||||
if status.Status == model.AfsOrderStatusWait4Approve || status.Status == model.AfsOrderStatusNew {
|
||||
afsOrder := c.buildAfsOrder(afsInfo)
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status)
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnAfsOrderStatusChanged(status)
|
||||
}
|
||||
retVal = jdapi.Err2CallbackResponse(err, status.VendorStatus)
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackAfsMsg2Status(msg *jdapi.CallbackOrderMsg, afsInfo *jdapi.AfsServiceResponse) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.BillID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: model.VendorIDJD,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: afsInfo.OrderID,
|
||||
RefVendorID: model.VendorIDJD,
|
||||
VendorStatus: msg.StatusID,
|
||||
Status: c.GetAfsStatusFromVendorStatus(msg.StatusID),
|
||||
StatusTime: utils.Str2Time(msg.Timestamp),
|
||||
Remark: msg.Remark,
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := AfsVendorStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) convertAfsReasonType(vendorReasonType int) int8 {
|
||||
if status, ok := afsReasonTypeMap[vendorReasonType]; ok {
|
||||
return status
|
||||
}
|
||||
return model.AfsReasonNotOthers
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) convertAfsAppealType(vendorAppealType string) int8 {
|
||||
if status, ok := afsAppealTypeMap[vendorAppealType]; ok {
|
||||
return status
|
||||
}
|
||||
globals.SugarLogger.Warnf("jd convertAfsAppealType unknown vendorAppealType:%d", vendorAppealType)
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) buildAfsOrder(afsInfo *jdapi.AfsServiceResponse) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDJD,
|
||||
AfsOrderID: afsInfo.AfsServiceOrder,
|
||||
VendorOrderID: afsInfo.OrderID,
|
||||
VendorStoreID: afsInfo.StationID,
|
||||
StoreID: int(utils.Str2Int64WithDefault(afsInfo.StationNumOutSystem, 0)),
|
||||
AfsCreatedAt: afsInfo.CreateTime.GoTime(),
|
||||
FreightUserMoney: afsInfo.OrderFreightMoney,
|
||||
AfsFreightMoney: afsInfo.AfsFreight,
|
||||
BoxMoney: afsInfo.PackagingMoney,
|
||||
TongchengFreightMoney: afsInfo.TongchengFreightMoney,
|
||||
SkuBoxMoney: afsInfo.MealBoxMoney,
|
||||
|
||||
VendorStatus: utils.Int2Str(afsInfo.AfsServiceState),
|
||||
VendorReasonType: utils.Int2Str(afsInfo.QuestionTypeCid),
|
||||
ReasonType: c.convertAfsReasonType(afsInfo.QuestionTypeCid),
|
||||
ReasonDesc: utils.LimitUTF8StringLen(afsInfo.QuestionDesc, 1024),
|
||||
ReasonImgList: utils.LimitUTF8StringLen(jdapi.ProcessQuestionPic(afsInfo.QuestionPic), 1024),
|
||||
VendorAppealType: afsInfo.ApplyDeal,
|
||||
AppealType: c.convertAfsAppealType(afsInfo.ApplyDeal),
|
||||
VendorOrgCode: afsInfo.VenderID,
|
||||
}
|
||||
afsOrder.Status = c.GetAfsStatusFromVendorStatus(afsOrder.VendorStatus)
|
||||
|
||||
for _, x := range afsInfo.AfsDetailList {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
// VendorID: model.VendorIDJD,
|
||||
// AfsOrderID: afsOrder.AfsOrderID,
|
||||
// VendorOrderID: afsOrder.VendorOrderID,
|
||||
// VendorStoreID: afsOrder.VendorStoreID,
|
||||
// StoreID: afsOrder.StoreID,
|
||||
// IsAfsOrder: 1,
|
||||
|
||||
Count: x.SkuCount,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorSkuID: utils.Int64ToStr(x.WareID),
|
||||
SkuID: int(utils.Str2Int64WithDefault(x.SkuIDIsv, 0)),
|
||||
Name: x.WareName,
|
||||
UserMoney: x.AfsMoney,
|
||||
PmSkuSubsidyMoney: x.PlatPayMoney,
|
||||
}
|
||||
if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal {
|
||||
orderSku.StoreSubName = utils.Int2Str(x.PromotionType)
|
||||
}
|
||||
afsOrder.PmSkuSubsidyMoney += orderSku.PmSkuSubsidyMoney
|
||||
orderSku.PmSubsidyMoney += orderSku.PmSkuSubsidyMoney
|
||||
|
||||
for _, y := range x.AfsSkuDiscountList {
|
||||
orderSku.PmSubsidyMoney += y.PlatPayMoney
|
||||
}
|
||||
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).AfsOpenApprove(order.AfsOrderID, afsApproveTypeMap[approveType], reason, ctx.GetUserName())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(order.VendorOrgCode).ConfirmReceipt(order.AfsOrderID, ctx.GetUserName())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func orderSkus2AfsSkus(refundSkuList []*model.OrderSku) (list []*jdapi.VenderAfsSkuDTO) {
|
||||
for _, v := range refundSkuList {
|
||||
actType := int(utils.Str2Int64WithDefault(v.StoreSubName, 0))
|
||||
if actType == 0 { //!(actType == jdapi.PromotionTypeOverflowGiveGift || actType == jdapi.PromotionTypeBuyGiveGift) {
|
||||
actType = 1
|
||||
}
|
||||
list = append(list, &jdapi.VenderAfsSkuDTO{
|
||||
SkuID: utils.Str2Int64(v.VendorSkuID),
|
||||
SkuCount: v.Count,
|
||||
PromotionType: actType,
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return c.PartRefundOrder(ctx, order, order.Skus, reason)
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(order.VendorOrgCode).AfsSubmit(order.VendorOrderID, ctx.GetUserName(), utils.Int2Str(jdapi.AfsReasonTypeWrongGoods), reason, "", order.ConsigneeName, order.ConsigneeMobile, order.ConsigneeAddress, orderSkus2AfsSkus(refundSkuList))
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
const (
|
||||
JDDJ_BAD_COMMENTS_MAX_MODIFY_TIME = 72 // 小时
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) onOrderComment2(a *jdapi.API, msg *jdapi.CallbackOrderMsg) (err error) {
|
||||
intOrderID := utils.Str2Int64(msg.BillID)
|
||||
result, err := a.GetCommentByOrderId2(intOrderID)
|
||||
if err == nil {
|
||||
globals.SugarLogger.Debugf("onOrderComment comment:%s", utils.Format4Output(result, true))
|
||||
orderCommend := &model.OrderComment{
|
||||
VendorOrderID: utils.Int64ToStr(result.OrderID),
|
||||
VendorID: model.VendorIDJD,
|
||||
UserCommentID: "",
|
||||
VendorStoreID: utils.Int64ToStr(result.StoreID),
|
||||
TagList: string(utils.MustMarshal(result.VenderTags)),
|
||||
Score: int8(result.Score4),
|
||||
Content: result.Score4Content,
|
||||
ModifyDuration: JDDJ_BAD_COMMENTS_MAX_MODIFY_TIME,
|
||||
OriginalMsg: string(utils.MustMarshal(result)),
|
||||
}
|
||||
if result.CreateTime != nil {
|
||||
orderCommend.CommentCreatedAt = result.CreateTime.GoTime()
|
||||
}
|
||||
if result.OrgCommentContent != "" {
|
||||
orderCommend.IsReplied = 1
|
||||
}
|
||||
err = partner.CurOrderManager.OnOrderComments([]*model.OrderComment{orderCommend})
|
||||
}
|
||||
if err != nil {
|
||||
globals.SugarLogger.Warnf("onOrderComment orderID:%s failed with error:%v", msg.BillID, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).OrgReplyComment(utils.Str2Int64(orderComment.VendorOrderID), orderComment.VendorStoreID, replyComment, ctx.GetUserName())
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
func TestSwitch2SelfDeliver(t *testing.T) {
|
||||
orderID := "817540316000041"
|
||||
if order, err := partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJD); err == nil {
|
||||
// globals.SugarLogger.Debug(order)
|
||||
if err = CurPurchaseHandler.Swtich2SelfDeliver(order, ""); err == nil {
|
||||
} else {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
} else {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
_, err := CurPurchaseHandler.GetOrder("", "815536199000222")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderStatus(t *testing.T) {
|
||||
status, err := CurPurchaseHandler.GetOrderStatus("", "929203144000041")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(status)
|
||||
}
|
||||
|
||||
func TestListOrders(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "", nil, time.Now(), "")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetSelfTakeCode(t *testing.T) {
|
||||
order, err := partner.CurOrderManager.LoadOrder("921160248000222", model.VendorIDJD)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
selfTakeCode, err := CurPurchaseHandler.GetSelfTakeCode(jxcontext.AdminCtx, order)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(selfTakeCode)
|
||||
}
|
||||
@@ -1,480 +0,0 @@
|
||||
package jd
|
||||
|
||||
// 这里函数取得的信息,除了与自身实体相关的ID(比如PARENT ID),都已经转换成了本地ID了
|
||||
|
||||
// type tSkuInfoExt struct {
|
||||
// model.SkuName
|
||||
// JdCatID int64 `orm:"column(jd_cat_id)"` // 商家类别
|
||||
// JdCategoryID int `orm:"column(jd_category_id)"` // 到家类别
|
||||
// SkuCatID int64 `orm:"column(sku_cat_id)"` // 商家特殊类别
|
||||
// Comment string `orm:"size(255)" json:"comment"`
|
||||
// }
|
||||
|
||||
// var (
|
||||
// skuAddParamsKeyMap = map[string]int{
|
||||
// jdapi.KeyUpcCode: 1,
|
||||
// }
|
||||
// )
|
||||
|
||||
// func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
|
||||
// var jdPid int64
|
||||
// if cat.ParentID != 0 {
|
||||
// pCat := &model.SkuCategory{}
|
||||
// pCat.ID = cat.ParentID
|
||||
// if err = dao.GetEntity(db, pCat); err == nil {
|
||||
// jdPid = pCat.JdID
|
||||
// } else {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// result, err2 := getAPI("").AddShopCategory(jdPid, cat.Name, int(cat.Level), cat.Seq, userName)
|
||||
// if err = err2; err == nil {
|
||||
// if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
|
||||
// cat.JdID = jdID
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// cat.JdID = jxutils.GenFakeID()
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// return getAPI("").UpdateShopCategory(cat.JdID, cat.Name)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// return getAPI("").DelShopCategory(cat.JdID)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
|
||||
// var parentJDID int64
|
||||
// if parentCatID != 0 {
|
||||
// cat := &model.SkuCategory{}
|
||||
// cat.ID = parentCatID
|
||||
// if err = dao.GetEntity(db, cat); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// parentJDID = cat.JdID
|
||||
// }
|
||||
// var cats []*model.SkuCategory
|
||||
// if err = dao.GetRows(db, &cats, `
|
||||
// SELECT *
|
||||
// FROM sku_category
|
||||
// WHERE parent_id = ? AND deleted_at = ?
|
||||
// ORDER BY seq`, parentCatID, utils.DefaultTimeValue); err == nil {
|
||||
// jdCatIDs := make([]int64, len(cats))
|
||||
// for k, v := range cats {
|
||||
// jdCatIDs[k] = v.JdID
|
||||
// }
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// err = getAPI("").ChangeShopCategoryOrder(parentJDID, jdCatIDs)
|
||||
// }
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) cuSku(db *dao.DaoDB, sku *model.Sku, handler func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (string, error)) (err error) {
|
||||
// var skuInfoExt tSkuInfoExt
|
||||
// err = dao.GetRow(nil, &skuInfoExt, `
|
||||
// SELECT
|
||||
// t2.*, IF(t2.jd_category_id > 0, t2.jd_category_id, t3.jd_category_id) jd_category_id,
|
||||
// t3.jd_id jd_cat_id,
|
||||
// t4.jd_id sku_cat_id
|
||||
// FROM sku t1
|
||||
// JOIN sku_name t2 ON t1.name_id = t2.id
|
||||
// JOIN sku_category t3 ON t2.category_id = t3.id
|
||||
// LEFT JOIN sku_category t4 ON t1.category_id = t4.id
|
||||
// WHERE t1.id = ?
|
||||
// `, sku.ID)
|
||||
// if err == nil {
|
||||
// shopCategories := []int64{skuInfoExt.JdCatID}
|
||||
// // SPU只支持SPU的商家分类,不支持单独SKU的,去除SKU的分类
|
||||
// // if skuInfoExt.SkuCatID != 0 {
|
||||
// // shopCategories = append(shopCategories, skuInfoExt.SkuCatID)
|
||||
// // }
|
||||
// if skuInfoExt.JdCategoryID == 0 {
|
||||
// skuInfoExt.JdCategoryID = getDefJdCategoryID()
|
||||
// }
|
||||
// if skuInfoExt.BrandID == 0 {
|
||||
// skuInfoExt.BrandID = DefBrandID
|
||||
// }
|
||||
// addParams := map[string]interface{}{}
|
||||
|
||||
// if skuInfoExt.IsGlobal == 0 { //如果不是全国可售,要查可售区域
|
||||
// sellPlaces, err2 := dao.GetSellCities(db, skuInfoExt.ID, model.VendorIDJD)
|
||||
// if err = err2; err == nil && len(sellPlaces) > 0 {
|
||||
// sellCites := make([]int, len(sellPlaces))
|
||||
// for k, v := range sellPlaces {
|
||||
// sellCites[k] = v.JdCode
|
||||
// }
|
||||
// addParams["sellCities"] = sellCites
|
||||
// }
|
||||
// }
|
||||
// if addParams["sellCities"] == nil {
|
||||
// addParams["sellCities"] = []int{0}
|
||||
// }
|
||||
// if skuInfoExt.DescImg != "" {
|
||||
// addParams[jdapi.KeyProductDesc] = fmt.Sprintf(`<img src="%s" alt="一张图片" />`, skuInfoExt.DescImg)
|
||||
// addParams[jdapi.KeyIfViewDesc] = 0
|
||||
// } else {
|
||||
// addParams[jdapi.KeyIfViewDesc] = 1
|
||||
// }
|
||||
// if err == nil {
|
||||
// skuName := jxutils.ComposeSkuName(skuInfoExt.Prefix, skuInfoExt.Name, sku.Comment, skuInfoExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount)
|
||||
// skuPrice := jxutils.CaculateSkuPrice(skuInfoExt.Price, sku.SpecQuality, sku.SpecUnit, skuInfoExt.Unit)
|
||||
// if skuInfoExt.Upc != "" {
|
||||
// addParams[jdapi.KeyUpcCode] = skuInfoExt.Upc
|
||||
// }
|
||||
// result, err2 := handler(&skuInfoExt, skuPrice, skuName, shopCategories, addParams)
|
||||
// if err = err2; err == nil {
|
||||
// if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
|
||||
// sku.JdID = jdID
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
|
||||
// if skuExt.IsSpu == 0 {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// vendorSkuID, err = getAPI("").AddSku(utils.Int2Str(sku.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2), jxStatus2jdStatus(sku.Status), true, addParams)
|
||||
// if err != nil {
|
||||
// if jdSkuID := jdapi.GetJdSkuIDFromError(err); jdSkuID > 0 {
|
||||
// vendorSkuID = utils.Int64ToStr(jdSkuID)
|
||||
// err = nil
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// vendorSkuID = utils.Int64ToStr(jxutils.GenFakeID())
|
||||
// }
|
||||
// } else {
|
||||
// vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
|
||||
// }
|
||||
// return vendorSkuID, err
|
||||
// })
|
||||
// }
|
||||
|
||||
// // func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) {
|
||||
// // jdSkuID := utils.Str2Int64(vendorSkuID)
|
||||
// // a := getAPI(vendorOrgCode)
|
||||
// // skuList, _, err := a.QuerySkuInfos(&jdapi.QuerySkuParam{
|
||||
// // SkuID: jdSkuID,
|
||||
// // })
|
||||
// // if err == nil {
|
||||
// // if len(skuList) >= 1 {
|
||||
// // skuNameExt = &model.SkuNameExt{}
|
||||
// // if imgList, err2 := a.QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{
|
||||
// // SkuIDs: []int64{jdSkuID},
|
||||
// // }); err2 == nil && len(imgList) > 0 {
|
||||
// // skuNameExt.Img = imgList[0].SourceImgURL
|
||||
// // }
|
||||
// // sku := skuList[0]
|
||||
// // prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku.SkuName)
|
||||
// // if name == "" {
|
||||
// // name = sku.SkuName
|
||||
// // unit = "份"
|
||||
// // specUnit = "g"
|
||||
// // }
|
||||
// // skuNameExt.Prefix = prefix
|
||||
// // skuNameExt.Name = name
|
||||
// // skuNameExt.Unit = unit
|
||||
// // skuNameExt.Price = sku.SkuPrice
|
||||
// // skuNameExt.Skus = []*model.SkuWithVendor{
|
||||
// // &model.SkuWithVendor{
|
||||
// // Sku: &model.Sku{
|
||||
// // SpecQuality: specQuality,
|
||||
// // SpecUnit: specUnit,
|
||||
// // Weight: jxutils.FloatWeight2Int(float32(sku.Weight)),
|
||||
// // JdID: sku.SkuID,
|
||||
// // Status: jdStatus2jxStatus(sku.FixedStatus),
|
||||
// // Comment: comment,
|
||||
// // },
|
||||
// // },
|
||||
// // }
|
||||
// // skuNameExt.Skus[0].ID = int(utils.Str2Int64(sku.OutSkuID))
|
||||
|
||||
// // db := dao.GetDB()
|
||||
// // shopCategories := sku.ShopCategories
|
||||
// // if len(shopCategories) > 0 {
|
||||
// // skuCat := &model.SkuCategory{}
|
||||
// // skuCat.JdID = shopCategories[0]
|
||||
// // if dao.GetEntity(db, skuCat, "JdID") == nil {
|
||||
// // skuNameExt.CategoryID = skuCat.ID
|
||||
// // }
|
||||
// // }
|
||||
// // sellCities := sku.SellCities
|
||||
// // for _, v := range sellCities {
|
||||
// // if v == 0 {
|
||||
// // skuNameExt.IsGlobal = 1
|
||||
// // }
|
||||
// // }
|
||||
// // if len(sellCities) == 0 || skuNameExt.IsGlobal == 1 {
|
||||
// // skuNameExt.IsGlobal = 1
|
||||
// // } else {
|
||||
// // var places []*model.Place
|
||||
// // if err = dao.GetRows(db, &places, "SELECT * FROM place WHERE jd_code IN ("+dao.GenQuestionMarks(len(sellCities))+") AND level = 2", sellCities); err == nil {
|
||||
// // skuNameExt.Places = make([]int, len(places))
|
||||
// // for k, v := range places {
|
||||
// // skuNameExt.Places[k] = v.Code
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // } else {
|
||||
// // err = partner.ErrCanNotFindItem
|
||||
// // }
|
||||
// // }
|
||||
// // return skuNameExt, err
|
||||
// // }
|
||||
|
||||
// func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// return p.cuSku(db, sku, func(skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
|
||||
// params := utils.MergeMaps(addParams)
|
||||
// params[jdapi.KeyCategoryId] = skuExt.JdCategoryID
|
||||
// params[jdapi.KeyShopCategories] = shopCategories
|
||||
// params[jdapi.KeyBrandId] = skuExt.BrandID
|
||||
// params[jdapi.KeySkuName] = skuName
|
||||
// params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
|
||||
// params[jdapi.KeyImages] = jxutils.BatchString2Slice(skuExt.Img, skuExt.Img2)
|
||||
// params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
|
||||
// if skuExt.IsSpu == 0 {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// vendorSkuID, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
|
||||
// }
|
||||
// } else {
|
||||
// vendorSkuID, err = p.syncSkuNameAsSpu(db, sku, skuExt, price, skuName, shopCategories, addParams)
|
||||
// }
|
||||
// return vendorSkuID, err
|
||||
// })
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// params := map[string]interface{}{
|
||||
// jdapi.KeyFixedStatus: jdapi.SkuFixedStatusDeleted,
|
||||
// }
|
||||
// sql := `
|
||||
// SELECT t2.*
|
||||
// FROM sku t1
|
||||
// JOIN sku_name t2 ON t1.name_id = t2.id
|
||||
// WHERE t1.id = ?
|
||||
// `
|
||||
// var skuExt tSkuInfoExt
|
||||
// err = dao.GetRow(db, &skuExt, sql, sku.ID)
|
||||
// if err == nil {
|
||||
// if skuExt.IsSpu == 0 {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// _, err = getAPI("").UpdateSku(utils.Int2Str(sku.ID), params)
|
||||
// }
|
||||
// } else {
|
||||
// _, err = p.syncSkuNameAsSpu(db, sku, &skuExt, 0, "", nil, nil)
|
||||
// }
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // func (p *PurchaseHandler) RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
// // globals.SugarLogger.Debugf("jd RefreshAllSkusID")
|
||||
|
||||
// // db := dao.GetDB()
|
||||
// // var skuPairs []*jdapi.SkuIDPair
|
||||
// // const stepCount = 2
|
||||
|
||||
// // rootTask := tasksch.NewSeqTask("jd RefreshAllSkusID", ctx,
|
||||
// // func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
||||
// // switch step {
|
||||
// // case 0:
|
||||
// // err = dao.GetRows(db, &skuPairs, `
|
||||
// // SELECT t1.id out_sku_id, t1.jd_id sku_id
|
||||
// // FROM sku t1
|
||||
// // WHERE t1.deleted_at = ?
|
||||
// // `, utils.DefaultTimeValue)
|
||||
// // default:
|
||||
// // taskName := "RefreshAllSkusID update id"
|
||||
// // if step != stepCount-1 {
|
||||
// // taskName = "RefreshAllSkusID update uuid"
|
||||
// // }
|
||||
// // task1 := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetIsContinueWhenError(true).SetBatchSize(jdapi.MaxBatchSize4BatchUpdateOutSkuId), ctx,
|
||||
// // func(t *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
// // skuPairs := make([]*jdapi.SkuIDPair, len(batchItemList))
|
||||
// // for k, v := range batchItemList {
|
||||
// // pair := v.(*jdapi.SkuIDPair)
|
||||
// // skuPairs[k] = &jdapi.SkuIDPair{
|
||||
// // SkuId: pair.SkuId,
|
||||
// // OutSkuId: pair.OutSkuId,
|
||||
// // }
|
||||
// // if step != stepCount-1 {
|
||||
// // skuPairs[k].OutSkuId = utils.GetUUID()
|
||||
// // }
|
||||
// // }
|
||||
// // globals.SugarLogger.Debug(utils.Format4Output(skuPairs, false))
|
||||
// // if globals.EnableJdStoreWrite {
|
||||
// // _, err = getAPI("").BatchUpdateOutSkuId(skuPairs)
|
||||
// // }
|
||||
// // return nil, err
|
||||
// // }, skuPairs)
|
||||
// // rootTask.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 splitAddParams(addParams map[string]interface{}) (spuAddParams, skuAddParams map[string]interface{}) {
|
||||
// if addParams != nil {
|
||||
// spuAddParams = make(map[string]interface{})
|
||||
// skuAddParams = make(map[string]interface{})
|
||||
// for key := range addParams {
|
||||
// if skuAddParamsKeyMap[key] == 1 {
|
||||
// skuAddParams[key] = addParams[key]
|
||||
// } else {
|
||||
// spuAddParams[key] = addParams[key]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return spuAddParams, skuAddParams
|
||||
// }
|
||||
|
||||
// // 这个处理JD SPU,补丁形式
|
||||
// func (p *PurchaseHandler) syncSkuNameAsSpu(db *dao.DaoDB, sku *model.Sku, skuExt *tSkuInfoExt, price int, skuName string, shopCategories []int64, addParams map[string]interface{}) (vendorSkuID string, err error) {
|
||||
// // SPU的SKU NAME不需要规格信息
|
||||
// skuName = jxutils.ComposeSkuName(skuExt.Prefix, skuExt.Name, sku.Comment, "", 0, "", 0)
|
||||
// skuNameJdID := skuExt.JdID
|
||||
// globals.SugarLogger.Debugf("syncSkuNameAsSpu1 sku.id=%d, bareSkuName:%s, skuName:%s, skuNameJdID:%d", sku.ID, skuExt.Name, skuName, skuNameJdID)
|
||||
// spuAddParams, skuAddParams := splitAddParams(addParams)
|
||||
// if !jxutils.IsEmptyID(skuNameJdID) && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 删除SKU
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
|
||||
// }
|
||||
// }
|
||||
// if err == nil {
|
||||
// updateFields := []string{}
|
||||
// if skuExt.JdSyncStatus&model.SyncFlagDeletedMask != 0 {
|
||||
// sql := `
|
||||
// SELECT COUNT(*) ct
|
||||
// FROM sku t1
|
||||
// WHERE t1.name_id = ? AND (t1.status <> ? OR t1.jd_sync_status <> 0)
|
||||
// `
|
||||
// var count struct {
|
||||
// Ct int
|
||||
// }
|
||||
// if err = dao.GetRow(db, &count, sql, sku.NameID, model.SkuStatusDeleted); err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// if count.Ct <= 1 && sku.JdSyncStatus&model.SyncFlagDeletedMask != 0 { // 1就是最后删的那个
|
||||
// updateFields = append(updateFields, model.FieldJdSyncStatus)
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// if err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil {
|
||||
// err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else if skuExt.JdSyncStatus&model.SyncFlagNewMask != 0 && jxutils.IsEmptyID(skuNameJdID) {
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// spuName := jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0)
|
||||
// skus := []map[string]interface{}{
|
||||
// map[string]interface{}{
|
||||
// jdapi.KeyOutSkuId: utils.Int2Str(sku.ID),
|
||||
// jdapi.KeySkuName: skuName,
|
||||
// jdapi.KeyFixedStatus: jxStatus2jdStatus(sku.Status),
|
||||
// jdapi.KeySkuPrice: price,
|
||||
// jdapi.KeyWeight: jxutils.IntWeight2Float(sku.Weight),
|
||||
// jdapi.KeyIsSale: true,
|
||||
// jdapi.FakeKeySpecAttr: composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit),
|
||||
// },
|
||||
// }
|
||||
// skus[0] = utils.MergeMaps(skus[0], skuAddParams)
|
||||
// updateFields = append(updateFields, model.FieldJdSyncStatus)
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// vendorSpuID, skuPairs, err2 := getAPI("").AddSpu(utils.Int2Str(skuExt.ID), skuExt.JdCategoryID, shopCategories, skuExt.BrandID, spuName, []string{skuExt.Img}, jxStatus2jdStatus(skuExt.Status), spuAddParams, skus)
|
||||
// if err = err2; err == nil {
|
||||
// skuExt.JdID = vendorSpuID
|
||||
// // skuNameJdID = skuExt.JdID // 这个是故意去掉的,这样之后的首次SKU修改操作就会被忽略,下一条语句也就可以不用了
|
||||
// // sku.JdSyncStatus &= ^model.SyncFlagNewMask
|
||||
// vendorSkuID = utils.Int64ToStr(skuPairs[0].SkuId)
|
||||
// updateFields = append(updateFields, model.FieldJdID)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else if skuExt.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
|
||||
// params := utils.MergeMaps(map[string]interface{}{
|
||||
// jdapi.KeySpuName: jxutils.ComposeSpuName(skuExt.Prefix, skuExt.Name, 0),
|
||||
// jdapi.KeyShopCategories: shopCategories,
|
||||
// jdapi.KeyCategoryId: skuExt.JdCategoryID,
|
||||
// jdapi.KeyBrandId: skuExt.BrandID,
|
||||
// jdapi.KeyImages: []string{skuExt.Img},
|
||||
// jdapi.KeyFixedStatus: jxStatus2jdStatus(skuExt.Status),
|
||||
// }, spuAddParams)
|
||||
// updateFields = append(updateFields, model.FieldJdSyncStatus)
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// err = getAPI("").UpdateSpu(utils.Int2Str(skuExt.ID), params)
|
||||
// }
|
||||
// }
|
||||
// if err == nil {
|
||||
// if skuExt.JdSyncStatus != 0 && len(updateFields) > 0 {
|
||||
// skuExt.JdSyncStatus = 0
|
||||
// _, err = dao.UpdateEntity(db, &skuExt.SkuName, updateFields...)
|
||||
// globals.SugarLogger.Debugf("syncSkuNameAsSpu4 sku.id=%d, skuName:%s, skuName:%s", sku.ID, skuExt.Name, utils.Format4Output(&skuExt.SkuName, false))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if err == nil && !jxutils.IsEmptyID(skuNameJdID) {
|
||||
// if sku.JdSyncStatus&model.SyncFlagNewMask != 0 { // 非首次新增SKU
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// vendorSkuID2, err2 := getAPI("").AppendSku(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{skuExt.Img}, jxStatus2jdStatus(sku.Status), true, composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit), skuAddParams)
|
||||
// if err = err2; err == nil {
|
||||
// vendorSkuID = utils.Int64ToStr(vendorSkuID2)
|
||||
// }
|
||||
// }
|
||||
// } else if sku.JdSyncStatus&model.SyncFlagModifiedMask != 0 {
|
||||
// params := make(map[string]interface{})
|
||||
// params[jdapi.KeySkuName] = skuName
|
||||
// params[jdapi.KeyImages] = []string{skuExt.Img}
|
||||
// params[jdapi.KeyFixedStatus] = jxStatus2jdStatus(sku.Status)
|
||||
// params[jdapi.KeyWeight] = jxutils.IntWeight2Float(sku.Weight)
|
||||
// params[jdapi.KeySkuPrice] = price
|
||||
// if globals.EnableJdStoreWrite {
|
||||
// err = getAPI("").UpdateSkuBaseInfo(utils.Int2Str(skuExt.ID), utils.Int2Str(sku.ID), utils.MergeMaps(params, skuAddParams))
|
||||
// if sku.JdSyncStatus&model.SyncFlagSpecMask != 0 {
|
||||
// skuIndex := sku.SkuIndex
|
||||
// if skuIndex > 0 {
|
||||
// saleAttrValue := composeSkuSpec(sku.SpecQuality, sku.SpecUnit, skuExt.Unit)
|
||||
// globals.SugarLogger.Debugf("syncSkuNameAsSpu outSuperId:%d, saleAttrId:%d, saleAttrValueId:%d, saleAttrValueName:%s", skuExt.ID, jdapi.SaleAttrIDBase, jdapi.SaleAttrValueIDBase+skuIndex-1, saleAttrValue)
|
||||
// err = getAPI("").UpdateSpuSaleAttr(utils.Int2Str(skuExt.ID), utils.Int2Str(jdapi.SaleAttrIDBase), "", utils.Int2Str(jdapi.SaleAttrValueIDBase+skuIndex-1), saleAttrValue)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if err == nil {
|
||||
// sku.JdSyncStatus = 0
|
||||
// }
|
||||
// }
|
||||
// return vendorSkuID, err
|
||||
// }
|
||||
|
||||
// func composeSkuSpec(specQuality float32, specUnit, unit string) string {
|
||||
// prefix := ""
|
||||
// if unit == model.SpecialUnit {
|
||||
// prefix = "约"
|
||||
// }
|
||||
// value := prefix + jxutils.ComposeSkuSpec(specQuality, specUnit)
|
||||
// suffix := "/" + unit
|
||||
// if utf8.RuneCountInString(value) <= 8-utf8.RuneCountInString(suffix) {
|
||||
// value += suffix
|
||||
// }
|
||||
// return value
|
||||
// }
|
||||
@@ -1,485 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
const (
|
||||
DefBrandID = 35247
|
||||
|
||||
DefJdCategoryID = 20362
|
||||
DefJdCategoryID4Jxgy = 22410 // 其他国产水果
|
||||
)
|
||||
|
||||
func getDefJdCategoryID() int {
|
||||
if beego.BConfig.RunMode == "jxgy" {
|
||||
return DefJdCategoryID4Jxgy
|
||||
}
|
||||
return DefJdCategoryID
|
||||
}
|
||||
|
||||
func jdCat2Jx(jdCat *jdapi.CategoryInfo) (jxCat *partner.BareCategoryInfo) {
|
||||
return &partner.BareCategoryInfo{
|
||||
VendorCatID: utils.Int64ToStr(jdCat.Id),
|
||||
Level: jdCat.Level,
|
||||
Name: jdCat.Name,
|
||||
Seq: jdCat.Sort,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*partner.BareCategoryInfo, err error) {
|
||||
result, err := getAPI(vendorOrgCode).QueryCategoriesByOrgCode()
|
||||
if err == nil {
|
||||
catMap := make(map[int64]*partner.BareCategoryInfo)
|
||||
level := 1
|
||||
for {
|
||||
processedCount := 0
|
||||
for _, jdCat := range result {
|
||||
if jdCat.Level == level {
|
||||
processedCount++
|
||||
jxCat := jdCat2Jx(jdCat)
|
||||
if level == 1 {
|
||||
cats = append(cats, jxCat)
|
||||
} else {
|
||||
parentCat := catMap[jdCat.ParentId]
|
||||
if parentCat != nil {
|
||||
parentCat.Children = append(parentCat.Children, jxCat)
|
||||
}
|
||||
}
|
||||
catMap[jdCat.Id] = jxCat
|
||||
}
|
||||
}
|
||||
if processedCount == 0 {
|
||||
break
|
||||
}
|
||||
level++
|
||||
}
|
||||
}
|
||||
return cats, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) {
|
||||
globals.SugarLogger.Debugf("CreateCategory2 cat:%s", utils.Format4Output(cat, true))
|
||||
parentID := int64(0)
|
||||
if cat.Level != 1 {
|
||||
parentID = utils.Str2Int64(cat.ParentVendorCatID)
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
result, err2 := getAPI(cat.VendorOrgCode).AddShopCategory(parentID, cat.Name, int(cat.Level), cat.Seq, ctx.GetUserName())
|
||||
if err = err2; err == nil {
|
||||
if jdID := utils.Str2Int64WithDefault(result, 0); jdID != 0 {
|
||||
cat.VendorCatID = utils.Int64ToStr(jdID)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cat.VendorCatID = utils.Int64ToStr(jxutils.GenFakeID())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) {
|
||||
globals.SugarLogger.Debugf("UpdateCategory2 cat:%s", utils.Format4Output(cat, true))
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(cat.VendorOrgCode).UpdateShopCategory(utils.Str2Int64(cat.VendorCatID), cat.Name)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteCategory2(ctx *jxcontext.Context, vendorOrgCode, vendorCatID string) (err error) {
|
||||
globals.SugarLogger.Debugf("DeleteCategory2 vendorOrgCode:%s, vendorCatID:%s", vendorOrgCode, vendorCatID)
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).DelShopCategory(utils.Str2Int64(vendorCatID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).ChangeShopCategoryOrder(utils.Str2Int64WithDefault(vendorParentCatID, 0), utils.StringSlice2Int64(vendorCatIDList))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getVendorCategories(level int, pid int64) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
// 得到平台的分类,不需要指定分账号
|
||||
cats, err := api.JdAPI.QueryChildCategoriesForOP(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range cats {
|
||||
if v.Status == 1 {
|
||||
cat := &model.SkuVendorCategory{
|
||||
VendorID: model.VendorIDJD,
|
||||
Name: v.Name,
|
||||
Level: level,
|
||||
VendorCategoryID: utils.Int64ToStr(v.Id),
|
||||
}
|
||||
if level > 1 {
|
||||
cat.ParentID = utils.Int64ToStr(v.ParentId)
|
||||
if level == 3 {
|
||||
cat.IsLeaf = 1
|
||||
}
|
||||
}
|
||||
vendorCats = append(vendorCats, cat)
|
||||
if level < 3 {
|
||||
childVendorCats, err2 := p.getVendorCategories(level+1, v.Id)
|
||||
if err2 == nil && len(childVendorCats) > 0 {
|
||||
vendorCats = append(vendorCats, childVendorCats...)
|
||||
} else {
|
||||
cat.IsLeaf = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vendorCats, nil
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
vendorCats, err = p.getVendorCategories(1, 0)
|
||||
return vendorCats, err
|
||||
}
|
||||
|
||||
func skuInfo2Param(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (param *jdapi.OpSkuParam) {
|
||||
param = &jdapi.OpSkuParam{
|
||||
TraceID: ctx.GetTrackInfo(),
|
||||
OutSkuID: utils.Int2Str(sku.SkuID),
|
||||
ShopCategories: []int64{utils.Str2Int64(sku.VendorCatID)},
|
||||
CategoryID: sku.VendorVendorCatID,
|
||||
BrandID: DefBrandID,
|
||||
SkuName: utils.LimitUTF8StringLen(sku.SkuName, jdapi.MaxSkuNameCharCount),
|
||||
SkuPrice: int(sku.Price),
|
||||
Weight: float64(jxutils.IntWeight2Float(sku.Weight)),
|
||||
FixedStatus: jxStatus2jdStatus(sku.MergedStatus),
|
||||
IsSale: jdapi.IsSaleNo, // todo ?
|
||||
|
||||
Upc: sku.Upc,
|
||||
// Images: jxutils.BatchString2Slice(sku.Img, sku.Img2),
|
||||
}
|
||||
if sku.ImgMix != "" {
|
||||
param.Images = jxutils.BatchString2Slice(sku.ImgMix, sku.Img2)
|
||||
} else {
|
||||
param.Images = jxutils.BatchString2Slice(sku.Img, sku.Img2)
|
||||
}
|
||||
|
||||
if param.CategoryID == 0 {
|
||||
param.CategoryID = int64(getDefJdCategoryID())
|
||||
}
|
||||
// 京东强制要求upc的商品,如果没有设置upc,自动生成一个假的
|
||||
if param.Upc == "" && isSkuMustHaveUpc(sku.Unit, param.CategoryID) {
|
||||
param.Upc = jxutils.GenFakeUPC(sku.SkuID)
|
||||
}
|
||||
if sku.IsGlobal == 0 && len(sku.SellCities) > 0 {
|
||||
param.SellCities = utils.StringSlice2Int64(sku.SellCities)
|
||||
}
|
||||
if sku.DescImg != "" {
|
||||
param.ProductDesc = fmt.Sprintf(`<img src="%s" alt="一张图片" />`, sku.DescImg)
|
||||
}
|
||||
return param
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) {
|
||||
globals.SugarLogger.Debugf("CreateSku2 sku:%s", utils.Format4Output(sku, true))
|
||||
param := skuInfo2Param(ctx, sku)
|
||||
if globals.EnableJdStoreWrite {
|
||||
sku.VendorSkuID, err = getAPI(sku.VendorOrgCode).AddSku2(param)
|
||||
} else {
|
||||
sku.VendorSkuID = utils.Int64ToStr(jxutils.GenFakeID())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) {
|
||||
globals.SugarLogger.Debugf("UpdateSku2 sku:%s", utils.Format4Output(sku, true))
|
||||
param := skuInfo2Param(ctx, sku)
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(sku.VendorOrgCode).UpdateSku2(param)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *partner.StoreSkuInfo) (err error) {
|
||||
globals.SugarLogger.Debugf("DeleteSku2 vendorOrgCode:%s, sku:%s", vendorOrgCode, utils.Format4Output(sku, true))
|
||||
|
||||
// 京东到家只能通过商家ID删除SKU,如果没有的话,先绑定,再删除
|
||||
if sku.SkuID == 0 {
|
||||
skuPairList := []*jdapi.SkuIDPair{
|
||||
&jdapi.SkuIDPair{
|
||||
SkuId: utils.Str2Int64(sku.VendorSkuID),
|
||||
OutSkuId: sku.VendorSkuID,
|
||||
},
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(vendorOrgCode).BatchUpdateOutSkuId(skuPairList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sku.SkuID = int(utils.Str2Int64(sku.VendorSkuID))
|
||||
}
|
||||
}
|
||||
param := &jdapi.OpSkuParam{
|
||||
TraceID: ctx.GetTrackInfo(),
|
||||
OutSkuID: utils.Int2Str(sku.SkuID),
|
||||
FixedStatus: jdapi.SkuFixedStatusDeleted,
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(vendorOrgCode).UpdateSku2(param)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetSkus(ctx *jxcontext.Context, vendorOrgCode string, skuID int, vendorSkuID string) (skuNameList []*partner.SkuNameInfo, err error) {
|
||||
param := &jdapi.QuerySkuParam{
|
||||
SkuID: utils.Str2Int64WithDefault(vendorSkuID, 0),
|
||||
IsFilterDel: jdapi.IsFilterDelTrue,
|
||||
PageNo: 1,
|
||||
PageSize: jdapi.MaxSkuIDsCount4QueryListBySkuIds, // 为了同时取图,这个值不要大于jdapi.MaxSkuIDsCount4QueryListBySkuIds
|
||||
}
|
||||
for {
|
||||
skuList, _, err2 := getAPI(vendorOrgCode).QuerySkuInfos(param)
|
||||
if err = err2; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(skuList) > 0 {
|
||||
batchSkuNameList := make([]*partner.SkuNameInfo, len(skuList))
|
||||
for k, v := range skuList {
|
||||
batchSkuNameList[k] = vendorSku2Jx(v)
|
||||
}
|
||||
setSkuNameListPic(vendorOrgCode, batchSkuNameList)
|
||||
skuNameList = append(skuNameList, batchSkuNameList...)
|
||||
}
|
||||
if len(skuList) < param.PageSize {
|
||||
break
|
||||
}
|
||||
param.PageNo++
|
||||
}
|
||||
return skuNameList, err
|
||||
}
|
||||
|
||||
func setSkuNameListPic(vendorOrgCode string, skuNameList []*partner.SkuNameInfo) []*partner.SkuNameInfo {
|
||||
jdSkuIDs := make([]int64, len(skuNameList))
|
||||
for k, v := range skuNameList {
|
||||
jdSkuIDs[k] = utils.Str2Int64(v.SkuList[0].VendorSkuID)
|
||||
}
|
||||
|
||||
imgMap := make(map[int64]*jdapi.ImgHandleQueryResult)
|
||||
if imgList, err2 := getAPI(vendorOrgCode).QueryListBySkuIds(&jdapi.QueryListBySkuIdsParam{
|
||||
SkuIDs: jdSkuIDs,
|
||||
}); err2 == nil {
|
||||
for _, v := range imgList {
|
||||
if v.ImgType == jdapi.ImgTypeMain {
|
||||
imgResult := imgMap[v.SkuID]
|
||||
if imgResult == nil || imgResult.IsMain < v.IsMain {
|
||||
imgMap[v.SkuID] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用扒页面方式获取商品图片
|
||||
if false {
|
||||
var leftJdSkuIDs []int64
|
||||
for _, v := range jdSkuIDs {
|
||||
if imgMap[v] == nil {
|
||||
leftJdSkuIDs = append(leftJdSkuIDs, v)
|
||||
}
|
||||
}
|
||||
task := tasksch.NewParallelTask("jd setSkuNameListPic", nil, jxcontext.AdminCtx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
jdSkuID := batchItemList[0].(int64)
|
||||
imgList, err := getAPI(vendorOrgCode).GetSkuPageImageInfo(jdSkuID)
|
||||
if err == nil && len(imgList) > 0 {
|
||||
retVal = [][]string{
|
||||
[]string{utils.Int64ToStr(jdSkuID), imgList[0].Big},
|
||||
}
|
||||
}
|
||||
return retVal, err
|
||||
}, leftJdSkuIDs)
|
||||
task.Run()
|
||||
if resultList, err := task.GetResult(0); err == nil {
|
||||
for _, v := range resultList {
|
||||
strList := v.([]string)
|
||||
imgMap[utils.Str2Int64(strList[0])] = &jdapi.ImgHandleQueryResult{
|
||||
SourceImgURL: strList[1],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置商品图片
|
||||
for _, v := range skuNameList {
|
||||
if imgResult := imgMap[utils.Str2Int64(v.SkuList[0].VendorSkuID)]; imgResult != nil {
|
||||
v.PictureList = []string{imgResult.SourceImgURL}
|
||||
}
|
||||
}
|
||||
return skuNameList
|
||||
}
|
||||
|
||||
func vendorSku2Jx(vendorSku *jdapi.SkuMain) (skuName *partner.SkuNameInfo) {
|
||||
prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(vendorSku.SkuName)
|
||||
weight := int(vendorSku.Weight * 1000)
|
||||
if weight <= 0 {
|
||||
weight = jxutils.FormatSkuWeight(specQuality, specUnit)
|
||||
}
|
||||
skuID := int(utils.Str2Int64WithDefault(vendorSku.OutSkuID, 0))
|
||||
vendorSkuID := utils.Int64ToStr(vendorSku.SkuID)
|
||||
skuName = &partner.SkuNameInfo{
|
||||
NameID: skuID,
|
||||
VendorNameID: vendorSkuID,
|
||||
VendorCatIDList: []string{utils.Int64ToStr(vendorSku.CategoryID)},
|
||||
|
||||
Prefix: prefix,
|
||||
Name: name,
|
||||
Unit: unit,
|
||||
SkuList: []*partner.SkuInfo{
|
||||
&partner.SkuInfo{
|
||||
StoreSkuInfo: partner.StoreSkuInfo{
|
||||
VendorSkuID: vendorSkuID,
|
||||
SkuID: skuID,
|
||||
|
||||
VendorPrice: int64(vendorSku.SkuPrice),
|
||||
Status: jdStatus2jxStatus(vendorSku.FixedStatus),
|
||||
},
|
||||
SkuName: vendorSku.SkuName,
|
||||
Comment: comment,
|
||||
SpecQuality: float64(specQuality),
|
||||
SpecUnit: specUnit,
|
||||
Weight: weight,
|
||||
},
|
||||
},
|
||||
}
|
||||
return skuName
|
||||
}
|
||||
|
||||
func jdStatus2jxStatus(jdStatus int) (jxStatus int) {
|
||||
switch jdStatus {
|
||||
case jdapi.SkuFixedStatusOnline:
|
||||
jxStatus = model.SkuStatusNormal
|
||||
case jdapi.SkuFixedStatusOffline:
|
||||
jxStatus = model.SkuStatusDontSale
|
||||
case jdapi.SkuFixedStatusDeleted:
|
||||
jxStatus = model.SkuStatusDeleted
|
||||
}
|
||||
return jxStatus
|
||||
}
|
||||
|
||||
func jxStatus2jdStatus(jxStatus int) (jdStatus int) {
|
||||
switch jxStatus {
|
||||
case model.SkuStatusNormal:
|
||||
jdStatus = jdapi.SkuFixedStatusOnline
|
||||
case model.SkuStatusDontSale:
|
||||
jdStatus = jdapi.SkuFixedStatusOffline
|
||||
case model.SkuStatusDeleted:
|
||||
jdStatus = jdapi.SkuFixedStatusDeleted
|
||||
}
|
||||
return jdStatus
|
||||
}
|
||||
|
||||
func isSkuMustHaveUpc(unit string, vendorVendorCatID int64) bool {
|
||||
return unit != model.SpecialUnit || !upcLessMap[vendorVendorCatID]
|
||||
}
|
||||
|
||||
var (
|
||||
upcLessMap = map[int64]bool{
|
||||
20250: true,
|
||||
20252: true,
|
||||
20258: true,
|
||||
20259: true,
|
||||
20261: true,
|
||||
20262: true,
|
||||
20263: true,
|
||||
20264: true,
|
||||
20265: true,
|
||||
20266: true,
|
||||
20267: true,
|
||||
22822: true,
|
||||
20269: true,
|
||||
20270: true,
|
||||
20271: true,
|
||||
20272: true,
|
||||
20273: true,
|
||||
20275: true,
|
||||
20276: true,
|
||||
20277: true,
|
||||
20278: true,
|
||||
20279: true,
|
||||
20281: true,
|
||||
20282: true,
|
||||
20283: true,
|
||||
20285: true,
|
||||
20286: true,
|
||||
20287: true,
|
||||
22821: true,
|
||||
20289: true,
|
||||
20290: true,
|
||||
23018: true,
|
||||
20354: true,
|
||||
20355: true,
|
||||
20357: true,
|
||||
20359: true,
|
||||
23019: true,
|
||||
20294: true,
|
||||
20295: true,
|
||||
20296: true,
|
||||
20297: true,
|
||||
20298: true,
|
||||
20299: true,
|
||||
20300: true,
|
||||
20302: true,
|
||||
20303: true,
|
||||
20304: true,
|
||||
22840: true,
|
||||
22841: true,
|
||||
20317: true,
|
||||
20320: true,
|
||||
20321: true,
|
||||
20323: true,
|
||||
20325: true,
|
||||
20326: true,
|
||||
20328: true,
|
||||
20329: true,
|
||||
20331: true,
|
||||
20335: true,
|
||||
20337: true,
|
||||
20338: true,
|
||||
20339: true,
|
||||
22842: true,
|
||||
22843: true,
|
||||
23020: true,
|
||||
20309: true,
|
||||
20310: true,
|
||||
20311: true,
|
||||
20312: true,
|
||||
20313: true,
|
||||
20314: true,
|
||||
20315: true,
|
||||
22410: true,
|
||||
23050: true,
|
||||
20319: true,
|
||||
20322: true,
|
||||
20330: true,
|
||||
20332: true,
|
||||
20334: true,
|
||||
20336: true,
|
||||
20340: true,
|
||||
20342: true,
|
||||
23049: true,
|
||||
20356: true,
|
||||
20358: true,
|
||||
20360: true,
|
||||
20361: true,
|
||||
20362: true,
|
||||
20364: true,
|
||||
}
|
||||
)
|
||||
@@ -1,61 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
)
|
||||
|
||||
func TestCreateSku(t *testing.T) {
|
||||
// t.Log(beego.BConfig.RunMode)
|
||||
skuID := 21741
|
||||
sku := &model.Sku{}
|
||||
sku.ID = skuID
|
||||
dao.GetEntity(nil, sku)
|
||||
t.Log(sku)
|
||||
// err := CurPurchaseHandler.CreateSku(sku)
|
||||
// if err != nil {
|
||||
// t.Fatal(err.Error())
|
||||
// }
|
||||
}
|
||||
|
||||
func TestGetAllCategories(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.GetAllCategories(jxcontext.AdminCtx, "")
|
||||
if err != nil || len(result) == 0 {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
// func TestReadSku(t *testing.T) {
|
||||
// skuName, err := CurPurchaseHandler.ReadSku(jxcontext.AdminCtx, "", "2005582952")
|
||||
// t.Log(utils.Format4Output(skuName, false))
|
||||
// if err != nil {
|
||||
// t.Fatal(err.Error())
|
||||
// }
|
||||
// if skuName.Name != "味事达酱香鲜特级酿造酱油" || skuName.Skus[0].SpecUnit != "ml" {
|
||||
// t.Fatal("ReadSku return data wrong")
|
||||
// t.Log(string(utils.MustMarshal(skuName)))
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestGetVendorCategories(t *testing.T) {
|
||||
catList, err := CurPurchaseHandler.GetVendorCategories(jxcontext.AdminCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(catList, false))
|
||||
}
|
||||
|
||||
func TestGetSkus(t *testing.T) {
|
||||
skuNameList, err := CurPurchaseHandler.GetSkus(jxcontext.AdminCtx, "", 0, "2023747677")
|
||||
t.Log(utils.Format4Output(skuNameList, false))
|
||||
t.Log(len(skuNameList))
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,520 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/baseapi/utils/errlist"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
type tJdStoreInfo struct {
|
||||
model.Store
|
||||
VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空
|
||||
|
||||
FreightDeductionPack string `orm:"size(32)" json:"freightDeductionPack"` //
|
||||
|
||||
JdCityCode int
|
||||
JdDistrictCode int
|
||||
JdStoreStatus int
|
||||
VendorStoreID string `orm:"column(vendor_store_id)"`
|
||||
RealLastOperator string
|
||||
SyncStatus int
|
||||
VendorStoreName string
|
||||
}
|
||||
|
||||
var (
|
||||
specialDistrictMap = map[int]int{
|
||||
13989: 310032,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (*dao.StoreDetail, error) {
|
||||
a := getAPI(vendorOrgCode)
|
||||
result, err := a.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,
|
||||
},
|
||||
}
|
||||
if result.IsAutoOrder == 0 {
|
||||
retVal.IsAutoOrder = 1
|
||||
} else {
|
||||
retVal.IsAutoOrder = -1
|
||||
}
|
||||
retVal.OriginalName = result.StationName
|
||||
_, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, globals.StoreName)
|
||||
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 place, err2 := dao.GetPlaceByJdCode(db, cityCode); err2 == nil {
|
||||
if place.Level == model.PlaceLevelCity {
|
||||
retVal.CityCode = place.Code
|
||||
retVal.CityName = utils.Interface2String(result.CityName)
|
||||
districtName := result.CountyName // 京东的市区号码与通用数据完全无法关联,只有通过名字来关联
|
||||
if retVal.CityCode != 0 && districtName != "" {
|
||||
if district, err2 := dao.GetPlaceByName(db, districtName, 3, place.Code); err2 == nil {
|
||||
retVal.DistrictCode = district.Code
|
||||
}
|
||||
}
|
||||
} else if place.Level == model.PlaceLevelDistrict {
|
||||
retVal.CityCode = place.ParentCode
|
||||
retVal.DistrictCode = place.Code
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("门店:%s的城市码:%d异常", vendorStoreID, cityCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
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.VendorStoreID = vendorStoreID
|
||||
retVal.ID = int(utils.Str2Int64WithDefault(result.OutSystemID, 0))
|
||||
deliveryRange, err2 := a.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, t2.freight_deduction_pack, t2.vendor_org_code, t2.vendor_store_name
|
||||
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 {
|
||||
a := getAPI(store.VendorOrgCode)
|
||||
// phone := ""
|
||||
// if store.MarketManPhone != "" {
|
||||
// phone = store.MarketManPhone
|
||||
// } else {
|
||||
// phone = model.VendorStoreTel
|
||||
// }
|
||||
storeParams := &jdapi.OpStoreParams{
|
||||
StationNo: store.VendorStoreID,
|
||||
Operator: userName,
|
||||
Phone: store.Tel1,
|
||||
Mobile: store.Tel1,
|
||||
}
|
||||
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 {
|
||||
if store.VendorStoreName != "" {
|
||||
storeParams.StationName = store.VendorStoreName
|
||||
} else {
|
||||
storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD)
|
||||
}
|
||||
storeParams.StationName = utils.LimitUTF8StringLen(storeParams.StationName, jdapi.MaxStoreNameLen)
|
||||
}
|
||||
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreAddress) != 0 {
|
||||
storeParams.StationAddress = store.Address
|
||||
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
|
||||
//TODO 彭州市做特殊处理 2020-05-25
|
||||
if store.JdDistrictCode == 49318 {
|
||||
storeParams.City = 49318
|
||||
storeParams.County = 310045
|
||||
}
|
||||
}
|
||||
|
||||
// storeParams.DeliveryRangeType = store.DeliveryRangeType
|
||||
// if store.DeliveryRangeType == model.DeliveryRangeTypePolygon {
|
||||
// storeParams.CoordinatePoints = store.DeliveryRange
|
||||
// } else {
|
||||
// storeParams.DeliveryRangeRadius = int(utils.Str2Int64WithDefault(store.DeliveryRange, 0))
|
||||
// }
|
||||
}
|
||||
if specialDistrictMap[storeParams.County] != 0 {
|
||||
storeParams.City = storeParams.County
|
||||
storeParams.County = specialDistrictMap[storeParams.County]
|
||||
}
|
||||
storeParams.StoreNotice = store.PromoteInfo
|
||||
modifyCloseStatus := false
|
||||
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagDeletedMask|model.SyncFlagStoreStatus) != 0 {
|
||||
modifyCloseStatus = true
|
||||
_, storeParams.CloseStatus = JxStoreStatus2JdStatus(jxutils.MergeStoreStatus(store.Status, store.JdStoreStatus))
|
||||
}
|
||||
fillOpTimeParams(storeParams, store.GetOpTimeList())
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(storeParams, false))
|
||||
errList := errlist.New()
|
||||
if globals.EnableJdStoreWrite {
|
||||
errList.AddErr(a.UpdateStoreInfo4Open2(storeParams, modifyCloseStatus))
|
||||
}
|
||||
if store.FreightDeductionPack != "" {
|
||||
storeDetail, err2 := dao.GetStoreDetail(db, store.ID, model.VendorIDJD)
|
||||
if err2 == nil {
|
||||
if storeDetail.FreightDeductionPackObj != nil {
|
||||
freightParams := &jdapi.UpdateStoreFreightParam{
|
||||
StationNo: store.VendorStoreID,
|
||||
UserPin: userName,
|
||||
OpenDistanceFreight: true,
|
||||
StartCharge: int64(storeDetail.FreightDeductionPackObj.StartPrice),
|
||||
}
|
||||
if len(storeDetail.FreightDeductionPackObj.FreightDeductionList) > 0 {
|
||||
for _, v := range storeDetail.FreightDeductionPackObj.FreightDeductionList {
|
||||
if v.DeductFreight > 0 {
|
||||
freightParams.FreeFreightInfoList = append(freightParams.FreeFreightInfoList, &jdapi.FreeFreightInfo{
|
||||
FullFreeMoney: int64(v.BeginPrice),
|
||||
FreeType: jdapi.FreightFreeTypePartBase,
|
||||
FreeMoney: int64(v.DeductFreight),
|
||||
FreeFreightTimes: []*jdapi.FreeFreightTime{
|
||||
&jdapi.FreeFreightTime{
|
||||
FreeBeginTime: utils.Time2Str(time.Now()),
|
||||
FreeEndTime: utils.Time2Str(time.Now().Add(24 * time.Hour * 365 * 2)),
|
||||
},
|
||||
},
|
||||
})
|
||||
break // 京东只能设置一个满减,之前理解有误
|
||||
}
|
||||
}
|
||||
}
|
||||
freightParams.IsFullFree = len(freightParams.FreeFreightInfoList) > 0
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(freightParams, false))
|
||||
if globals.EnableJdStoreWrite {
|
||||
errList.AddErr(a.UpdateStoreFreightConfigNew(freightParams))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
err = errList.GetErrListAsOne()
|
||||
}
|
||||
}
|
||||
return 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(store.VendorOrgCode).UpdateStoreInfo4Open2(storeParams, false)
|
||||
}
|
||||
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 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, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
result, err := getAPI(vendorOrgCode).GetStoreInfoByStationNo2(vendorStoreID)
|
||||
if err == nil {
|
||||
storeStatus = JdStoreStatus2JxStatus(int(result.Yn), result.CloseStatus)
|
||||
}
|
||||
return storeStatus, err
|
||||
}
|
||||
|
||||
// 当前京东的storeCrud消息不会在门店状态改变时发送,所以意义不大,先放在这里
|
||||
func (c *PurchaseHandler) OnStoreMsg(vendorOrgCode string, 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, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
|
||||
_, err = getAPI(vendorOrgCode).UpdateStoreConfig4Open(vendorStoreID, isSetEnable)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) {
|
||||
_, closeStatus := JxStoreStatus2JdStatus(status)
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).UpdateStoreInfo4Open2(&jdapi.OpStoreParams{
|
||||
StationNo: vendorStoreID,
|
||||
Operator: ctx.GetUserName(),
|
||||
CloseStatus: closeStatus,
|
||||
}, true)
|
||||
}
|
||||
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, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
|
||||
params := &jdapi.OpStoreParams{
|
||||
StationNo: vendorStoreID,
|
||||
Operator: ctx.GetUserName(),
|
||||
}
|
||||
fillOpTimeParams(params, opTimeList)
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).UpdateStoreInfo4Open2(params, false)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) {
|
||||
vendorStoreIDs, err = getAPI(vendorOrgCode).GetStationsByVenderId()
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) storeUploadImgByURL(vendorOrgCode, inImgURL string) (imgURL string, err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
if vendorOrgCode == globals.JdOrgCode {
|
||||
imgURL, err = api.JdPageAPI.StoreUploadImgByURL(inImgURL)
|
||||
} else {
|
||||
imgURL, err = getAPI(vendorOrgCode).StoreUploadImgByURL(inImgURL)
|
||||
}
|
||||
} else {
|
||||
imgURL = utils.GetUUID()
|
||||
}
|
||||
return imgURL, err
|
||||
}
|
||||
|
||||
func addStoreInfo2Err(err error, storeID int) error {
|
||||
if err != nil {
|
||||
errExt, _ := err.(*utils.ErrorWithCode)
|
||||
if errExt == 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 addStoreInfo2Err(err, storeDetail.ID)
|
||||
}
|
||||
licenceURL, err := c.storeUploadImgByURL(storeDetail.VendorOrgCode, storeDetail.Licence)
|
||||
if err != nil {
|
||||
return addStoreInfo2Err(err, storeDetail.ID)
|
||||
}
|
||||
expireStart, err := utils.TryStr2Time(licenceDetail.StartDate)
|
||||
if err != nil {
|
||||
return addStoreInfo2Err(fmt.Errorf("执照有效开始时间:%s非法,请手动处理", licenceDetail.StartDate), storeDetail.ID)
|
||||
}
|
||||
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.VendorOrgCode, 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.VendorOrgCode, 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 {
|
||||
globals.SugarLogger.Debugf("SaveQualifyTest4,[%v]", utils.Format4Output(qualifyList, false))
|
||||
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, vendorOrgCode, vendorStoreID string, storeID int64) (err error) {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).UpdateStoreInfo4Open2(
|
||||
&jdapi.OpStoreParams{
|
||||
StationNo: vendorStoreID,
|
||||
Operator: ctx.GetUserName(),
|
||||
OutSystemID: utils.Int2Str(int(storeID)),
|
||||
}, false)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
|
||||
return vendorStoreID, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"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/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api/apimanager"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
|
||||
switch funcID {
|
||||
case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice:
|
||||
batchSize = jdapi.MaxStoreSkuBatchSize
|
||||
case partner.FuncCreateActs, partner.FuncCancelActs:
|
||||
batchSize = 1
|
||||
}
|
||||
return batchSize
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getStoreSkusBareInfoLimitSize(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) {
|
||||
var batchSkuInfoList []*jdapi.BaseStockCenterRequest
|
||||
batchSkuList := partner.BareStoreSkuInfoList(inStoreSkuList).GetVendorSkuIDIntList()
|
||||
for _, v := range inStoreSkuList {
|
||||
if !dao.IsVendorThingIDEmpty(v.VendorSkuID) {
|
||||
batchSkuInfoList = append(batchSkuInfoList, &jdapi.BaseStockCenterRequest{
|
||||
StationNo: vendorStoreID,
|
||||
SkuId: utils.Str2Int64(v.VendorSkuID),
|
||||
})
|
||||
}
|
||||
}
|
||||
if len(batchSkuInfoList) > 0 {
|
||||
var stockInfo []*jdapi.QueryStockResponse
|
||||
var priceInfo []*jdapi.StorePriceInfo
|
||||
task := tasksch.NewParallelTask("获取京东到家平台门店商品信息", tasksch.NewParallelConfig().SetParallelCount(2), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
subTaskID := batchItemList[0].(int)
|
||||
if subTaskID == 0 {
|
||||
stockInfo, err = getAPI(vendorOrgCode).QueryOpenUseable(batchSkuInfoList)
|
||||
} else {
|
||||
priceInfo, err = getAPI(vendorOrgCode).GetStationInfoList(vendorStoreID, batchSkuList)
|
||||
}
|
||||
return nil, err
|
||||
}, []int{0, 1})
|
||||
tasksch.HandleTask(task, parentTask, false).Run()
|
||||
_, err = task.GetResult(0)
|
||||
if err == nil {
|
||||
storeSkuMap := putils.StoreSkuList2MapByVendorSkuID(inStoreSkuList)
|
||||
for _, v := range stockInfo {
|
||||
sku := storeSkuMap[utils.Int64ToStr(v.SkuID)]
|
||||
sku.Status = jdStoreSkuStatus2Jx(v.Vendibility)
|
||||
sku.Stock = v.UsableQty
|
||||
if sku.Stock > 0 {
|
||||
outStoreSkuList = append(outStoreSkuList, sku)
|
||||
}
|
||||
}
|
||||
for _, v := range priceInfo {
|
||||
sku := storeSkuMap[utils.Int64ToStr(v.SkuID)]
|
||||
sku.VendorPrice = v.Price
|
||||
}
|
||||
}
|
||||
}
|
||||
return outStoreSkuList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) {
|
||||
result, err := putils.FreeBatchStoreSkuInfo("获取门店商品信息", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) {
|
||||
list, err := p.getStoreSkusBareInfoLimitSize(ctx, vendorOrgCode, task, storeID, vendorStoreID, batchedStoreSkuList)
|
||||
if err == nil {
|
||||
result = list
|
||||
}
|
||||
return result, len(list), err
|
||||
}, ctx, parentTask, inStoreSkuList, jdapi.MaxStoreSkuBatchSize, true)
|
||||
for _, v := range result {
|
||||
outStoreSkuList = append(outStoreSkuList, v.(*partner.StoreSkuInfo))
|
||||
}
|
||||
return outStoreSkuList, err
|
||||
}
|
||||
|
||||
func jdStoreSkuStatus2Jx(jdStoreSkuStatus int) (jxSkuStatus int) {
|
||||
if jdStoreSkuStatus == 0 {
|
||||
jxSkuStatus = model.SkuStatusNormal
|
||||
} else {
|
||||
jxSkuStatus = model.SkuStatusDontSale
|
||||
}
|
||||
return jxSkuStatus
|
||||
}
|
||||
|
||||
func jxStoreSkuStatus2Jd(jxStoreSkuStatus int) (isSale bool) {
|
||||
return jxStoreSkuStatus == model.SkuStatusNormal
|
||||
}
|
||||
|
||||
func isErrPartialFailed(err error) bool {
|
||||
if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.Code() == jdapi.ResponseInnerCodePartialFailed {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getStrOutSkuIDs(l []*jdapi.StoreSkuBatchUpdateResponse, isSuccess bool) (outSkuIDs []string) {
|
||||
for _, v := range l {
|
||||
if isSuccess && jdapi.IsCodeSuccess(v.Code) {
|
||||
outSkuIDs = append(outSkuIDs, v.OutSkuID)
|
||||
} else if !isSuccess && !jdapi.IsCodeSuccess(v.Code) {
|
||||
outSkuIDs = append(outSkuIDs, v.OutSkuID)
|
||||
}
|
||||
}
|
||||
return outSkuIDs
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
var skuVendibilityList []*jdapi.StockVendibility
|
||||
jdStatus := jxStoreSkuStatus2Jd(status)
|
||||
for _, v := range storeSkuList {
|
||||
skuVendibilityList = append(skuVendibilityList, &jdapi.StockVendibility{
|
||||
OutSkuId: utils.Int2Str(v.SkuID),
|
||||
DoSale: jdStatus,
|
||||
})
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
var responseList []*jdapi.StoreSkuBatchUpdateResponse
|
||||
var err2 error
|
||||
if vendorOrgCode != apimanager.FakeJdOrgCode {
|
||||
responseList, err2 = getAPI(vendorOrgCode).BatchUpdateVendibility(ctx.GetTrackInfo(), "", vendorStoreID, skuVendibilityList, ctx.GetUserName())
|
||||
} else {
|
||||
responseList, err2 = getAPI(vendorOrgCode).FakeBatchUpdateVendibility(ctx.GetTrackInfo(), "", vendorStoreID, skuVendibilityList, ctx.GetUserName())
|
||||
}
|
||||
if err = err2; err != nil {
|
||||
failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品状态")
|
||||
// successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false)))
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if len(storeSkuList) == 1 && vendorOrgCode != apimanager.FakeJdOrgCode {
|
||||
if globals.EnableJdStoreWrite {
|
||||
_, err = getAPI(vendorOrgCode).UpdateStationPrice(ctx.GetTrackInfo(), utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), vendorStoreID, int(storeSkuList[0].VendorPrice))
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品价格")
|
||||
}
|
||||
} else {
|
||||
var skuPriceInfoList []*jdapi.SkuPriceInfo
|
||||
for _, v := range storeSkuList {
|
||||
skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
|
||||
OutSkuId: utils.Int2Str(v.SkuID),
|
||||
Price: int(v.VendorPrice),
|
||||
})
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
var responseList []*jdapi.StoreSkuBatchUpdateResponse
|
||||
var err2 error
|
||||
if vendorOrgCode != apimanager.FakeJdOrgCode {
|
||||
responseList, err2 = getAPI(vendorOrgCode).UpdateVendorStationPrice(ctx.GetTrackInfo(), "", vendorStoreID, skuPriceInfoList)
|
||||
} else {
|
||||
responseList, err2 = getAPI(vendorOrgCode).FakeUpdateVendorStationPrice(ctx.GetTrackInfo(), "", vendorStoreID, skuPriceInfoList)
|
||||
}
|
||||
if err = err2; err != nil {
|
||||
failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品价格")
|
||||
}
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if len(storeSkuList) == 1 && vendorOrgCode != apimanager.FakeJdOrgCode {
|
||||
if globals.EnableJdStoreWrite {
|
||||
err = getAPI(vendorOrgCode).UpdateCurrentQty(ctx.GetTrackInfo(), vendorStoreID, utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), storeSkuList[0].Stock)
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品库存")
|
||||
}
|
||||
} else {
|
||||
var skuStockList []*jdapi.SkuStock
|
||||
for _, v := range storeSkuList {
|
||||
skuStockList = append(skuStockList, &jdapi.SkuStock{
|
||||
OutSkuId: utils.Int2Str(v.SkuID),
|
||||
StockQty: v.Stock,
|
||||
})
|
||||
}
|
||||
if globals.EnableJdStoreWrite {
|
||||
var responseList []*jdapi.StoreSkuBatchUpdateResponse
|
||||
var err2 error
|
||||
if vendorOrgCode != apimanager.FakeJdOrgCode {
|
||||
responseList, err2 = getAPI(vendorOrgCode).BatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", vendorStoreID, skuStockList, ctx.GetUserName())
|
||||
} else {
|
||||
responseList, err2 = getAPI(vendorOrgCode).FakeBatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", vendorStoreID, skuStockList, ctx.GetUserName())
|
||||
}
|
||||
if err = err2; err != nil {
|
||||
failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品库存")
|
||||
// successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false)))
|
||||
}
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
||||
globals.SugarLogger.Debugf("jd SyncStoreProducts, storeID:%d", storeID)
|
||||
db := dao.GetDB()
|
||||
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
storeSkuList, err := dao.GetStoreSkus2(db, model.VendorIDJD, storeID, skuIDs, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
task := tasksch.NewParallelTask("SyncStoreProducts京东", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeSku := batchItemList[0].(*dao.StoreSkuSyncInfo)
|
||||
if storeSku.VendorSkuID != "" && storeSku.StoreSkuStatus == model.SkuStatusNormal {
|
||||
if globals.EnableJdStoreWrite {
|
||||
synchronized, err2 := getAPI(vendorOrgCode).SyncProduct(storeDetail.VendorStoreID, storeSku.VendorSkuID)
|
||||
if err = err2; err == nil && synchronized {
|
||||
retVal = []int{1}
|
||||
}
|
||||
} else {
|
||||
retVal = []int{1}
|
||||
}
|
||||
}
|
||||
return retVal, err
|
||||
}, storeSkuList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
if !isAsync {
|
||||
result, err2 := task.GetResult(0)
|
||||
if err = err2; err == nil {
|
||||
hint = utils.Int2Str(len(result))
|
||||
}
|
||||
} else {
|
||||
hint = task.GetID()
|
||||
}
|
||||
return hint, err
|
||||
}
|
||||
|
||||
//京东api返回
|
||||
func SelectStoreSkuListByResponseList(storeSkuList []*partner.StoreSkuInfo, responseList []*jdapi.StoreSkuBatchUpdateResponse, storeID int, vendorName, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) {
|
||||
responseMap := make(map[string]string)
|
||||
if len(responseList) > 0 {
|
||||
for _, v := range responseList {
|
||||
if v.Code != "0" {
|
||||
responseMap[v.OutSkuID] = v.Msg
|
||||
}
|
||||
}
|
||||
for _, v := range storeSkuList {
|
||||
if responseMap[utils.Int2Str(v.SkuID)] != "" {
|
||||
respFailed := &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
ErrMsg: responseMap[utils.Int2Str(v.SkuID)],
|
||||
StoreID: storeID,
|
||||
VendoreName: vendorName,
|
||||
SyncType: syncType,
|
||||
}
|
||||
selectedStoreSkuList = append(selectedStoreSkuList, respFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedStoreSkuList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
for _, v := range storeSkuList {
|
||||
if vendorActID, err2 := createSkuAct(ctx, putils.GetFixDirectDownAct(vendorOrgCode, storeID, v.SkuID), putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, []*partner.StoreSkuInfo{v})); err2 != nil {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
VendoreID: model.VendorIDJD,
|
||||
StoreID: storeID,
|
||||
ErrMsg: err2.Error(),
|
||||
})
|
||||
} else {
|
||||
v.VendorActID = vendorActID
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
for _, v := range storeSkuList {
|
||||
if err2 := cancelSkuAct(ctx, putils.GetFixDirectDownAct(vendorOrgCode, storeID, v.SkuID), v.VendorActID); err2 != nil {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
VendoreID: model.VendorIDJD,
|
||||
StoreID: storeID,
|
||||
ErrMsg: err2.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/putils"
|
||||
)
|
||||
|
||||
func TestGetStoreSkusBareInfo(t *testing.T) {
|
||||
// list := []*partner.StoreSkuInfo{
|
||||
// &partner.StoreSkuInfo{
|
||||
// SkuID: 2212,
|
||||
// VendorSkuID: "2019458103",
|
||||
// },
|
||||
// }
|
||||
// for i := 0; i < 30-1; i++ {
|
||||
// list = append(list, list[0])
|
||||
// }
|
||||
skuNameList, err := CurPurchaseHandler.GetSkus(jxcontext.AdminCtx, "", 0, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list := putils.StoreSkuFullList2Bare(skuNameList)
|
||||
|
||||
storeSkuList, err := CurPurchaseHandler.GetStoreSkusBareInfo(jxcontext.AdminCtx, "", nil, 2, "11053496", list)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
var focusedStoreSkuList []*partner.StoreSkuInfo
|
||||
for _, v := range storeSkuList {
|
||||
if v.Stock > 0 {
|
||||
focusedStoreSkuList = append(focusedStoreSkuList, v)
|
||||
}
|
||||
}
|
||||
t.Log(utils.Format4Output(focusedStoreSkuList, false))
|
||||
t.Log(len(focusedStoreSkuList))
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
)
|
||||
|
||||
const (
|
||||
TestStoreNo = 100164
|
||||
TestJdStoreNo = "11736989"
|
||||
)
|
||||
|
||||
func TestReadStore(t *testing.T) {
|
||||
result, err := new(PurchaseHandler).ReadStore(jxcontext.AdminCtx, "", TestJdStoreNo)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestUpdateStore(t *testing.T) {
|
||||
handler := new(PurchaseHandler)
|
||||
result, err := handler.ReadStore(jxcontext.AdminCtx, "", TestJdStoreNo)
|
||||
|
||||
// result := &model.Store{}
|
||||
// result.ID = 100164
|
||||
// err := dao.GetEntity(nil, result)
|
||||
db := dao.GetDB()
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
result.Name += "h"
|
||||
newName := result.Name
|
||||
err = handler.UpdateStore(db, TestStoreNo, "autotest")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// same
|
||||
result, err = handler.ReadStore(jxcontext.AdminCtx, "", TestJdStoreNo)
|
||||
if result.Name != newName {
|
||||
t.Fatalf("result is not same, desired newName:%s, newName:%s", newName, result.Name)
|
||||
}
|
||||
|
||||
// restore
|
||||
result.Name = strings.Trim(result.Name, "h")
|
||||
err = handler.UpdateStore(db, TestStoreNo, "autotest")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateStore2(t *testing.T) {
|
||||
handler := new(PurchaseHandler)
|
||||
|
||||
// result := &model.Store{}
|
||||
// result.ID = 100164
|
||||
// err := dao.GetEntity(nil, result)
|
||||
db := dao.GetDB()
|
||||
// restore
|
||||
err := handler.UpdateStore(db, 1, "autotest")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// func TestCoordRangeConversion(t *testing.T) {
|
||||
// jxRange := "108841759,34332892;108842271,34330820;108846013,34331422;108846110,34333189;108847722,34331853;108856703,34331729;108866149,34327507;108873423,34320980;108877737,34312856;108877727,34299624;108870105,34287988;108855137,34290911;108867884,34286298;108858260,34281316;108854162,34283490;108853803,34280145;108846110,34279291;108830587,34282539;108818806,34291500;108814493,34299624;108813596,34308465;108818797,34320980;108830582,34329941;108841759,34332892"
|
||||
// jdRange := "108.841759,34.332892;108.842271,34.330820;108.846013,34.331422;108.846110,34.333189;108.847722,34.331853;108.856703,34.331729;108.866149,34.327507;108.873423,34.320980;108.877737,34.312856;108.877727,34.299624;108.870105,34.287988;108.855137,34.290911;108.867884,34.286298;108.858260,34.281316;108.854162,34.283490;108.853803,34.280145;108.846110,34.279291;108.830587,34.282539;108.818806,34.291500;108.814493,34.299624;108.813596,34.308465;108.818797,34.320980;108.830582,34.329941;108.841759,34.332892"
|
||||
|
||||
// if JdRange2JxRange(jdRange) != jxRange {
|
||||
// t.Fatal("result doesn't match")
|
||||
// }
|
||||
|
||||
// if JxRange2JdRange(jxRange) != jdRange {
|
||||
// t.Fatal("result doesn't match")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestSyncQualify(t *testing.T) {
|
||||
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), 102610, model.VendorIDJD)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
err = CurPurchaseHandler.SyncQualify(jxcontext.AdminCtx, storeDetail)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package jd
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) OnWaybillMsg(vendorOrgCode string, msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal = c.onWaybillMsg(vendorOrgCode, msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.OrderID, model.VendorIDJD))
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onWaybillMsg(vendorOrgCode string, msg *jdapi.CallbackDeliveryStatusMsg) (retVal *jdapi.CallbackResponse) {
|
||||
order := c.callbackMsg2Waybill(msg)
|
||||
switch msg.DeliveryStatus {
|
||||
case jdapi.DeliveryStatusWait4Grap:
|
||||
order.Status = model.WaybillStatusNew
|
||||
case jdapi.DeliveryStatusAccepted, jdapi.DeliveryStatusCourierChaged: // 将更换配送员也当成接单消息
|
||||
// todo 性能问题,暂时取消调用
|
||||
// if result, err := getAPI(vendorOrgCode).QuerySingleOrder(msg.OrderID); err == nil {
|
||||
// // 默认配送费=订单应付运费(orderReceivableFreight)
|
||||
// //订单应付运费为未优惠前应付运费(满免优惠,运费优惠券,VIP免基础运费,用户小费)ps:用户小费是用户给配送员的小费
|
||||
// order.DesiredFee = utils.Interface2Int64WithDefault(result["orderReceivableFreight"], 0) +
|
||||
// utils.Interface2Int64WithDefault(result["merchantPaymentDistanceFreightMoney"], 0) +
|
||||
// utils.Interface2Int64WithDefault(result["tips"], 0)
|
||||
// }
|
||||
order.Status = model.WaybillStatusAccepted
|
||||
case jdapi.DeliveryStatusCourierCanceled:
|
||||
order.Status = model.WaybillStatusAcceptCanceled
|
||||
case jdapi.DeliveryStatusCourierArrived:
|
||||
order.Status = model.WaybillStatusCourierArrived
|
||||
case jdapi.DeliveryStatusFailedGetGoodsWaiting:
|
||||
order.Status = model.WaybillStatusApplyFailedGetGoods
|
||||
case jdapi.DeliveryStatusFailedGetGoodsRejected:
|
||||
order.Status = model.WaybillStatusRefuseFailedGetGoods
|
||||
case jdapi.DeliveryStatusFailedGetGoods:
|
||||
order.Status = model.WaybillStatusAgreeFailedGetGoods
|
||||
case jdapi.DeliveryStatusGotGoods:
|
||||
order.Status = model.WaybillStatusDelivering
|
||||
case jdapi.DeliveryStatusFailedDelivery:
|
||||
order.Status = model.WaybillStatusDeliverFailed
|
||||
case jdapi.DeliveryStatusFinished:
|
||||
order.Status = model.WaybillStatusDelivered
|
||||
default:
|
||||
order.Status = model.WaybillStatusUnknown
|
||||
}
|
||||
return jdapi.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order), order.VendorStatus)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Waybill(msg *jdapi.CallbackDeliveryStatusMsg) (retVal *model.Waybill) {
|
||||
retVal = &model.Waybill{
|
||||
VendorOrderID: msg.OrderID,
|
||||
OrderVendorID: model.VendorIDJD,
|
||||
VendorWaybillID: msg.OrderID,
|
||||
WaybillVendorID: model.VendorIDJD,
|
||||
CourierName: msg.DeliveryManName,
|
||||
CourierMobile: msg.DeliveryManPhone,
|
||||
VendorStatus: msg.DeliveryStatus,
|
||||
StatusTime: utils.Str2Time(msg.DeliveryStatusTime),
|
||||
Remark: msg.Remark,
|
||||
|
||||
VendorOrgCode: AppKey2OrgCode(msg.AppKey),
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jcqapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdshopapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxstore/common"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func OnCallbackMsg(msg *jdshopapi.CallBackResult) (err error) {
|
||||
msgType := msg.MsgType
|
||||
switch msgType {
|
||||
case jcqapi.TopicOrderPay:
|
||||
utils.CallFuncAsync(func() {
|
||||
SaveJdsOrders(msg)
|
||||
})
|
||||
case jcqapi.TopicOrderCancel:
|
||||
utils.CallFuncAsync(func() {
|
||||
order := getRealOrderID(msg.OrderID)
|
||||
if order != nil {
|
||||
if order.Status != model.OrderStatusCanceled {
|
||||
CurPurchaseHandler.CancelOrder(jxcontext.AdminCtx, order, "系统取消")
|
||||
}
|
||||
}
|
||||
})
|
||||
case jcqapi.TopicOrderOut:
|
||||
utils.CallFuncAsync(func() {
|
||||
globals.SugarLogger.Debugf("jdsOrderOut", utils.Format4Output(msg, false))
|
||||
orders := getAllRealOrderID(msg.OrderID)
|
||||
if len(orders) > 0 {
|
||||
for _, order := range orders {
|
||||
if order.ActualPayPrice == 0 {
|
||||
if jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) == 0 {
|
||||
order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderTotalPrice) + utils.Str2Float64(msg.FreightPrice) - utils.Str2Float64(msg.SellerDiscount))
|
||||
} else {
|
||||
order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment))
|
||||
}
|
||||
order.TotalShopMoney = utils.Float64TwoInt64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage)
|
||||
partner.CurOrderManager.UpdateOrderFields(order, []string{"ActualPayPrice", "TotalShopMoney"})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("暂不支持的topic类型!topic: %v", msgType)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func SaveJdsOrders(msg *jdshopapi.CallBackResult) (err error) {
|
||||
order, err := result2Orders(msg)
|
||||
if err != nil || order == nil {
|
||||
return err
|
||||
}
|
||||
partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order))
|
||||
noticeMsg := fmt.Sprintf("京东商城新订单,订单号:[%v] ,将要发到的门店id:[%v] , 门店名:[%v]", order.VendorOrderID, order.StoreID, order.StoreName)
|
||||
if order.OrderType == model.OrderTypeAddressErr {
|
||||
noticeMsg += " 此订单地址有问题,需要矫正坐标!"
|
||||
}
|
||||
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "DDC5657B43EE11E9A9FF525400E86DC0", "京东商城来新订单了!", noticeMsg)
|
||||
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "1439B3E07D3911EA881A525400E86DC0", "京东商城来新订单了!", noticeMsg)
|
||||
return err
|
||||
}
|
||||
|
||||
func result2Orders(msg *jdshopapi.CallBackResult) (order *model.GoodsOrder, err error) {
|
||||
//有可能是库里已经有这个订单了
|
||||
orderE, err := partner.CurOrderManager.LoadOrder(msg.OrderID+"000001", model.VendorIDJDShop)
|
||||
if orderE != nil {
|
||||
return order, fmt.Errorf("已经存在此订单!")
|
||||
}
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID2: msg.OrderID,
|
||||
VendorOrderID: msg.OrderID + "000001",
|
||||
VendorID: model.VendorIDJDShop,
|
||||
BaseFreightMoney: jxutils.StandardPrice2Int(utils.Str2Float64(msg.FreightPrice)),
|
||||
VendorStatus: msg.OrderState,
|
||||
VendorUserID: msg.Pin,
|
||||
BuyerComment: msg.OrderRemark,
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
OriginalData: string(utils.MustMarshal(msg)),
|
||||
OrderCreatedAt: utils.Str2Time(msg.OrderStartTime),
|
||||
ConsigneeAddress: Decrypt(msg.ConsigneeInfo.FullAddress),
|
||||
ConsigneeName: Decrypt(msg.ConsigneeInfo.Fullname),
|
||||
ConsigneeMobile: Decrypt(msg.ConsigneeInfo.Mobile),
|
||||
ConsigneeMobile2: Decrypt(msg.ConsigneeInfo.Telephone),
|
||||
ActualPayPrice: jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)),
|
||||
Status: model.OrderStatusNew,
|
||||
TotalShopMoney: utils.Float64TwoInt64(math.Round(float64(jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment))) * jdshopapi.JdsPayPercentage)),
|
||||
DeliveryType: model.OrderDeliveryTypeStoreSelf,
|
||||
StatusTime: utils.Str2Time(msg.OrderStartTime),
|
||||
OrderSeq: 0,
|
||||
}
|
||||
if order.TotalShopMoney < 100 {
|
||||
order.TotalShopMoney = 100
|
||||
}
|
||||
if order.ConsigneeAddress != "" {
|
||||
lng, lat, err2 := api.AutonaviAPI.GetCoordinateFromAddressByPage(order.ConsigneeAddress)
|
||||
if err = err2; err != nil {
|
||||
globals.SugarLogger.Infof("高德page err: %v", err)
|
||||
}
|
||||
lng2, lat2, _ := api.AutonaviAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "")
|
||||
distance := jxutils.EarthDistance(lng, lat, lng2, lat2)
|
||||
if distance > 1 {
|
||||
order.OrderType = model.OrderTypeAddressErr
|
||||
}
|
||||
if err == nil && lng != 0 && lat != 0 {
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng)
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat)
|
||||
} else {
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng2)
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat2)
|
||||
}
|
||||
order.CoordinateType = model.CoordinateTypeMars
|
||||
}
|
||||
for _, v := range msg.ItemInfoList {
|
||||
sku := &model.OrderSku{
|
||||
VendorID: model.VendorIDJDShop,
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
Count: utils.Str2Int(v.ItemTotal),
|
||||
VendorSkuID: v.SkuID,
|
||||
SkuName: v.SkuName,
|
||||
VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)),
|
||||
SalePrice: jxutils.StandardPrice2Int(utils.Str2Float64(v.JdPrice)),
|
||||
// SkuID: utils.Str2Int(v.OuterSkuID),
|
||||
}
|
||||
if v.OuterSkuID != "" {
|
||||
sku.SkuID = utils.Str2Int(v.OuterSkuID)
|
||||
}
|
||||
_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.SkuName)
|
||||
sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit)
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
storeList, err := common.GetStoreListByLocation(jxcontext.AdminCtx, jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), 3000, false, true)
|
||||
if err != nil {
|
||||
globals.SugarLogger.Debugf("jds GetStoreListByLocation error: %v", err.Error())
|
||||
return order, err
|
||||
}
|
||||
if len(storeList) > 0 {
|
||||
for _, store := range storeList {
|
||||
order.StoreID = store.ID
|
||||
order.JxStoreID = store.ID
|
||||
order.StoreName = store.Name
|
||||
globals.SugarLogger.Debugf("jds GetStoreListByLocation, orderID: %v storeID :%v", order.VendorOrderID, order.StoreID)
|
||||
//结算类型
|
||||
storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), order.StoreID, model.VendorIDJDShop)
|
||||
if storeDetail != nil {
|
||||
if storeDetail.PayPercentage < 50 {
|
||||
order.EarningType = model.EarningTypePoints
|
||||
} else {
|
||||
order.EarningType = model.EarningTypeQuote
|
||||
}
|
||||
}
|
||||
var (
|
||||
shopPriceSum int
|
||||
saleNormalSum int
|
||||
)
|
||||
for _, sku := range order.Skus {
|
||||
storeSkuList, _ := dao.GetStoresSkusInfo(dao.GetDB(), []int{order.StoreID}, []int{sku.SkuID})
|
||||
if len(storeSkuList) > 0 {
|
||||
if storeSkuList[0].Status == model.StoreSkuBindStatusNormal {
|
||||
saleNormalSum += 1
|
||||
}
|
||||
shopPriceSum += storeSkuList[0].Price * sku.Count
|
||||
}
|
||||
}
|
||||
//可售数小于一半就不行
|
||||
if math.Mod(float64(len(order.Skus)), float64(2)) == 0 {
|
||||
if saleNormalSum < len(order.Skus)/2 {
|
||||
buildOrderTo102919(order)
|
||||
continue
|
||||
} else {
|
||||
if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) {
|
||||
buildOrderTo102919(order)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if saleNormalSum <= len(order.Skus)/2 {
|
||||
buildOrderTo102919(order)
|
||||
continue
|
||||
} else {
|
||||
if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) {
|
||||
buildOrderTo102919(order)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
buildOrderTo102919(order)
|
||||
}
|
||||
storeMaps, _ := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDJDShop}, []int{order.StoreID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "")
|
||||
if len(storeMaps) > 0 {
|
||||
order.VendorStoreID = storeMaps[0].VendorStoreID
|
||||
}
|
||||
// 如果是暂停,表示是预订单g
|
||||
if msg.OrderState == jdshopapi.OrderStatusPause || msg.OrderState == jdshopapi.OrderStatusPopPause {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
if time2, err := api.JdShopAPI.GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil {
|
||||
if time2 == "" {
|
||||
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
|
||||
} else {
|
||||
order.ExpectedDeliveredTime = utils.Str2Time(time2).Add(-time.Minute * 30)
|
||||
}
|
||||
}
|
||||
order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour)
|
||||
} else if msg.OrderState == jdshopapi.OrderStatusWait {
|
||||
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
|
||||
order.BusinessType = model.BusinessTypeImmediate
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("暂不支持的京东商城订单类型!type: %v", msg.OrderState)
|
||||
return nil, err
|
||||
}
|
||||
if msg.IDSopShipmenttype == jdshopapi.IdSopShipmenttypeTC {
|
||||
if time2, err := api.JdShopAPI.GetOrderExtInfoByOrderId(order.VendorOrderID2); err == nil {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
order.ExpectedDeliveredTime = utils.Str2Time(time2).Add(-time.Minute * 30)
|
||||
}
|
||||
}
|
||||
setJdsOrderSeq(order)
|
||||
if order.OrderType == model.OrderTypeAddressErr {
|
||||
buildOrderTo102919(order)
|
||||
}
|
||||
return order, err
|
||||
}
|
||||
|
||||
func buildOrderTo102919(order *model.GoodsOrder) {
|
||||
order.StoreID = 102919
|
||||
order.JxStoreID = 102919
|
||||
order.StoreName = "商城模板(成都发货)"
|
||||
order.VendorStoreID = model.JdShopMainVendorStoreID
|
||||
order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled
|
||||
}
|
||||
|
||||
func setJdsOrderSeq(order *model.GoodsOrder) (err error) {
|
||||
type tCount struct {
|
||||
Count int `json:"count"`
|
||||
}
|
||||
var count = &tCount{}
|
||||
sql := `
|
||||
SELECT count(*) count FROM goods_order WHERE store_id = ? AND order_create_at >= ? AND order_create_at <= ? AND vendor_id = ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
order.StoreID, utils.Time2Date(time.Now()), utils.Time2Date(time.Now().AddDate(0, 0, 1)), order.VendorID,
|
||||
}
|
||||
err = dao.GetRow(dao.GetDB(), &count, sql, sqlParams)
|
||||
order.OrderSeq = count.Count + 1
|
||||
return err
|
||||
}
|
||||
|
||||
func Decrypt(p string) (result string) {
|
||||
if p == "" {
|
||||
return ""
|
||||
}
|
||||
data, _ := base64.StdEncoding.DecodeString(strings.ReplaceAll(p, " ", "+"))
|
||||
key := GetKey(hex.EncodeToString(data)[4:36])
|
||||
globals.SugarLogger.Debugf("Decrypt keys : %v", key)
|
||||
data2, _ := base64.StdEncoding.DecodeString(key)
|
||||
b := bytes.NewBuffer(data)
|
||||
b.Next(18)
|
||||
iv := make([]byte, 16)
|
||||
b.Read(iv)
|
||||
main := make([]byte, len(data)-18-16)
|
||||
b.Read(main)
|
||||
decryptedData, _ := utils.AESCBCDecpryt(main, data2[:16], iv)
|
||||
return string(decryptedData)
|
||||
}
|
||||
|
||||
func getRealOrderID(orderID string) (order *model.GoodsOrder) {
|
||||
var (
|
||||
db = dao.GetDB()
|
||||
)
|
||||
sql := `
|
||||
SELECT * FROM goods_order WHERE vendor_order_id2 = ? ORDER BY vendor_order_id DESC LIMIT 1
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
orderID,
|
||||
}
|
||||
dao.GetRow(db, &order, sql, sqlParams)
|
||||
return order
|
||||
}
|
||||
|
||||
func getAllRealOrderID(orderID string) (orders []*model.GoodsOrder) {
|
||||
var (
|
||||
db = dao.GetDB()
|
||||
)
|
||||
sql := `
|
||||
SELECT * FROM goods_order WHERE vendor_order_id2 = ?
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
orderID,
|
||||
}
|
||||
dao.GetRows(db, &orders, sql, sqlParams)
|
||||
return orders
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
CurPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
putils.DefSingleStorePlatform
|
||||
}
|
||||
|
||||
func init() {
|
||||
if api.JdShopAPI != nil {
|
||||
CurPurchaseHandler = New()
|
||||
partner.RegisterPurchasePlatform(CurPurchaseHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func New() (obj *PurchaseHandler) {
|
||||
obj = new(PurchaseHandler)
|
||||
obj.ISingleStoreStoreSkuHandler = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDJDShop
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
if globals.EnableJdShopWrite {
|
||||
if imgType > model.ImgTypeLocal {
|
||||
result, err := api.JdShopAPI.UploadPicture(imgData, 0, imgName)
|
||||
if err == nil {
|
||||
imgHint = result.PictureURL
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imgHint = utils.GetUpperUUID()
|
||||
}
|
||||
return imgHint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
result, err := api.JdShopAPI.FindVendorCategories()
|
||||
for _, v := range result {
|
||||
cat := &model.SkuVendorCategory{
|
||||
VendorID: model.VendorIDJDShop,
|
||||
Name: v.Name,
|
||||
Level: v.Lev,
|
||||
VendorCategoryID: utils.Int2Str(v.ID),
|
||||
}
|
||||
if v.Lev > 1 {
|
||||
cat.ParentID = utils.Int2Str(v.Fid)
|
||||
cat.IsLeaf = 1
|
||||
}
|
||||
vendorCats = append(vendorCats, cat)
|
||||
}
|
||||
return vendorCats, err
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
KeyList []*Key
|
||||
)
|
||||
|
||||
type Key struct {
|
||||
ID string `json:"id"`
|
||||
KeyExp int64 `json:"key_exp"`
|
||||
KeyStatus int `json:"key_status"`
|
||||
KeyDigest string `json:"key_digest"`
|
||||
KeyType string `json:"key_type"`
|
||||
KeyString string `json:"key_string"`
|
||||
KeyEffective int64 `json:"key_effective"`
|
||||
Version int `json:"version"`
|
||||
}
|
||||
|
||||
func InitKey() {
|
||||
keyResult, err := api.JdShopAPI.KeyGet()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, v := range keyResult.Response.ServiceKeyList[0].Keys {
|
||||
data, _ := json.Marshal(v)
|
||||
vv := &Key{}
|
||||
err = json.Unmarshal(data, &vv)
|
||||
KeyList = append(KeyList, vv)
|
||||
}
|
||||
globals.SugarLogger.Debugf("jdshop key refreshed..")
|
||||
}
|
||||
|
||||
func GetKey(keySign string) (key string) {
|
||||
for _, v := range KeyList {
|
||||
data, _ := base64.StdEncoding.DecodeString(v.ID)
|
||||
if keySign == hex.EncodeToString(data) {
|
||||
return v.KeyString
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("no key can equal..")
|
||||
return key
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdshopapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := &jdshopapi.AllOrdersResult{}
|
||||
utils.Map2StructByJson(orderData, &result, false)
|
||||
jdsOrder := result.OrderList[0]
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: utils.Int64ToStr(jdsOrder.OrderID),
|
||||
VendorID: model.VendorIDJDShop,
|
||||
BaseFreightMoney: jxutils.StandardPrice2Int(jdsOrder.Freight),
|
||||
VendorStatus: utils.Int2Str(jdsOrder.OrderStatus),
|
||||
VendorUserID: jdsOrder.UserPin,
|
||||
BuyerComment: jdsOrder.UserRemark,
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
OriginalData: string(utils.MustMarshal(jdsOrder)),
|
||||
}
|
||||
return order
|
||||
}
|
||||
func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) {
|
||||
resultOrders, err := api.JdShopAPI.AllOrders(&jdshopapi.AllOrdersParam{
|
||||
OrderID: vendorOrderID,
|
||||
Current: 1,
|
||||
PageSize: 1,
|
||||
})
|
||||
return p.Map2Order(utils.Struct2FlatMap(resultOrders)), err
|
||||
}
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
jdsOrder, err := GetJdsOrder(vendorOrderID)
|
||||
return status2Jxstatus(jdsOrder.OrderState), err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
var status int
|
||||
if isAcceptIt {
|
||||
status = model.OrderStatusAccepted
|
||||
} else {
|
||||
status = model.OrderStatusCanceled
|
||||
}
|
||||
return ChangeOrderStatus(order.VendorOrderID, status, "")
|
||||
}
|
||||
func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
status, err := p.GetOrderStatus("", order.VendorOrderID2)
|
||||
//说明此时该订单在平台上已经取消了
|
||||
if status == model.OrderStatusCanceled {
|
||||
err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单在京东商城已被取消!")
|
||||
} else {
|
||||
err = ChangeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "自动拣货完成")
|
||||
err = p.OrderExport(jxcontext.AdminCtx, order.VendorOrderID, order.VendorOrderID, true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) {
|
||||
return err
|
||||
} // 取货失败后再次招唤平台配送
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) {
|
||||
return err
|
||||
} // 投递失败后确认收到退货
|
||||
func (p *PurchaseHandler) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) {
|
||||
return isCan, err
|
||||
}
|
||||
func (p *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
ChangeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "")
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
ChangeOrderStatus(order.VendorOrderID, model.OrderStatusFinished, "")
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
return mobile, err
|
||||
}
|
||||
func (p *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, reason)
|
||||
if order.EclpOutID != "" {
|
||||
_, err = api.JdEclpAPI.CancelOrder(order.EclpOutID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
func (p *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
var (
|
||||
db = dao.GetDB()
|
||||
diffShopPrice int64
|
||||
diffSalePrice int64
|
||||
)
|
||||
if order.Status >= model.OrderStatusDelivering {
|
||||
return fmt.Errorf("配送中以后的订单无法进行售前退款!")
|
||||
}
|
||||
//1、删除原order_sku 中售前调整的商品
|
||||
for _, sku := range removedSkuList {
|
||||
sql := `DELETE FROM order_sku WHERE vendor_order_id = ? AND vendor_id = ? AND sku_id = ?`
|
||||
sqlParams := []interface{}{order.VendorOrderID, order.VendorID, sku.SkuID}
|
||||
dao.ExecuteSQL(db, sql, sqlParams)
|
||||
|
||||
diffShopPrice += sku.ShopPrice
|
||||
diffSalePrice += sku.SalePrice
|
||||
}
|
||||
//2、修改goods_order 中的shopprice,若是扣点的订单,还要改new_earning_price和total_shop_money
|
||||
order.AdjustCount += 1
|
||||
order.ShopPrice = order.ShopPrice - diffShopPrice
|
||||
if order.EarningType == model.EarningTypePoints {
|
||||
order.TotalShopMoney = utils.Float64TwoInt64(float64(float64(order.TotalShopMoney)/jdshopapi.JdsPayPercentage-float64(diffSalePrice)) * jdshopapi.JdsPayPercentage)
|
||||
jxutils.RefreshOrderEarningPrice2(order, order.OrderPayPercentage)
|
||||
partner.CurOrderManager.UpdateOrderFields(order, []string{"TotalShopMoney", "NewEarningPrice"})
|
||||
}
|
||||
partner.CurOrderManager.UpdateOrderFields(order, []string{"AdjustCount", "ShopPrice"})
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetJdsOrders(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd string, current, pageSize int) (orderResult *jdshopapi.AllOrdersResult, err error) {
|
||||
orderResult, err = api.JdShopAPI.AllOrders(&jdshopapi.AllOrdersParam{
|
||||
Current: current,
|
||||
PageSize: pageSize,
|
||||
OrderCreateDateRange: []string{orderCreatedStart, orderCreatedEnd},
|
||||
})
|
||||
return orderResult, err
|
||||
}
|
||||
|
||||
func ChangeOrderStatus(vendorOrderID string, status int, remark string) (err error) {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: vendorOrderID,
|
||||
VendorID: model.VendorIDJDShop,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: vendorOrderID,
|
||||
RefVendorID: model.VendorIDJDShop,
|
||||
VendorStatus: utils.Int2Str(status),
|
||||
Status: status,
|
||||
StatusTime: time.Now(),
|
||||
Remark: remark,
|
||||
}
|
||||
jxutils.CallMsgHandlerAsync(func() {
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged("", orderStatus)
|
||||
}, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJDShop))
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OrderExport(ctx *jxcontext.Context, vendorOrderID, vendorWaybillID string, isAuto bool) (err error) {
|
||||
companyID := jdshopapi.JdsDeliveryCompany3rd
|
||||
//表示是门店手动发京东
|
||||
if !isAuto {
|
||||
companyID = jdshopapi.JdsDeliveryCompanyJD
|
||||
}
|
||||
err = api.JdShopAPI.OrderShipment(utils.Str2Int64(vendorOrderID[:12]), companyID, vendorWaybillID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OrderTransfer(ctx *jxcontext.Context, vendorOrderID, vendorWaybillID string, isAuto bool) (err error) {
|
||||
companyID := jdshopapi.JdsDeliveryCompany3rd
|
||||
//表示是门店手动发京东
|
||||
if !isAuto {
|
||||
companyID = jdshopapi.JdsDeliveryCompanyJD
|
||||
}
|
||||
err = api.JdShopAPI.UpdateWaybill(vendorOrderID[:12], companyID, vendorOrderID)
|
||||
return err
|
||||
}
|
||||
|
||||
func status2Jxstatus(status string) (statusJx int) {
|
||||
if status == jdshopapi.OrderStatusPopPause || status == jdshopapi.OrderStatusPause {
|
||||
statusJx = model.OrderStatusNew
|
||||
} else if status == jdshopapi.OrderStatusWait {
|
||||
statusJx = model.OrderStatusAccepted
|
||||
} else if status == jdshopapi.OrderStatusCancel {
|
||||
statusJx = model.OrderStatusCanceled
|
||||
}
|
||||
return statusJx
|
||||
}
|
||||
|
||||
const (
|
||||
ProdURL = "http://116.196.82.188:8080/v2/"
|
||||
)
|
||||
|
||||
func apiToYd(url string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
cl := &http.Client{}
|
||||
err = platformapi.AccessPlatformAPIWithRetry(cl,
|
||||
func() *http.Request {
|
||||
request, _ := http.NewRequest(http.MethodPost, ProdURL+url, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
return request
|
||||
},
|
||||
nil,
|
||||
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
if jsonResult1 == nil {
|
||||
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||
}
|
||||
if err == nil {
|
||||
if jsonResult1["code"] != nil {
|
||||
if utils.Interface2Int64WithDefault(jsonResult1["code"], 0) != 0 {
|
||||
errLevel = platformapi.ErrLevelGeneralFail
|
||||
err = utils.NewErrorCode(jsonResult1["desc"].(string), jsonResult1["code"].(string))
|
||||
baseapi.SugarLogger.Debugf("yd AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||
}
|
||||
}
|
||||
retVal = jsonResult1
|
||||
}
|
||||
return errLevel, err
|
||||
})
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func GetJdsOrder(vendorOrderID string) (jdsOrder *jdshopapi.GetOrderResult, err error) {
|
||||
params := make(map[string]interface{})
|
||||
params["orderID"] = vendorOrderID
|
||||
params["token"] = jdshopapi.JdsYdToken
|
||||
result, err := apiToYd("order/GetJdsOrder", params)
|
||||
jdsOrder2 := &jdshopapi.GetOrderResult{}
|
||||
err = utils.UnmarshalUseNumber([]byte(strings.ReplaceAll(result["data"].(string), "\\", "")), &jdsOrder2)
|
||||
return jdsOrder2, err
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, afsOrder *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
var status int
|
||||
if approveType == partner.AfsApproveTypeRefused {
|
||||
status = model.AfsOrderStatusFailed
|
||||
} else {
|
||||
status = model.AfsOrderStatusFinished
|
||||
|
||||
}
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: afsOrder.AfsOrderID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: afsOrder.VendorID,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: afsOrder.VendorOrderID,
|
||||
RefVendorID: afsOrder.VendorID,
|
||||
VendorStatus: utils.Int2Str(status),
|
||||
Status: status,
|
||||
StatusTime: time.Now(),
|
||||
Remark: reason,
|
||||
}
|
||||
partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
err = fmt.Errorf("京东商城当前不支持ConfirmReceivedReturnGoods")
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
err = c.PartRefundOrder(ctx, order, order.Skus, reason)
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
globals.SugarLogger.Debugf("PartRefundOrder jdshop, orderID :%v", order.VendorOrderID)
|
||||
var (
|
||||
skuMap = make(map[int]*model.OrderSku)
|
||||
salePrice int64
|
||||
db = dao.GetDB()
|
||||
)
|
||||
for _, sku := range order.Skus {
|
||||
skuMap[sku.SkuID] = sku
|
||||
}
|
||||
orderStatus := buildOrderStatus(ctx, order, reason)
|
||||
afsOrder := &model.AfsOrder{
|
||||
VendorID: order.VendorID,
|
||||
AfsOrderID: orderStatus.VendorOrderID,
|
||||
VendorOrderID: orderStatus.RefVendorOrderID,
|
||||
// VendorStoreID: order.VendorStoreID,
|
||||
// StoreID: jxutils.GetSaleStoreIDFromOrder(order),
|
||||
AfsCreatedAt: time.Now(),
|
||||
VendorAppealType: "",
|
||||
AppealType: model.AfsAppealTypeRefund,
|
||||
VendorReasonType: utils.Int2Str(model.AfsReasonNotOthers),
|
||||
ReasonType: model.AfsReasonNotOthers,
|
||||
ReasonDesc: utils.LimitUTF8StringLen(reason, 1024),
|
||||
ReasonImgList: "",
|
||||
RefundType: model.AfsTypePartRefund,
|
||||
|
||||
VendorOrgCode: "",
|
||||
}
|
||||
for _, sku := range refundSkuList {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
Count: sku.Count,
|
||||
VendorSkuID: utils.Int2Str(sku.SkuID),
|
||||
SkuID: sku.SkuID,
|
||||
}
|
||||
storeSkus, _ := dao.GetStoresSkusInfo(db, []int{model.JdShopMainStoreID}, []int{sku.SkuID})
|
||||
if len(storeSkus) > 0 {
|
||||
orderSku.VendorSkuID = utils.Int64ToStr(storeSkus[0].JdsID)
|
||||
}
|
||||
if skuMap[sku.SkuID] != nil {
|
||||
orderSku.Name = skuMap[sku.SkuID].SkuName
|
||||
orderSku.UserMoney = skuMap[sku.SkuID].SalePrice * int64(sku.Count)
|
||||
salePrice += skuMap[sku.SkuID].SalePrice * int64(sku.Count)
|
||||
}
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
|
||||
return err
|
||||
}
|
||||
|
||||
func buildOrderStatus(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (orderStatus *model.OrderStatus) {
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: utils.Int64ToStr(GenAfsOrderNo(ctx)), // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: order.VendorID,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: order.VendorOrderID,
|
||||
RefVendorID: order.VendorID,
|
||||
VendorStatus: utils.Int2Str(model.AfsOrderStatusWait4Approve),
|
||||
Status: model.AfsOrderStatusWait4Approve,
|
||||
StatusTime: time.Now(),
|
||||
Remark: reason,
|
||||
}
|
||||
orderStatus.Status = model.AfsOrderStatusWait4Approve
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func GenAfsOrderNo(ctx *jxcontext.Context) (orderNo int64) {
|
||||
const prefix = 70
|
||||
const randPartNum = 100
|
||||
orderNoBeginTimestamp := utils.Str2Time("2010-01-01 00:00:00").Unix()
|
||||
orderNo = time.Now().Unix() - orderNoBeginTimestamp
|
||||
orderNo = orderNo * randPartNum
|
||||
md5Bytes := md5.Sum([]byte(utils.GetUUID()))
|
||||
randPart := 0
|
||||
for k, v := range md5Bytes {
|
||||
randPart += int(v) << ((k % 3) * 8)
|
||||
}
|
||||
orderNo += int64(randPart % randPartNum)
|
||||
orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix
|
||||
return orderNo
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
func (c *PurchaseHandler) StartRefreshComment() {
|
||||
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdshopapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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/globals/api"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (storeDetail *dao.StoreDetail, err error) {
|
||||
// result, err := api.JdShopAPI.NewInfoList(utils.Str2Int64(vendorStoreID))
|
||||
// storeDetail.VendorStoreID = vendorStoreID
|
||||
// storeDetail.Status = JdsStatus2jxStatus(result.StoreStatus)
|
||||
result2, err := api.JdShopAPI.QueryEntityStore(utils.Str2Int64(vendorStoreID))
|
||||
if result2 == nil {
|
||||
return storeDetail, fmt.Errorf("未查询到该平台门店,平台门店ID:[%v]", vendorStoreID)
|
||||
}
|
||||
storeDetail = &dao.StoreDetail{}
|
||||
storeDetail.ID = utils.Str2Int(result2.ExStoreID)
|
||||
storeDetail.Name = result2.StoreName
|
||||
storeDetail.Address = result2.Address
|
||||
storeDetail.Tel1 = result2.Phone
|
||||
storeDetail.DistrictCode = result2.AddrCode
|
||||
zbs := strings.Split(result2.Coordinate, ",")
|
||||
storeDetail.Lat = jxutils.StandardCoordinate2Int(utils.Str2Float64(zbs[0]))
|
||||
storeDetail.Lng = jxutils.StandardCoordinate2Int(utils.Str2Float64(zbs[1]))
|
||||
return storeDetail, err
|
||||
}
|
||||
|
||||
// stoerIDs为nil表示所有
|
||||
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, _, err := jxutils.DownloadFileByURL(jdshopapi.JdsStoreImg)
|
||||
timeMap := map[string]string{
|
||||
"businessBeginTime": int2TimeStr(int(store.OpenTime1)),
|
||||
"businessEndTime": int2TimeStr(int(store.CloseTime1)),
|
||||
}
|
||||
timeJSON, _ := json.Marshal(timeMap)
|
||||
updateEntityStoreParam := &jdshopapi.UpdateEntityStoreParam{
|
||||
StoreID: utils.Str2Int(store.VendorStoreID),
|
||||
Name: store.Name,
|
||||
AddCode: store.JdsCode,
|
||||
AddCodeName: store.DistrictName,
|
||||
AddName: store.ProvinceName + store.CityName + store.DistrictName + "@!" + store.Address,
|
||||
Coordinate: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)),
|
||||
Phone: store.Tel1,
|
||||
ExtendJSON: string(timeJSON),
|
||||
ImageFile: base64.StdEncoding.EncodeToString(data),
|
||||
CustomerID: utils.Int2Str(store.ID),
|
||||
}
|
||||
if store.JdsStreetCode != 0 {
|
||||
updateEntityStoreParam.AddCode = store.JdsStreetCode
|
||||
}
|
||||
if updateEntityStoreParam.AddCode == 0 {
|
||||
updateEntityStoreParam.AddCode = store.JdCode
|
||||
}
|
||||
err = api.JdShopAPI.UpdateEntityStore(updateEntityStoreParam)
|
||||
if err == nil {
|
||||
// if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 {
|
||||
// mergeStatus := jxutils.MergeStoreStatus(store.Status, store.VendorStatus)
|
||||
// err = api.JdShopAPI.UpdateStoreStatus(utils.Str2Int(store.VendorStoreID), jxStatus2JdsStatus(mergeStatus))
|
||||
// }
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
|
||||
store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop)
|
||||
if err != nil {
|
||||
return vendorStoreID, err
|
||||
}
|
||||
data, _, err := jxutils.DownloadFileByURL(jdshopapi.JdsStoreImg)
|
||||
timeMap := map[string]string{
|
||||
"businessBeginTime": int2TimeStr(int(store.OpenTime1)),
|
||||
"businessEndTime": int2TimeStr(int(store.CloseTime1)),
|
||||
}
|
||||
timeJSON, _ := json.Marshal(timeMap)
|
||||
createEntityStoreParam := &jdshopapi.CreateEntityStoreParam{
|
||||
Name: store.Name,
|
||||
AddCode: store.JdsCode,
|
||||
AddCodeName: store.DistrictName,
|
||||
AddName: store.ProvinceName + store.CityName + store.DistrictName + "@!" + store.Address,
|
||||
Coordinate: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)) + "," + utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)),
|
||||
Phone: store.Tel1,
|
||||
ExtendJSON: string(timeJSON),
|
||||
ImageFile: base64.StdEncoding.EncodeToString(data),
|
||||
CategoryName: jdshopapi.JdsStoreCategoryName,
|
||||
CustomerID: utils.Int2Str(store.ID),
|
||||
}
|
||||
if store.JdsStreetCode != 0 {
|
||||
createEntityStoreParam.AddCode = store.JdsStreetCode
|
||||
}
|
||||
if createEntityStoreParam.AddCode == 0 {
|
||||
createEntityStoreParam.AddCode = store.JdCode
|
||||
}
|
||||
//证明这个店可能隶属直辖市或者东莞
|
||||
if model.ZXCityCodeMap[store.CityCode] != "" {
|
||||
result, _ := api.AutonaviAPI.GetCoordinateAreaInfo(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat))
|
||||
if result["regeocode"] != nil {
|
||||
street := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})["township"].(string)
|
||||
if street != "" {
|
||||
result1, _ := api.JdShopAPI.GetProvince()
|
||||
for _, v := range result1 {
|
||||
if strings.Contains(store.CityName, v.AreaName) {
|
||||
result2, _ := api.JdShopAPI.GetCity(v.AreaID)
|
||||
for _, vv := range result2 {
|
||||
if strings.Contains(store.DistrictName, vv.AreaName) {
|
||||
result3, _ := api.JdShopAPI.GetCounty(vv.AreaID)
|
||||
for _, vvv := range result3 {
|
||||
if street == vvv.AreaName {
|
||||
createEntityStoreParam.AddCode = vvv.AreaID
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vendorStoreID, err = api.JdShopAPI.CreateEntityStore(createEntityStoreParam)
|
||||
return vendorStoreID, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
// store, err := dao.GetStoreDetail(db, storeID, model.VendorIDJDShop)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err = api.JdShopAPI.DeleteStoresByID(utils.Str2Int64(store.VendorStoreID))
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
return storeStatus, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) {
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func int2TimeStr(time int) (str string) {
|
||||
str += utils.Int2Str(time / 1000)
|
||||
str += utils.Int2Str(time % 1000 / 100)
|
||||
str += ":"
|
||||
str += utils.Int2Str(time % 100 / 10)
|
||||
str += utils.Int2Str(time % 10)
|
||||
return str
|
||||
}
|
||||
|
||||
func jxStatus2JdsStatus(status int) (result int) {
|
||||
if status == model.StoreStatusOpened {
|
||||
result = jdshopapi.JdsStoreStatusOnline
|
||||
} else if status == model.StoreStatusHaveRest || status == model.StoreStatusClosed {
|
||||
result = jdshopapi.JdsStoreStatusRest
|
||||
} else {
|
||||
result = jdshopapi.JdsStoreStatusDisable
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func JdsStatus2jxStatus(status int) (result int) {
|
||||
if status == jdshopapi.JdsStoreStatusOnline {
|
||||
result = model.StoreStatusOpened
|
||||
} else if status == jdshopapi.JdsStoreStatusRest {
|
||||
result = model.StoreStatusClosed
|
||||
} else {
|
||||
result = model.StoreStatusDisabled
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,896 +0,0 @@
|
||||
package jdshop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdshopapi"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/yinbaoapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
const (
|
||||
deleteErr1 = "已经删除的不能直接下架"
|
||||
deleteErr2 = "SKU"
|
||||
deleteErr3 = "已删除"
|
||||
)
|
||||
|
||||
var (
|
||||
sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`)
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
for _, v := range storeSkuList {
|
||||
//判断京东商城上是否有这个商品了,如果有就是添加规格而不是创建商品
|
||||
name := filterSensitiveWord(v.Name)
|
||||
flag := false
|
||||
result, err := api.JdShopAPI.SearchWare4Valid(name, 1, 100)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品")
|
||||
return failedList, err
|
||||
}
|
||||
for _, v := range result.Data {
|
||||
if v.Title == name {
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if result.TotalItem > 0 && len(result.Data) > 0 && flag {
|
||||
for _, vv := range v.StoreSkuSyncInfoJds {
|
||||
v.JdsWareID = result.Data[0].WareID
|
||||
vv.JdsWareID = result.Data[0].WareID
|
||||
updateSkusParam, err := buildUpdateSkusParam(v, vv, true)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品")
|
||||
return failedList, err
|
||||
}
|
||||
vendorSkuID, err := api.JdShopAPI.UpdateSkus(updateSkusParam)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品")
|
||||
return failedList, err
|
||||
}
|
||||
vv.VendorSkuID = vendorSkuID
|
||||
}
|
||||
} else {
|
||||
createSkuParamWare, createSkuParamSkus, err := buildCreateWareParam(v)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品")
|
||||
return failedList, err
|
||||
}
|
||||
createSkuResult, err := api.JdShopAPI.CreateWare(createSkuParamWare, createSkuParamSkus)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "创建商品")
|
||||
return failedList, err
|
||||
} else {
|
||||
//追加商品透图
|
||||
imageURL := ""
|
||||
img := v.Img
|
||||
if img != "" {
|
||||
suffix := img[strings.LastIndex(img, "."):]
|
||||
if suffix != ".png" {
|
||||
if resBinary, _, _ := jxutils.DownloadFileByURL(img + model.SkuNameImgToPng); err == nil {
|
||||
downloadURL, _ := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix()))
|
||||
imageURL, _ = uploadImg(downloadURL, name, "tou")
|
||||
}
|
||||
} else {
|
||||
imageURL, _ = uploadImg(img, name, "tou")
|
||||
}
|
||||
}
|
||||
api.JdShopAPI.TransparentImageAdd(createSkuResult.WareID, imageURL)
|
||||
}
|
||||
var paramAttrs = make(map[string]*jdshopapi.CreateSkuParamSkus)
|
||||
var resultAttrs = make(map[string]int64)
|
||||
for _, vv := range createSkuParamSkus {
|
||||
for _, vvv := range vv.SaleAttrs {
|
||||
paramAttrs[vvv.AttrValues[0]] = vv
|
||||
}
|
||||
}
|
||||
for _, vv1 := range createSkuResult.Skus {
|
||||
for _, vvv1 := range vv1.SaleAttrs {
|
||||
if paramAttrs[vvv1.AttrValues[0]] != nil {
|
||||
resultAttrs[paramAttrs[vvv1.AttrValues[0]].OuterID] = vv1.SkuID
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, vv2 := range v.StoreSkuSyncInfoJds {
|
||||
vv2.JdsWareID = createSkuResult.WareID
|
||||
if resultAttrs[utils.Int2Str(vv2.SkuID)] != 0 {
|
||||
vv2.VendorSkuID = utils.Int64ToStr(resultAttrs[utils.Int2Str(vv2.SkuID)])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
for _, v := range storeSkuList {
|
||||
name := filterSensitiveWord(v.Name)
|
||||
updateWareParam := &jdshopapi.UpdateWareParam{
|
||||
WareID: v.JdsWareID,
|
||||
Title: name,
|
||||
VenderID: jdshopapi.VenderID,
|
||||
// PromiseID: jdshopapi.JdsPromiseID,
|
||||
ShopCategorys: []int{utils.Str2Int(v.VendorCatID)},
|
||||
JdPrice: jxutils.IntPrice2Standard(v.UnitPrice),
|
||||
}
|
||||
if v.VendorVendorCatID != jdshopapi.JdsOtherMeatCatID {
|
||||
updateWareParam.PromiseID = jdshopapi.JdsPromiseID
|
||||
}
|
||||
var desc string
|
||||
if v.DescImg != "" {
|
||||
pic3, err2 := uploadImg2(v.DescImg, name, "desc")
|
||||
err = err2
|
||||
desc = `<p><img src="` + jdshopapi.JdsImgURL + pic3 + `" style="width: auto; height: auto; max-width: 100%;"><br></p><p><br></p>`
|
||||
} else {
|
||||
desc = `<p><br></p><p><br></p>`
|
||||
}
|
||||
updateWareParam.Introduction = desc
|
||||
updateWareParam.MobileDesc = desc
|
||||
img := ""
|
||||
if v.ImgMix != "" {
|
||||
img = v.ImgMix
|
||||
} else {
|
||||
img = v.Img
|
||||
}
|
||||
if img != "" {
|
||||
pic1, err2 := uploadImg2(img, name, "1")
|
||||
err = err2
|
||||
err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 1, pic1)
|
||||
if v.Img2 != "" {
|
||||
pic2, err2 := uploadImg2(v.Img2, name, "2")
|
||||
err = err2
|
||||
err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 2, pic2)
|
||||
} else {
|
||||
err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 2, pic1)
|
||||
}
|
||||
err = api.JdShopAPI.ImageUpdate(v.JdsWareID, 3, pic1)
|
||||
}
|
||||
var features = []*jdshopapi.CreateSkuParamFeatures{
|
||||
&jdshopapi.CreateSkuParamFeatures{
|
||||
Key: "is7ToReturn", //不支持7天无理由退货
|
||||
Value: "0",
|
||||
},
|
||||
&jdshopapi.CreateSkuParamFeatures{
|
||||
Key: "tssp", //支持自提
|
||||
Value: "",
|
||||
},
|
||||
// &jdshopapi.CreateSkuParamFeatures{
|
||||
// Key: "fdms", //分单?
|
||||
// Value: "1",
|
||||
// },
|
||||
}
|
||||
updateWareParam.Features = features
|
||||
err = api.JdShopAPI.UpdateWare(updateWareParam)
|
||||
if err == nil {
|
||||
//追加商品透图
|
||||
imageURL := ""
|
||||
img := v.Img
|
||||
if img != "" {
|
||||
suffix := img[strings.LastIndex(img, "."):]
|
||||
if suffix != ".png" {
|
||||
if resBinary, _, err := jxutils.DownloadFileByURL(img + model.SkuNameImgToPng); err == nil {
|
||||
downloadURL, err2 := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix()))
|
||||
err = err2
|
||||
imageURL, err = uploadImg(downloadURL, name, "tou")
|
||||
}
|
||||
} else {
|
||||
imageURL, err = uploadImg(img, name, "tou")
|
||||
}
|
||||
}
|
||||
api.JdShopAPI.TransparentImageAdd(v.JdsWareID, imageURL)
|
||||
}
|
||||
for _, vv := range v.StoreSkuSyncInfoJds {
|
||||
updateSkusParam, err := buildUpdateSkusParam(v, vv, false)
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "更新商品基础信息")
|
||||
return failedList, err
|
||||
}
|
||||
_, err = api.JdShopAPI.UpdateSkus(updateSkusParam)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "更新商品基础信息")
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
for _, v := range storeSkuList {
|
||||
if v.IsDeletedBySku {
|
||||
err = api.JdShopAPI.DeleteSku(utils.Str2Int64(v.VendorSkuID))
|
||||
} else {
|
||||
err = api.JdShopAPI.UpOrDown(utils.Str2Int64(v.VendorSkuID2), 2)
|
||||
if err == nil {
|
||||
err = api.JdShopAPI.DeleteWare(utils.Str2Int(v.VendorSkuID2))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "删除商品")...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) {
|
||||
var (
|
||||
pageNo = 1
|
||||
pageSize = 20
|
||||
)
|
||||
_, totalCount, err := api.JdShopAPI.SearchSkuList(pageNo, pageSize)
|
||||
for ; pageNo <= totalCount/pageSize+1; pageNo++ {
|
||||
result, _, err := api.JdShopAPI.SearchSkuList(pageNo, pageSize)
|
||||
if err == nil {
|
||||
for _, v := range result {
|
||||
if skuName := vendorSku2Jx(v); skuName != nil {
|
||||
skuNameList = append(skuNameList, skuName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return skuNameList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite {
|
||||
var stock = 0
|
||||
for _, v := range storeSkuList {
|
||||
if storeID == model.JdShopMainStoreID {
|
||||
if status == model.SkuStatusNormal {
|
||||
stock = 9999
|
||||
}
|
||||
if v.JdsStockSwitch == model.NO {
|
||||
stock = 0
|
||||
}
|
||||
err = api.JdShopAPI.UpdateSkuStock(utils.Str2Int(v.VendorSkuID), stock)
|
||||
} else {
|
||||
storeSkus, err2 := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.JdShopMainStoreID}, []int{v.SkuID})
|
||||
err = err2
|
||||
if len(storeSkus) > 0 {
|
||||
if storeSkus[0].JdsID != 0 && vendorStoreID != "" {
|
||||
if storeSkus[0].Status == model.SkuStatusNormal {
|
||||
stock = 9999
|
||||
}
|
||||
err = api.JdShopAPI.UpdateSkuSiteStock(storeSkus[0].JdsID, stock, utils.Str2Int(vendorStoreID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品库存")
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
for _, v := range storeSkuList {
|
||||
err = api.JdShopAPI.UpdateSkuJdPrice(utils.Str2Int(v.VendorSkuID), jxutils.IntPrice2Standard(v.VendorPrice))
|
||||
if err != nil {
|
||||
failedList = append(failedList, putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJDShop], "修改商品价格")...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableJdShopWrite {
|
||||
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) {
|
||||
result, err := api.JdShopAPI.FindShopCategories()
|
||||
for _, v := range result {
|
||||
var cat = &partner.BareCategoryInfo{
|
||||
VendorCatID: utils.Int64ToStr(v.CID),
|
||||
Name: v.Name,
|
||||
}
|
||||
if v.ParentCID == 0 {
|
||||
cat.Level = 1
|
||||
} else {
|
||||
cat.Level = 2
|
||||
}
|
||||
cats = append(cats, cat)
|
||||
}
|
||||
return cats, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
status, err2 := updateOrCreateCategories(storeCat, true)
|
||||
err = err2
|
||||
if status == -1 {
|
||||
return fmt.Errorf("京东商城店内分类创建失败!")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
// flag := false
|
||||
// for {
|
||||
result, err := api.JdShopAPI.FindShopCategories()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range result {
|
||||
if v.Name == storeCat.Name {
|
||||
storeCat.VendorCatID = utils.Int64ToStr(v.CID)
|
||||
// flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if storeCat.VendorCatID == "" {
|
||||
return fmt.Errorf("京东商城店内分类创建可能失败了!storeID: %v", storeID)
|
||||
}
|
||||
// if flag {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
status, err2 := updateOrCreateCategories(storeCat, false)
|
||||
err = err2
|
||||
if status == -1 {
|
||||
return fmt.Errorf("京东商城店内分类更新失败!")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) {
|
||||
if globals.EnableJdShopWrite && vendorStoreID == model.JdShopMainVendorStoreID {
|
||||
_, err = api.JdShopAPI.DeleteShopCategory(utils.Str2Int64(vendorCatID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp {
|
||||
return sensitiveWordRegexp
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
|
||||
if strings.Contains(err.Error(), deleteErr1) || (strings.Contains(err.Error(), deleteErr2) && strings.Contains(err.Error(), deleteErr3)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ybSkuStatus2Jx(ybStatus int) (jxSkuStatus int) {
|
||||
if ybStatus == yinbaoapi.SkuStatusEnable {
|
||||
jxSkuStatus = model.SkuStatusNormal
|
||||
} else if ybStatus == yinbaoapi.SkuStatusDisabled {
|
||||
jxSkuStatus = model.SkuStatusDontSale
|
||||
} else if ybStatus == yinbaoapi.SkuStatusDeleted {
|
||||
jxSkuStatus = model.SkuStatusDeleted
|
||||
}
|
||||
return jxSkuStatus
|
||||
}
|
||||
|
||||
func vendorSku2Jx(result *jdshopapi.SearchSkuListResult) (skuName *partner.SkuNameInfo) {
|
||||
if result == nil {
|
||||
globals.SugarLogger.Warnf("vendorSku2Jx, strange result:%s", utils.Format4Output(result, true))
|
||||
return nil
|
||||
}
|
||||
skuName = &partner.SkuNameInfo{
|
||||
VendorNameID: utils.Int64ToStr(result.WareID),
|
||||
SkuList: []*partner.SkuInfo{
|
||||
&partner.SkuInfo{
|
||||
StoreSkuInfo: partner.StoreSkuInfo{
|
||||
SkuID: utils.Str2Int(result.OuterID),
|
||||
VendorSkuID: utils.Int64ToStr(result.SkuID),
|
||||
VendorNameID: utils.Int64ToStr(result.WareID),
|
||||
Stock: result.StockNum,
|
||||
VendorPrice: utils.Float64TwoInt64(result.JdPrice * 100),
|
||||
},
|
||||
Comment: result.SaleAttrs[0].AttrValueAlias[0],
|
||||
},
|
||||
},
|
||||
}
|
||||
return skuName
|
||||
}
|
||||
|
||||
func updateOrCreateCategories(storeCat *dao.SkuStoreCatInfo, isCreate bool) (status int64, err error) {
|
||||
var createShopCategoryParams []*jdshopapi.CreateShopCategoryParam
|
||||
result, err := api.JdShopAPI.FindShopCategories()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
for _, v := range result {
|
||||
createShopCategoryParam := &jdshopapi.CreateShopCategoryParam{
|
||||
HomeShow: "0",
|
||||
ID: utils.Int64ToStr(v.CID),
|
||||
Open: "",
|
||||
OrderNo: utils.Int2Str(v.OrderNo),
|
||||
ParentID: utils.Int64ToStr(v.ParentCID),
|
||||
Title: v.Name,
|
||||
Type: jdshopapi.UpdateCatType,
|
||||
}
|
||||
createShopCategoryParams = append(createShopCategoryParams, createShopCategoryParam)
|
||||
}
|
||||
createShopCategoryParam2 := &jdshopapi.CreateShopCategoryParam{
|
||||
HomeShow: "0",
|
||||
Open: "",
|
||||
OrderNo: utils.Int2Str(storeCat.Seq),
|
||||
ParentID: storeCat.ParentVendorCatID,
|
||||
Title: storeCat.Name,
|
||||
}
|
||||
if isCreate {
|
||||
createShopCategoryParam2.Type = jdshopapi.CreateCatType
|
||||
createShopCategoryParam2.ID = "1"
|
||||
createShopCategoryParams = append(createShopCategoryParams, createShopCategoryParam2)
|
||||
} else {
|
||||
for _, v := range createShopCategoryParams {
|
||||
if v.ID == storeCat.VendorCatID {
|
||||
v.Title = createShopCategoryParam2.Title
|
||||
v.OrderNo = createShopCategoryParam2.OrderNo
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err = api.JdShopAPI.CreateShopCategory(createShopCategoryParams)
|
||||
return status, err
|
||||
}
|
||||
|
||||
func buildCreateWareParam(storeSku *dao.StoreSkuSyncInfo) (createSkuParamWare *jdshopapi.CreateSkuParamWare, createSkuParamSkus []*jdshopapi.CreateSkuParamSkus, err error) {
|
||||
var (
|
||||
images []*jdshopapi.CreateSkuParamImages
|
||||
vendorCatID int
|
||||
)
|
||||
if storeSku.VendorCatID == "0" {
|
||||
resultCat, _ := api.JdShopAPI.FindShopCategories()
|
||||
for _, v := range resultCat {
|
||||
if v.Name == storeSku.CategoryName {
|
||||
vendorCatID = int(v.CID)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vendorCatID = utils.Str2Int(storeSku.VendorCatID)
|
||||
}
|
||||
name := filterSensitiveWord(storeSku.Name)
|
||||
createSkuParamWare = &jdshopapi.CreateSkuParamWare{
|
||||
Title: name,
|
||||
ShopCategorys: []int{vendorCatID},
|
||||
CategoryID: int(storeSku.VendorVendorCatID),
|
||||
BrandID: jdshopapi.JxBrandId,
|
||||
// TransportID: jdshopapi.TransportID,
|
||||
WareStatus: 8, //上架待审核
|
||||
OuterID: utils.Int2Str(storeSku.NameID),
|
||||
VenderID: jdshopapi.VenderID,
|
||||
Length: 100,
|
||||
Width: 100,
|
||||
Height: 100,
|
||||
Weight: 0.5,
|
||||
JdPrice: jxutils.IntPrice2Standard(storeSku.UnitPrice),
|
||||
// MarketPrice: jxutils.IntPrice2Standard(storeSku.UnitPrice),
|
||||
// PromiseID: jdshopapi.JdsPromiseID,
|
||||
}
|
||||
|
||||
if storeSku.VendorVendorCatID != jdshopapi.JdsOtherMeatCatID {
|
||||
createSkuParamWare.PromiseID = jdshopapi.JdsPromiseID
|
||||
}
|
||||
|
||||
if storeSku.VendorVendorCatID == jdshopapi.JdsBeefCatID {
|
||||
createSkuParamWare.MultiCategoryID = jdshopapi.JdsBeefLastCatID
|
||||
}
|
||||
|
||||
//上传京东图片
|
||||
//规则,有两张就传两张,没有就重复传一张
|
||||
pic1, err := uploadImg(storeSku.Img, name, "1")
|
||||
img1 := &jdshopapi.CreateSkuParamImages{
|
||||
ColorID: "0000000000",
|
||||
ImgIndex: 1,
|
||||
ImgURL: pic1,
|
||||
}
|
||||
img2 := &jdshopapi.CreateSkuParamImages{
|
||||
ColorID: "0000000000",
|
||||
ImgIndex: 2,
|
||||
}
|
||||
if storeSku.Img2 == "" {
|
||||
img2.ImgURL = pic1
|
||||
} else {
|
||||
pic2, err2 := uploadImg(storeSku.Img, name, "2")
|
||||
err = err2
|
||||
img2.ImgURL = pic2
|
||||
}
|
||||
img3 := &jdshopapi.CreateSkuParamImages{
|
||||
ColorID: "0000000000",
|
||||
ImgIndex: 3,
|
||||
ImgURL: pic1,
|
||||
}
|
||||
images = append(images, img1)
|
||||
images = append(images, img2)
|
||||
images = append(images, img3)
|
||||
createSkuParamWare.Images = images
|
||||
//商品详情拼接
|
||||
var desc string
|
||||
if storeSku.DescImg != "" {
|
||||
pic3, err2 := uploadImg(storeSku.DescImg, name, "desc")
|
||||
err = err2
|
||||
desc = `<p><img src="` + jdshopapi.JdsImgURL + pic3 + `" style="width: auto; height: auto; max-width: 100%;"><br></p><p><br></p>`
|
||||
} else {
|
||||
desc = `<p><br></p><p><br></p>`
|
||||
}
|
||||
createSkuParamWare.MobileDesc = desc
|
||||
createSkuParamWare.Introduction = desc
|
||||
|
||||
//设置商品属性值
|
||||
var (
|
||||
attrIDs = make(map[string]int) //贮存方式,净含量,保质期IDs
|
||||
zctjValueID int64 //贮存条件冷藏0-4的id
|
||||
gcjkValueID int64 //国产,进口的id
|
||||
lbValueID int64 //类别的ID
|
||||
bcztValueID int64 //保存状态ID
|
||||
rmsjValueID int64 //热卖时间ID
|
||||
attrsProp []*jdshopapi.CreateSkuParamAttrs
|
||||
)
|
||||
attrs, err := api.JdShopAPI.FindAttrs(int(storeSku.VendorVendorCatID))
|
||||
for _, v := range attrs {
|
||||
if v.Name == "保质期" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "贮存条件" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "净含量" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "规格" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "国产/进口" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "类别" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "保存状态" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "热卖时间" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
}
|
||||
}
|
||||
values, _, err := api.JdShopAPI.FindValuesByAttrId(attrIDs["贮存条件"])
|
||||
for _, v := range values {
|
||||
if v.Name == "冷藏 0-4℃" {
|
||||
zctjValueID = v.ID
|
||||
}
|
||||
}
|
||||
if attrIDs["国产/进口"] != 0 {
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["国产/进口"])
|
||||
err = err2
|
||||
for _, v := range values2 {
|
||||
if v.Name == "国产" {
|
||||
gcjkValueID = v.ID
|
||||
}
|
||||
}
|
||||
attrgcjk := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["国产/进口"]),
|
||||
AttrValues: []string{utils.Int64ToStr(gcjkValueID)},
|
||||
}
|
||||
attrsProp = append(attrsProp, attrgcjk)
|
||||
}
|
||||
if attrIDs["保存状态"] != 0 {
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["保存状态"])
|
||||
err = err2
|
||||
for _, v := range values2 {
|
||||
if v.Name == "冷藏" || v.Name == "活鲜" {
|
||||
bcztValueID = v.ID
|
||||
}
|
||||
}
|
||||
attrbczt := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["保存状态"]),
|
||||
AttrValues: []string{utils.Int64ToStr(bcztValueID)},
|
||||
}
|
||||
attrsProp = append(attrsProp, attrbczt)
|
||||
}
|
||||
if attrIDs["热卖时间"] != 0 {
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["热卖时间"])
|
||||
err = err2
|
||||
for _, v := range values2 {
|
||||
if v.Name == "12月" {
|
||||
rmsjValueID = v.ID
|
||||
}
|
||||
}
|
||||
attrrmsj := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["热卖时间"]),
|
||||
AttrValues: []string{utils.Int64ToStr(rmsjValueID)},
|
||||
}
|
||||
attrsProp = append(attrsProp, attrrmsj)
|
||||
}
|
||||
if storeSku.VendorVendorCatID == jdshopapi.JdsBeefCatID {
|
||||
var exValueID int64
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(150390)
|
||||
err = err2
|
||||
for _, v := range values2 {
|
||||
if v.Name == "其它" {
|
||||
exValueID = v.ID
|
||||
}
|
||||
}
|
||||
attrex := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(150390),
|
||||
AttrValues: []string{utils.Int64ToStr(exValueID)},
|
||||
}
|
||||
attrsProp = append(attrsProp, attrex)
|
||||
}
|
||||
attrZctj := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["贮存条件"]),
|
||||
AttrValues: []string{utils.Int64ToStr(zctjValueID)},
|
||||
}
|
||||
attrJhl := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["净含量"]),
|
||||
AttrValues: []string{"0.5"},
|
||||
}
|
||||
attrBzq := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["保质期"]),
|
||||
AttrValues: []string{"5"},
|
||||
}
|
||||
attrsProp = append(attrsProp, attrZctj)
|
||||
attrsProp = append(attrsProp, attrJhl)
|
||||
attrsProp = append(attrsProp, attrBzq)
|
||||
createSkuParamWare.MultiCateProps = attrsProp
|
||||
var features = []*jdshopapi.CreateSkuParamFeatures{
|
||||
&jdshopapi.CreateSkuParamFeatures{
|
||||
Key: "is7ToReturn", //不支持7天无理由退货
|
||||
Value: "0",
|
||||
},
|
||||
&jdshopapi.CreateSkuParamFeatures{
|
||||
Key: "tssp", //支持自提
|
||||
Value: "",
|
||||
},
|
||||
// &jdshopapi.CreateSkuParamFeatures{
|
||||
// Key: "fdms", //分单?
|
||||
// Value: "1",
|
||||
// },
|
||||
}
|
||||
createSkuParamWare.Features = features
|
||||
//组合sku
|
||||
var vendorPrice int64 = 0
|
||||
for _, v := range storeSku.StoreSkuSyncInfoJds {
|
||||
var (
|
||||
ggValueID int64 //规格的属性id
|
||||
attrsPropSku []*jdshopapi.CreateSkuParamAttrs
|
||||
multiPropSku []*jdshopapi.CreateSkuParamAttrs
|
||||
specQuality string
|
||||
)
|
||||
valuesSku, maxNo, _ := api.JdShopAPI.FindValuesByAttrId(attrIDs["规格"])
|
||||
if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] {
|
||||
specQuality = strings.TrimRight(fmt.Sprintf("%.2f", float64(v.SpecQuality)), "0.") + v.SpecUnit
|
||||
} else {
|
||||
specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit
|
||||
}
|
||||
if v.Comment != "" {
|
||||
specQuality = v.Comment
|
||||
}
|
||||
for _, v := range valuesSku {
|
||||
if v.Name == specQuality {
|
||||
ggValueID = v.ID
|
||||
}
|
||||
}
|
||||
if ggValueID == 0 { //说明没有建这个规格,要建上
|
||||
catID, _ := api.JdShopAPI.SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1)
|
||||
ggValueID = catID
|
||||
}
|
||||
attrSku := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["规格"]),
|
||||
AttrValues: []string{utils.Int64ToStr(ggValueID)},
|
||||
}
|
||||
attrsPropSku = append(attrsPropSku, attrSku)
|
||||
sku := &jdshopapi.CreateSkuParamSkus{
|
||||
JdPrice: jxutils.IntPrice2Standard(v.VendorPrice),
|
||||
// StockNum: 9999,
|
||||
Type: "com.jd.pop.ware.ic.api.domain.sku",
|
||||
Type2: "com.jd.pop.ware.ic.api.domain.Sku",
|
||||
OuterID: utils.Int2Str(v.SkuID),
|
||||
}
|
||||
sku.SaleAttrs = attrsPropSku
|
||||
if attrIDs["类别"] != 0 {
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["类别"])
|
||||
err = err2
|
||||
lbValueID = values2[len(values2)-1].ID
|
||||
attrlb := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["类别"]),
|
||||
AttrValues: []string{utils.Int64ToStr(lbValueID)},
|
||||
}
|
||||
multiPropSku = append(multiPropSku, attrlb)
|
||||
}
|
||||
sku.MultiCateProps = multiPropSku
|
||||
createSkuParamSkus = append(createSkuParamSkus, sku)
|
||||
|
||||
if v.VendorPrice > vendorPrice {
|
||||
vendorPrice = v.VendorPrice
|
||||
}
|
||||
if v.Status == model.SkuStatusNormal {
|
||||
sku.StockNum = 9999
|
||||
} else {
|
||||
sku.StockNum = 0
|
||||
}
|
||||
}
|
||||
//市场价固定500
|
||||
createSkuParamWare.MarketPrice = 500
|
||||
return createSkuParamWare, createSkuParamSkus, err
|
||||
}
|
||||
|
||||
//京东商城上传图片,若平台上已经有了这个图就直接拿来用了
|
||||
func uploadImg(img, name, index string) (imgURL string, err error) {
|
||||
result, err := api.JdShopAPI.QueryPicture(name + index)
|
||||
if len(result) > 0 {
|
||||
imgURL = result[0].PictureURL
|
||||
} else {
|
||||
data, _, err := jxutils.DownloadFileByURL(img)
|
||||
if err != nil {
|
||||
return imgURL, err
|
||||
}
|
||||
uploadResult, err := api.JdShopAPI.UploadPicture(data, 0, name+index)
|
||||
if err != nil {
|
||||
return imgURL, err
|
||||
}
|
||||
imgURL = uploadResult.PictureURL
|
||||
}
|
||||
return imgURL, err
|
||||
}
|
||||
|
||||
func uploadImg2(img, name, index string) (imgURL string, err error) {
|
||||
data, _, err := jxutils.DownloadFileByURL(img)
|
||||
if err != nil {
|
||||
return imgURL, err
|
||||
}
|
||||
uploadResult, err := api.JdShopAPI.UploadPicture(data, 0, name+index)
|
||||
if err != nil {
|
||||
return imgURL, err
|
||||
}
|
||||
imgURL = uploadResult.PictureURL
|
||||
return imgURL, err
|
||||
}
|
||||
|
||||
func filterSensitiveWord(name string) (result string) {
|
||||
for _, v := range jdshopapi.SensitiveWordMap {
|
||||
if strings.Contains(name, v) {
|
||||
return strings.ReplaceAll(name, v, "")
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func buildUpdateSkusParam(storeSku *dao.StoreSkuSyncInfo, v *dao.StoreSkuSyncInfo, isCreate bool) (updateSkusParam *jdshopapi.UpdateSkusParam, err error) {
|
||||
var (
|
||||
ggValueID int64 //规格的属性id
|
||||
attrsPropSku []*jdshopapi.CreateSkuParamAttrs
|
||||
skus []*jdshopapi.UpdateSkusParamSkus
|
||||
multiPropSku []*jdshopapi.CreateSkuParamAttrs
|
||||
specQuality string
|
||||
)
|
||||
updateSkusParam = &jdshopapi.UpdateSkusParam{
|
||||
WareID: storeSku.JdsWareID,
|
||||
}
|
||||
sku := &jdshopapi.UpdateSkusParamSkus{
|
||||
WareID: storeSku.JdsWareID,
|
||||
JdPrice: jxutils.IntPrice2Standard(v.VendorPrice),
|
||||
Type: "com.jd.pop.ware.ic.api.domain.sku",
|
||||
Type2: "com.jd.pop.ware.ic.api.domain.Sku",
|
||||
OuterID: utils.Int2Str(v.SkuID),
|
||||
}
|
||||
//库存设置
|
||||
if v.StoreSkuStatus == model.SkuStatusNormal {
|
||||
sku.StockNum = "9999"
|
||||
} else {
|
||||
sku.StockNum = "0"
|
||||
}
|
||||
//规格类别设置
|
||||
attrIDs := make(map[string]int)
|
||||
attrs, err := api.JdShopAPI.FindAttrs(int(storeSku.VendorVendorCatID))
|
||||
for _, v := range attrs {
|
||||
if v.Name == "规格" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
} else if v.Name == "类别" {
|
||||
attrIDs[v.Name] = v.ID
|
||||
}
|
||||
}
|
||||
if attrIDs["类别"] != 0 {
|
||||
values2, _, err2 := api.JdShopAPI.FindValuesByAttrId(attrIDs["类别"])
|
||||
err = err2
|
||||
lbValueID := values2[len(values2)-1].ID
|
||||
attrlb := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["类别"]),
|
||||
AttrValues: []string{utils.Int64ToStr(lbValueID)},
|
||||
}
|
||||
multiPropSku = append(multiPropSku, attrlb)
|
||||
}
|
||||
sku.MultiCateProps = multiPropSku
|
||||
if v.SpecUnit == model.SpecUnitNames[1] || v.SpecUnit == model.SpecUnitNames[2] {
|
||||
if math.Mod(float64(v.SpecQuality), 10) != 0 {
|
||||
specQuality = strings.TrimRight(fmt.Sprintf("%.2f", float64(v.SpecQuality)), "0.") + v.SpecUnit
|
||||
} else {
|
||||
specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit
|
||||
}
|
||||
} else {
|
||||
specQuality = utils.Float64ToStr(float64(v.SpecQuality)) + v.SpecUnit
|
||||
}
|
||||
valuesSku, maxNo, _ := api.JdShopAPI.FindValuesByAttrId(attrIDs["规格"])
|
||||
if isCreate {
|
||||
for _, vv := range valuesSku {
|
||||
if vv.Name == specQuality {
|
||||
ggValueID = vv.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
if ggValueID == 0 { //说明没有建这个规格,要建上
|
||||
catID, _ := api.JdShopAPI.SaveVenderAttrValue(specQuality, attrIDs["规格"], int(storeSku.VendorVendorCatID), maxNo+1)
|
||||
ggValueID = catID
|
||||
}
|
||||
attrSku := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: utils.Int2Str(attrIDs["规格"]),
|
||||
AttrValues: []string{utils.Int64ToStr(ggValueID)},
|
||||
}
|
||||
attrsPropSku = append(attrsPropSku, attrSku)
|
||||
sku.SaleAttrs = attrsPropSku
|
||||
} else {
|
||||
vendorSku, err2 := api.JdShopAPI.FindSkuById(utils.Str2Int64(v.VendorSkuID))
|
||||
err = err2
|
||||
vendorAttrValue := vendorSku.SaleAttrs[0].AttrValueAlias[0]
|
||||
if v.Comment != "" {
|
||||
specQuality = v.Comment
|
||||
}
|
||||
if v.Comment != vendorAttrValue {
|
||||
err = api.JdShopAPI.UpdateWareSaleAttrvalueAlias(&jdshopapi.UpdateWareSaleAttrvalueAliasParam{
|
||||
WareID: v.JdsWareID,
|
||||
Props: []*jdshopapi.CreateSkuParamAttrs2{
|
||||
&jdshopapi.CreateSkuParamAttrs2{
|
||||
AttrID: vendorSku.SaleAttrs[0].AttrID,
|
||||
AttrValues: []string{vendorSku.SaleAttrs[0].AttrValues[0]},
|
||||
AttrValueAlias: []string{specQuality},
|
||||
Type: "com.jd.pop.ware.ic.api.domain.prop",
|
||||
Type2: "com.jd.pop.ware.ic.api.domain.Prop",
|
||||
},
|
||||
},
|
||||
})
|
||||
sku.SkuID = utils.Str2Int64(v.VendorSkuID)
|
||||
}
|
||||
attrSku := &jdshopapi.CreateSkuParamAttrs{
|
||||
AttrID: vendorSku.SaleAttrs[0].AttrID,
|
||||
AttrValues: []string{vendorSku.SaleAttrs[0].AttrValues[0]},
|
||||
}
|
||||
attrsPropSku = append(attrsPropSku, attrSku)
|
||||
sku.SaleAttrs = attrsPropSku
|
||||
}
|
||||
skus = append(skus, sku)
|
||||
updateSkusParam.Skus = skus
|
||||
return updateSkusParam, err
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
}
|
||||
|
||||
var (
|
||||
CurPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
func init() {
|
||||
globals.SugarLogger.Debug("init jx")
|
||||
if true {
|
||||
CurPurchaseHandler = new(PurchaseHandler)
|
||||
// 不能注册京西
|
||||
// partner.RegisterPurchasePlatform(CurPurchaseHandler)
|
||||
partner.RegisterPurchaseOrderHandler(CurPurchaseHandler.GetVendorID(), CurPurchaseHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDJX
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
return imgHint, err
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
package localjx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestGenOrderNo(t *testing.T) {
|
||||
orderNo := GenOrderNo(jxcontext.AdminCtx)
|
||||
t.Log(orderNo)
|
||||
}
|
||||
|
||||
func TestGetAvailableDeliverTime(t *testing.T) {
|
||||
timeInfo, err := GetAvailableDeliverTime(jxcontext.AdminCtx, 100118)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(timeInfo, false))
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package localjx
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/tonglianpayapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func pay4OrderByTL(ctx *jxcontext.Context, order *model.GoodsOrder, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) {
|
||||
// if order.FromStoreID != 0 {
|
||||
// result, _ := orderman.GetMatterStoreOrderCount(nil, order.FromStoreID)
|
||||
// if !result.Flag {
|
||||
// return nil, fmt.Errorf("该门店[%v]已在一周内申请过物料,请勿重复申请!", order.FromStoreID)
|
||||
// }
|
||||
// }
|
||||
payCreatedAt := time.Now()
|
||||
param := &tonglianpayapi.CreateUnitorderOrderParam{
|
||||
Trxamt: int(order.ActualPayPrice),
|
||||
NotifyUrl: globals.TLPayNotifyURL,
|
||||
Reqsn: order.VendorOrderID,
|
||||
PayType: vendorPayType,
|
||||
}
|
||||
//暂时做兼容处理
|
||||
if vendorPayType == "JSAPI" {
|
||||
param.PayType = tonglianpayapi.PayTypeWxXcx
|
||||
}
|
||||
if vendorPayType == tonglianpayapi.PayTypeWxXcx {
|
||||
if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini {
|
||||
param.Acct = authInfo.GetAuthID()
|
||||
}
|
||||
}
|
||||
if vendorPayType == tonglianpayapi.PayTypeH5 {
|
||||
param2 := &tonglianpayapi.CreateH5UnitorderOrderParam{
|
||||
Trxamt: int(order.ActualPayPrice),
|
||||
NotifyUrl: globals.TLPayNotifyURL,
|
||||
Body: "京西菜市",
|
||||
Charset: "UTF-8",
|
||||
}
|
||||
err = api.TLpayAPI.CreateH5UnitorderOrder(param2)
|
||||
} else {
|
||||
result, err := api.TLpayAPI.CreateUnitorderOrder(param)
|
||||
if err == nil {
|
||||
var result2 tonglianpayapi.PayInfo
|
||||
json.Unmarshal([]byte(result.PayInfo), &result2)
|
||||
prePayID := result2.Package[strings.LastIndex(result2.Package, "=")+1 : len(result2.Package)]
|
||||
orderPay = &model.OrderPay{
|
||||
PayOrderID: param.Reqsn,
|
||||
PayType: payType,
|
||||
VendorPayType: vendorPayType,
|
||||
TransactionID: result.TrxID,
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: order.VendorID,
|
||||
Status: 0,
|
||||
PayCreatedAt: payCreatedAt,
|
||||
PrepayID: prePayID,
|
||||
CodeURL: utils.LimitUTF8StringLen(result.PayInfo, 3200),
|
||||
TotalFee: int(order.ActualPayPrice),
|
||||
}
|
||||
}
|
||||
}
|
||||
return orderPay, err
|
||||
}
|
||||
|
||||
func OnTLPayCallback(call *tonglianpayapi.CallBackResult) (err error) {
|
||||
globals.SugarLogger.Debugf("OnTLPayCallback msg:%s", utils.Format4Output(call, true))
|
||||
switch call.TrxCode {
|
||||
case tonglianpayapi.MsgTypePay:
|
||||
err = onTLpayFinished(call)
|
||||
case tonglianpayapi.MsgTypeRefund:
|
||||
err = onTLpayRefund(call)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onTLpayFinished(call *tonglianpayapi.CallBackResult) (err error) {
|
||||
orderPay := &model.OrderPay{
|
||||
PayOrderID: call.CusorderID,
|
||||
// PayType: model.PayTypeTL,
|
||||
}
|
||||
orderPay.DeletedAt = utils.DefaultTimeValue
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetEntity(db, orderPay, "PayOrderID", "DeletedAt"); err == nil {
|
||||
if orderPay.Status != 0 {
|
||||
globals.SugarLogger.Debugf("already pay msg:%s, err:%v", utils.Format4Output(call, true), err)
|
||||
return err
|
||||
}
|
||||
loc, _ := time.LoadLocation("Local")
|
||||
t1, _ := time.ParseInLocation("20060102150405", call.PayTime, loc)
|
||||
orderPay.PayFinishedAt = utils.Time2Pointer(t1)
|
||||
// orderPay.TransactionID = call.ChnlTrxID
|
||||
orderPay.OriginalData = utils.Format4Output(call, true)
|
||||
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
orderPay.Status = model.PayStatusYes
|
||||
} else {
|
||||
orderPay.Status = model.PayStatusFailed
|
||||
}
|
||||
dao.UpdateEntity(db, orderPay)
|
||||
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
err = OnPayFinished(orderPay)
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("onTLpayFinished msg:%s, err:%v", utils.Format4Output(call, true), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onTLpayRefund(call *tonglianpayapi.CallBackResult) (err error) {
|
||||
orderPayRefund := &model.OrderPayRefund{
|
||||
RefundID: call.CusorderID,
|
||||
}
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
|
||||
if call.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
orderPayRefund.Status = model.RefundStatusYes
|
||||
} else {
|
||||
orderPayRefund.Status = model.RefundStatusFailed
|
||||
}
|
||||
orderPayRefund.OriginalData = utils.Format4Output(call, true)
|
||||
dao.UpdateEntity(db, orderPayRefund)
|
||||
} else if dao.IsNoRowsError(err) {
|
||||
globals.SugarLogger.Warnf("收到异常的退款事件, call:%s", utils.Format4Output(call, true))
|
||||
}
|
||||
|
||||
orderPay := &model.OrderPay{
|
||||
VendorOrderID: orderPayRefund.VendorOrderID,
|
||||
VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID),
|
||||
PayType: model.PayTypeWX,
|
||||
Status: model.PayStatusYes,
|
||||
}
|
||||
orderPay.DeletedAt = utils.DefaultTimeValue
|
||||
if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil {
|
||||
orderPay.Status = model.PayStatusRefund
|
||||
dao.UpdateEntity(db, orderPay)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func RefundOrderByTL(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) {
|
||||
result, err := api.TLpayAPI.PayRefund(&tonglianpayapi.PayRefundParam{
|
||||
Trxamt: refundFee,
|
||||
Reqsn: utils.GetUUID(),
|
||||
Remark: refundDesc,
|
||||
OldTrxID: orderPay.TransactionID,
|
||||
})
|
||||
if err == nil {
|
||||
orderPayRefund = &model.OrderPayRefund{
|
||||
RefundID: refundID,
|
||||
VendorRefundID: result.TrxID,
|
||||
VendorOrderID: orderPay.VendorOrderID,
|
||||
VendorID: orderPay.VendorID,
|
||||
Status: model.RefundStatusNo,
|
||||
TransactionID: orderPay.TransactionID,
|
||||
RefundFee: refundFee,
|
||||
RefundCreatedAt: time.Now(),
|
||||
}
|
||||
dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName())
|
||||
db := dao.GetDB()
|
||||
if result.TrxStatus == tonglianpayapi.TrxStatusSuccess {
|
||||
orderPayRefund.Status = model.RefundStatusYes
|
||||
} else {
|
||||
orderPayRefund.Status = model.RefundStatusFailed
|
||||
}
|
||||
orderPayRefund.OriginalData = utils.Format4Output(result, true)
|
||||
dao.CreateEntity(db, orderPayRefund)
|
||||
|
||||
orderPay.Status = model.PayStatusRefund
|
||||
dao.UpdateEntity(db, orderPay)
|
||||
}
|
||||
return orderPayRefund, err
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package localjx
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
)
|
||||
|
||||
type GetJxShopUsersResult struct {
|
||||
model.User
|
||||
BuyCount int `json:"buyCount"`
|
||||
ActualPayPrice int `json:"actualPayPrice"`
|
||||
GoodCommentCount int `json:"goodCommentCount"`
|
||||
BadCommentCount int `json:"badCommentCount"`
|
||||
UserMembers []*model.UserMember `json:"userMembers"`
|
||||
}
|
||||
|
||||
func GetJxShopUsers(ctx *jxcontext.Context, keyword string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||||
var (
|
||||
requestList []*GetJxShopUsersResult
|
||||
db = dao.GetDB()
|
||||
)
|
||||
sql := `
|
||||
SELECT SQL_CALC_FOUND_ROWS DISTINCT a.*, b.buy_count, b.actual_pay_price
|
||||
FROM user a,
|
||||
(SELECT a.user_id, COUNT(*) buy_count, SUM(c.actual_pay_price) actual_pay_price
|
||||
FROM user a
|
||||
JOIN auth_bind b ON b.user_id = a.user_id AND b.deleted_at = ? AND b.type_id = ?
|
||||
JOIN goods_order c ON c.user_id = a.user_id AND c.status <> ? AND c.store_id <> ?
|
||||
WHERE a.deleted_at = ?
|
||||
GROUP BY 1) b
|
||||
WHERE a.user_id = b.user_id
|
||||
`
|
||||
sqlParams := []interface{}{
|
||||
utils.DefaultTimeValue, api.WeixinMiniAppID2,
|
||||
model.OrderStatusCanceled, model.MatterStoreID,
|
||||
utils.DefaultTimeValue,
|
||||
}
|
||||
if keyword != "" {
|
||||
sql += " AND (a.user_id LIKE ? OR a.name LIKE ? OR a.mobile LIKE ? OR a.user_id2 LIKE ?)"
|
||||
sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
|
||||
}
|
||||
sql += "LIMIT ? OFFSET ?"
|
||||
pageSize = jxutils.FormalizePageSize(pageSize)
|
||||
sqlParams = append(sqlParams, pageSize, offset)
|
||||
dao.Begin(db)
|
||||
defer dao.Commit(db)
|
||||
if err = dao.GetRows(db, &requestList, sql, sqlParams...); err == nil {
|
||||
pagedInfo = &model.PagedInfo{
|
||||
TotalCount: dao.GetLastTotalRowCount(db),
|
||||
// Data: requestList,
|
||||
}
|
||||
for _, v := range requestList {
|
||||
userMembers, _ := dao.GetUserMember(db, v.UserID, "", model.MemberTypeDiscountCard, model.YES)
|
||||
v.UserMembers = userMembers
|
||||
}
|
||||
pagedInfo.Data = requestList
|
||||
}
|
||||
return pagedInfo, err
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package localjx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func vendorPayType2WxpayType(vendorPayType string) string {
|
||||
return vendorPayType
|
||||
}
|
||||
|
||||
func getOrderBrief(order *model.GoodsOrder) string {
|
||||
return fmt.Sprintf("%s等共%d件商品", order.Skus[0].SkuName, order.GoodsCount)
|
||||
}
|
||||
|
||||
func pay4OrderByWX(ctx *jxcontext.Context, order *model.GoodsOrder, vendorPayType string) (orderPay *model.OrderPay, err error) {
|
||||
payCreatedAt := time.Now()
|
||||
param := &wxpayapi.CreateOrderParam{
|
||||
OutTradeNo: utils.Int64ToStr(GenPayOrderID(order)),
|
||||
Body: getOrderBrief(order),
|
||||
NotifyURL: globals.WxpayNotifyURL,
|
||||
SpbillCreateIP: ctx.GetRealRemoteIP(),
|
||||
TradeType: vendorPayType2WxpayType(vendorPayType),
|
||||
TotalFee: int(order.ActualPayPrice),
|
||||
|
||||
TimeStart: wxpayapi.Time2PayTime(payCreatedAt),
|
||||
// TimeExpire: wxpayapi.Time2PayTime(payCreatedAt.Add(PayWaitingTime)),
|
||||
ProfitSharing: wxpayapi.OptYes,
|
||||
}
|
||||
if authInfo, err := ctx.GetV2AuthInfo(); err == nil && authInfo.GetAuthType() == weixin.AuthTypeMini {
|
||||
param.OpenID = authInfo.GetAuthID()
|
||||
}
|
||||
result, err := api.WxpayAPI.CreateUnifiedOrder(param)
|
||||
if err == nil {
|
||||
orderPay = &model.OrderPay{
|
||||
PayOrderID: param.OutTradeNo,
|
||||
PayType: model.PayTypeWX,
|
||||
VendorPayType: vendorPayType,
|
||||
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: order.VendorID,
|
||||
Status: 0,
|
||||
PayCreatedAt: payCreatedAt,
|
||||
PrepayID: result.PrepayID,
|
||||
CodeURL: result.CodeURL,
|
||||
TotalFee: int(order.ActualPayPrice),
|
||||
}
|
||||
}
|
||||
return orderPay, err
|
||||
}
|
||||
|
||||
func OnWxPayCallback(msg *wxpayapi.CallbackMsg) (err error) {
|
||||
globals.SugarLogger.Debugf("OnWxPayCallback msg:%s", utils.Format4Output(msg, true))
|
||||
switch msg.MsgType {
|
||||
case wxpayapi.MsgTypePay:
|
||||
err = onWxpayFinished(msg.Data.(*wxpayapi.PayResultMsg))
|
||||
case wxpayapi.MsgTypeRefund:
|
||||
err = onWxpayRefund(msg.Data.(*wxpayapi.RefundResultMsg))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onWxpayFinished(msg *wxpayapi.PayResultMsg) (err error) {
|
||||
orderPay := &model.OrderPay{
|
||||
PayOrderID: msg.OutTradeNo,
|
||||
PayType: model.PayTypeWX,
|
||||
}
|
||||
orderPay.DeletedAt = utils.DefaultTimeValue
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetEntity(db, orderPay, "PayOrderID", "PayType", "DeletedAt"); err == nil {
|
||||
orderPay.PayFinishedAt = utils.Time2Pointer(wxpayapi.PayTime2Time(msg.TimeEnd))
|
||||
orderPay.TransactionID = msg.TransactionID
|
||||
orderPay.OriginalData = utils.Format4Output(msg, true)
|
||||
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
||||
orderPay.Status = model.PayStatusYes
|
||||
} else {
|
||||
orderPay.Status = model.PayStatusFailed
|
||||
}
|
||||
dao.UpdateEntity(db, orderPay)
|
||||
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
||||
err = OnPayFinished(orderPay)
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("onWxpayFinished msg:%s, err:%v", utils.Format4Output(msg, true), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func onWxpayRefund(msg *wxpayapi.RefundResultMsg) (err error) {
|
||||
orderPayRefund := &model.OrderPayRefund{
|
||||
RefundID: msg.ReqInfoObj.OutRefundNo,
|
||||
}
|
||||
db := dao.GetDB()
|
||||
if err = dao.GetEntity(db, orderPayRefund, "RefundID"); err == nil {
|
||||
if msg.ResultCode == wxpayapi.ResponseCodeSuccess {
|
||||
orderPayRefund.Status = model.RefundStatusYes
|
||||
} else {
|
||||
orderPayRefund.Status = model.RefundStatusFailed
|
||||
}
|
||||
orderPayRefund.OriginalData = utils.Format4Output(msg, true)
|
||||
dao.UpdateEntity(db, orderPayRefund)
|
||||
} else if dao.IsNoRowsError(err) {
|
||||
globals.SugarLogger.Warnf("收到异常的退款事件, msg:%s", utils.Format4Output(msg, true))
|
||||
}
|
||||
|
||||
orderPay := &model.OrderPay{
|
||||
VendorOrderID: orderPayRefund.VendorOrderID,
|
||||
VendorID: jxutils.GetPossibleVendorIDFromVendorOrderID(orderPayRefund.VendorOrderID),
|
||||
PayType: model.PayTypeWX,
|
||||
Status: model.PayStatusYes,
|
||||
}
|
||||
orderPay.DeletedAt = utils.DefaultTimeValue
|
||||
if err = dao.GetEntity(db, orderPay, "VendorOrderID", "VendorID", "PayType", "Status", "DeletedAt"); err == nil {
|
||||
orderPay.Status = model.PayStatusRefund
|
||||
dao.UpdateEntity(db, orderPay)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func refundOrderByWX(ctx *jxcontext.Context, orderPay *model.OrderPay, refundID string, refundFee int, refundDesc string) (orderPayRefund *model.OrderPayRefund, err error) {
|
||||
result, err := api.WxpayAPI.PayRefund(&wxpayapi.PayRefundParam{
|
||||
OutTradeNo: orderPay.VendorOrderID,
|
||||
NotifyURL: globals.WxpayNotifyURL,
|
||||
OutRefundNo: refundID,
|
||||
TotalFee: orderPay.TotalFee,
|
||||
RefundFee: refundFee,
|
||||
RefundDesc: wxpayapi.CData(refundDesc),
|
||||
})
|
||||
if err == nil {
|
||||
orderPayRefund = &model.OrderPayRefund{
|
||||
RefundID: refundID,
|
||||
VendorRefundID: result.RefundID,
|
||||
VendorOrderID: orderPay.VendorOrderID,
|
||||
VendorID: orderPay.VendorID,
|
||||
Status: model.RefundStatusNo,
|
||||
TransactionID: orderPay.TransactionID,
|
||||
RefundFee: orderPay.TotalFee,
|
||||
RefundCreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
return orderPayRefund, err
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"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/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/jx/phpjx"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
return order
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrder(vendorOrgCode, orderID string) (order *model.GoodsOrder, err error) {
|
||||
order, err = partner.CurOrderManager.LoadOrder(orderID, model.VendorIDJX)
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX)
|
||||
if err == nil {
|
||||
status = order.Status
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
var status int
|
||||
if isAcceptIt {
|
||||
status = model.OrderStatusAccepted
|
||||
} else {
|
||||
status = model.OrderStatusCanceled
|
||||
}
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, status)
|
||||
} else {
|
||||
err = localjx.AcceptOrRefuseOrder(order, isAcceptIt, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinishedPickup)
|
||||
} else {
|
||||
err = localjx.PickupGoods(order, isSelfDelivery, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusDelivering)
|
||||
} else {
|
||||
err = localjx.SelfDeliverDelivering(order, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished)
|
||||
} else {
|
||||
err = localjx.SelfDeliverDelivered(order, userName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
} else {
|
||||
err = localjx.AgreeOrRefuseCancel(ctx, order, isAgree, reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusCanceled)
|
||||
} else {
|
||||
err = localjx.CancelOrder(ctx, order, reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
} else {
|
||||
err = localjx.AdjustOrder(ctx, order, removedSkuList, reason)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) {
|
||||
return vendorOrderIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ConfirmSelfTake(ctx *jxcontext.Context, vendorOrderID, selfTakeCode string) (err error) {
|
||||
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX)
|
||||
if err == nil {
|
||||
if model.IsOrderJXTemp(order) {
|
||||
err = phpjx.NotifyOrderStatusChanged(order, model.OrderStatusFinished)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
var status int
|
||||
if approveType == partner.AfsApproveTypeRefused {
|
||||
status = model.AfsOrderStatusFailed
|
||||
} else {
|
||||
status = model.AfsOrderStatusFinished
|
||||
}
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: order.AfsOrderID, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: order.VendorID,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: order.VendorOrderID,
|
||||
RefVendorID: order.VendorID,
|
||||
VendorStatus: utils.Int2Str(status),
|
||||
Status: status,
|
||||
StatusTime: time.Now(),
|
||||
Remark: reason,
|
||||
}
|
||||
if status == model.AfsOrderStatusFinished {
|
||||
orderPays, err := dao.GetOrderPayList(dao.GetDB(), order.VendorOrderID, order.VendorID)
|
||||
if err == nil {
|
||||
_, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(order.SkuUserMoney), reason)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
err = fmt.Errorf("京西商城当前不支持ConfirmReceivedReturnGoods")
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
err = c.PartRefundOrder(ctx, order, order.Skus, reason)
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
globals.SugarLogger.Debugf("PartRefundOrder jx, orderID :%v", order.VendorOrderID)
|
||||
var (
|
||||
skuMap = make(map[int]*model.OrderSku)
|
||||
appID = ""
|
||||
salePrice int64
|
||||
db = dao.GetDB()
|
||||
)
|
||||
if time.Now().Sub(order.OrderCreatedAt) > 24*time.Hour {
|
||||
return fmt.Errorf("已超过售后申请时间,如有疑问请联系门店!")
|
||||
}
|
||||
referer := ctx.GetRequest().Referer()
|
||||
index := strings.Index(referer, "//")
|
||||
if index > 0 {
|
||||
list := strings.Split(referer[index+2:], "/")
|
||||
if len(list) >= 2 {
|
||||
appID = list[1]
|
||||
}
|
||||
}
|
||||
for _, sku := range order.Skus {
|
||||
skuMap[sku.SkuID] = sku
|
||||
}
|
||||
orderStatus := buildOrderStatus(ctx, order, reason, isJxShop(appID))
|
||||
afsOrder := &model.AfsOrder{
|
||||
VendorID: order.VendorID,
|
||||
AfsOrderID: orderStatus.VendorOrderID,
|
||||
VendorOrderID: orderStatus.RefVendorOrderID,
|
||||
VendorStoreID: order.VendorStoreID,
|
||||
StoreID: order.StoreID,
|
||||
AfsCreatedAt: time.Now(),
|
||||
VendorAppealType: "",
|
||||
AppealType: model.AfsAppealTypeRefund,
|
||||
VendorReasonType: utils.Int2Str(model.AfsReasonNotOthers),
|
||||
ReasonType: model.AfsReasonNotOthers,
|
||||
ReasonDesc: utils.LimitUTF8StringLen(reason, 1024),
|
||||
ReasonImgList: "",
|
||||
RefundType: model.AfsTypePartRefund,
|
||||
|
||||
VendorOrgCode: "",
|
||||
}
|
||||
for _, sku := range refundSkuList {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
Count: sku.Count,
|
||||
VendorSkuID: utils.Int2Str(sku.SkuID),
|
||||
SkuID: sku.SkuID,
|
||||
}
|
||||
if skuMap[sku.SkuID] != nil {
|
||||
orderSku.Name = skuMap[sku.SkuID].SkuName
|
||||
orderSku.UserMoney = skuMap[sku.SkuID].SalePrice * int64(sku.Count)
|
||||
salePrice += skuMap[sku.SkuID].SalePrice * int64(sku.Count)
|
||||
}
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
|
||||
if !isJxShop(appID) {
|
||||
orderPays, err := dao.GetOrderPayList(db, order.VendorOrderID, order.VendorID)
|
||||
if err == nil {
|
||||
_, err = localjx.RefundOrderByTL(ctx, orderPays[0], order.VendorOrderID, int(salePrice), reason)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
if afsOrder != nil {
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func buildOrderStatus(ctx *jxcontext.Context, order *model.GoodsOrder, reason string, isJxShop bool) (orderStatus *model.OrderStatus) {
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: utils.Int64ToStr(jxutils.GenAfsOrderNo()), // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: order.VendorID,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: order.VendorOrderID,
|
||||
RefVendorID: order.VendorID,
|
||||
VendorStatus: utils.Int2Str(model.AfsOrderStatusWait4Approve),
|
||||
// Status: model.AfsOrderStatusWait4Approve,
|
||||
StatusTime: time.Now(),
|
||||
Remark: reason,
|
||||
}
|
||||
if isJxShop {
|
||||
orderStatus.Status = model.AfsOrderStatusWait4Approve
|
||||
} else {
|
||||
orderStatus.Status = model.AfsOrderStatusFinished
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func isJxShop(appID string) bool {
|
||||
if appID == api.WeixinMiniAppID2 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
appKey = "4A86853D-E4B6-454E-940A-B68ECDA2B73E"
|
||||
|
||||
MsgTypeOrder = "order"
|
||||
MsgTypeAfsOrder = "afsOrder"
|
||||
)
|
||||
|
||||
type CallbackResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type CallbackMsg struct {
|
||||
AppKey string `json:"appKey"`
|
||||
MsgType string `json:"msgType"`
|
||||
SubMsgType string `json:"subMsgType"`
|
||||
ThingID string `json:"thingID"`
|
||||
ThingID2 string `json:"thingID2"`
|
||||
Data string `json:"data"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
func OnCallbackMsg(msg *CallbackMsg) (retVal, errCode string, err error) {
|
||||
if msg.AppKey != appKey {
|
||||
return retVal, errCode, fmt.Errorf("无效的AppKey:%s", msg.AppKey)
|
||||
}
|
||||
if msg.MsgType == MsgTypeOrder {
|
||||
retVal, errCode, err = OnOrderMsg(msg)
|
||||
} else if msg.MsgType == MsgTypeAfsOrder {
|
||||
err = OnAfsOrderMsg(msg)
|
||||
}
|
||||
return retVal, errCode, err
|
||||
}
|
||||
|
||||
func postFakeMsg(orderNo string, status int) {
|
||||
msg := &CallbackMsg{
|
||||
AppKey: appKey,
|
||||
MsgType: MsgTypeOrder,
|
||||
SubMsgType: utils.Int2Str(status),
|
||||
ThingID: orderNo,
|
||||
Timestamp: time.Now().Unix(),
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
OnCallbackMsg(msg)
|
||||
})
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestBuildNewJxOrder(t *testing.T) {
|
||||
order, err := partner.CurOrderManager.LoadOrder("920931913000041", model.VendorIDJD)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
order.VendorID = model.VendorIDJX
|
||||
order.VendorStoreID = utils.Int2Str(order.StoreID)
|
||||
for _, sku := range order.Skus {
|
||||
sku.VendorID = model.VendorIDJX
|
||||
sku.VendorSkuID = utils.Int2Str(sku.SkuID)
|
||||
}
|
||||
order2 := &Data4Neworder{
|
||||
GoodsOrder: *order,
|
||||
Skus: order.Skus,
|
||||
}
|
||||
msg := &CallbackMsg{
|
||||
AppKey: appKey,
|
||||
MsgType: MsgTypeOrder,
|
||||
SubMsgType: utils.Int2Str(model.OrderStatusNew),
|
||||
ThingID: order.VendorOrderID,
|
||||
Data: utils.Format4Output(order2, true),
|
||||
}
|
||||
t.Logf("\n%s", msg.AppKey)
|
||||
t.Logf("\n%s", msg.MsgType)
|
||||
t.Logf("\n%s", msg.SubMsgType)
|
||||
t.Logf("\n%s", msg.ThingID)
|
||||
t.Logf("\n%s", msg.Data)
|
||||
|
||||
var order3 *model.GoodsOrder
|
||||
err = utils.UnmarshalUseNumber([]byte(msg.Data), &order3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(order3.OrderCreatedAt)
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
type API struct {
|
||||
token string
|
||||
appKey string
|
||||
appSecret string
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
}
|
||||
|
||||
const (
|
||||
ResponseCodeSuccess = 200
|
||||
)
|
||||
|
||||
const (
|
||||
prodURL = "https://www.jingxicaishi.com/index.php/Weimendian/index"
|
||||
)
|
||||
|
||||
var (
|
||||
exceedLimitCodes = map[int]int{}
|
||||
canRetryCodes = map[int]int{}
|
||||
)
|
||||
|
||||
var (
|
||||
jxAPI *API
|
||||
)
|
||||
|
||||
func NewAPI(token, appKey, appSecret string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
return &API{
|
||||
token: token,
|
||||
appKey: appKey,
|
||||
appSecret: appSecret,
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
jxAPI = NewAPI("", "", "")
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(apiStr string, jxParams map[string]interface{}, traceInfo string) (retVal map[string]interface{}, err error) {
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
params := utils.MergeMaps(jxParams, map[string]interface{}{
|
||||
"timestamp": utils.GetCurTimeStr(),
|
||||
})
|
||||
var request *http.Request
|
||||
if false {
|
||||
|
||||
} else {
|
||||
fullURL := prodURL + "/" + apiStr
|
||||
// baseapi.SugarLogger.Debug(utils.Map2URLValues(params).Encode())
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
||||
request.Header.Set("charset", "UTF-8")
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
if traceInfo != "" {
|
||||
request.Header.Set(platformapi.KeyTrackInfo, traceInfo)
|
||||
}
|
||||
// request.Close = true //todo 为了性能考虑还是不要关闭
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
if jsonResult1 == nil {
|
||||
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||
}
|
||||
code := int(utils.Interface2Int64WithDefault(jsonResult1["code"], 0))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
newErr := utils.NewErrorIntCode(jsonResult1["msg"].(string), code)
|
||||
if _, ok := exceedLimitCodes[code]; ok {
|
||||
return platformapi.ErrLevelExceedLimit, newErr
|
||||
} else if _, ok := canRetryCodes[code]; ok {
|
||||
return platformapi.ErrLevelRecoverableErr, newErr
|
||||
} else {
|
||||
baseapi.SugarLogger.Debugf("jx AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
}
|
||||
})
|
||||
return retVal, err
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
var (
|
||||
orderStatusMap = map[int]int{
|
||||
model.OrderStatusFinishedPickup: 7,
|
||||
model.OrderStatusDelivering: 8,
|
||||
// 4,
|
||||
model.OrderStatusFinished: 3,
|
||||
model.OrderStatusCanceled: 3,
|
||||
}
|
||||
)
|
||||
|
||||
func translateOrderStatus(status int) (outStatus int) {
|
||||
return status //orderStatusMap[status]
|
||||
}
|
||||
|
||||
func (a *API) NotifyOrderStatusChanged(order *model.GoodsOrder) (err error) {
|
||||
status := translateOrderStatus(order.Status)
|
||||
if status > 0 {
|
||||
_, err = a.AccessAPI("orderChangeStatus", map[string]interface{}{
|
||||
"orderid": order.VendorOrderID,
|
||||
"status": status,
|
||||
"data": "", //string(utils.MustMarshal(order)),
|
||||
}, "")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) NotifyAfsOrderStatusChanged(afsOrder *model.AfsOrder) (err error) {
|
||||
status := translateOrderStatus(afsOrder.Status)
|
||||
if status > 0 {
|
||||
_, err = a.AccessAPI("afsOrderChangeStatus", map[string]interface{}{
|
||||
"orderid": afsOrder.VendorOrderID,
|
||||
"afsOrderID": afsOrder.AfsOrderID,
|
||||
"status": status,
|
||||
"data": "", //string(utils.MustMarshal(order)),
|
||||
}, "")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
func TestNotifyOrderStatusChanged(t *testing.T) {
|
||||
order, err := partner.CurOrderManager.LoadOrder("920931913000041", model.VendorIDJX)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = jxAPI.NotifyOrderStatusChanged(order)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
func NotifyOrderStatusChanged(order *model.GoodsOrder, status int) (err error) {
|
||||
orderMsg := *order
|
||||
orderMsg.Status = status
|
||||
if err = jxAPI.NotifyOrderStatusChanged(&orderMsg); err == nil {
|
||||
postFakeMsg(orderMsg.VendorOrderID, orderMsg.Status)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type Data4Neworder struct {
|
||||
model.GoodsOrder
|
||||
Skus []*model.OrderSku `json:"skus"`
|
||||
}
|
||||
|
||||
func OnOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
retVal, errCode, err = onOrderMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX))
|
||||
return retVal, errCode, err
|
||||
}
|
||||
|
||||
func onOrderMsg(msg *CallbackMsg) (retVal, errCode string, err error) {
|
||||
subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0))
|
||||
if subMsgType == model.OrderStatusNew || subMsgType == model.OrderStatusAdjust {
|
||||
var order *Data4Neworder
|
||||
if err = utils.UnmarshalUseNumber([]byte(msg.Data), &order); err == nil {
|
||||
if order.VendorStatus == "" {
|
||||
order.VendorStatus = utils.Int2Str(order.Status)
|
||||
}
|
||||
retVal, errCode, err = onOrderNew(msg, subMsgType, order)
|
||||
}
|
||||
} else {
|
||||
status := callbackMsg2Status(msg)
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged("", status)
|
||||
}
|
||||
return retVal, errCode, err
|
||||
}
|
||||
|
||||
func callbackMsg2Status(msg *CallbackMsg) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.ThingID,
|
||||
VendorID: model.VendorIDJX,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: msg.ThingID,
|
||||
RefVendorID: model.VendorIDJX,
|
||||
VendorStatus: msg.SubMsgType,
|
||||
Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)),
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
Remark: "",
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func onOrderNew(msg *CallbackMsg, subMsgType int, order *Data4Neworder) (retVal, errCode string, err error) {
|
||||
globals.SugarLogger.Debugf("onOrderNew orderID:%s", msg.ThingID)
|
||||
order.StoreID = int(utils.Str2Int64WithDefault(order.VendorStoreID, 0))
|
||||
if order.DeliveryType == "" {
|
||||
order.DeliveryType = model.OrderDeliveryTypeStoreSelf
|
||||
}
|
||||
order.GoodsOrder.Skus = order.Skus
|
||||
order.VendorID = model.VendorIDJX
|
||||
order.Flag = model.OrderFlagMaskTempJX
|
||||
for _, v := range order.GoodsOrder.Skus {
|
||||
v.SkuID = int(utils.Str2Int64WithDefault(v.VendorSkuID, 0))
|
||||
}
|
||||
jxutils.RefreshOrderSkuRelated(&order.GoodsOrder)
|
||||
orderStatus := model.Order2Status(&order.GoodsOrder)
|
||||
if subMsgType == model.OrderStatusNew {
|
||||
err = partner.CurOrderManager.OnOrderNew(&order.GoodsOrder, orderStatus)
|
||||
} else if subMsgType == model.OrderStatusAdjust {
|
||||
err = partner.CurOrderManager.OnOrderAdjust(&order.GoodsOrder, orderStatus)
|
||||
}
|
||||
return retVal, errCode, err
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package phpjx
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
type Data4AfsOrderSku struct {
|
||||
VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid
|
||||
PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销)
|
||||
Name string `orm:"size(255)" json:"name"` // 商品名
|
||||
SalePrice int64 `json:"salePrice"` // 售卖价
|
||||
Count int `json:"count"` // 订单下单数量
|
||||
}
|
||||
|
||||
type Data4AfsOrder struct {
|
||||
VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID
|
||||
AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID
|
||||
AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间
|
||||
VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid
|
||||
|
||||
VendorStatus string `orm:"size(255)" json:"vendorStatus"`
|
||||
VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` // 原始售后原因
|
||||
ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述
|
||||
ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片
|
||||
VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 原始售后方式
|
||||
Skus []*Data4AfsOrderSku
|
||||
}
|
||||
|
||||
func OnAfsOrderMsg(msg *CallbackMsg) (err error) {
|
||||
jxutils.CallMsgHandlerAsync(func() {
|
||||
err = onAfsOrderMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX))
|
||||
return err
|
||||
}
|
||||
|
||||
func buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) {
|
||||
var afsOrder *Data4AfsOrder
|
||||
if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil {
|
||||
outAfsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDJX,
|
||||
AfsOrderID: afsOrder.AfsOrderID,
|
||||
VendorOrderID: afsOrder.VendorOrderID,
|
||||
VendorStoreID: afsOrder.VendorStoreID,
|
||||
StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)),
|
||||
AfsCreatedAt: afsOrder.AfsCreatedAt,
|
||||
|
||||
VendorStatus: afsOrder.VendorStatus,
|
||||
VendorReasonType: afsOrder.VendorReasonType,
|
||||
ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)),
|
||||
ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024),
|
||||
ReasonImgList: afsOrder.ReasonImgList,
|
||||
VendorAppealType: afsOrder.VendorAppealType,
|
||||
AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)),
|
||||
Flag: model.OrderFlagMaskTempJX,
|
||||
}
|
||||
outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0))
|
||||
|
||||
for _, x := range afsOrder.Skus {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
Count: x.Count,
|
||||
VendorSkuID: x.VendorSkuID,
|
||||
SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)),
|
||||
Name: x.Name,
|
||||
}
|
||||
if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal {
|
||||
orderSku.StoreSubName = utils.Int2Str(x.PromotionType)
|
||||
}
|
||||
outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku)
|
||||
}
|
||||
}
|
||||
return outAfsOrder, err
|
||||
}
|
||||
|
||||
func callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus {
|
||||
orderStatus := &model.OrderStatus{
|
||||
VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中
|
||||
VendorID: model.VendorIDJX,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: msg.ThingID,
|
||||
RefVendorID: model.VendorIDJX,
|
||||
VendorStatus: msg.SubMsgType,
|
||||
Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)),
|
||||
StatusTime: utils.Timestamp2Time(msg.Timestamp),
|
||||
Remark: "",
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func onAfsOrderMsg(msg *CallbackMsg) (err error) {
|
||||
subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0))
|
||||
status := callbackAfsMsg2Status(msg)
|
||||
if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew {
|
||||
afsOrder, err2 := buildAfsOrder(msg)
|
||||
if err = err2; err == nil {
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status)
|
||||
}
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged("", status)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func postFakeAfsMsg(orderNo, afsOrderID string, status int) {
|
||||
msg := &CallbackMsg{
|
||||
AppKey: appKey,
|
||||
MsgType: MsgTypeAfsOrder,
|
||||
SubMsgType: utils.Int2Str(status),
|
||||
ThingID: orderNo,
|
||||
ThingID2: afsOrderID,
|
||||
Timestamp: time.Now().Unix(),
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
OnCallbackMsg(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func NotifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) {
|
||||
orderMsg := *order
|
||||
orderMsg.Status = status
|
||||
if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil {
|
||||
postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package jx
|
||||
|
||||
// 这里函数取得的信息,除了与自身实体相关的ID(比如PARENT ID),都已经转换成了本地ID了
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
// func (p *PurchaseHandler) CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*partner.BareCategoryInfo, err error) {
|
||||
return cats, err
|
||||
}
|
||||
|
||||
// func (p *PurchaseHandler) UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error {
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteCategory2(ctx *jxcontext.Context, vendorOrgCode, vendorCatID string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// func (p *PurchaseHandler) CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error) {
|
||||
// return skuNameExt, err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// func (p *PurchaseHandler) DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error) {
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *partner.StoreSkuInfo) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
return vendorCats, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetSkus(ctx *jxcontext.Context, vendorOrgCode string, skuID int, vendorSkuID string) (skuNameList []*partner.SkuNameInfo, err error) {
|
||||
return skuNameList, err
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (storeDetail *dao.StoreDetail, err error) {
|
||||
return storeDetail, err
|
||||
}
|
||||
|
||||
// stoerIDs为nil表示所有
|
||||
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
return storeStatus, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) {
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package jx
|
||||
|
||||
import (
|
||||
"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/partner"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
|
||||
batchSize = 1
|
||||
return batchSize
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) {
|
||||
return outStoreSkuList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (successList []*partner.StoreSkuInfo, err error) {
|
||||
return successList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) {
|
||||
return successList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (successList []*partner.StoreSkuInfo, err error) {
|
||||
return successList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
return failedList, err
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
func jxActType2Mtwm(actType int) int {
|
||||
if actType == model.ActSkuDirectDown {
|
||||
actType = mtwmapi.RetailActTypeDirectDown
|
||||
} else if actType == model.ActSkuSecKill {
|
||||
actType = mtwmapi.RetailActTypeSecKill
|
||||
} else {
|
||||
actType = 0
|
||||
}
|
||||
return actType
|
||||
}
|
||||
|
||||
func actOrderRules2Mtwm(actOrderRules []*model.ActOrderRule) (actDetails []*mtwmapi.FullDiscountActDetail) {
|
||||
for _, v := range actOrderRules {
|
||||
actDetails = append(actDetails, &mtwmapi.FullDiscountActDetail{
|
||||
OriginalPrice: jxutils.IntPrice2Standard(v.SalePrice),
|
||||
ActPrice: jxutils.IntPrice2Standard(v.DeductPrice),
|
||||
})
|
||||
}
|
||||
return actDetails
|
||||
}
|
||||
|
||||
func storeSku2ActData(act *model.Act2, actStoreSku []*model.ActStoreSku2, handler func(int8) bool) (actData []*mtwmapi.RetailDiscountActData) {
|
||||
orderLimit := 1
|
||||
if act.LimitCount > 0 {
|
||||
orderLimit = act.LimitCount
|
||||
}
|
||||
for _, v := range actStoreSku {
|
||||
if handler == nil || handler(v.SyncStatus) {
|
||||
dayLimit := -1
|
||||
if v.Stock > 0 {
|
||||
dayLimit = v.Stock
|
||||
}
|
||||
actData = append(actData, &mtwmapi.RetailDiscountActData{
|
||||
AppFoodCode: utils.Int2Str(v.SkuID),
|
||||
// UserType: 0,
|
||||
StartTime: act.BeginAt.Unix(),
|
||||
EndTime: act.EndAt.Unix(),
|
||||
OrderLimit: orderLimit,
|
||||
DayLimit: dayLimit,
|
||||
// Period: "",
|
||||
// WeeksTime: "",
|
||||
SettingType: mtwmapi.SettingTypeAsPrice,
|
||||
ActPrice: jxutils.IntPrice2Standard(v.ActualActPrice),
|
||||
// DiscountCoefficient: 0,
|
||||
// Sequence: int(v.ActPrice), // 此字段不允许重复
|
||||
// ItemID: utils.Str2Int64WithDefault(v.VendorActID, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
return actData
|
||||
}
|
||||
|
||||
func storeSku2ActData4Delete(actStoreSku []*model.ActStoreSku2, handler func(int8) bool) (actIDList []string) {
|
||||
for _, v := range actStoreSku {
|
||||
if handler == nil || handler(v.SyncStatus) {
|
||||
if v.VendorActID != "" {
|
||||
actIDList = append(actIDList, v.VendorActID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return actIDList
|
||||
}
|
||||
|
||||
func isCreateOrUpdate(syncStatus int8) bool {
|
||||
return model.IsSyncStatusNeedCreate(syncStatus) || model.IsSyncStatusNeedUpdate(syncStatus)
|
||||
}
|
||||
|
||||
func createOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*model.ActStoreSku2) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
actData := storeSku2ActData(act, actStoreSku, isCreateOrUpdate)
|
||||
if len(actData) > 0 {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
actResult, faileInfoList, err2 := api.MtwmAPI.RetailDiscountBatchSave2(vendorStoreID, jxActType2Mtwm(act.Type), actData)
|
||||
err = err2
|
||||
// 忽略错误,都放在failedList里
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// globals.SugarLogger.Debugf("mtwm createOneShopAct actResult:%s, faileInfoList:%s err2:%v", utils.Format4Output(actResult, true), utils.Format4Output(faileInfoList, true), err2)
|
||||
actStoreSkuMap := make(map[int]*model.ActStoreSku2)
|
||||
for _, v := range actStoreSku {
|
||||
actStoreSkuMap[v.SkuID] = v
|
||||
}
|
||||
|
||||
for _, v := range actResult {
|
||||
if v2 := actStoreSkuMap[int(utils.Str2Int64WithDefault(v.AppFoodCode, 0))]; v2 != nil {
|
||||
v2.VendorActID = utils.Int64ToStr(v.ActID)
|
||||
}
|
||||
}
|
||||
for _, v := range faileInfoList {
|
||||
if v2 := actStoreSkuMap[int(utils.Str2Int64WithDefault(v.AppFoodCode, 0))]; v2 != nil {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: &partner.StoreSkuInfo{
|
||||
SkuID: v2.SkuID,
|
||||
},
|
||||
VendoreID: model.VendorIDMTWM,
|
||||
StoreID: int(utils.Str2Int64WithDefault(vendorStoreID, 0)),
|
||||
ErrMsg: v.ErrorMsg,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, v := range actStoreSku {
|
||||
v.VendorActID = utils.Int64ToStr(jxutils.GenFakeID())
|
||||
}
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func cancelOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*model.ActStoreSku2) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if list := storeSku2ActData4Delete(actStoreSku, nil /*model.IsSyncStatusNeedDelete*/); len(list) > 0 {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
failedList2, err2 := api.MtwmAPI.RetailDiscountDelete2(vendorStoreID, jxActType2Mtwm(act.Type), list)
|
||||
actStoreSkuMap := make(map[string]*model.ActStoreSku2)
|
||||
for _, v := range actStoreSku {
|
||||
actStoreSkuMap[v.VendorActID] = v
|
||||
}
|
||||
for _, v := range failedList2 {
|
||||
if !mtwmapi.CanDeleteActErrMsgIgnore(v.ErrorMsg) {
|
||||
failedList = append(failedList, &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: &partner.StoreSkuInfo{
|
||||
SkuID: actStoreSkuMap[utils.Int64ToStr(v.ActID)].SkuID,
|
||||
},
|
||||
StoreID: int(utils.Str2Int64WithDefault(vendorStoreID, 0)),
|
||||
ErrMsg: v.ErrorMsg,
|
||||
VendoreID: model.VendorIDMTWM,
|
||||
})
|
||||
}
|
||||
}
|
||||
err = err2
|
||||
err = nil // 强制不返回错误,使用部分错误
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func getActStoreSkuFromTaskResult(taskReslt []interface{}) (list []*model.ActStoreSku2) {
|
||||
for _, v := range taskReslt {
|
||||
actStoreSkuList := v.([]*model.ActStoreSku2)
|
||||
list = append(list, actStoreSkuList...)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func createSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (createdList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("mtwm createSkuAct")
|
||||
actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
|
||||
task := tasksch.NewParallelTask("mtwm createSkuAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
list := batchItemList[0].([]*model.ActStoreSku2)
|
||||
failedList, err2 := createOneShopAct(act, list[0].VendorStoreID, list)
|
||||
if err = err2; err2 == nil {
|
||||
if len(failedList) > 0 {
|
||||
failedMap := putils.StoreSkuInfoWithErrList2MapBySku(failedList)
|
||||
list = []*model.ActStoreSku2{}
|
||||
for _, v := range actStoreSku {
|
||||
if failedMap[v.SkuID] == nil {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
list = []*model.ActStoreSku2{}
|
||||
}
|
||||
retVal = []interface{}{list}
|
||||
}
|
||||
return retVal, err
|
||||
}, actStoreSkuListList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err := task.GetResult(0)
|
||||
return getActStoreSkuFromTaskResult(result), err
|
||||
}
|
||||
|
||||
func cancelSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
|
||||
globals.SugarLogger.Debugf("mtwm cancelSkuAct")
|
||||
actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
|
||||
task := tasksch.NewParallelTask("mtwm cancelSkuAct", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
actStoreSkuList := batchItemList[0].([]*model.ActStoreSku2)
|
||||
if _, err = cancelOneShopAct(act, actStoreSkuList[0].VendorStoreID, actStoreSkuList); err == nil {
|
||||
retVal = []interface{}{actStoreSkuList}
|
||||
}
|
||||
return retVal, err
|
||||
}, actStoreSkuListList)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
result, err := task.GetResult(0)
|
||||
return getActStoreSkuFromTaskResult(result), err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm SyncAct, actID:%d", act.ID)
|
||||
var actStoreSkuList4Create, actStoreSkuList4Delete []*model.ActStoreSku2
|
||||
var updateItems []*dao.KVUpdateItem
|
||||
|
||||
actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuList)
|
||||
for storeID := range actStoreSkuMap {
|
||||
for _, actStoreSku := range actStoreSkuMap[storeID] {
|
||||
if model.IsSyncStatusDelete(actStoreSku.SyncStatus) {
|
||||
actStoreSkuList4Delete = append(actStoreSkuList4Delete, actStoreSku)
|
||||
} else if model.IsSyncStatusNew(actStoreSku.SyncStatus) {
|
||||
actStoreSkuList4Create = append(actStoreSkuList4Create, actStoreSku)
|
||||
}
|
||||
}
|
||||
}
|
||||
err = func() (err error) {
|
||||
if model.IsSyncStatusDelete(act.SyncStatus) {
|
||||
canceledList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, canceledList, model.SyncFlagModifiedMask)...)
|
||||
if err = err2; err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
} else if model.IsSyncStatusNew(act.SyncStatus) {
|
||||
createdList, err2 := createSkuAct(ctx, nil, act, actStoreSkuList4Create)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, createdList, model.SyncFlagNewMask)...)
|
||||
if err = err2; err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagNewMask))
|
||||
}
|
||||
} else if model.IsSyncStatusUpdate(act.SyncStatus) {
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(updateItems, false))
|
||||
if len(actStoreSkuList4Create) > 0 {
|
||||
addedList, err2 := createSkuAct(ctx, nil, act, actStoreSkuList4Create)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, addedList, model.SyncFlagNewMask)...)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(actStoreSkuList4Delete) > 0 {
|
||||
deletedList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList4Delete)
|
||||
updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deletedList, model.SyncFlagDeletedMask)...)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}()
|
||||
db := dao.GetDB()
|
||||
_, err2 := dao.BatchUpdateActEntity(db, model.IsSyncStatusDelete(act.SyncStatus), updateItems)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
func OnCallbackMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) {
|
||||
if CurPurchaseHandler != nil {
|
||||
if msg.Cmd == mtwmapi.MsgTypeStoreStatusChanged {
|
||||
response = CurPurchaseHandler.onStoreStatusChanged(msg)
|
||||
} else if msg.Cmd == mtwmapi.MsgTypePrivateNumberDowngrade {
|
||||
response = CurPurchaseHandler.onNumberDowngrade(msg)
|
||||
} else {
|
||||
if orderID := GetOrderIDFromMsg(msg); orderID != "" {
|
||||
jxutils.CallMsgHandler(func() {
|
||||
switch msg.Cmd {
|
||||
case mtwmapi.MsgTypeWaybillStatus:
|
||||
response = CurPurchaseHandler.onWaybillMsg(msg)
|
||||
default:
|
||||
response = CurPurchaseHandler.onOrderMsg(msg)
|
||||
}
|
||||
}, jxutils.ComposeUniversalOrderID(orderID, model.VendorIDMTWM))
|
||||
}
|
||||
/*if msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
|
||||
utils.CallFuncAsync(func() {
|
||||
OnFinancialMsg(msg)
|
||||
})
|
||||
} */
|
||||
}
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
func GetOrderIDFromMsg(msg *mtwmapi.CallbackMsg) string {
|
||||
return msg.FormData.Get(mtwmapi.KeyOrderID)
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
)
|
||||
|
||||
const (
|
||||
PublicWelfareDonation = 1 // 美团公益捐款金额现阶段是每单一分钱
|
||||
)
|
||||
|
||||
// 存储美团退款订单结账信息
|
||||
func OnFinancialMsg(msg *mtwmapi.CallbackMsg) (err error) {
|
||||
if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund { // 部分退款处理
|
||||
orderData := msg.FormData
|
||||
if orderData.Get("notify_type") == mtwmapi.NotifyTypeSuccess {
|
||||
err = partner.CurOrderManager.SaveAfsOrderFinancialInfo(CurPurchaseHandler.AfsOrderDetail2Financial(orderData))
|
||||
}
|
||||
}
|
||||
if msg.Cmd == mtwmapi.MsgTypeOrderRefund { // todo 全额退款处理
|
||||
orderData := msg.FormData
|
||||
if orderData.Get("notify_type") == mtwmapi.NotifyTypeSuccess {
|
||||
globals.SugarLogger.Debug(orderData.Get("order_id")) // 获得退款订单ID,去本地数据库拿?饿百消息推送只给了订单号,也没有通过订单号查询退款信息的接口
|
||||
afsOrderID := orderData.Get("order_id")
|
||||
orderFinancial, err := partner.CurOrderManager.LoadOrderFinancial(afsOrderID, model.VendorIDMTWM)
|
||||
if err == nil {
|
||||
globals.SugarLogger.Debug(utils.Format4Output(orderFinancial, false))
|
||||
err = partner.CurOrderManager.SaveAfsOrderFinancialInfo(CurPurchaseHandler.OrderFinancialDetail2Refund(orderFinancial, orderData))
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm OnFinancialMsg, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrderFinancial", afsOrderID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OrderFinancialDetail2Refund(orderFinancial *model.OrderFinancial, orderData url.Values) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
AfsOrderID: orderData.Get("refund_id"),
|
||||
VendorOrderID: orderData.Get("order_id"),
|
||||
AfsCreatedAt: utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp"))),
|
||||
// BoxMoney: orderFinancial.BoxMoney,
|
||||
// SkuBoxMoney: orderFinancial.SkuBoxMoney, // 美团的餐盒费已经拆到单条SKU里面去了,退款时直接计算用户支付sku金额就好了
|
||||
FreightUserMoney: orderFinancial.FreightMoney,
|
||||
SkuUserMoney: orderFinancial.ActualPayMoney - orderFinancial.FreightMoney,
|
||||
PmSubsidyMoney: orderFinancial.PmSubsidyMoney,
|
||||
}
|
||||
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
|
||||
globals.SugarLogger.Debug(utils.Format4Output(order, false))
|
||||
if err == nil {
|
||||
afsOrder.JxStoreID = order.JxStoreID
|
||||
afsOrder.VendorStoreID = order.VendorStoreID
|
||||
afsOrder.StoreID = order.StoreID
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
for _, sku := range orderFinancial.Skus {
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: sku.VendorID,
|
||||
VendorOrderID: sku.VendorOrderID,
|
||||
// OrderFinancialID: sku.VendorOrderID,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorStoreID: afsOrder.VendorStoreID,
|
||||
StoreID: afsOrder.StoreID,
|
||||
JxStoreID: afsOrder.JxStoreID,
|
||||
VendorSkuID: sku.VendorSkuID,
|
||||
SkuID: sku.SkuID,
|
||||
PromotionType: sku.PromotionType,
|
||||
Name: sku.Name,
|
||||
ShopPrice: sku.ShopPrice,
|
||||
SalePrice: sku.SalePrice,
|
||||
Count: sku.Count,
|
||||
UserMoney: sku.UserMoney,
|
||||
PmSubsidyMoney: sku.PmSubsidyMoney,
|
||||
IsAfsOrder: 1,
|
||||
}
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSkuFinancial)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AfsOrderDetail2Financial(orderData url.Values) (afsOrder *model.AfsOrder) {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
AfsOrderID: orderData.Get("order_id"),
|
||||
VendorOrderID: orderData.Get("order_id"),
|
||||
AfsCreatedAt: utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp"))),
|
||||
RefundMoney: jxutils.StandardPrice2Int(utils.Str2Float64(orderData.Get("money"))),
|
||||
}
|
||||
// if orderData.Get("timestamp") != "" {
|
||||
// afsOrder.AfsCreateAt = utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp")))
|
||||
// } else {
|
||||
// globals.SugarLogger.Warnf("ebai OrderFinancialDetail2Refund timestamp is not found in afsOrder:%s", afsOrder.AfsOrderID)
|
||||
// afsOrder.AfsCreateAt = time.Now()
|
||||
// }
|
||||
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
|
||||
if err == nil {
|
||||
afsOrder.JxStoreID = order.JxStoreID
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm AfsOrderDetail2Financial, afsOrderID:%s is not found from partner.CurOrderManager.LoadOrder", afsOrder.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
food := orderData.Get("food")
|
||||
var refundDetail []map[string]interface{}
|
||||
utils.UnmarshalUseNumber([]byte(food), &refundDetail)
|
||||
for _, xMap := range refundDetail {
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
AfsOrderID: afsOrder.AfsOrderID,
|
||||
VendorOrderID: afsOrder.VendorOrderID,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorSkuID: utils.Interface2String(xMap["app_food_code"]),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(xMap["sku_id"]), 0)),
|
||||
Name: utils.Interface2String(xMap["food_name"]),
|
||||
UserMoney: jxutils.StandardPrice2Int(utils.MustInterface2Float64(xMap["refund_price"]))*utils.MustInterface2Int64(xMap["count"]) + jxutils.StandardPrice2Int(utils.MustInterface2Float64(xMap["box_price"]))*int64(utils.MustInterface2Float64(xMap["box_num"])),
|
||||
IsAfsOrder: 1,
|
||||
}
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSkuFinancial)
|
||||
afsOrder.SkuUserMoney += orderSkuFinancial.UserMoney
|
||||
// afsOrder.PmSubsidyMoney += orderSkuFinancial.PmSubsidyMoney // 美团只给了一个扣款金额,很尴尬、、
|
||||
}
|
||||
afsOrder.PmSubsidyMoney += afsOrder.RefundMoney - afsOrder.SkuUserMoney
|
||||
if len(refundDetail) <= 0 {
|
||||
globals.SugarLogger.Warnf("mtwm AfsOrderDetail2Financial, orderID:%s have no refund_detail", afsOrder.VendorOrderID)
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
// 存储美团正向订单结账信息
|
||||
func (p *PurchaseHandler) OnOrderDetail(result map[string]interface{}, operation string) (err error) {
|
||||
globals.SugarLogger.Debug(utils.Int64ToStr(utils.MustInterface2Int64(result["order_id"])))
|
||||
err = partner.CurOrderManager.SaveOrderFinancialInfo(p.OrderDetail2Financial(result), operation)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) OrderDetail2Financial(result map[string]interface{}) (orderFinancial *model.OrderFinancial) {
|
||||
orderFinancial = &model.OrderFinancial{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
VendorOrderID: utils.Int64ToStr(utils.MustInterface2Int64(result["order_id"])),
|
||||
}
|
||||
// orderFinancial.DeliveryConfirmTime = utils.Str2TimeWithDefault(utils.Interface2String(result["order_completed_time"]), utils.DefaultTimeValue)
|
||||
order, err := partner.CurOrderManager.LoadOrder(orderFinancial.VendorOrderID, orderFinancial.VendorID)
|
||||
jxStoreID := 0
|
||||
if err == nil {
|
||||
jxStoreID = order.JxStoreID
|
||||
if order.Skus != nil {
|
||||
for _, x := range order.Skus {
|
||||
orderFinancial.ShopPriceMoney += x.ShopPrice * int64(x.Count)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm OrderDetail2Financial, orderID:%s is not found from partner.CurOrderManager.LoadOrder", orderFinancial.VendorOrderID)
|
||||
err = nil
|
||||
}
|
||||
if result["package_bag_money"] != nil {
|
||||
orderFinancial.BoxMoney = utils.MustInterface2Int64(result["package_bag_money"])
|
||||
}
|
||||
detail := result["detail"]
|
||||
if detail != nil {
|
||||
var data []map[string]interface{}
|
||||
utils.UnmarshalUseNumber([]byte(utils.Interface2String(detail)), &data)
|
||||
for _, x := range data {
|
||||
orderSkuFinancial := &model.OrderSkuFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
// OrderFinancialID: orderFinancial.VendorOrderID,
|
||||
// ConfirmTime: utils.Str2TimeWithDefault(utils.Interface2String(result["ctime"]), utils.DefaultTimeValue),
|
||||
VendorStoreID: result["app_poi_code"].(string),
|
||||
StoreID: 0,
|
||||
JxStoreID: jxStoreID,
|
||||
VendorSkuID: utils.Interface2String(x["sku_id"]),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(x["sku_id"]), 0)),
|
||||
Name: utils.Interface2String(x["food_name"]),
|
||||
SalePrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(x["price"])),
|
||||
Count: int(utils.MustInterface2Int64(x["quantity"])),
|
||||
SkuBoxMoney: jxutils.StandardPrice2Int(utils.MustInterface2Float64(x["box_price"])) * jxutils.StandardPrice2Int(utils.MustInterface2Float64(x["box_num"])),
|
||||
IsAfsOrder: 0,
|
||||
}
|
||||
orderFinancial.Skus = append(orderFinancial.Skus, orderSkuFinancial)
|
||||
orderFinancial.SalePriceMoney += orderSkuFinancial.SalePrice * int64(orderSkuFinancial.Count)
|
||||
orderFinancial.SkuBoxMoney += orderSkuFinancial.SkuBoxMoney
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm OrderDetail2Financial, orderID:%s have no detail", orderFinancial.VendorOrderID)
|
||||
}
|
||||
extras := result["extras"]
|
||||
if extras != nil {
|
||||
var data []map[string]interface{}
|
||||
utils.UnmarshalUseNumber([]byte(utils.Interface2String(extras)), &data)
|
||||
for _, x := range data {
|
||||
if x["rider_fee"] == nil {
|
||||
activity := &model.OrderDiscountFinancial{
|
||||
VendorID: orderFinancial.VendorID,
|
||||
VendorOrderID: orderFinancial.VendorOrderID,
|
||||
// ActivityName: utils.Interface2String(x["remark"]),
|
||||
// ActivityMoney: jxutils.StandardPrice2Int(utils.MustInterface2Float64(x["reduce_fee"])),
|
||||
// VendorActivityID: utils.Int64ToStr(utils.MustInterface2Int64(x["act_detail_id"])),
|
||||
}
|
||||
if x["act_detail_id"] != nil { // 容错处理
|
||||
activity.VendorActivityID = utils.Int64ToStr(utils.MustInterface2Int64(x["act_detail_id"]))
|
||||
orderFinancial.Discounts = append(orderFinancial.Discounts, activity)
|
||||
}
|
||||
// 通过活动Id去取,京西活动补贴
|
||||
// orderFinancial.JxSubsidyMoney +=
|
||||
}
|
||||
}
|
||||
}
|
||||
poiReceiveDetail := result["poi_receive_detail"]
|
||||
if poiReceiveDetail != nil {
|
||||
var data map[string]interface{}
|
||||
utils.UnmarshalUseNumber([]byte(utils.Interface2String(poiReceiveDetail)), &data)
|
||||
orderFinancial.ReceivableFreight = utils.MustInterface2Int64(data["logisticsFee"])
|
||||
orderFinancial.FreightMoney = utils.MustInterface2Int64(data["logisticsFee"])
|
||||
orderFinancial.ActualPayMoney = utils.MustInterface2Int64(data["onlinePayment"])
|
||||
orderFinancial.PmMoney = utils.MustInterface2Int64(data["foodShareFeeChargeByPoi"])
|
||||
orderFinancial.ShopMoney = utils.MustInterface2Int64(data["wmPoiReceiveCent"])
|
||||
for _, x := range data["actOrderChargeByMt"].([]interface{}) {
|
||||
orderFinancial.TotalDiscountMoney += utils.MustInterface2Int64(x.(map[string]interface{})["moneyCent"])
|
||||
orderFinancial.PmSubsidyMoney += utils.MustInterface2Int64(x.(map[string]interface{})["moneyCent"])
|
||||
}
|
||||
for _, x := range data["actOrderChargeByPoi"].([]interface{}) {
|
||||
orderFinancial.TotalDiscountMoney += utils.MustInterface2Int64(x.(map[string]interface{})["moneyCent"])
|
||||
}
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm OrderDetail2Financial, orderID:%s have no poi_receive_detail", orderFinancial.VendorOrderID)
|
||||
}
|
||||
if utils.MustInterface2Int64(result["is_third_shipping"]) == SelfDeliveryCarrierNo { // is_third_shipping int 是否是第三方配送平台配送,0表否,1表是)
|
||||
orderFinancial.SelfDeliveryDiscountMoney = orderFinancial.ReceivableFreight
|
||||
orderFinancial.DistanceFreightMoney = 0
|
||||
// 通过本地数据库去取是否转美团/达达,并计算运费
|
||||
// wayBill, err := partner.CurOrderManager.LoadWaybill(orderFinancial.VendorOrderID, orderFinancial.VendorID)
|
||||
// if err == nil {
|
||||
// orderFinancial.JxFreightMoney = wayBill.DesiredFee
|
||||
// }
|
||||
}
|
||||
// // 美团订单单独处理部分,美团正向订单接口推送时总结算金额没有计算公益捐款一分钱,是否在这里直接提前扣除?
|
||||
// // 3/18之后的订单一直都不显示公益捐款金额,而且结算现在结算到了3/18之后的订单,没有的已经不计算了,先注释
|
||||
// // 2019-04-03 10.52 询问赵mf, 此计划是必须参加的,而且是长期的,每单固定扣除一分钱
|
||||
orderFinancial.DonationMoney = PublicWelfareDonation
|
||||
// 不应该对第三方结账金额做更改,就算有异常,也要保留异常,知道问题出在哪里
|
||||
// orderFinancial.ShopMoney -= PublicWelfareDonation
|
||||
globals.SugarLogger.Debug(orderFinancial.VendorOrderID)
|
||||
return orderFinancial
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
func TestOnFinancialMsg(t *testing.T) {
|
||||
msg := &mtwmapi.CallbackMsg{
|
||||
Cmd: "orderRefund",
|
||||
FormData: url.Values{},
|
||||
}
|
||||
msg.FormData.Set("timestamp", utils.Int64ToStr(time.Now().Unix()))
|
||||
msg.FormData.Set("order_id", "33762863167364867")
|
||||
msg.FormData.Set("notify_type", "agree")
|
||||
msg.FormData.Set("money", "23.56")
|
||||
food := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"app_food_code": "123",
|
||||
"food_name": "商品1",
|
||||
"sku_id": "123",
|
||||
"refund_price": 3.14,
|
||||
"count": 2,
|
||||
"box_num": 1,
|
||||
"box_price": 1,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"app_food_code": "124",
|
||||
"food_name": "商品2",
|
||||
"sku_id": "124",
|
||||
"refund_price": 3.15,
|
||||
"count": 2,
|
||||
"box_num": 1,
|
||||
"box_price": 1,
|
||||
},
|
||||
}
|
||||
msg.FormData.Set("food", string(utils.MustMarshal(food)))
|
||||
res := CurPurchaseHandler.onAfsOrderMsg(msg)
|
||||
fmt.Println(res)
|
||||
}
|
||||
|
||||
func TestOnOrderDetail(t *testing.T) {
|
||||
result := map[string]interface{}{
|
||||
"app_order_code": "", "app_poi_code": "2828472", "avg_send_time": 2410, "backup_recipient_phone": "[\"13164714130_7645\"]", "caution": " 【如遇缺货】: 缺货时电话与我沟通 收餐人隐私号 13049813276_5307,手机号 139****5027", "city_id": 440300, "ctime": 1555036346, "day_seq": 1, "delivery_time": 0, "detail": "[{\"app_food_code\":\"27262\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"红管鱿鱼约250g/份\",\"food_property\":\"\",\"price\":23.54,\"quantity\":1,\"sku_id\":\"27262\",\"spec\":\"250g\",\"unit\":\"份\"},{\"app_food_code\":\"24987\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"带皮猪梅花肉约250g/份\",\"food_property\":\"\",\"price\":15.84,\"quantity\":1,\"sku_id\":\"24987\",\"spec\":\"250g\",\"unit\":\"份\"},{\"app_food_code\":\"27179\",\"box_num\":0,\"box_price\":0,\"cart_id\":0,\"food_discount\":1,\"food_name\":\"[畅销]龙骨约250g/份\",\"food_property\":\"\",\"price\":18.59,\"quantity\":1,\"sku_id\":\"27179\",\"spec\":\"250g\",\"unit\":\"份\"}]", "dinners_number": 0, "expect_deliver_time": 0, "extras": "[{\"act_detail_id\":664795195,\"mt_charge\":0,\"poi_charge\":5,\"reduce_fee\":5,\"remark\":\"满46.0元减5.0元\",\"type\":2},{\"act_detail_id\":665051798,\"mt_charge\":0,\"poi_charge\":4,\"reduce_fee\":4,\"remark\":\"减配送费4.0元\",\"type\":25},{\"act_detail_id\":274839715,\"mt_charge\":0.5,\"poi_charge\":0,\"reduce_fee\":0.5,\"remark\":\"用户使用了支付红包减0.5元\",\"type\":9},{\"mt_charge\":0,\"poi_charge\":0,\"reduce_fee\":0,\"remark\":\"送30元商家代金券\",\"type\":100},{}]", "has_invoiced": 0, "invoice_title": "", "is_favorites": false, "is_poi_first_order": true, "is_pre": 0, "is_third_shipping": 0, "latitude": 22.530194, "logistics_code": "1001", "longitude": 114.08372, "order_id": 28284722536001020, "order_send_time": 1555036356, "original_price": 63.97, "package_bag_money": 0, "pay_type": 2, "pick_type": 0, "poi_receive_detail": "{\"actOrderChargeByMt\":[{\"comment\":\"活动款\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":50}],\"actOrderChargeByPoi\":[{\"comment\":\"满46.0元减5.0元\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":500},{\"comment\":\"减配送费4.0元\",\"feeTypeDesc\":\"活动款\",\"feeTypeId\":10019,\"moneyCent\":400}],\"foodShareFeeChargeByPoi\":490,\"logisticsFee\":600,\"onlinePayment\":5447,\"wmPoiReceiveCent\":4406}", "recipient_address": "汇港名苑 (南2区1005)@#广东省深圳市福田区滨河大道滨河大道3119号汇港名苑", "recipient_name": "颜(女士)", "recipient_phone": "13049813276_5307", "remark": "", "result": "ok", "shipper_phone": "", "shipping_fee": 6, "shipping_type": 0, "source_id": 3, "status": 2, "taxpayer_id": "", "total": 54.47, "utime": 1555036346, "wm_order_id_view": 28284722536001020, "wm_poi_address": "深圳市福田区南园街道南华社区滨河路2037号下小庙南区70栋101号滨河街市场", "wm_poi_id": 2828472, "wm_poi_name": "京西菜市(华强南店)", "wm_poi_phone": "13724313878",
|
||||
}
|
||||
err := new(PurchaseHandler).OnOrderDetail(result, partner.CreatedPeration)
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
CurPurchaseHandler *PurchaseHandler
|
||||
)
|
||||
|
||||
type PurchaseHandler struct {
|
||||
partner.BasePurchasePlatform
|
||||
putils.DefSingleStorePlatform
|
||||
|
||||
storeIDs []string
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
func init() {
|
||||
if api.MtwmAPI != nil {
|
||||
CurPurchaseHandler = New()
|
||||
partner.RegisterPurchasePlatform(CurPurchaseHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func New() (obj *PurchaseHandler) {
|
||||
obj = new(PurchaseHandler)
|
||||
obj.ISingleStoreStoreSkuHandler = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetVendorID() int {
|
||||
return model.VendorIDMTWM
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error) {
|
||||
cats, err := api.MtwmAPI.RetailGetSpTagIds()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vendorCatMapList := make([]map[string]*model.SkuVendorCategory, 3)
|
||||
manID := 10000
|
||||
for i := 0; i < 3; i++ {
|
||||
vendorCatMapList[i] = make(map[string]*model.SkuVendorCategory)
|
||||
for _, v := range cats {
|
||||
if v.Level == 3 {
|
||||
namePathList := strings.Split(strings.Trim(v.NamePath, ","), ",")
|
||||
if len(namePathList) != 3 {
|
||||
panic(fmt.Sprintf("%s没有三级结构", v.NamePath))
|
||||
}
|
||||
name := namePathList[i]
|
||||
if _, ok := vendorCatMapList[i][name]; !ok {
|
||||
cat := &model.SkuVendorCategory{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
Name: name, //utils.Interface2String(v["name"]),
|
||||
Level: i + 1, //int(utils.MustInterface2Int64(v["level"])),
|
||||
}
|
||||
vendorCats = append(vendorCats, cat)
|
||||
vendorCatMapList[i][name] = cat
|
||||
if i == 2 {
|
||||
cat.IsLeaf = 1
|
||||
cat.VendorCategoryID = utils.Int64ToStr(v.ID)
|
||||
} else {
|
||||
cat.VendorCategoryID = utils.Int2Str(manID) // 非叶子结点编码没有实际使用
|
||||
manID++
|
||||
}
|
||||
if i > 0 {
|
||||
cat.ParentID = vendorCatMapList[i-1][namePathList[i-1]].VendorCategoryID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vendorCats, nil
|
||||
}
|
||||
|
||||
func rangeMtwm2JX(areaStr string) string {
|
||||
var area []interface{}
|
||||
if err := utils.UnmarshalUseNumber([]byte(areaStr), &area); err == nil {
|
||||
if len(area) > 0 {
|
||||
coordList := make([]string, len(area))
|
||||
for k, v := range area {
|
||||
vv := v.(map[string]interface{})
|
||||
coordList[k] = fmt.Sprintf("%.6f,%.6f", jxutils.IntCoordinate2Standard(int(utils.ForceInterface2Int64(vv["x"]))), jxutils.IntCoordinate2Standard(int(utils.ForceInterface2Int64(vv["y"]))))
|
||||
}
|
||||
return strings.Join(coordList, ";")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func rangeJX2Mtwm(coords string) string {
|
||||
pairs := strings.Split(strings.Trim(coords, ";"), ";")
|
||||
if len(pairs) > 0 {
|
||||
coordList := make([]map[string]interface{}, len(pairs))
|
||||
for k, v := range pairs {
|
||||
pair := strings.Split(v, ",")
|
||||
coordList[k] = map[string]interface{}{
|
||||
"x": jxutils.StandardCoordinate2Int(utils.Str2Float64(pair[0])),
|
||||
"y": jxutils.StandardCoordinate2Int(utils.Str2Float64(pair[1])),
|
||||
}
|
||||
}
|
||||
return string(utils.MustMarshal(coordList))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func openTimeMtwm2JX(vendorOpenTime string) (opTimeList []int16) {
|
||||
timePairs := strings.Split(vendorOpenTime, ",")
|
||||
for _, v := range timePairs {
|
||||
times := strings.Split(v, "-")
|
||||
if len(times) >= 2 {
|
||||
opTimeList = append(opTimeList, jxutils.StrTime2JxOperationTime(times[0]+":00", 700), jxutils.StrTime2JxOperationTime(times[1]+":00", 2000))
|
||||
}
|
||||
}
|
||||
return opTimeList
|
||||
}
|
||||
|
||||
func openTimeJX2Mtwm(opTimeList []int16) string {
|
||||
timesLen := len(opTimeList) / 2 * 2
|
||||
var strPairs []string
|
||||
for i := 0; i < timesLen; i += 2 {
|
||||
if opTimeList[i] != 0 {
|
||||
strPairs = append(strPairs, jxutils.JxOperationTime2StrTime(opTimeList[i])+"-"+jxutils.JxOperationTime2StrTime(opTimeList[i+1]))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return strings.Join(strPairs, ",")
|
||||
}
|
||||
|
||||
func bizStatusMtwm2JX(openLevel, online int) int {
|
||||
if online != mtwmapi.PoiStatusOnline {
|
||||
return model.StoreStatusDisabled
|
||||
} else {
|
||||
if openLevel == mtwmapi.PoiOpenLevelHaveRest {
|
||||
return model.StoreStatusClosed
|
||||
}
|
||||
}
|
||||
return model.StoreStatusOpened
|
||||
}
|
||||
|
||||
func bizStatusJX2Mtwm(status int) (openLevel, online int) {
|
||||
if status == model.StoreStatusDisabled {
|
||||
return mtwmapi.PoiOpenLevelHaveRest, mtwmapi.PoiStatusOnline //mtwmapi.PoiStatusOffline
|
||||
} else if status == model.StoreStatusHaveRest || status == model.StoreStatusClosed {
|
||||
return mtwmapi.PoiOpenLevelHaveRest, mtwmapi.PoiStatusOnline
|
||||
}
|
||||
return mtwmapi.PoiOpenLevelNormal, mtwmapi.PoiStatusOnline
|
||||
}
|
||||
|
||||
func skuStatusJX2Mtwm(status int) int {
|
||||
if status == model.SkuStatusNormal {
|
||||
return mtwmapi.SellStatusOnline
|
||||
}
|
||||
return mtwmapi.SellStatusOffline
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error) {
|
||||
globals.SugarLogger.Debugf("mtwm UploadImg imgURL:%s, imgName:%s", imgURL, imgName)
|
||||
poiCode4UploadImg := p.getUploadImgPoiCode()
|
||||
if poiCode4UploadImg == "" {
|
||||
return "", fmt.Errorf("找不到一个美团门店来上传图片")
|
||||
}
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if imgType > model.ImgTypeLocal {
|
||||
if imgData != nil {
|
||||
imgHint, err = api.MtwmAPI.ImageUpload(poiCode4UploadImg, imgName, imgData)
|
||||
} else {
|
||||
imgHint, err = api.MtwmAPI.ImageUploadByURL(poiCode4UploadImg, imgName, imgURL)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imgHint = utils.GetUpperUUID()
|
||||
}
|
||||
return imgHint, err
|
||||
}
|
||||
|
||||
func getStoreIDFromList(storeIDs []string) (poiCode string) {
|
||||
if len(storeIDs) > 0 {
|
||||
poiCode = storeIDs[0]
|
||||
}
|
||||
return poiCode
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getUploadImgPoiCode() (poiCode string) {
|
||||
var storeIDs []string
|
||||
p.locker.RLock()
|
||||
storeIDs = p.storeIDs
|
||||
p.locker.RUnlock()
|
||||
if len(storeIDs) > 0 {
|
||||
return getStoreIDFromList(storeIDs)
|
||||
}
|
||||
|
||||
p.locker.Lock()
|
||||
storeIDs = p.storeIDs
|
||||
if len(storeIDs) > 0 {
|
||||
p.locker.Unlock()
|
||||
return getStoreIDFromList(storeIDs)
|
||||
}
|
||||
|
||||
defer p.locker.Unlock()
|
||||
storeIDs, err := api.MtwmAPI.PoiGetIDs()
|
||||
if err == nil {
|
||||
if len(storeIDs) > 0 {
|
||||
p.storeIDs = storeIDs
|
||||
poiCode = getStoreIDFromList(storeIDs)
|
||||
} else {
|
||||
// p.storeIDs = []string{""}
|
||||
}
|
||||
}
|
||||
return poiCode
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
||||
)
|
||||
|
||||
const (
|
||||
testShopVendorID = "2523687"
|
||||
testShopID = 2
|
||||
)
|
||||
|
||||
func init() {
|
||||
testinit.Init()
|
||||
}
|
||||
|
||||
func TestGetVendorCategories(t *testing.T) {
|
||||
result, err := new(PurchaseHandler).GetVendorCategories(jxcontext.AdminCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
@@ -1,797 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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 (
|
||||
FakeMsgType = "fakeMsgType"
|
||||
|
||||
fakeFinishedPickup = "fake_finished_pickup"
|
||||
fakeUserApplyCancel = "fake_user_apply_cancel"
|
||||
fakeMerchantAgreeApplyCancel = "fake_merchant_agree_apply_cancel"
|
||||
fakeRefuseUserApplyCancel = "fake_refuse_user_apply_cancel"
|
||||
fakeUserUndoApplyCancel = "fake_user_undo_apply_cancel"
|
||||
fakeOrderAdjustFinished = "fake_order_adjust_finished"
|
||||
|
||||
keyVendorOrgCode = "vendorOrgCode"
|
||||
)
|
||||
|
||||
const (
|
||||
SelfDeliveryCarrierNo = 1 // 美团配送方式:0-美团专送,1-商家自送
|
||||
)
|
||||
|
||||
const (
|
||||
// pickupOrderDelay = 260 * time.Second
|
||||
// pickupOrderDelay = 1 * time.Second
|
||||
|
||||
// callDeliveryDelay = 10 * time.Minute
|
||||
// callDeliveryDelayGap = 30
|
||||
)
|
||||
|
||||
var (
|
||||
specPat = regexp.MustCompile(`(\d+)(.+)`)
|
||||
)
|
||||
|
||||
var (
|
||||
VendorStatus2StatusMap = map[string]int{
|
||||
mtwmapi.OrderStatusUserCommitted: model.OrderStatusUnknown,
|
||||
mtwmapi.OrderStatusNew: model.OrderStatusNew,
|
||||
// mtwmapi.OrderStatusReceived: model.OrderStatusAccepted,
|
||||
// mtwmapi.OrderStatusAccepted: model.OrderStatusFinishedPickup,
|
||||
mtwmapi.OrderStatusAccepted: model.OrderStatusAccepted,
|
||||
|
||||
mtwmapi.OrderStatusDelivering: model.OrderStatusDelivering,
|
||||
mtwmapi.OrderStatusDelivered: model.OrderStatusUnknown, // 以mtwmapi.OrderStatusFinished为结束状态,这个当成一个中间状态(且很少看到这个状态)
|
||||
mtwmapi.OrderStatusFinished: model.OrderStatusFinished,
|
||||
mtwmapi.OrderStatusCanceled: model.OrderStatusCanceled,
|
||||
|
||||
fakeFinishedPickup: model.OrderStatusFinishedPickup,
|
||||
fakeOrderAdjustFinished: model.OrderStatusAdjust,
|
||||
fakeRefuseUserApplyCancel: model.OrderStatusVendorRejectCancel,
|
||||
fakeUserApplyCancel: model.OrderStatusApplyCancel,
|
||||
fakeUserUndoApplyCancel: model.OrderStatusUndoApplyCancel,
|
||||
fakeMerchantAgreeApplyCancel: model.OrderStatusCanceled,
|
||||
}
|
||||
|
||||
skuActTypeMap = map[int]int{
|
||||
mtwmapi.ExtrasPromotionTypeTeJiaCai: 1,
|
||||
mtwmapi.ExtrasPromotionTypeZheKouCai: 1,
|
||||
mtwmapi.ExtrasPromotionTypeSecondHalfPrice: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, orderMap map[string]interface{}, err error) {
|
||||
result, err := api.MtwmAPI.OrderGetOrderDetail(utils.Str2Int64(vendorOrderID), true)
|
||||
if err == nil {
|
||||
result[keyVendorOrgCode] = vendorOrgCode
|
||||
order = p.Map2Order(result)
|
||||
}
|
||||
return order, result, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) {
|
||||
order, _, err = p.getOrder(vendorOrgCode, vendorOrderID)
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
status, err = api.MtwmAPI.OrderViewStatus(utils.Str2Int64(vendorOrderID))
|
||||
if err == nil {
|
||||
status = p.getStatusFromVendorStatus(utils.Int2Str(status))
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := orderData
|
||||
vendorOrderID := utils.Int64ToStr(utils.MustInterface2Int64(result["order_id"]))
|
||||
// 因为美团外卖不能自动设置商家门店号,且只能通过商家门店号来访问门店,
|
||||
// 为了在后台设置简单一致,把app_poi_code直接当成平台门店号使用(即在后台设置时,平台门店号与商家门店号一样)
|
||||
// 订单中wm_poi_id实际来平台门店号,app_poi_code为商家门店号,这样一来,这两个就相同了
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: vendorOrderID,
|
||||
// VendorOrderID2: utils.Int64ToStr(utils.MustInterface2Int64(result["wm_order_id_view"])),
|
||||
VendorID: model.VendorIDMTWM,
|
||||
VendorStoreID: result["app_poi_code"].(string),
|
||||
StoreID: 0,
|
||||
// VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["wm_poi_id"])),
|
||||
// StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["app_poi_code"]), 0)),
|
||||
StoreName: result["wm_poi_name"].(string),
|
||||
ConsigneeName: result["recipient_name"].(string),
|
||||
ConsigneeMobile: jxutils.FormalizeMobile(result["recipient_phone"].(string)),
|
||||
ConsigneeAddress: result["recipient_address"].(string),
|
||||
CoordinateType: model.CoordinateTypeMars,
|
||||
BuyerComment: utils.TrimBlankChar(utils.Interface2String(result["caution"])),
|
||||
ExpectedDeliveredTime: getTimeFromTimestamp(utils.Interface2Int64WithDefault(result["delivery_time"], 0)),
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(result["status"])),
|
||||
OrderSeq: int(utils.MustInterface2Int64(result["day_seq"])),
|
||||
StatusTime: getTimeFromTimestamp(utils.MustInterface2Int64(result["ctime"])),
|
||||
OrderCreatedAt: getTimeFromTimestamp(utils.MustInterface2Int64(result["ctime"])),
|
||||
// OrderFinishedAt: getTimeFromTimestamp(utils.MustInterface2Int64(result["order_completed_time"])),
|
||||
OriginalData: string(utils.MustMarshal(result)),
|
||||
ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["total"])),
|
||||
BaseFreightMoney: jxutils.StandardPrice2Int(utils.Interface2Float64WithDefault(result["shipping_fee"], 0)),
|
||||
|
||||
InvoiceTitle: utils.Interface2String(result["invoice_title"]),
|
||||
InvoiceTaxerID: utils.Interface2String(result["taxpayer_id"]),
|
||||
InvoiceEmail: jxutils.GetOneEmailFromStr(utils.Interface2String(result["caution"])),
|
||||
|
||||
VendorOrgCode: utils.Interface2String(result[keyVendorOrgCode]),
|
||||
}
|
||||
if result["order_completed_time"] != nil {
|
||||
order.OrderFinishedAt = getTimeFromTimestamp(utils.MustInterface2Int64(result["order_completed_time"]))
|
||||
} else {
|
||||
order.OrderFinishedAt = utils.DefaultTimeValue
|
||||
}
|
||||
pickType := int(utils.Interface2Int64WithDefault(result["pick_type"], 0))
|
||||
if pickType == mtwmapi.OrderPickTypeSelf {
|
||||
order.DeliveryType = model.OrderDeliveryTypeSelfTake
|
||||
} else {
|
||||
logisticsCode := utils.Interface2String(result["logistics_code"])
|
||||
if logisticsCode == mtwmapi.PeiSongTypeSelf {
|
||||
order.DeliveryType = model.OrderDeliveryTypeStoreSelf
|
||||
} else {
|
||||
order.DeliveryType = model.OrderDeliveryTypePlatform
|
||||
}
|
||||
}
|
||||
openUID := utils.Interface2Int64WithDefault(result["openUid"], 0)
|
||||
if openUID > 0 {
|
||||
order.VendorUserID = utils.Int64ToStr(openUID)
|
||||
}
|
||||
// 不设置最晚拣货时间,以缺省值为准
|
||||
// if utils.IsTimeZero(order.PickDeadline) && !utils.IsTimeZero(order.StatusTime) {
|
||||
// order.PickDeadline = order.StatusTime.Add(pickupOrderDelay) // 美团外卖要求在5分钟内拣货,不然订单会被取消
|
||||
// }
|
||||
order.Status = p.getStatusFromVendorStatus(order.VendorStatus)
|
||||
if utils.IsTimeZero(order.ExpectedDeliveredTime) {
|
||||
order.BusinessType = model.BusinessTypeImmediate
|
||||
} else {
|
||||
order.BusinessType = model.BusinessTypeDingshida
|
||||
}
|
||||
|
||||
originalLng := utils.MustInterface2Float64(result["longitude"])
|
||||
originalLat := utils.MustInterface2Float64(result["latitude"])
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(originalLng)
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(originalLat)
|
||||
|
||||
var detail []map[string]interface{}
|
||||
if err := utils.UnmarshalUseNumber([]byte(result["detail"].(string)), &detail); err != nil {
|
||||
panic(fmt.Sprintf("mtwm Map2Order vendorID:%s failed with error:%v", vendorOrderID, err))
|
||||
}
|
||||
|
||||
// 添加需要赠送的东西
|
||||
if result["extras"] != nil {
|
||||
var extraList []*mtwmapi.OrderExtraInfo
|
||||
if err := utils.UnmarshalUseNumber([]byte(result["extras"].(string)), &extraList); err != nil {
|
||||
panic(fmt.Sprintf("mtwm Map2Order vendorID:%s failed with error:%v", vendorOrderID, err))
|
||||
}
|
||||
for _, extra := range extraList {
|
||||
order.DiscountMoney += jxutils.StandardPrice2Int(extra.ReduceFee)
|
||||
if extra.Type == mtwmapi.ExtrasPromotionTypeTaoCanZeng || extra.Type == mtwmapi.ExtrasPromotionTypeManZeng {
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: model.VendorIDMTWM,
|
||||
Count: 1,
|
||||
SkuID: 0,
|
||||
VendorSkuID: "",
|
||||
SkuName: extra.Remark,
|
||||
Weight: 0,
|
||||
SalePrice: 0,
|
||||
StoreSubName: utils.Int2Str(extra.Type),
|
||||
}
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if poiReceiveDetailStr := utils.Interface2String(result["poi_receive_detail"]); poiReceiveDetailStr != "" {
|
||||
var poiReceiveDetail *mtwmapi.PoiReceiveDetailInfo
|
||||
utils.UnmarshalUseNumber([]byte(poiReceiveDetailStr), &poiReceiveDetail)
|
||||
if poiReceiveDetail != nil {
|
||||
order.TotalShopMoney = poiReceiveDetail.WmPoiReceiveCent
|
||||
for _, v := range poiReceiveDetail.ActOrderChargeByMt {
|
||||
order.PmSubsidyMoney += v.MoneyCent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var skuBenefitDetailMap map[string]*mtwmapi.SkuBenefitDetailInfo
|
||||
if skuBenefitDetai := utils.Interface2String(result["sku_benefit_detail"]); skuBenefitDetai != "" {
|
||||
skuBenefitDetailMap = make(map[string]*mtwmapi.SkuBenefitDetailInfo)
|
||||
var skuBenefitDetailList []*mtwmapi.SkuBenefitDetailInfo
|
||||
utils.UnmarshalUseNumber([]byte(skuBenefitDetai), &skuBenefitDetailList)
|
||||
for _, v := range skuBenefitDetailList {
|
||||
skuBenefitDetailMap[v.SkuID] = v
|
||||
}
|
||||
}
|
||||
ignoreSkuMap := make(map[int]int)
|
||||
// detail := result["detail"].([]interface{})
|
||||
multiSkuMap := make(map[int]int)
|
||||
for _, product := range detail {
|
||||
// product := product2.(map[string]interface{})
|
||||
skuName := product["food_name"].(string)
|
||||
skuID := utils.Interface2String(product["sku_id"])
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
VendorID: model.VendorIDMTWM,
|
||||
Count: int(utils.MustInterface2Float64(product["quantity"])),
|
||||
SkuID: int(utils.Str2Int64WithDefault(skuID, 0)),
|
||||
VendorSkuID: skuID,
|
||||
SkuName: skuName,
|
||||
Weight: getSkuWeight(product),
|
||||
VendorPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])),
|
||||
SalePrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"])),
|
||||
}
|
||||
if sku.Weight == 0 {
|
||||
sku.Weight = 222 // 如果名字里找不到缺省给半斤左右的一个特别值
|
||||
}
|
||||
if skuBenefitDetailMap != nil && skuBenefitDetailMap[sku.VendorSkuID] != nil && ignoreSkuMap[sku.SkuID] == 0 /* && sku.Count == 1 */ {
|
||||
for _, v := range skuBenefitDetailMap[sku.VendorSkuID].WmAppOrderActDetails {
|
||||
if /*skuActTypeMap[v.Type] == 1 && */ strings.Index(v.Remark, skuName) >= 0 && sku.Count == v.Count {
|
||||
if sku.SalePrice-jxutils.StandardPrice2Int(v.MtCharge+v.PoiCharge) < 0 {
|
||||
continue
|
||||
} else {
|
||||
ignoreSkuMap[sku.SkuID] = 1
|
||||
sku.SalePrice -= jxutils.StandardPrice2Int(v.MtCharge + v.PoiCharge)
|
||||
}
|
||||
sku.StoreSubName = utils.Int2Str(v.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
if sku.SalePrice < 0 {
|
||||
sku.SalePrice = jxutils.StandardPrice2Int(utils.MustInterface2Float64(product["price"]))
|
||||
}
|
||||
// if product["isGift"].(bool) {
|
||||
// sku.SkuType = 1
|
||||
// }
|
||||
order.Skus = append(order.Skus, sku)
|
||||
multiSkuMap[sku.SkuID]++
|
||||
}
|
||||
for _, v := range order.Skus {
|
||||
if multiSkuMap[v.SkuID] > 1 && v.SalePrice == v.VendorPrice {
|
||||
v.IsVendorAct = model.YES
|
||||
}
|
||||
}
|
||||
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
return order
|
||||
}
|
||||
|
||||
func getRefundSkuDetailList(msg *mtwmapi.CallbackMsg) (skuList []*mtwmapi.RefundSkuDetail, err error) {
|
||||
if false {
|
||||
skuList = api.MtwmAPI.GetRefundSkuDetailFromMsg(msg)
|
||||
} else {
|
||||
refundOrderDetailList, err2 := api.MtwmAPI.GetOrderRefundDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), mtwmapi.RefundTypePart)
|
||||
if err = err2; err == nil {
|
||||
for _, v := range refundOrderDetailList {
|
||||
skuList = append(skuList, v.WmAppRetailForOrderPartRefundList...)
|
||||
}
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("getRefundSkuDetailList orderID:%s skuList:%s", GetOrderIDFromMsg(msg), utils.Format4Output(skuList, true))
|
||||
return skuList, err
|
||||
}
|
||||
|
||||
func getSkuWeight(product map[string]interface{}) (weight int) {
|
||||
if weight = int(utils.Interface2Int64WithDefault(product["weight"], 0)); weight == 0 {
|
||||
searchResult := specPat.FindStringSubmatch(product["spec"].(string))
|
||||
if len(searchResult) == 3 {
|
||||
weight = jxutils.FormatSkuWeight(float32(utils.Str2Float64WithDefault(searchResult[1], 0)), utils.TrimBlankChar(searchResult[2]))
|
||||
}
|
||||
if weight == 0 {
|
||||
_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(product["food_name"].(string))
|
||||
weight = jxutils.FormatSkuWeight(specQuality, specUnit)
|
||||
}
|
||||
}
|
||||
return weight
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onOrderMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) {
|
||||
var err error
|
||||
if c.isAfsMsg(msg) {
|
||||
response = c.OnAfsOrderMsg(msg)
|
||||
} else {
|
||||
status := c.callbackMsg2Status(msg)
|
||||
if partner.CurOrderManager.GetStatusDuplicatedCount(status) > 0 {
|
||||
return nil
|
||||
}
|
||||
if msg.Cmd == mtwmapi.MsgTypeNewOrder {
|
||||
order, orderMap, err2 := c.getOrder(msg.AppID, GetOrderIDFromMsg(msg))
|
||||
if err = err2; err == nil {
|
||||
err = partner.CurOrderManager.OnOrderNew(order, c.callbackMsg2Status(msg))
|
||||
if err == nil {
|
||||
utils.CallFuncAsync(func() {
|
||||
if msg.Cmd == mtwmapi.MsgTypeNewOrder {
|
||||
c.OnOrderDetail(orderMap, partner.CreatedPeration)
|
||||
} else {
|
||||
c.OnOrderDetail(orderMap, partner.UpdatedPeration)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if status != nil {
|
||||
if status.Status == model.OrderStatusAdjust {
|
||||
var order *model.GoodsOrder
|
||||
if order, err = c.GetOrder(msg.AppID, GetOrderIDFromMsg(msg)); err == nil {
|
||||
skuList, err2 := getRefundSkuDetailList(msg)
|
||||
if err = err2; err == nil {
|
||||
var removedSkuList []*model.OrderSku
|
||||
for _, mtwmSku := range skuList {
|
||||
order.ActualPayPrice -= jxutils.StandardPrice2Int(mtwmSku.RefundPrice) * int64(mtwmSku.Count)
|
||||
removedSkuList = append(removedSkuList, &model.OrderSku{
|
||||
SkuID: int(utils.Str2Int64WithDefault(mtwmSku.SkuID, 0)),
|
||||
Count: mtwmSku.Count,
|
||||
})
|
||||
}
|
||||
order = jxutils.RemoveSkuFromOrder(order, removedSkuList)
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
err = partner.CurOrderManager.OnOrderAdjust(order, status)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if status.Status == model.OrderStatusDelivering {
|
||||
// 美团订单即使时在配送状态时,如果之前没有调用过拣货完成,也会对门店指标生成影响,这里强制再调用拣货完成,且忽略错误
|
||||
utils.CallFuncAsync(func() {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.PreparationMealComplete(utils.Str2Int64(status.VendorOrderID))
|
||||
}
|
||||
})
|
||||
}
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged(msg.AppID, status)
|
||||
if err == nil && msg.Cmd == mtwmapi.MsgTypeOrderFinished {
|
||||
utils.CallFuncAsync(func() {
|
||||
orderMap, err := api.MtwmAPI.OrderGetOrderDetail(utils.Str2Int64(GetOrderIDFromMsg(msg)), true)
|
||||
if err == nil && utils.MustInterface2Int64(orderMap["is_third_shipping"]) == SelfDeliveryCarrierNo {
|
||||
c.OnOrderDetail(orderMap, partner.UpdatedPeration)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mtwmapi.Err2CallbackResponse(err, "")
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Status(msg *mtwmapi.CallbackMsg) (orderStatus *model.OrderStatus) {
|
||||
orderID := GetOrderIDFromMsg(msg)
|
||||
vendorStatus := msg.Cmd
|
||||
remark := ""
|
||||
statusTime := utils.Str2Int64(msg.FormData.Get("timestamp"))
|
||||
switch msg.Cmd {
|
||||
case mtwmapi.MsgTypeUserUrgeOrder, mtwmapi.MsgTypeOrderModified, mtwmapi.MsgTypeOrderFinancial:
|
||||
vendorStatus = msg.Cmd
|
||||
case mtwmapi.MsgTypeOrderCanceled:
|
||||
vendorStatus = mtwmapi.OrderStatusCanceled
|
||||
remark = msg.FormData.Get("reason")
|
||||
case FakeMsgType, mtwmapi.MsgTypeNewOrder, mtwmapi.MsgTypeOrderAccepted, mtwmapi.MsgTypeOrderFinished:
|
||||
vendorStatus = msg.FormData.Get("status")
|
||||
statusTime = utils.Str2Int64(msg.FormData.Get("utime"))
|
||||
case mtwmapi.MsgTypeOrderRefund, mtwmapi.MsgTypeOrderPartialRefund:
|
||||
notifyType := msg.FormData.Get("notify_type")
|
||||
vendorStatus = msg.Cmd + "-" + notifyType
|
||||
if true { // 已经提前判断了,到这里的都是售中
|
||||
remark = msg.FormData.Get("reason")
|
||||
if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
|
||||
if notifyType == mtwmapi.NotifyTypePartyApply {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
// goods, err := dao.GetSimpleOrder(dao.GetDB(), orderID)
|
||||
// if err == nil {
|
||||
// if goods.Status < model.OrderStatusDelivering {
|
||||
api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(orderID), "自动确认退款")
|
||||
// } else {
|
||||
// api.MtwmAPI.OrderRefundReject(utils.Str2Int64(orderID), "商品配送中,请联系门店。") // todo 京东与饿百都没有售前用户提出订单调整的,自动拒绝调整单
|
||||
// }
|
||||
// }
|
||||
}
|
||||
} else if notifyType == mtwmapi.NotifyTypeSuccess {
|
||||
vendorStatus = fakeOrderAdjustFinished
|
||||
}
|
||||
} else if msg.Cmd == mtwmapi.MsgTypeOrderRefund {
|
||||
if notifyType == mtwmapi.NotifyTypeApply {
|
||||
vendorStatus = fakeUserApplyCancel
|
||||
} else if notifyType == mtwmapi.NotifyTypeCancelRefund || notifyType == mtwmapi.NotifyTypeCancelRefundComplaint {
|
||||
vendorStatus = fakeUserUndoApplyCancel
|
||||
} else if notifyType == mtwmapi.NotifyTypeReject {
|
||||
vendorStatus = fakeRefuseUserApplyCancel
|
||||
} else if notifyType == mtwmapi.NotifyTypeSuccess {
|
||||
vendorStatus = fakeMerchantAgreeApplyCancel // todo 可能导致订单取消消息重复
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
globals.SugarLogger.Errorf("mtwm unkonw msg:%s", utils.Format4Output(msg, false))
|
||||
}
|
||||
if vendorStatus != "" {
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDMTWM,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: orderID,
|
||||
RefVendorID: model.VendorIDMTWM,
|
||||
VendorStatus: vendorStatus,
|
||||
Status: c.getStatusFromVendorStatus(vendorStatus),
|
||||
StatusTime: getTimeFromTimestamp(statusTime),
|
||||
Remark: remark,
|
||||
}
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) postFakeMsg(vendorOrderID, cmd, vendorStatus string) {
|
||||
msg := &mtwmapi.CallbackMsg{
|
||||
Cmd: cmd,
|
||||
FormData: make(url.Values),
|
||||
}
|
||||
timeStr := utils.Int64ToStr(time.Now().Unix())
|
||||
msg.FormData.Set(mtwmapi.KeyOrderID, vendorOrderID)
|
||||
msg.FormData.Set("status", vendorStatus)
|
||||
msg.FormData.Set("timestamp", timeStr)
|
||||
msg.FormData.Set("utime", timeStr)
|
||||
utils.CallFuncAsync(func() {
|
||||
c.onOrderMsg(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
|
||||
if isAcceptIt {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
// err = api.MtwmAPI.OrderReceived(utils.Str2Int64(order.VendorOrderID))
|
||||
err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID))
|
||||
if err != nil {
|
||||
if utils.IsErrMatch(err, utils.Int2Str(mtwmapi.ErrCodeOpFailed), []string{
|
||||
"订单已经确认过了",
|
||||
}) {
|
||||
err = nil
|
||||
} else {
|
||||
globals.SugarLogger.Warnf("mtwm AcceptOrRefuseOrder orderID:%s failed with err:%v", order.VendorOrderID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// if err == nil {
|
||||
// c.postFakeMsg(order.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusReceived)
|
||||
// }
|
||||
} else {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = c.CancelOrder(jxcontext.AdminCtx, order, "bu")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery)
|
||||
if !isSelfDelivery {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
// err = api.MtwmAPI.OrderConfirm(utils.Str2Int64(order.VendorOrderID))
|
||||
err = api.MtwmAPI.PreparationMealComplete(utils.Str2Int64(order.VendorOrderID))
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
c.postFakeMsg(order.VendorOrderID, FakeMsgType, fakeFinishedPickup)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
return err
|
||||
}
|
||||
|
||||
// 美团预定单不能转商家自送
|
||||
func (c *PurchaseHandler) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) {
|
||||
return order.BusinessType != model.BusinessTypeDingshida, nil
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.OrderLogisticsChange2Self(utils.Str2Int64(order.VendorOrderID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
// 您好,之前的答复已经更正为,调用变更配送状态的接口,会校验门店的配送类型。美团配送的门店即便转自配后因门店配送类型是美团配送所以无法调用接口变更配送状态。可提醒顾客点击确认收货。谢谢
|
||||
// 非自配送门店订单调用OrderArrived好像会报错:{"data":"ng","error":{"code":1038,"msg":"只允许商家配送调用该接口"}}
|
||||
// err = api.MtwmAPI.OrderArrived(utils.Str2Int64(order.VendorOrderID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm SelfDeliverDelivering orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.OrderDelivering(utils.Str2Int64(order.VendorOrderID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm SelfDeliverDelivered orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.OrderArrived(utils.Str2Int64(order.VendorOrderID))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getTimeFromTimestamp(timeStamp int64) time.Time {
|
||||
if timeStamp < 1538103149 { // 立即达订单给的是1(而不是空,0),1538103149不是特殊值,只是一个任意之前的时间,这样写可以处理
|
||||
return utils.DefaultTimeValue
|
||||
}
|
||||
return utils.Timestamp2Time(timeStamp)
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
err = errors.New("美团外卖还未实现GetOrderRealMobile")
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if isAgree {
|
||||
err = api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason)
|
||||
} else {
|
||||
err = api.MtwmAPI.OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if err = api.MtwmAPI.OrderCancel(utils.Str2Int64(order.VendorOrderID), reason, mtwmapi.CancelReasonOther); err == nil {
|
||||
// 调用开放平台接口取消订单,不推送取消订单消息和退款消息。
|
||||
c.postFakeMsg(order.VendorOrderID, mtwmapi.MsgTypeOrderCanceled, mtwmapi.OrderStatusCanceled)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
// 美团外卖必须要确认订单后才能调整单
|
||||
if order.Status < model.OrderStatusFinishedPickup {
|
||||
err = c.PickupGoods(order, false, ctx.GetUserName())
|
||||
}
|
||||
if err == nil {
|
||||
var skuList []*mtwmapi.RefundSku
|
||||
for _, sku := range removedSkuList {
|
||||
skuID := utils.Int2Str(jxutils.GetSkuIDFromOrderSku(sku))
|
||||
skuList = append(skuList, &mtwmapi.RefundSku{
|
||||
AppFoodCode: skuID,
|
||||
SkuID: skuID,
|
||||
Count: sku.Count,
|
||||
})
|
||||
}
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.OrderApplyPartRefund(utils.Str2Int64(order.VendorOrderID), reason, skuList)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ListOrders(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, queryDate time.Time, vendorStoreID string) (vendorOrderIDs []string, err error) {
|
||||
if utils.IsTimeZero(queryDate) {
|
||||
return nil, fmt.Errorf("queryDate必须指定")
|
||||
}
|
||||
queryDate = utils.Time2Date(queryDate)
|
||||
|
||||
var vendorStoreIDs []string
|
||||
if vendorStoreID == "" {
|
||||
vendorStoreIDs, err = c.GetAllStoresVendorID(ctx, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
vendorStoreIDs = []string{vendorStoreID}
|
||||
}
|
||||
task := tasksch.NewParallelTask("mtwm ListOrders", nil, ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorStoreID := batchItemList[0].(string)
|
||||
var orderIDs []string
|
||||
seqStart := 1
|
||||
i := 0
|
||||
for {
|
||||
batchSize := int(math.Min(math.Pow(2, float64(i*3)), float64(mtwmapi.MaxGap4GetOrderIdByDaySeq)))
|
||||
seqEnd := seqStart + batchSize - 1
|
||||
var tmpOrderIDs []int64
|
||||
if seqStart == seqEnd {
|
||||
if vendorOderID, err2 := api.MtwmAPI.GetOrderIdByDaySeqSingle(vendorStoreID, queryDate, seqStart); err2 == nil {
|
||||
tmpOrderIDs = []int64{vendorOderID}
|
||||
}
|
||||
} else {
|
||||
tmpOrderIDs, err = api.MtwmAPI.GetOrderIdByDaySeq(vendorStoreID, queryDate, seqStart, seqEnd)
|
||||
}
|
||||
if len(tmpOrderIDs) > 0 {
|
||||
for _, v := range tmpOrderIDs {
|
||||
orderIDs = append(orderIDs, utils.Int64ToStr(v))
|
||||
}
|
||||
}
|
||||
if err != nil || len(tmpOrderIDs) < batchSize {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
seqStart = seqEnd + 1
|
||||
i++
|
||||
}
|
||||
retVal = orderIDs
|
||||
return retVal, nil
|
||||
}, vendorStoreIDs)
|
||||
tasksch.HandleTask(task, parentTask, true).Run()
|
||||
orderList, err := task.GetResult(0)
|
||||
if err == nil && len(orderList) > 0 {
|
||||
vendorOrderIDs = make([]string, len(orderList))
|
||||
for k, v := range orderList {
|
||||
vendorOrderIDs[k] = v.(string)
|
||||
}
|
||||
}
|
||||
return vendorOrderIDs, err
|
||||
}
|
||||
|
||||
// func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, order *model.GoodsOrder, tipFee int64) (err error) {
|
||||
// if globals.EnableMtwmStoreWrite {
|
||||
// err = api.MtwmAPI.OrderUpdateTip(utils.Str2Int64(order.VendorOrderID), jxutils.IntPrice2Standard(tipFee))
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) GetOrderConsigneeNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) {
|
||||
offset := 0
|
||||
for {
|
||||
result, err2 := api.MtwmAPI.OrderBatchPullPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit)
|
||||
if err = err2; err == nil {
|
||||
for _, v := range result {
|
||||
v2 := &partner.OrderPhoneNumberInfo{
|
||||
VendorOrderID: utils.Int64ToStr(v.OrderID),
|
||||
PhoneNumber: v.RealPhoneNumber,
|
||||
}
|
||||
if v2.PhoneNumber == "" {
|
||||
v2.PhoneNumber = v.RealOrderPhoneNumber
|
||||
}
|
||||
numberList = append(numberList, v2)
|
||||
}
|
||||
if len(result) <= mtwmapi.MaxBatchPullPhoneNumberLimit {
|
||||
break
|
||||
}
|
||||
offset += mtwmapi.MaxBatchPullPhoneNumberLimit
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return numberList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderCourierNumber(ctx *jxcontext.Context, storeID int, vendorStoreID string) (numberList []*partner.OrderPhoneNumberInfo, err error) {
|
||||
offset := 0
|
||||
for {
|
||||
result, err2 := api.MtwmAPI.OrderGetRiderInfoPhoneNumber(vendorStoreID, offset, mtwmapi.MaxBatchPullPhoneNumberLimit)
|
||||
if err = err2; err == nil {
|
||||
for _, v := range result {
|
||||
numberList = append(numberList, &partner.OrderPhoneNumberInfo{
|
||||
VendorOrderID: utils.Int64ToStr(v.OrderID),
|
||||
PhoneNumber: v.RiderRealPhoneNumber,
|
||||
})
|
||||
}
|
||||
if len(result) <= mtwmapi.MaxBatchPullPhoneNumberLimit {
|
||||
break
|
||||
}
|
||||
offset += mtwmapi.MaxBatchPullPhoneNumberLimit
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return numberList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) onNumberDowngrade(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) {
|
||||
userNumberMap := make(map[string]*partner.OrderPhoneNumberInfo)
|
||||
courierNumberMap := make(map[string]*partner.OrderPhoneNumberInfo)
|
||||
orderMap := make(map[string]int)
|
||||
ctx := jxcontext.AdminCtx
|
||||
task := tasksch.NewParallelTask("美团外卖平台处理隐私号降级通知", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
step := batchItemList[0].(int)
|
||||
switch step {
|
||||
case 0:
|
||||
userNumberList, err2 := p.GetOrderConsigneeNumber(ctx, 0, "")
|
||||
if err = err2; err == nil {
|
||||
for _, v := range userNumberList {
|
||||
userNumberMap[v.VendorOrderID] = v
|
||||
orderMap[v.VendorOrderID] = 1
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
courierNumberList, err2 := p.GetOrderCourierNumber(ctx, 0, "")
|
||||
if err = err2; err == nil {
|
||||
for _, v := range courierNumberList {
|
||||
courierNumberMap[v.VendorOrderID] = v
|
||||
orderMap[v.VendorOrderID] = 1
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
orderList := jxutils.StringMap2List(orderMap)
|
||||
if len(orderList) > 0 {
|
||||
updateTask := tasksch.NewParallelTask("美团外卖平台处理隐私号降级通知/处理订单", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
vendorOrderID := batchItemList[0].(string)
|
||||
db := dao.GetDB()
|
||||
if userNumberMap[vendorOrderID] != nil {
|
||||
_, err = dao.UpdateEntityByKV(db, &model.GoodsOrder{}, map[string]interface{}{
|
||||
"ConsigneeMobile": userNumberMap[vendorOrderID].PhoneNumber,
|
||||
"ConsigneeMobile2": userNumberMap[vendorOrderID].PhoneNumber,
|
||||
}, map[string]interface{}{
|
||||
model.FieldVendorOrderID: vendorOrderID,
|
||||
model.FieldVendorID: model.VendorIDMTWM,
|
||||
})
|
||||
}
|
||||
if courierNumberMap[vendorOrderID] != nil {
|
||||
_, err = dao.UpdateEntityByKV(db, &model.Waybill{}, map[string]interface{}{
|
||||
"CourierMobile": courierNumberMap[vendorOrderID].PhoneNumber,
|
||||
}, map[string]interface{}{
|
||||
"VendorWaybillID": vendorOrderID,
|
||||
"WaybillVendorID": model.VendorIDMTWM,
|
||||
})
|
||||
}
|
||||
return retVal, err
|
||||
}, orderList)
|
||||
tasksch.HandleTask(updateTask, task, true).Run()
|
||||
_, err = updateTask.GetResult(0)
|
||||
}
|
||||
}
|
||||
return retVal, err
|
||||
}, []int{0, 1, 2})
|
||||
tasksch.HandleTask(task, nil, true).Run()
|
||||
return response
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
|
||||
orderInfo, err := api.MtwmAPI.GetDistributeOrderDetail(vendorOrderID, vendorStoreID)
|
||||
if err == nil {
|
||||
tipFee = jxutils.StandardPrice2Int(orderInfo.TipAmount)
|
||||
}
|
||||
return tipFee, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.OrderModityTips(vendorOrderID, vendorStoreID, jxutils.IntPrice2Standard(tipFee))
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
var (
|
||||
// AfsVendorStatus2StatusMap = map[int]int{
|
||||
// mtwmapi.ResTypePending: model.AfsOrderStatusWait4Approve,
|
||||
// mtwmapi.ResTypeMerchantRefused: model.AfsOrderStatusFailed,
|
||||
// mtwmapi.ResTypeMerchantAgreed: model.AfsOrderStatusFinished,
|
||||
// mtwmapi.ResTypeCSRefused: model.AfsOrderStatusFailed,
|
||||
// mtwmapi.ResTypeCSAgreed: model.AfsOrderStatusFinished,
|
||||
// mtwmapi.ResTypeTimeoutAutoAgreed: model.AfsOrderStatusFinished,
|
||||
// mtwmapi.ResTypeAutoAgreed: model.AfsOrderStatusFinished,
|
||||
// mtwmapi.ResTypeUserCancelApply: model.AfsOrderStatusFailed,
|
||||
// mtwmapi.ResTypeUserCancelComplain: model.AfsOrderStatusFailed,
|
||||
// }
|
||||
AfsVendorStatus2StatusMap = map[string]int{
|
||||
mtwmapi.NotifyTypeApply: model.AfsOrderStatusWait4Approve,
|
||||
mtwmapi.NotifyTypePartyApply: model.AfsOrderStatusWait4Approve,
|
||||
mtwmapi.NotifyTypeSuccess: model.AfsOrderStatusFinished,
|
||||
mtwmapi.NotifyTypeReject: model.AfsOrderStatusFailed,
|
||||
mtwmapi.NotifyTypeCancelRefund: model.AfsOrderStatusFailed,
|
||||
mtwmapi.NotifyTypeCancelRefundComplaint: model.AfsOrderStatusFailed,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) isAfsMsg(msg *mtwmapi.CallbackMsg) bool {
|
||||
if msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
|
||||
// refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
|
||||
orderID := utils.Str2Int64(GetOrderIDFromMsg(msg))
|
||||
status, err := api.MtwmAPI.OrderViewStatus(orderID)
|
||||
if err == nil {
|
||||
return utils.Int2Str(status) == mtwmapi.OrderStatusFinished
|
||||
}
|
||||
globals.SugarLogger.Warnf("mtwm isAfsMsg OrderGetOrderDetail2 orderID:%d failed with error:%v", orderID, err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) OnAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwmapi.CallbackResponse) {
|
||||
jxutils.CallMsgHandlerAsync(func() {
|
||||
retVal = c.onAfsOrderMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(GetOrderIDFromMsg(msg), model.VendorIDEBAI))
|
||||
return retVal
|
||||
}
|
||||
|
||||
// todo 对于退款与部分退款,order.go与这个文件中对于状态的处理不一致
|
||||
func (c *PurchaseHandler) onAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwmapi.CallbackResponse) {
|
||||
var err error
|
||||
orderStatus := c.callbackAfsMsg2Status(msg)
|
||||
needCallNew := orderStatus.Status == model.AfsOrderStatusWait4Approve || orderStatus.Status == model.AfsOrderStatusNew
|
||||
if !needCallNew {
|
||||
_, err := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, orderStatus.VendorID)
|
||||
if err != nil {
|
||||
if dao.IsNoRowsError(err) {
|
||||
needCallNew = true
|
||||
} else {
|
||||
return mtwmapi.Err2CallbackResponse(err, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needCallNew {
|
||||
var afsOrder *model.AfsOrder
|
||||
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
|
||||
if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
|
||||
afsOrder = &model.AfsOrder{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
AfsOrderID: orderStatus.VendorOrderID,
|
||||
VendorOrderID: orderStatus.RefVendorOrderID,
|
||||
VendorStoreID: "",
|
||||
StoreID: 0,
|
||||
AfsCreatedAt: utils.Timestamp2Time(refundData.Timestamp),
|
||||
VendorAppealType: "",
|
||||
AppealType: model.AfsAppealTypeRefund,
|
||||
VendorReasonType: "",
|
||||
ReasonType: model.AfsReasonNotOthers,
|
||||
ReasonDesc: utils.LimitUTF8StringLen(refundData.Reason, 1024),
|
||||
ReasonImgList: utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024),
|
||||
RefundType: model.AfsTypePartRefund,
|
||||
|
||||
VendorOrgCode: msg.AppID,
|
||||
// FreightUserMoney: afsInfo.OrderFreightMoney,
|
||||
// AfsFreightMoney: afsInfo.AfsFreight,
|
||||
// BoxMoney: afsInfo.PackagingMoney,
|
||||
// TongchengFreightMoney: afsInfo.TongchengFreightMoney,
|
||||
// SkuBoxMoney: afsInfo.MealBoxMoney,
|
||||
}
|
||||
for _, sku := range refundData.FoodList {
|
||||
orderSku := &model.OrderSkuFinancial{
|
||||
// VendorID: model.VendorIDMTWM,
|
||||
// AfsOrderID: afsOrder.AfsOrderID,
|
||||
// VendorOrderID: afsOrder.VendorOrderID,
|
||||
// VendorStoreID: afsOrder.VendorStoreID,
|
||||
// StoreID: afsOrder.StoreID,
|
||||
// IsAfsOrder: 1,
|
||||
|
||||
Count: sku.Count,
|
||||
// ConfirmTime: afsOrder.AfsCreateAt,
|
||||
VendorSkuID: sku.SkuID,
|
||||
SkuID: int(utils.Str2Int64WithDefault(sku.SkuID, 0)),
|
||||
Name: sku.FoodName,
|
||||
UserMoney: jxutils.StandardPrice2Int(sku.RefundPrice)*int64(sku.Count) + jxutils.StandardPrice2Int(sku.BoxPrice)*int64(sku.BoxNum),
|
||||
}
|
||||
afsOrder.SkuUserMoney += orderSku.UserMoney
|
||||
afsOrder.Skus = append(afsOrder.Skus, orderSku)
|
||||
}
|
||||
afsOrder.PmSubsidyMoney += afsOrder.RefundMoney - afsOrder.SkuUserMoney
|
||||
} else {
|
||||
if afsOrder = c.createAfsOrder(msg.FormData); afsOrder != nil {
|
||||
// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDMTWM); err2 == nil {
|
||||
// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg.FormData)
|
||||
afsOrder.AfsOrderID = orderStatus.VendorOrderID
|
||||
afsOrder.RefundType = model.AfsTypeFullRefund
|
||||
afsOrder.AppealType = model.AfsAppealTypeRefund
|
||||
afsOrder.VendorReasonType = ""
|
||||
afsOrder.ReasonType = model.AfsReasonNotOthers
|
||||
afsOrder.ReasonDesc = utils.LimitUTF8StringLen(refundData.Reason, 1024)
|
||||
afsOrder.ReasonImgList = utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024)
|
||||
}
|
||||
}
|
||||
if afsOrder != nil {
|
||||
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
|
||||
}
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
|
||||
}
|
||||
return mtwmapi.Err2CallbackResponse(err, "")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) createAfsOrder(orderData url.Values) (afsOrder *model.AfsOrder) {
|
||||
afsOrder, err := partner.CurOrderManager.CreateAfsOrderFromOrder(orderData.Get("order_id"), model.VendorIDMTWM)
|
||||
if err == nil {
|
||||
afsOrder.AfsOrderID = orderData.Get("refund_id")
|
||||
afsOrder.AfsCreatedAt = utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp")))
|
||||
if afsOrder.AfsOrderID == "" {
|
||||
afsOrder.AfsOrderID = afsOrder.VendorOrderID
|
||||
}
|
||||
} else {
|
||||
afsOrder = nil
|
||||
}
|
||||
return afsOrder
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackAfsMsg2Status(msg *mtwmapi.CallbackMsg) (orderStatus *model.OrderStatus) {
|
||||
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorID: model.VendorIDMTWM,
|
||||
OrderType: model.OrderTypeAfsOrder,
|
||||
RefVendorOrderID: utils.Int64ToStr(refundData.OrderID),
|
||||
RefVendorID: model.VendorIDMTWM,
|
||||
VendorStatus: fmt.Sprintf("%s:%d", refundData.NotifyType, refundData.ResType),
|
||||
Status: c.GetAfsStatusFromVendorStatus(refundData.ResType, refundData.NotifyType),
|
||||
StatusTime: utils.Timestamp2Time(refundData.Timestamp),
|
||||
Remark: refundData.Reason,
|
||||
}
|
||||
if refundData.RefundID > 0 {
|
||||
orderStatus.VendorOrderID = utils.Int64ToStr(refundData.RefundID)
|
||||
} else {
|
||||
orderStatus.VendorOrderID = orderStatus.RefVendorOrderID
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(resType int, notifyType string) int {
|
||||
status := AfsVendorStatus2StatusMap[notifyType]
|
||||
if status == model.AfsOrderStatusWait4Approve && resType != mtwmapi.ResTypePending {
|
||||
status = model.AfsOrderStatusNew
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if approveType == partner.AfsApproveTypeRefused {
|
||||
err = api.MtwmAPI.OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason)
|
||||
} else {
|
||||
err = api.MtwmAPI.OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
err = fmt.Errorf("内部错误,美团外卖平台不支持确认收到退货操作")
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return fmt.Errorf("%s不支持售后全额退款,请让买家发起退款", model.VendorChineseNames[model.VendorIDMTWM])
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
return c.AdjustOrder(ctx, order, refundSkuList, reason)
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
RefreshCommentTime = 7 * 24 * time.Hour // 此值必须大于24小时
|
||||
RefreshCommentTimeInterval = 60 * time.Minute
|
||||
BAD_COMMENTS_MAX_MODIFY_TIME = 24 * 6 // 小时
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) StartRefreshComment() {
|
||||
utils.AfterFuncWithRecover(5*time.Second, func() {
|
||||
c.refreshCommentOnce()
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) refreshCommentOnce() {
|
||||
c.RefreshComment(time.Now().Add(-RefreshCommentTime), time.Now())
|
||||
utils.AfterFuncWithRecover(RefreshCommentTimeInterval, func() {
|
||||
c.refreshCommentOnce()
|
||||
})
|
||||
}
|
||||
|
||||
func formalizeTagList(mtwmTagList string) (outTagList string) {
|
||||
if mtwmTagList != "" {
|
||||
outTagList = string(utils.Format4Output(strings.Split(mtwmTagList, ","), true))
|
||||
}
|
||||
return outTagList
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) RefreshComment(fromTime, toTime time.Time) (err error) {
|
||||
storeMapList, err2 := dao.GetStoresMapList(dao.GetDB(), []int{model.VendorIDMTWM}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "")
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
task := tasksch.NewParallelTask("mtwm RefreshComment", nil, jxcontext.AdminCtx,
|
||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||||
storeMap := batchItemList[0].(*model.StoreMap)
|
||||
endDateStr := time.Now().Add(-24 * time.Hour).Format("20060102")
|
||||
startDateStr := time.Now().Add(-RefreshCommentTime).Format("20060102")
|
||||
commentList, err2 := api.MtwmAPI.CommentQuery(storeMap.VendorStoreID, startDateStr, endDateStr, 0, 0, mtwmapi.CommentReplyStatusAll)
|
||||
|
||||
var orderCommentList []*model.OrderComment
|
||||
if err = err2; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, mtwmComment := range commentList {
|
||||
createdTime, err := utils.TryStr2Time(mtwmComment.CommentTime)
|
||||
if err == nil {
|
||||
orderComment := &model.OrderComment{
|
||||
VendorOrderID: utils.Int64ToStr(mtwmComment.CommentID), // 美团评价不能得到订单号,以评价ID代替
|
||||
VendorID: model.VendorIDMTWM,
|
||||
UserCommentID: utils.Int64ToStr(mtwmComment.CommentID),
|
||||
VendorStoreID: storeMap.VendorStoreID,
|
||||
TagList: formalizeTagList(mtwmComment.CommentLables),
|
||||
Score: int8(mtwmComment.FoodCommentScore),
|
||||
ModifyDuration: BAD_COMMENTS_MAX_MODIFY_TIME,
|
||||
OriginalMsg: string(utils.MustMarshal(mtwmComment)),
|
||||
IsReplied: int8(mtwmComment.ReplyStatus),
|
||||
}
|
||||
if orderComment.IsReplied == 0 {
|
||||
orderComment.Content = mtwmComment.CommentContent
|
||||
orderComment.CommentCreatedAt = createdTime
|
||||
} else {
|
||||
orderComment.Content = mtwmComment.AddComment
|
||||
if updatedTime, err := utils.TryStr2Time(mtwmComment.CommentTime); err == nil {
|
||||
orderComment.CommentCreatedAt = updatedTime
|
||||
}
|
||||
}
|
||||
orderCommentList = append(orderCommentList, orderComment)
|
||||
}
|
||||
}
|
||||
return orderCommentList, nil
|
||||
}, storeMapList)
|
||||
task.Run()
|
||||
resultList, err2 := task.GetResult(0)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
var orderCommentList []*model.OrderComment
|
||||
for _, result := range resultList {
|
||||
orderComment := result.(*model.OrderComment)
|
||||
orderCommentList = append(orderCommentList, orderComment)
|
||||
}
|
||||
if len(orderCommentList) > 0 {
|
||||
err = partner.CurOrderManager.OnOrderComments(orderCommentList)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
globals.SugarLogger.Debugf("mtwm ReplyOrderComment, orderComment:%s, replyComment:%s", utils.Format4Output(orderComment, true), replyComment)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.CommentAddReply(orderComment.VendorStoreID, utils.Str2Int64(orderComment.UserCommentID), replyComment)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
_ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
)
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.GetOrder("", "33437032333978492")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetOrderStatus(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.GetOrderStatus("", "71884881906304496")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestListOrders(t *testing.T) {
|
||||
result, err := CurPurchaseHandler.ListOrders(jxcontext.AdminCtx, "", nil, time.Now(), "4626746")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/baseapi/utils/errlist"
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
opTimeErrReg = regexp.MustCompile(`当前配送营业时间为:([\d:~,]*)`)
|
||||
)
|
||||
|
||||
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) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (retVal *dao.StoreDetail, err error) {
|
||||
result, err := api.MtwmAPI.PoiGet(vendorStoreID)
|
||||
if err == nil {
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
retVal = &dao.StoreDetail{
|
||||
Store: model.Store{
|
||||
Address: result.Address,
|
||||
Tel1: result.Phone,
|
||||
},
|
||||
}
|
||||
retVal.OriginalName = result.Name
|
||||
_, retVal.Name = jxutils.SplitStoreName(retVal.OriginalName, partner.StoreNameSeparator, globals.StoreNameMtwm)
|
||||
|
||||
retVal.SetOpTime(openTimeMtwm2JX(result.ShippingTime))
|
||||
retVal.Status = bizStatusMtwm2JX(result.OpenLevel, result.IsOnline)
|
||||
|
||||
tel2 := result.StandbyTel
|
||||
if tel2 != "" && tel2 != retVal.Tel1 {
|
||||
retVal.Tel2 = tel2
|
||||
}
|
||||
|
||||
retVal.Lng = int(result.Longitude)
|
||||
retVal.Lat = int(result.Latitude)
|
||||
|
||||
lng := jxutils.IntCoordinate2Standard(retVal.Lng)
|
||||
lat := jxutils.IntCoordinate2Standard(retVal.Lat)
|
||||
db := dao.GetDB()
|
||||
retVal.DistrictCode = api.AutonaviAPI.GetCoordinateDistrictCode(lng, lat)
|
||||
city, err := dao.GetPlaceByCode(db, result.CityID)
|
||||
retVal.CityName = city.Name
|
||||
retVal.CityCode = result.CityID
|
||||
|
||||
poiCode := result.AppPoiCode
|
||||
retVal.VendorStoreID = vendorStoreID
|
||||
retVal.ID = int(utils.Str2Int64WithDefault(poiCode, 0))
|
||||
retVal.DeliveryRangeType = model.DeliveryRangeTypePolygon
|
||||
var deliveryRangeInfo []map[string]interface{}
|
||||
deliveryRangeInfo, err = api.MtwmAPI.ShippingFetch(poiCode)
|
||||
if err != nil {
|
||||
deliveryRangeInfo, err = api.MtwmAPI.ShippingList(poiCode)
|
||||
}
|
||||
if err == nil {
|
||||
if len(deliveryRangeInfo) > 0 {
|
||||
retVal.DeliveryRange = rangeMtwm2JX(deliveryRangeInfo[0]["area"].(string))
|
||||
logisticsCode := utils.Interface2String(deliveryRangeInfo[0]["logistics_code"])
|
||||
if logisticsCode == "" || logisticsCode == mtwmapi.PeiSongTypeSelf {
|
||||
retVal.DeliveryType = scheduler.StoreDeliveryTypeByStore
|
||||
} else {
|
||||
retVal.DeliveryType = scheduler.StoreDeliveryTypeByPlatform
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
func (p *PurchaseHandler) CreateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
return p.UpdateStore(db, storeID, userName)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStore2(db *dao.DaoDB, storeID int, userName string) (vendorStoreID string, err error) {
|
||||
return vendorStoreID, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error) {
|
||||
var name string
|
||||
if db == nil {
|
||||
db = dao.GetDB()
|
||||
}
|
||||
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDMTWM)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
errList := errlist.New()
|
||||
|
||||
remoteStoreInfo, err := api.MtwmAPI.PoiGet(storeDetail.VendorStoreID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mergedStoreStatus := jxutils.MergeStoreStatus(storeDetail.Status, storeDetail.VendorStatus)
|
||||
name = remoteStoreInfo.Name
|
||||
if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
|
||||
if storeDetail.VendorStoreName != "" {
|
||||
name = storeDetail.VendorStoreName
|
||||
}
|
||||
// else {
|
||||
// name = jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM)
|
||||
// }
|
||||
}
|
||||
// openLevel, isOnline := bizStatusJX2Mtwm(mergedStoreStatus)
|
||||
//TODO 美团暂时不用那个电话
|
||||
phone := storeDetail.Tel1
|
||||
// if storeDetail.MarketManPhone != "" {
|
||||
// phone = storeDetail.MarketManPhone
|
||||
// } else {
|
||||
// phone = model.VendorStoreTel
|
||||
// }
|
||||
params := map[string]interface{}{
|
||||
"name": name, //jxutils.ComposeStoreName(storeDetail.Store.Name, model.VendorIDMTWM),
|
||||
"address": storeDetail.Address, // 美团好像地址也不能改的?
|
||||
"longitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Longitude)),
|
||||
"latitude": jxutils.IntCoordinate2Standard(int(remoteStoreInfo.Latitude)),
|
||||
"phone": phone,
|
||||
"shipping_fee": remoteStoreInfo.ShippingFee,
|
||||
"shipping_time": remoteStoreInfo.ShippingTime,
|
||||
"open_level": remoteStoreInfo.OpenLevel,
|
||||
"is_online": remoteStoreInfo.IsOnline,
|
||||
"third_tag_name": remoteStoreInfo.ThirdTagName,
|
||||
"promotion_info": storeDetail.PromoteInfo,
|
||||
}
|
||||
// globals.SugarLogger.Debug(utils.Format4Output(params, false))
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
errList.AddErr(api.MtwmAPI.PoiSave(storeDetail.VendorStoreID, params))
|
||||
}
|
||||
// PoiSave有时会报错:商家已接入美团配送,不可修改门店配送相关信息,这里放弃信息修改
|
||||
// if err != nil {
|
||||
// if utils.IsErrMatch(err, utils.Int2Str(mtwmapi.ErrCodeCanNotModifyStoreDeliveryInfo), nil) {
|
||||
// globals.SugarLogger.Infof("mtwm UpdateStore vendorStoreID:%s, params:%s failed with err:%v", storeDetail.VendorStoreID, utils.Format4Output(params, true), err)
|
||||
// if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 {
|
||||
// err = p.UpdateStoreStatus(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, mergedStoreStatus)
|
||||
// } else {
|
||||
// err = nil
|
||||
// }
|
||||
// }
|
||||
// errList.AddErr(err)
|
||||
// }
|
||||
if storeDetail.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreStatus) != 0 {
|
||||
errList.AddErr(p.UpdateStoreStatus(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, mergedStoreStatus))
|
||||
}
|
||||
errList.AddErr(p.UpdateStoreOpTime(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID, storeDetail.GetOpTimeList()))
|
||||
errList.AddErr(p.UpdateStoreBoxFee(jxcontext.AdminCtx, storeDetail.VendorOrgCode, storeID, storeDetail.VendorStoreID))
|
||||
return errList.GetErrListAsOne()
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
return "", errors.New("美团外卖不支持此操作")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) onStoreStatusChanged(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) {
|
||||
var err error
|
||||
poiStatus := int(utils.Str2Int64(msg.FormData.Get("poi_status")))
|
||||
vendorStoreID := msg.FormData.Get("app_poi_code")
|
||||
storeStatus := 0
|
||||
if poiStatus == mtwmapi.MsgPoiStatusOpened {
|
||||
storeStatus = model.StoreStatusOpened
|
||||
} else if poiStatus == mtwmapi.MsgPoiStatusClosed {
|
||||
storeStatus = model.StoreStatusClosed
|
||||
} else if poiStatus == mtwmapi.MsgPoiStatusOffline {
|
||||
storeStatus = model.StoreStatusDisabled
|
||||
} else {
|
||||
storeStatus, err = p.GetStoreStatus(jxcontext.AdminCtx, "", 0, vendorStoreID)
|
||||
}
|
||||
if err == nil {
|
||||
err = partner.CurStoreManager.OnStoreStatusChanged(vendorStoreID, model.VendorIDMTWM, storeStatus)
|
||||
}
|
||||
response = mtwmapi.Err2CallbackResponse(err, "")
|
||||
return response
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
result, err := api.MtwmAPI.PoiGet(vendorStoreID)
|
||||
if err == nil {
|
||||
return bizStatusMtwm2JX(result.OpenLevel, result.IsOnline), nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) EnableAutoAcceptOrder(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, isSetEnable bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, status int) (err error) {
|
||||
openLevel, isOnline := bizStatusJX2Mtwm(status)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if isOnline != mtwmapi.PoiStatusOnline {
|
||||
err = api.MtwmAPI.PoiOffline(vendorStoreID)
|
||||
} else {
|
||||
if err = api.MtwmAPI.PoiOnline(vendorStoreID); err == nil { // 这个函数成功返回也并不表示上线成功。。。
|
||||
remoteStoreInfo, err2 := api.MtwmAPI.PoiGet(vendorStoreID)
|
||||
if err = err2; err != nil {
|
||||
return err
|
||||
}
|
||||
if remoteStoreInfo.IsOnline == mtwmapi.PoiStatusOnline {
|
||||
if openLevel == mtwmapi.PoiOpenLevelHaveRest {
|
||||
err = api.MtwmAPI.PoiClose(vendorStoreID)
|
||||
} else {
|
||||
err = api.MtwmAPI.PoiOpen(vendorStoreID)
|
||||
}
|
||||
} else {
|
||||
err = errors.New("门店还未上线,不能修改营业状态")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func errOpStr2Int16(str string) []int16 {
|
||||
list := strings.Split(str, "~")
|
||||
if len(list) >= 2 {
|
||||
return []int16{jxutils.StrTime2JxOperationTime(list[0]+":00", 0), jxutils.StrTime2JxOperationTime(list[1]+":00", 2359)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getOpTimeListFromErr(err error) (opTimeList []int16) {
|
||||
if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == mtwmapi.ErrCodeOpFailed {
|
||||
if result := opTimeErrReg.FindStringSubmatch(errExt.ErrMsg()); len(result) >= 2 {
|
||||
timeStrList := strings.Split(result[1], ",")
|
||||
for _, v := range timeStrList {
|
||||
v = utils.TrimBlankChar(v)
|
||||
if len(v) == len("00:00~02:00") {
|
||||
opTimeList = append(opTimeList, errOpStr2Int16(v)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return opTimeList
|
||||
}
|
||||
|
||||
// 此函数只是简单实现,不支持区间切分,只做单一区间限制
|
||||
func constrainOpTimeList(opTimeList, validOpTimeList []int16) (newOpTimeList []int16) {
|
||||
for k := 0; k < len(opTimeList); k += 2 {
|
||||
beginTime := opTimeList[k]
|
||||
endTime := opTimeList[k+1]
|
||||
for k2 := 0; k2 < len(validOpTimeList); k2 += 2 {
|
||||
beginTime2 := validOpTimeList[k2]
|
||||
endTime2 := validOpTimeList[k2+1]
|
||||
if beginTime >= beginTime2 && beginTime <= endTime2 {
|
||||
newOpTimeList = append(newOpTimeList, beginTime)
|
||||
newOpTimeList = append(newOpTimeList, int16(math.Min(float64(endTime), float64(endTime2))))
|
||||
} else if beginTime2 >= beginTime && beginTime2 <= endTime {
|
||||
newOpTimeList = append(newOpTimeList, beginTime2)
|
||||
newOpTimeList = append(newOpTimeList, int16(math.Min(float64(endTime), float64(endTime2))))
|
||||
}
|
||||
}
|
||||
}
|
||||
return newOpTimeList
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreOpTime(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, opTimeList []int16) (err error) {
|
||||
shippingTime := openTimeJX2Mtwm(opTimeList)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.PoiShipTimeUpdate(vendorStoreID, shippingTime)
|
||||
if err != nil {
|
||||
shippingTime = ""
|
||||
if validOpTimeList := getOpTimeListFromErr(err); len(validOpTimeList) > 0 {
|
||||
shippingTime = openTimeJX2Mtwm(constrainOpTimeList(opTimeList, validOpTimeList))
|
||||
}
|
||||
if shippingTime != "" {
|
||||
err = api.MtwmAPI.PoiShipTimeUpdate(vendorStoreID, shippingTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetAllStoresVendorID(ctx *jxcontext.Context, vendorOrgCode string) (vendorStoreIDs []string, err error) {
|
||||
vendorStoreIDs, err = api.MtwmAPI.PoiGetIDs()
|
||||
return vendorStoreIDs, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) UpdateStoreBoxFee(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (err error) {
|
||||
boxFee, err := dao.GetSysConfigAsInt64(dao.GetDB(), model.ConfigSysMtwmBoxFee)
|
||||
if err == nil {
|
||||
if globals.EnableMtwmStoreWrite && globals.IsProductEnv() {
|
||||
err = api.MtwmAPI.PackagePriceUpdate(vendorStoreID, 1, int(boxFee))
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,676 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/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/business/partner/putils"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
updateTypeStock = iota
|
||||
updateTypeStatus
|
||||
updateTypePrice
|
||||
)
|
||||
|
||||
const (
|
||||
defVendorCatID = 200001903 // 生菜
|
||||
|
||||
specialStoreID = "8171010"
|
||||
// specialStoreID = "2523687"
|
||||
)
|
||||
|
||||
var (
|
||||
sensitiveWordRegexp = regexp.MustCompile(`包含敏感词:(\[.*\])`)
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
|
||||
switch funcID {
|
||||
case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice:
|
||||
batchSize = mtwmapi.MaxStoreSkuBatchSize
|
||||
case partner.FuncDeleteStoreSkus:
|
||||
batchSize = mtwmapi.MaxBatchDeleteSize
|
||||
case partner.FuncCreateStoreSkus:
|
||||
batchSize = 1 // 可考虑用批量操作
|
||||
case partner.FuncUpdateStoreSkus:
|
||||
batchSize = 1 // mtwmapi.MaxStoreSkuBatchSize
|
||||
case partner.FuncGetStoreSkusFullInfo:
|
||||
batchSize = 1
|
||||
case partner.FuncCreateActs:
|
||||
batchSize = mtwmapi.MaxRetailDiscountCreateBatchSize
|
||||
case partner.FuncCancelActs:
|
||||
batchSize = mtwmapi.MaxRetailDiscountDeleteBatchSize
|
||||
}
|
||||
return batchSize
|
||||
}
|
||||
|
||||
// 门店分类
|
||||
func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) {
|
||||
remoteCats, err := api.MtwmAPI.RetailCatList(vendorStoreID)
|
||||
if err == nil {
|
||||
cats = convertVendorCatList(remoteCats)
|
||||
}
|
||||
return cats, err
|
||||
}
|
||||
|
||||
func convertVendorCatList(remoteCats []*mtwmapi.RetailCategoryInfo) (cats []*partner.BareCategoryInfo) {
|
||||
for _, rCat := range remoteCats {
|
||||
cat := &partner.BareCategoryInfo{
|
||||
VendorCatID: rCat.Code,
|
||||
Name: rCat.Name,
|
||||
Level: rCat.Level,
|
||||
Seq: rCat.Sequence,
|
||||
Children: convertVendorCatList(rCat.Children),
|
||||
}
|
||||
if cat.VendorCatID == "" {
|
||||
cat.VendorCatID = rCat.Name
|
||||
}
|
||||
cats = append(cats, cat)
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) {
|
||||
return mtwmapi.IsErrCategoryExist(err)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) {
|
||||
return mtwmapi.IsErrCategoryNotExist(err)
|
||||
}
|
||||
|
||||
func catCode2Str(catCode int) (catCodeStr string) {
|
||||
if catCode > 0 {
|
||||
catCodeStr = utils.Int2Str(catCode)
|
||||
}
|
||||
return catCodeStr
|
||||
}
|
||||
|
||||
func tryCatName2Code(originName string) (catCodeStr string) {
|
||||
if intValue := utils.Str2Int64WithDefault(originName, 0); intValue > 0 {
|
||||
catCodeStr = utils.Int64ToStr(intValue)
|
||||
if catCodeStr != originName {
|
||||
catCodeStr = ""
|
||||
}
|
||||
}
|
||||
return catCodeStr
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
level := 1
|
||||
if storeCat.ParentCatName != "" {
|
||||
level = 2
|
||||
}
|
||||
originName := ""
|
||||
catName := storeCat.Name
|
||||
catCode := storeCat.ID
|
||||
|
||||
subCatName := ""
|
||||
subCatCode := 0
|
||||
if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 {
|
||||
// 修改一级分类
|
||||
originName = storeCat.VendorCatID
|
||||
}
|
||||
if level == 2 { // 二级分类
|
||||
// 创建二级分类
|
||||
originName = storeCat.ParentVendorCatID
|
||||
catName = storeCat.ParentCatName
|
||||
catCode = storeCat.ParentID
|
||||
subCatName = storeCat.Name
|
||||
subCatCode = storeCat.ID
|
||||
if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 {
|
||||
// 修改二级分类
|
||||
originName = storeCat.VendorCatID
|
||||
catName = storeCat.Name
|
||||
catCode = storeCat.ID
|
||||
subCatName = ""
|
||||
subCatCode = 0
|
||||
}
|
||||
}
|
||||
if catName == "" {
|
||||
panic("catName is empty")
|
||||
}
|
||||
catName = utils.FilterEmoji(catName)
|
||||
subCatName = utils.FilterEmoji(subCatName)
|
||||
globals.SugarLogger.Debugf("mtwm CreateStoreCategory vendorStoreID:%s, originName:%s, catCode:%d, catName:%s, subCatCode:%d, subCatName:%s, seq:%d",
|
||||
vendorStoreID, originName, catCode, catName, subCatCode, subCatName, storeCat.Seq)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
// err = api.MtwmAPI.RetailCatUpdate2(vendorStoreID, tryCatName2Code(originName), originName, catCode2Str(catCode), catName, catCode2Str(subCatCode), subCatName, storeCat.Seq)
|
||||
param4Update := &mtwmapi.Param4UpdateCat{
|
||||
CategoryCodeOrigin: tryCatName2Code(originName),
|
||||
CategoryNameOrigin: originName,
|
||||
CategoryCode: catCode2Str(catCode),
|
||||
SecondaryCategoryCode: catCode2Str(subCatCode),
|
||||
SecondaryCategoryName: subCatName,
|
||||
Sequence: storeCat.Seq,
|
||||
}
|
||||
err = api.MtwmAPI.RetailCatUpdate(vendorStoreID, catName, param4Update)
|
||||
if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 && // 修改分类名,但分类不存在
|
||||
p.IsErrCategoryNotExist(err) && originName != "" {
|
||||
storeCat.CatSyncStatus |= model.SyncFlagNewMask
|
||||
err = p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
// storeCat.VendorCatID = utils.FilterEmoji(storeCat.Name)
|
||||
storeCat.VendorCatID = utils.Int2Str(storeCat.ID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
|
||||
return p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat)
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) {
|
||||
if false {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
err = api.MtwmAPI.RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID)
|
||||
}
|
||||
} else {
|
||||
var catCodes []string
|
||||
if catCode := tryCatName2Code(vendorCatID); catCode != "" {
|
||||
catCodes = []string{catCode}
|
||||
}
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if level == 1 {
|
||||
err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil)
|
||||
} else {
|
||||
err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 门店商品
|
||||
|
||||
// 多门店平台不需要实现这个接口
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
|
||||
return mtwmapi.IsErrSkuNotExist(err)
|
||||
}
|
||||
|
||||
// func duplicateStoreSkuList(storeSkuList []*dao.StoreSkuSyncInfo, index int) (newStoreSkuList []*dao.StoreSkuSyncInfo) {
|
||||
// newStoreSkuList = make([]*dao.StoreSkuSyncInfo, len(storeSkuList))
|
||||
// for k, v := range storeSkuList {
|
||||
// tmp := *v
|
||||
// tmp.SkuName = fmt.Sprintf("%s.%d", tmp.SkuName, index)
|
||||
// tmp.SkuID = index*1000000 + tmp.SkuID
|
||||
// newStoreSkuList[k] = &tmp
|
||||
// }
|
||||
// return newStoreSkuList
|
||||
// }
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
|
||||
// if err == nil && vendorStoreID == specialStoreID {
|
||||
// for i := 0; i < 2; i++ {
|
||||
// p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
|
||||
// }
|
||||
// }
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
|
||||
// if err == nil && vendorStoreID == specialStoreID {
|
||||
// for i := 0; i < 2; i++ {
|
||||
// p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
|
||||
// }
|
||||
// }
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
// 对于多门店平台来说,storeSkuList中只有SkuID与VendorSkuID有意义
|
||||
func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
var syncType string
|
||||
foodDataList := make([]map[string]interface{}, len(storeSkuList))
|
||||
if isCreate {
|
||||
syncType = "创建商品"
|
||||
} else {
|
||||
syncType = "更新商品"
|
||||
}
|
||||
for i, storeSku := range storeSkuList {
|
||||
isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0
|
||||
foodData := make(map[string]interface{})
|
||||
foodDataList[i] = foodData
|
||||
foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(storeSku.SkuID)
|
||||
skus := []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"sku_id": foodData[mtwmapi.KeyAppFoodCode],
|
||||
},
|
||||
}
|
||||
foodData["skus"] = skus
|
||||
foodData["name"] = utils.LimitUTF8StringLen(utils.FilterEmoji(storeSku.SkuName), mtwmapi.MaxSkuNameCharCount)
|
||||
foodData["description"] = storeSku.Comment
|
||||
if isNeedUpdatePrice {
|
||||
foodData["price"] = jxutils.IntPrice2Standard(storeSku.VendorPrice)
|
||||
}
|
||||
if storeSku.MinOrderCount != 0 {
|
||||
foodData["min_order_count"] = storeSku.MinOrderCount
|
||||
} else {
|
||||
foodData["min_order_count"] = 1
|
||||
}
|
||||
foodData["unit"] = storeSku.Unit
|
||||
attr := switchAttr(storeSku.VendorVendorCatID)
|
||||
if attr != "" {
|
||||
foodData["common_attr_value"] = attr
|
||||
}
|
||||
catCode := tryCatName2Code(storeSku.VendorCatID)
|
||||
if catCode != "" {
|
||||
foodData["category_code"] = catCode
|
||||
} else {
|
||||
foodData["category_name"] = storeSku.VendorCatID
|
||||
}
|
||||
foodData["is_sold_out"] = skuStatusJX2Mtwm(storeSku.MergedStatus)
|
||||
if true { // vendorStoreID == specialStoreID {
|
||||
img2 := storeSku.Img2
|
||||
if img2 == "" {
|
||||
img2 = storeSku.Img
|
||||
}
|
||||
if storeSku.ImgMix != "" {
|
||||
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.ImgMix, img2, storeSku.ImgMix, storeSku.ImgMix, storeSku.ImgMix), ",")
|
||||
} else {
|
||||
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, storeSku.Img, storeSku.Img, storeSku.Img), ",")
|
||||
}
|
||||
} else {
|
||||
foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",")
|
||||
}
|
||||
if storeSku.DescImg != "" {
|
||||
foodData["picture_contents"] = storeSku.DescImg
|
||||
}
|
||||
foodData["sequence"] = storeSku.GetSeq()
|
||||
if storeSku.VendorVendorCatID != 0 {
|
||||
foodData["tag_id"] = utils.Int64ToStr(storeSku.VendorVendorCatID)
|
||||
} else {
|
||||
// foodData["tag_id"] = utils.Int64ToStr(defVendorCatID)
|
||||
}
|
||||
skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit)
|
||||
if isNeedUpdatePrice {
|
||||
skus[0]["price"] = foodData["price"]
|
||||
}
|
||||
skus[0]["stock"] = stockCount2Mtwm(model.MaxStoreSkuStockQty)
|
||||
if storeSku.Upc != "" {
|
||||
skus[0]["upc"] = storeSku.Upc
|
||||
}
|
||||
skus[0]["ladder_box_num"] = storeSku.LadderBoxNum
|
||||
skus[0]["ladder_box_price"] = jxutils.IntPrice2Standard(int64(storeSku.LadderBoxPrice))
|
||||
if foodData["tag_id"] != nil {
|
||||
skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用
|
||||
}
|
||||
}
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if len(foodDataList) == 1 {
|
||||
foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"]))
|
||||
err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0])
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
|
||||
} else if len(foodDataList) > 0 {
|
||||
failedFoodList, err2 := api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList)
|
||||
if err = err2; err == nil {
|
||||
if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil {
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
|
||||
// successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
|
||||
}
|
||||
} else if err2 != nil && len(failedFoodList) == 0 {
|
||||
if errExt, ok := err2.(*utils.ErrorWithCode); ok {
|
||||
err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, storeSku := range storeSkuList {
|
||||
storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID)
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) {
|
||||
if len(l) > 0 {
|
||||
vendorSkuIDs = make([]string, len(l))
|
||||
for k, v := range l {
|
||||
vendorSkuIDs[k] = v.AppFoodCode
|
||||
}
|
||||
}
|
||||
return vendorSkuIDs
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if len(storeSkuList) == 1 {
|
||||
err = api.MtwmAPI.RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID)
|
||||
failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], "删除商品")
|
||||
} else {
|
||||
// todo 部分失败
|
||||
err = api.MtwmAPI.RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList())
|
||||
if err != nil {
|
||||
if errExt, ok := err.(*utils.ErrorWithCode); ok {
|
||||
myMap := make(map[string][]*mtwmapi.AppFoodResult)
|
||||
json.Unmarshal([]byte(errExt.ErrMsg()), &myMap)
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, myMap["retail_error_list"], storeID, model.VendorChineseNames[model.VendorIDMTWM], "批量删除商品")
|
||||
}
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func switchAttr(vendorCatID int64) (attrs string) {
|
||||
switch vendorCatID {
|
||||
case 200002727:
|
||||
return mtwmapi.MtwmSkuAttr200002727
|
||||
case 200001555:
|
||||
return mtwmapi.MtwmSkuAttr200001555
|
||||
case 200002728:
|
||||
return mtwmapi.MtwmSkuAttr200002728
|
||||
case 200001519, 200000592:
|
||||
return mtwmapi.MtwmSkuAttr200000592
|
||||
case 200002704, 200002731:
|
||||
return mtwmapi.MtwmSkuAttr200002731
|
||||
case 200002716:
|
||||
return mtwmapi.MtwmSkuAttr200002716
|
||||
case 200002667, 200002713, 200002670:
|
||||
return mtwmapi.MtwmSkuAttr200002670
|
||||
case 200002680:
|
||||
return mtwmapi.MtwmSkuAttr200002680
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
func stockCount2Mtwm(stock int) (mtwmStock string) {
|
||||
return utils.Int2Str(stock)
|
||||
}
|
||||
|
||||
func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuList []*mtwmapi.BareStoreFoodInfo) {
|
||||
for _, storeSku := range storeSkuList {
|
||||
skuInfo := &mtwmapi.BareStoreFoodInfo{
|
||||
AppFoodCode: storeSku.VendorSkuID,
|
||||
Skus: []*mtwmapi.BareStoreSkuInfo{
|
||||
&mtwmapi.BareStoreSkuInfo{
|
||||
SkuID: storeSku.VendorSkuID,
|
||||
},
|
||||
},
|
||||
}
|
||||
if updateType == updateTypeStock {
|
||||
skuInfo.Skus[0].Stock = stockCount2Mtwm(storeSku.Stock)
|
||||
} else if updateType == updateTypePrice {
|
||||
skuInfo.Skus[0].Price = jxutils.IntPrice2StandardString(storeSku.VendorPrice)
|
||||
} else {
|
||||
skuInfo.Skus = nil
|
||||
}
|
||||
skuList = append(skuList, skuInfo)
|
||||
}
|
||||
return skuList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus)
|
||||
mtwmStatus := skuStatusJX2Mtwm(status)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
failedFoodList, err2 := api.MtwmAPI.RetailSellStatus(ctx.GetTrackInfo(), vendorStoreID, skuList, mtwmStatus)
|
||||
if err = err2; err == nil {
|
||||
if len(failedFoodList) > 0 {
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态")
|
||||
// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
|
||||
}
|
||||
} else if err2 != nil && len(failedFoodList) == 0 {
|
||||
if errExt, ok := err2.(*utils.ErrorWithCode); ok {
|
||||
err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态")
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
priceList := storeSku2Mtwm(storeSkuList, updateTypePrice)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
failedFoodList, err2 := api.MtwmAPI.RetailSkuPrice(ctx.GetTrackInfo(), vendorStoreID, priceList)
|
||||
if err = err2; err == nil {
|
||||
if len(failedFoodList) > 0 {
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格")
|
||||
}
|
||||
} else if err2 != nil && len(failedFoodList) == 0 {
|
||||
if errExt, ok := err2.(*utils.ErrorWithCode); ok {
|
||||
err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格")
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
stockList := storeSku2Mtwm(storeSkuList, updateTypeStock)
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
failedFoodList, err2 := api.MtwmAPI.RetailSkuStock(ctx.GetTrackInfo(), vendorStoreID, stockList)
|
||||
if err = err2; err == nil {
|
||||
if len(failedFoodList) > 0 {
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存")
|
||||
}
|
||||
//if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil {
|
||||
// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
|
||||
// }
|
||||
} else if err2 != nil && len(failedFoodList) == 0 {
|
||||
if errExt, ok := err2.(*utils.ErrorWithCode); ok {
|
||||
err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
|
||||
failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存")
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) {
|
||||
if mtwmSkuStatus == mtwmapi.SellStatusOnline {
|
||||
jxSkuStatus = model.SkuStatusNormal
|
||||
} else {
|
||||
jxSkuStatus = model.SkuStatusDontSale
|
||||
}
|
||||
return jxSkuStatus
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) {
|
||||
if len(storeSkuList) == 1 {
|
||||
skuInfo, err := api.MtwmAPI.RetailGet(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if skuName := vendorSku2Jx(skuInfo); skuName != nil {
|
||||
skuNameList = append(skuNameList, skuName)
|
||||
}
|
||||
} else {
|
||||
var storeSkuMap map[string]*partner.StoreSkuInfo
|
||||
if storeSkuList != nil {
|
||||
storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList)
|
||||
}
|
||||
for {
|
||||
// todo 待优化获取速度
|
||||
result, err := api.MtwmAPI.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if storeSkuMap == nil {
|
||||
skuNameList = append(skuNameList, vendorSkuList2Jx(result)...)
|
||||
} else {
|
||||
for _, v := range result {
|
||||
if storeSkuMap[v.AppFoodCode] != nil {
|
||||
if skuName := vendorSku2Jx(v); skuName != nil {
|
||||
skuNameList = append(skuNameList, skuName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(result) < mtwmapi.GeneralMaxLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return skuNameList, err
|
||||
}
|
||||
|
||||
func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) {
|
||||
if len(appFood.SkuList) == 0 {
|
||||
globals.SugarLogger.Warnf("vendorSku2Jx, strange appFood:%s", utils.Format4Output(appFood, true))
|
||||
return nil
|
||||
}
|
||||
prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(appFood.Name)
|
||||
vendorSku := appFood.SkuList[0]
|
||||
weight := int(utils.Str2Int64WithDefault(vendorSku.Weight, 0))
|
||||
if weight <= 0 {
|
||||
weight = jxutils.FormatSkuWeight(specQuality, specUnit)
|
||||
}
|
||||
skuID := int(utils.Str2Int64WithDefault(vendorSku.SkuID, 0))
|
||||
skuName = &partner.SkuNameInfo{
|
||||
NameID: int(utils.Str2Int64WithDefault(appFood.AppFoodCode, 0)),
|
||||
VendorNameID: appFood.AppFoodCode,
|
||||
|
||||
Prefix: prefix,
|
||||
Name: name,
|
||||
Unit: unit,
|
||||
SkuList: []*partner.SkuInfo{
|
||||
&partner.SkuInfo{
|
||||
StoreSkuInfo: partner.StoreSkuInfo{
|
||||
VendorSkuID: vendorSku.SkuID,
|
||||
SkuID: skuID,
|
||||
IsSpecialty: appFood.IsSpecialty,
|
||||
Stock: int(utils.Str2Int64WithDefault(vendorSku.Stock, partner.UnlimitedStoreSkuStock)),
|
||||
VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64WithDefault(vendorSku.Price, 0)),
|
||||
Status: mtwmSkuStatus2Jx(appFood.IsSoldOut),
|
||||
},
|
||||
SkuName: appFood.Name,
|
||||
Comment: comment,
|
||||
SpecQuality: float64(specQuality),
|
||||
SpecUnit: specUnit,
|
||||
Weight: weight,
|
||||
},
|
||||
},
|
||||
PictureList: appFood.PictureList,
|
||||
}
|
||||
if appFood.CategoryName != "" {
|
||||
// todo, 因为当前我们用的是分类名操作这种方式,所以要返回分类名(而不是分类code)
|
||||
skuName.VendorCatIDList = []string{appFood.CategoryName}
|
||||
if appFood.SecondaryCategoryName != "" {
|
||||
skuName.VendorCatIDList = append(skuName.VendorCatIDList, appFood.SecondaryCategoryName)
|
||||
}
|
||||
}
|
||||
return skuName
|
||||
}
|
||||
|
||||
func vendorSkuList2Jx(appFoodList []*mtwmapi.AppFood) (skuNameList []*partner.SkuNameInfo) {
|
||||
for _, appFood := range appFoodList {
|
||||
if skuName := vendorSku2Jx(appFood); skuName != nil {
|
||||
skuNameList = append(skuNameList, skuName)
|
||||
}
|
||||
}
|
||||
return skuNameList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp {
|
||||
return sensitiveWordRegexp
|
||||
}
|
||||
|
||||
//美团api返回
|
||||
func SelectStoreSkuListByFoodList(storeSkuList interface{}, foodList []*mtwmapi.AppFoodResult, storeID int, vendorName, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) {
|
||||
foodMap := make(map[string]string)
|
||||
if len(foodList) > 0 {
|
||||
for _, v := range foodList {
|
||||
foodMap[v.AppFoodCode] = v.ErrorMsg
|
||||
}
|
||||
if storeSkuLists, ok := storeSkuList.([]*partner.StoreSkuInfo); ok {
|
||||
for _, v := range storeSkuLists {
|
||||
if foodMap[v.VendorSkuID] != "" {
|
||||
foodFailed := &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: v,
|
||||
ErrMsg: foodMap[v.VendorSkuID],
|
||||
StoreID: storeID,
|
||||
VendoreName: vendorName,
|
||||
SyncType: syncType,
|
||||
}
|
||||
selectedStoreSkuList = append(selectedStoreSkuList, foodFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
if storeSkuLists, ok := storeSkuList.([]*dao.StoreSkuSyncInfo); ok {
|
||||
for _, v := range storeSkuLists {
|
||||
if foodMap[v.VendorSkuID] != "" {
|
||||
storeSkuInfo := &partner.StoreSkuInfo{
|
||||
SkuID: v.SkuID,
|
||||
VendorSkuID: v.VendorSkuID,
|
||||
NameID: v.NameID,
|
||||
VendorNameID: v.VendorNameID,
|
||||
VendorPrice: v.VendorPrice,
|
||||
Status: v.Status,
|
||||
}
|
||||
foodFailed := &partner.StoreSkuInfoWithErr{
|
||||
StoreSkuInfo: storeSkuInfo,
|
||||
ErrMsg: foodMap[v.VendorSkuID],
|
||||
StoreID: storeID,
|
||||
VendoreName: vendorName,
|
||||
SyncType: syncType,
|
||||
}
|
||||
selectedStoreSkuList = append(selectedStoreSkuList, foodFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedStoreSkuList
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
actStoreSkuList := putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, storeSkuList)
|
||||
failedList, err = createOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, actStoreSkuList)
|
||||
storeSkuMap := putils.StoreSkuList2MapBySkuID(storeSkuList)
|
||||
for _, v := range actStoreSkuList {
|
||||
storeSkuMap[v.SkuID].VendorActID = v.VendorActID
|
||||
}
|
||||
return failedList, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
|
||||
return cancelOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, putils.StoreSku2ActStoreSku(model.SyncFlagDeletedMask, vendorStoreID, storeSkuList))
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) {
|
||||
var foodDataList = []map[string]interface{}{}
|
||||
for _, v := range storeSkuList {
|
||||
var foodData = make(map[string]interface{})
|
||||
if v.IsSpecialty != 0 && v.IsSpecialty == -1 {
|
||||
v.IsSpecialty = 0
|
||||
}
|
||||
foodData["is_specialty"] = v.IsSpecialty
|
||||
foodData["app_food_code"] = v.SkuID
|
||||
foodDataList = append(foodDataList, foodData)
|
||||
}
|
||||
if globals.EnableMtwmStoreWrite {
|
||||
if len(foodDataList) == 1 {
|
||||
err = api.MtwmAPI.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0])
|
||||
} else if len(foodDataList) > 0 {
|
||||
_, err = api.MtwmAPI.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
// _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
)
|
||||
|
||||
func TestGetStoreSkusFullInfo(t *testing.T) {
|
||||
skuNameList, err := CurPurchaseHandler.GetStoreSkusFullInfo(jxcontext.AdminCtx, nil, 2, "2523687", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(skuNameList, false))
|
||||
t.Log(len(skuNameList))
|
||||
}
|
||||
|
||||
func TestGetStoreSkusBareInfo(t *testing.T) {
|
||||
storeSkuList, err := CurPurchaseHandler.GetStoreSkusBareInfo(jxcontext.AdminCtx, "", nil, 2, "2523687", []*partner.StoreSkuInfo{
|
||||
&partner.StoreSkuInfo{
|
||||
SkuID: 969,
|
||||
},
|
||||
&partner.StoreSkuInfo{
|
||||
SkuID: 1306,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
t.Log(utils.Format4Output(storeSkuList, false))
|
||||
t.Log(len(storeSkuList))
|
||||
}
|
||||
|
||||
func TestDeleteStoreAllSkus(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, 2, "2523687", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteStoreAllCategories(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllCategories(jxcontext.AdminCtx, nil, 2, "2523687", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStoreCategory(t *testing.T) {
|
||||
_, err := CurPurchaseHandler.GetStoreCategory(jxcontext.AdminCtx, 2, "2523687", "不存在的分类")
|
||||
if err == nil {
|
||||
t.Fatal("应该找不到这个分类")
|
||||
}
|
||||
catName := "小月饼"
|
||||
cat, err := CurPurchaseHandler.GetStoreCategory(jxcontext.AdminCtx, 2, "2523687", catName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if cat.Name != catName {
|
||||
t.Fatal("没有找到正确的商家分类")
|
||||
}
|
||||
t.Log(utils.Format4Output(cat, false))
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
// _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
)
|
||||
|
||||
// func TestSyncStoreCategory(t *testing.T) {
|
||||
// hint, err := CurPurchaseHandler.SyncStoreCategory(jxcontext.AdminCtx, nil, testShopID, false)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// t.Log(hint)
|
||||
// }
|
||||
|
||||
// func TestSyncLocalStoreCategory(t *testing.T) {
|
||||
// hint, err := CurPurchaseHandler.SyncLocalStoreCategory(jxcontext.AdminCtx, nil, testShopID, true, nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// t.Log(hint)
|
||||
// }
|
||||
|
||||
// func TestSyncStoreSkus(t *testing.T) {
|
||||
// hint, err := CurPurchaseHandler.SyncStoreSkus(jxcontext.AdminCtx, nil, testShopID, nil, false, true)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// t.Log(hint)
|
||||
// }
|
||||
|
||||
func TestDeleteRemoteSkus(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllSkus(jxcontext.AdminCtx, nil, testShopID, testShopVendorID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteRemoteCategories(t *testing.T) {
|
||||
err := CurPurchaseHandler.DeleteStoreAllCategories(jxcontext.AdminCtx, nil, testShopID, testShopVendorID, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
// _ "git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||||
)
|
||||
|
||||
func TestReadStore(t *testing.T) {
|
||||
store, err := CurPurchaseHandler.ReadStore(jxcontext.AdminCtx, "", "4351018")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(store, false))
|
||||
}
|
||||
|
||||
func TestUpdateStore(t *testing.T) {
|
||||
err := CurPurchaseHandler.UpdateStore(nil, 100002, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstrainOpTimeList(t *testing.T) {
|
||||
timeList := constrainOpTimeList([]int16{830, 1800}, []int16{
|
||||
0,
|
||||
200,
|
||||
930,
|
||||
1700,
|
||||
})
|
||||
t.Log(utils.Format4Output(timeList, false))
|
||||
if timeList[0] != 930 || timeList[1] != 1700 {
|
||||
t.Fatal("constrainOpTimeList failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOpTimeListFromErr(t *testing.T) {
|
||||
err := utils.NewErrorIntCode("当前配送营业时间为:07:00~24:00", mtwmapi.ErrCodeOpFailed)
|
||||
list := getOpTimeListFromErr(err)
|
||||
t.Log(list)
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package mtwm
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
)
|
||||
|
||||
var (
|
||||
VendorWaybillStatus2StatusMap = map[string]int{
|
||||
mtwmapi.WaybillStatusWait4Delivery: model.WaybillStatusNew,
|
||||
mtwmapi.WaybillStatusPending: model.WaybillStatusPending,
|
||||
mtwmapi.WaybillStatusAccepted: model.WaybillStatusAccepted,
|
||||
mtwmapi.WaybillStatusCourierArrived: model.WaybillStatusCourierArrived,
|
||||
mtwmapi.WaybillStatusPickedup: model.WaybillStatusDelivering,
|
||||
mtwmapi.WaybillStatusDelivered: model.WaybillStatusDelivered,
|
||||
mtwmapi.WaybillStatusCanceled: model.WaybillStatusCanceled,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) GetWaybillStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorWaybillStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.WaybillStatusUnknown
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) onWaybillMsg(msg *mtwmapi.CallbackMsg) (response *mtwmapi.CallbackResponse) {
|
||||
waybill := c.callbackMsg2Waybill(msg)
|
||||
err := partner.CurOrderManager.OnWaybillStatusChanged(waybill)
|
||||
if err == nil && waybill.Status == model.WaybillStatusDelivering {
|
||||
c.postFakeMsg(waybill.VendorOrderID, FakeMsgType, mtwmapi.OrderStatusDelivering)
|
||||
}
|
||||
return mtwmapi.Err2CallbackResponse(err, "")
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) callbackMsg2Waybill(msg *mtwmapi.CallbackMsg) (retVal *model.Waybill) {
|
||||
orderID := GetOrderIDFromMsg(msg)
|
||||
vendorStatus := msg.FormData.Get("logistics_status")
|
||||
retVal = &model.Waybill{
|
||||
VendorOrderID: orderID,
|
||||
OrderVendorID: model.VendorIDMTWM,
|
||||
VendorWaybillID: orderID,
|
||||
WaybillVendorID: model.VendorIDMTWM,
|
||||
CourierName: msg.FormData.Get("dispatcher_name"),
|
||||
CourierMobile: msg.FormData.Get("dispatcher_mobile"),
|
||||
VendorStatus: vendorStatus,
|
||||
Status: c.GetWaybillStatusFromVendorStatus(vendorStatus),
|
||||
StatusTime: getTimeFromTimestamp(utils.Str2Int64(msg.FormData.Get("time"))),
|
||||
Remark: "",
|
||||
|
||||
VendorOrgCode: msg.AppID,
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
|
||||
return nil
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
func OnCallbackMsg(msg *weimobapi.CallbackMsg) (response *weimobapi.CallbackResponse) {
|
||||
if curPurchaseHandler != nil {
|
||||
orderID := utils.Int64ToStr(msg.OrderNo)
|
||||
jxutils.CallMsgHandler(func() {
|
||||
response = curPurchaseHandler.onOrderMsg(msg)
|
||||
}, jxutils.ComposeUniversalOrderID(orderID, model.VendorIDWSC))
|
||||
}
|
||||
return response
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||||
"git.rosy.net.cn/jx-callback/business/partner"
|
||||
"git.rosy.net.cn/jx-callback/business/partner/delivery/dada"
|
||||
"git.rosy.net.cn/jx-callback/globals"
|
||||
"git.rosy.net.cn/jx-callback/globals/api"
|
||||
)
|
||||
|
||||
const (
|
||||
FakeOrderStatusAccepted = "fakeaccepted"
|
||||
FakeOrderStatusFinishedPickup = "fakefinishedpickup"
|
||||
)
|
||||
|
||||
const (
|
||||
maxAddFee = 300 // 最大增加费用,单位为分,超过不发三方配送了
|
||||
)
|
||||
|
||||
var (
|
||||
VendorStatus2StatusMap = map[string]int{
|
||||
utils.Int2Str(weimobapi.OrderStatusWait4Pay): model.OrderStatusWait4Pay,
|
||||
utils.Int2Str(weimobapi.OrderStatusPayed): model.OrderStatusNew,
|
||||
FakeOrderStatusAccepted: model.OrderStatusAccepted,
|
||||
FakeOrderStatusFinishedPickup: model.OrderStatusFinishedPickup,
|
||||
utils.Int2Str(weimobapi.OrderStatusDelivering): model.OrderStatusDelivering,
|
||||
utils.Int2Str(weimobapi.OrderStatusFinished): model.OrderStatusFinished,
|
||||
utils.Int2Str(weimobapi.OrderStatusCanceled): model.OrderStatusCanceled,
|
||||
|
||||
weimobapi.MsgEventCreateRights: model.OrderStatusLocked,
|
||||
}
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) onOrderMsg(msg *weimobapi.CallbackMsg) (response *weimobapi.CallbackResponse) {
|
||||
var (
|
||||
err error
|
||||
status *model.OrderStatus
|
||||
orderMapData map[string]interface{}
|
||||
)
|
||||
if msg.IsFake || weimobapi.MsgEventCreateOrder == msg.Event || weimobapi.MsgEventOrderStatusChange == msg.Event {
|
||||
orderMapData, err = api.WeimobAPI.QueryOrderDetail(msg.OrderNo, false)
|
||||
if err == nil {
|
||||
status = p.callbackMsg2Status(msg, orderMapData)
|
||||
if msg.Event == weimobapi.MsgEventCreateOrder || status.Status == model.OrderStatusNew {
|
||||
order := p.Map2Order(orderMapData)
|
||||
order.StatusTime = msg.StatusTime
|
||||
err = partner.CurOrderManager.OnOrderNew(order, status)
|
||||
} else {
|
||||
err = partner.CurOrderManager.OnOrderStatusChanged("", status)
|
||||
}
|
||||
}
|
||||
}
|
||||
return weimobapi.Err2CallbackResponse(err, "")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) callbackMsg2Status(msg *weimobapi.CallbackMsg, orderMapData map[string]interface{}) (orderStatus *model.OrderStatus) {
|
||||
orderID := utils.Int64ToStr(msg.OrderNo)
|
||||
var vendorStatus string
|
||||
if msg.IsFake {
|
||||
vendorStatus = msg.Event
|
||||
} else {
|
||||
if msg.Event == weimobapi.MsgEventCreateRights {
|
||||
vendorStatus = msg.Event
|
||||
} else {
|
||||
vendorStatus = p.getOrderStatus(orderMapData)
|
||||
}
|
||||
}
|
||||
orderStatus = &model.OrderStatus{
|
||||
VendorOrderID: orderID,
|
||||
VendorID: model.VendorIDWSC,
|
||||
OrderType: model.OrderTypeOrder,
|
||||
RefVendorOrderID: orderID,
|
||||
RefVendorID: model.VendorIDWSC,
|
||||
VendorStatus: vendorStatus,
|
||||
Status: p.getStatusFromVendorStatus(vendorStatus),
|
||||
StatusTime: msg.StatusTime,
|
||||
Remark: "",
|
||||
}
|
||||
return orderStatus
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getOrderStatus(orderMapData map[string]interface{}) (status string) {
|
||||
return utils.Int64ToStr(utils.MustInterface2Int64(orderMapData["orderStatus"]))
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) getStatusFromVendorStatus(vendorStatus string) int {
|
||||
if status, ok := VendorStatus2StatusMap[vendorStatus]; ok {
|
||||
return status
|
||||
}
|
||||
return model.OrderStatusUnknown
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrder(vendorOrgCode, vendorOrderID string) (order *model.GoodsOrder, err error) {
|
||||
globals.SugarLogger.Debugf("wsc GetOrder orderID:%s", vendorOrderID)
|
||||
result, err := api.WeimobAPI.QueryOrderDetail(utils.Str2Int64(vendorOrderID), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
order = p.Map2Order(result)
|
||||
return order, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetOrderStatus(vendorOrgCode, vendorOrderID string) (status int, err error) {
|
||||
return 0, fmt.Errorf("未实现")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder) {
|
||||
result := orderData
|
||||
vendorOrderID := utils.Int64ToStr(utils.MustInterface2Int64(result["orderNo"]))
|
||||
deliveryDetail := result["deliveryDetail"].(map[string]interface{})
|
||||
logisticsDeliveryDetail, _ := deliveryDetail["logisticsDeliveryDetail"].(map[string]interface{})
|
||||
// paymentInfo := result["paymentInfo"].(map[string]interface{})
|
||||
order = &model.GoodsOrder{
|
||||
VendorOrderID: vendorOrderID,
|
||||
VendorID: model.VendorIDWSC,
|
||||
VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["processStoreId"])), // 这个不是通常意义上的vendor store id
|
||||
// StoreID
|
||||
BuyerComment: utils.Interface2String(result["buyerRemark"]),
|
||||
ExpectedDeliveredTime: utils.DefaultTimeValue,
|
||||
PickDeadline: utils.DefaultTimeValue,
|
||||
VendorStatus: utils.Int64ToStr(utils.MustInterface2Int64(result["orderStatus"])),
|
||||
StatusTime: utils.Timestamp2Time(utils.MustInterface2Int64(result["createTime"]) / 1000),
|
||||
OrderCreatedAt: utils.Timestamp2Time(utils.MustInterface2Int64(result["createTime"]) / 1000),
|
||||
OriginalData: string(utils.MustMarshal(result)),
|
||||
ActualPayPrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(result["totalAmount"])),
|
||||
BusinessType: model.BusinessTypeImmediate,
|
||||
}
|
||||
if logisticsDeliveryDetail != nil {
|
||||
order.StoreName = utils.Interface2String(logisticsDeliveryDetail["processStoreTitle"])
|
||||
order.ConsigneeName = utils.Interface2String(logisticsDeliveryDetail["receiverName"])
|
||||
order.ConsigneeMobile = utils.Interface2String(logisticsDeliveryDetail["receiverMobile"])
|
||||
order.ConsigneeAddress = utils.Interface2String(logisticsDeliveryDetail["receiverAddress"])
|
||||
order.ConsigneeLng = jxutils.StandardCoordinate2Int(utils.Str2Float64(utils.Interface2String(logisticsDeliveryDetail["receiverLongitude"])))
|
||||
order.ConsigneeLat = jxutils.StandardCoordinate2Int(utils.Str2Float64(utils.Interface2String(logisticsDeliveryDetail["receiverLatitude"])))
|
||||
order.CoordinateType = model.CoordinateTypeMars
|
||||
// if expectDeliveryTimeStr, ok := logisticsDeliveryDetail["expectDeliveryTime"].(string); ok {
|
||||
// if expectDeliveryTimeStr =
|
||||
// }
|
||||
} else {
|
||||
selfPickupDetail, _ := deliveryDetail["selfPickupDetail"].(map[string]interface{})
|
||||
if selfPickupDetail != nil {
|
||||
order.StoreName = utils.Interface2String(selfPickupDetail["selfPickupSiteName"])
|
||||
}
|
||||
}
|
||||
order.Status = p.getStatusFromVendorStatus(order.VendorStatus)
|
||||
itemList := result["itemList"].([]interface{})
|
||||
for _, v := range itemList {
|
||||
item := v.(map[string]interface{})
|
||||
skuName := utils.Interface2String(item["goodsTitle"])
|
||||
_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(skuName)
|
||||
sku := &model.OrderSku{
|
||||
VendorOrderID: vendorOrderID,
|
||||
VendorID: model.VendorIDWSC,
|
||||
Count: int(utils.MustInterface2Int64(item["skuNum"])),
|
||||
SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(item["skuCode"]), 0)),
|
||||
VendorSkuID: utils.Int64ToStr(utils.MustInterface2Int64(item["skuId"])),
|
||||
SkuName: skuName,
|
||||
Weight: jxutils.FormatSkuWeight(specQuality, specUnit), // 订单信息里没有重量,只有名字里尝试找
|
||||
SalePrice: jxutils.StandardPrice2Int(utils.MustInterface2Float64(item["price"])),
|
||||
}
|
||||
order.Skus = append(order.Skus, sku)
|
||||
}
|
||||
jxutils.RefreshOrderSkuRelated(order)
|
||||
if logisticsDeliveryDetail != nil {
|
||||
p.arrangeSaleStore(order, utils.Interface2String(logisticsDeliveryDetail["receiverCity"]), utils.Interface2String(logisticsDeliveryDetail["receiverProvince"]))
|
||||
}
|
||||
p.setStoreOrderSeq(order)
|
||||
globals.SugarLogger.Debug(utils.Format4Output(order, false))
|
||||
return order
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
|
||||
if !isAcceptIt {
|
||||
if globals.EnableWscStoreWrite {
|
||||
err = api.WeimobAPI.CancelOrder(utils.Str2Int64(order.VendorOrderID), "")
|
||||
}
|
||||
} else {
|
||||
if jxutils.GetSaleStoreIDFromOrder(order) != 0 {
|
||||
// 微商城没有确认,只有取消,模拟接受
|
||||
p.postFakeMsg(utils.Str2Int64(order.VendorOrderID), FakeOrderStatusAccepted)
|
||||
} else {
|
||||
globals.SugarLogger.Debugf("weimob AcceptOrRefuseOrder orderID:%s can not find sale store", order.VendorOrderID)
|
||||
if globals.EnableWscStoreWrite {
|
||||
err = api.WeimobAPI.CancelOrder(utils.Str2Int64(order.VendorOrderID), "没有找到合适的配送店")
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery)
|
||||
if globals.EnableWscStoreWrite && !isSelfDelivery {
|
||||
_, err = dada.CurDeliveryHandler.CreateWaybill(order, 0)
|
||||
}
|
||||
// 微商城没有拣货完成,模拟
|
||||
p.postFakeMsg(utils.Str2Int64(order.VendorOrderID), FakeOrderStatusFinishedPickup)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 拣货失败后再次招唤平台配送
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) { // 投递失败后确认收到退货
|
||||
return err
|
||||
}
|
||||
|
||||
// 将订单从购物平台配送转为自送
|
||||
func (p *PurchaseHandler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableWscStoreWrite {
|
||||
err = api.WeimobAPI.DeliveryOrder(&weimobapi.DeliveryOrder{
|
||||
OrderNo: utils.Str2Int64(order.VendorOrderID),
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 将订单从购物平台配送转为自送后又送达
|
||||
func (p *PurchaseHandler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
|
||||
return err
|
||||
}
|
||||
|
||||
// 完全自送的门店表示开始配送
|
||||
func (p *PurchaseHandler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc SelfDeliverDelivering orderID:%s", order.VendorOrderID)
|
||||
if globals.EnableWscStoreWrite {
|
||||
err = api.WeimobAPI.DeliveryOrder(&weimobapi.DeliveryOrder{
|
||||
OrderNo: utils.Str2Int64(order.VendorOrderID),
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 完全自送的门店表示配送完成
|
||||
func (p *PurchaseHandler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc SelfDeliverDelivered orderID:%s", order.VendorOrderID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) postFakeMsg(orderNo int64, fakeStatus string) {
|
||||
msg := &weimobapi.CallbackMsg{
|
||||
IsFake: true,
|
||||
Event: fakeStatus,
|
||||
OrderNo: orderNo,
|
||||
StatusTime: time.Now(),
|
||||
}
|
||||
utils.CallFuncAsync(func() {
|
||||
OnCallbackMsg(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) arrangeSaleStore(order *model.GoodsOrder, cityName, provinceName string) {
|
||||
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) setStoreOrderSeq(order *model.GoodsOrder) {
|
||||
if order.StoreID > 0 {
|
||||
year, month, day := order.StatusTime.Date()
|
||||
dateBegin := time.Date(year, month, day, 0, 0, 0, 0, order.StatusTime.Location())
|
||||
// dateEnd := date1.Add(time.Hour * 24)
|
||||
sql := `
|
||||
SELECT COUNT(*) ct
|
||||
FROM goods_order t1
|
||||
WHERE t1.store_id = ? AND t1.order_created_at >= ? AND t1.vendor_id = ?
|
||||
`
|
||||
var count int
|
||||
db := dao.GetDB()
|
||||
if err := dao.GetRow(db, &count, sql, order.StoreID, dateBegin, model.VendorIDWSC); err == nil {
|
||||
order.OrderSeq = count + 1
|
||||
globals.SugarLogger.Debugf("setStoreOrderSeq orderID:%s, dateBegin:%s, orderSeq:%d", order.VendorOrderID, utils.Time2Str(dateBegin), order.OrderSeq)
|
||||
} else {
|
||||
globals.SugarLogger.Errorf("setStoreOrderSeq orderID:%s failed with error:%v", order.VendorOrderID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error) {
|
||||
err = errors.New("微盟微商城还未实现GetOrderRealMobile")
|
||||
return mobile, err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *PurchaseHandler) AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
// 审核售后单申请
|
||||
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 确认收到退货
|
||||
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 发起全款退款
|
||||
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||||
return fmt.Errorf("微商城不支持全款退款")
|
||||
}
|
||||
|
||||
// 发起部分退款
|
||||
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
|
||||
return fmt.Errorf("微商城不支持部分退款")
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||||
"git.rosy.net.cn/jx-callback/business/model"
|
||||
)
|
||||
|
||||
func (c *PurchaseHandler) ReplyOrderComment(ctx *jxcontext.Context, vendorOrgCode string, orderComment *model.OrderComment, replyComment string) (err error) {
|
||||
return err
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package wsc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func (p *PurchaseHandler) ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string) (*dao.StoreDetail, error) {
|
||||
return nil, errors.New("微盟微商城还没实现")
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) UpdateStore(db *dao.DaoDB, storeID int, userName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error) {
|
||||
return hint, err
|
||||
}
|
||||
|
||||
func (p *PurchaseHandler) GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error) {
|
||||
return 0, err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user