365 lines
14 KiB
Go
365 lines
14 KiB
Go
package partner
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"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/model/dao"
|
||
)
|
||
|
||
const (
|
||
StoreNameSeparator = "-"
|
||
)
|
||
|
||
const (
|
||
CreatedPeration = "create"
|
||
UpdatedPeration = "update"
|
||
)
|
||
|
||
const (
|
||
CancelWaybillReasonNotAcceptIntime = 1
|
||
CancelWaybillReasonSwitch2SelfFailed = 2
|
||
CancelWaybillReasonOther = 10
|
||
)
|
||
|
||
const (
|
||
PrinterStatusUnknown = 0
|
||
PrinterStatusOffline = 1
|
||
PrinterStatusOnlineOK = 2
|
||
PrinterStatusOnlineAbnormal = 3
|
||
)
|
||
|
||
const (
|
||
AfsApproveTypeRefund = 1 // 退款
|
||
AfsApproveTypeReturnGoods = 2 // 退货
|
||
AfsApproveTypeRefused = 3 // 驳回
|
||
)
|
||
|
||
const (
|
||
PrintResultSuccess = 0
|
||
PrintResultNoPrinter = 1
|
||
)
|
||
|
||
type PrinterStatus struct {
|
||
PrintResult int `json:"printResult"` // 0:成功,1:没有配置网络打印机
|
||
|
||
// PrinterStatusUnknown = 0
|
||
// PrinterStatusOffline = 1
|
||
// PrinterStatusOnlineOK = 2
|
||
// PrinterStatusOnlineAbnormal = 3
|
||
PrinterStatus int `json:"printerStatus"`
|
||
Printed int `json:"printed"` // 已经打印的单数
|
||
Waiting int `json:"waiting"` // 等待打印的单数,超过1一般不太正常
|
||
}
|
||
|
||
const (
|
||
TimerTypeNoOverride = 0 // GetStatusActionConfig 返回表示不修改缺省配置
|
||
TimerTypeByPass = 1
|
||
TimerTypeBaseNow = 2
|
||
TimerTypeBaseStatusTime = 3
|
||
TimerTypeBaseOrderCreatedAt = 4
|
||
)
|
||
|
||
type StatusActionParams struct {
|
||
TimerType int // 参见上面的相关常量定义
|
||
Timeout time.Duration // 超时时间,0在GetStatusActionConfig返回时表示不修改缺省
|
||
TimeoutGap int // 以秒为单位的随机时间,0在GetStatusActionConfig返回时表示不修改缺省
|
||
}
|
||
|
||
const (
|
||
WaybillFeeErrCodeCourierNotOpen = 1 //配送门店没有启用
|
||
WaybillFeeErrCodeCourierNotSupported = 2 //配送门店不被系统支持
|
||
WaybillFeeErrCodeCourierForbidden = 3 //配送门店内部禁用
|
||
WaybillFeeErrCodeCourierOthers = 10 //其它错误
|
||
)
|
||
|
||
type WaybillFeeInfo struct {
|
||
ErrCode int `json:"errCode"`
|
||
ErrStr string `json:"errStr"`
|
||
RefDeliveryFee int64 `json:"refDeliveryFee"`
|
||
RefAddFee int64 `json:"refAddFee"`
|
||
DeliveryFee int64 `json:"deliveryFee"`
|
||
TimeoutSecond int `json:"timeoutSecond"` // 系统会自动发运单的倒计时
|
||
Waybill *model.Waybill `json:"waybill"`
|
||
}
|
||
|
||
func (s *StatusActionParams) GetRefTimeout(statusTime time.Time, orderCreatedAt time.Time) (timeout time.Duration) {
|
||
switch s.TimerType {
|
||
case TimerTypeBaseNow:
|
||
timeout = s.Timeout
|
||
case TimerTypeBaseStatusTime:
|
||
timeout = statusTime.Sub(time.Now()) + s.Timeout
|
||
case TimerTypeBaseOrderCreatedAt:
|
||
timeout = orderCreatedAt.Sub(time.Now()) + s.Timeout
|
||
default:
|
||
timeout = 0
|
||
}
|
||
if timeout < 0 {
|
||
timeout = 0
|
||
}
|
||
return timeout
|
||
}
|
||
|
||
var (
|
||
CancelWaybillReasonStrNotAcceptIntime = "没有及时抢单"
|
||
CancelWaybillReasonStrSwitch2SelfFailed = "转自送失败"
|
||
CancelWaybillReasonStrOrderAlreadyFinished = "订单已经结束"
|
||
CancelWaybillReasonStrActive = "操作由人员主动发起"
|
||
)
|
||
|
||
var (
|
||
ErrCanNotFindItem = errors.New("没有找到指定的东西")
|
||
ErrStoreHaveNoCourier = errors.New("门店没有绑定相应的配送信息")
|
||
)
|
||
|
||
var (
|
||
CurOrderManager IOrderManager
|
||
CurStoreManager IStoreManager
|
||
|
||
PurchasePlatformHandlers map[int]IPurchasePlatformHandler
|
||
DeliveryPlatformHandlers map[int]*DeliveryPlatformHandlerInfo
|
||
UseableDeliveryVendorIDs []int
|
||
PrinterPlatformHandlers map[int]IPrinterHandler
|
||
)
|
||
|
||
type IOrderManager interface {
|
||
SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error)
|
||
|
||
OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error)
|
||
OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error)
|
||
OnOrderStatusChanged(orderStatus *model.OrderStatus) (err error)
|
||
OnOrderMsg(order *model.GoodsOrder, vendorStatus, remark string) (err error)
|
||
|
||
OnWaybillStatusChanged(bill *model.Waybill) (err error)
|
||
|
||
LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error)
|
||
LoadOrder2(vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error)
|
||
|
||
LoadOrderFinancial(vendorOrderID string, vendorID int) (order *model.OrderFinancial, err error)
|
||
LoadOrderFinancial2(vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error)
|
||
|
||
UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error)
|
||
UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error)
|
||
|
||
LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error)
|
||
OnOrderComments(orderCommentList []*model.OrderComment) (err error)
|
||
|
||
SaveOrderFinancialInfo(order *model.OrderFinancial, operation string) (err error)
|
||
SaveAfsOrderFinancialInfo(afsOrder *model.AfsOrder) (err error)
|
||
|
||
GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded bool) (bills []*model.Waybill, err error)
|
||
|
||
// afs order
|
||
OnAfsOrderAdjust(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error)
|
||
OnAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error)
|
||
OnAfsOrderStatusChanged(orderStatus *model.OrderStatus) (err error)
|
||
LoadAfsOrder(vendorAfsOrderID string, vendorID int) (afsOrder *model.AfsOrder, err error)
|
||
UpdateAfsOrderFields(afsOrder *model.AfsOrder, fieldList []string) (err error)
|
||
|
||
GetStatusDuplicatedCount(status *model.OrderStatus) (duplicatedCount int)
|
||
}
|
||
|
||
type IStoreManager interface {
|
||
OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error)
|
||
}
|
||
|
||
// purchase handler中
|
||
// 所有Sync,Refresh开头的函数都必须自己清理sync_status标记
|
||
// 所有非以Sync,Refresh开头的函数不用自己清理sync_status标记(VendorSync统一处理)
|
||
|
||
type IPurchasePlatformHandler interface {
|
||
// IPurchasePlatformPromotionHandler
|
||
GetVendorID() int
|
||
|
||
GetStatusFromVendorStatus(vendorStatus string) int
|
||
Map2Order(orderData map[string]interface{}) (order *model.GoodsOrder)
|
||
GetOrder(vendorOrderID string) (order *model.GoodsOrder, err error)
|
||
GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams)
|
||
|
||
AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error)
|
||
PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error)
|
||
|
||
AcceptOrRefuseFailedGetOrder(ctx *jxcontext.Context, order *model.GoodsOrder, isAcceptIt bool) (err error)
|
||
CallCourier(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) // 取货失败后再次招唤平台配送
|
||
ConfirmReceiveGoods(ctx *jxcontext.Context, order *model.GoodsOrder) (err error) // 投递失败后确认收到退货
|
||
|
||
// 将订单从购物平台配送转为自送
|
||
Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error)
|
||
|
||
// 将订单从购物平台配送转为自送后又送达
|
||
Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error)
|
||
|
||
// 完全自送的门店表示开始配送
|
||
SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error)
|
||
|
||
// 完全自送的门店表示配送完成
|
||
SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error)
|
||
|
||
GetOrderRealMobile(ctx *jxcontext.Context, order *model.GoodsOrder) (mobile string, err error)
|
||
|
||
ReplyOrderComment(ctx *jxcontext.Context, orderComment *model.OrderComment, replyComment string) (err error)
|
||
|
||
AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error)
|
||
CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error)
|
||
// order.Skus要包含原始订单中的Sku信息,removedSkuList中是要移除的Sku信息
|
||
AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error)
|
||
|
||
// 售后
|
||
// // 发起全款退款
|
||
// RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error)
|
||
// // 发起部分退款
|
||
// PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error)
|
||
// 审核售后单申请
|
||
AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error)
|
||
// // 确认收到退货
|
||
ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error)
|
||
|
||
////////
|
||
// Store
|
||
ReadStore(vendorStoreID string) (store *model.Store, err error)
|
||
UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error)
|
||
// EnableAutoAcceptOrder(vendorStoreID string, isEnabled bool) error
|
||
// OpenStore(vendorStoreID string, userName string) error
|
||
// CloseStore(vendorStoreID, closeNotice, userName string) error
|
||
|
||
SyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error)
|
||
RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error)
|
||
|
||
// !!!注意,此操作会先清除门店已有的商品,一般用于初始化,小心使用
|
||
FullSyncStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error)
|
||
DeleteRemoteStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync, isContinueWhenError bool) (hint string, err error)
|
||
UploadImg(ctx *jxcontext.Context, imgURL string, imgData []byte, imgName string) (imgHint string, err error)
|
||
GetStoreStatus(ctx *jxcontext.Context, vendorStoreID string) (storeStatus int, err error)
|
||
GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error)
|
||
|
||
// todo 如下两个函数需要合并一下s
|
||
GetStoresSku(ctx *jxcontext.Context, parentTask tasksch.ITask, storeIDs []int) (storeSkuList []*model.StoreSkuBind, err error)
|
||
GetStoreSkusInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*BareStoreSkuInfo) (outStoreSkuList []*BareStoreSkuInfo, err error)
|
||
}
|
||
|
||
// db *dao.DaoDB,
|
||
type IMultipleStoresHandler interface {
|
||
IPurchasePlatformHandler
|
||
ReadCategories() (cats []*model.SkuCategory, err error)
|
||
|
||
CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error)
|
||
UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
|
||
DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
|
||
ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error)
|
||
|
||
// sku
|
||
CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
|
||
ReadSku(vendorSkuID string) (skuNameExt *model.SkuNameExt, err error)
|
||
UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
|
||
DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
|
||
|
||
RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error)
|
||
}
|
||
|
||
type ISingleStoreHandler interface {
|
||
IPurchasePlatformHandler
|
||
SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error)
|
||
|
||
RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error)
|
||
}
|
||
|
||
type CreateWaybillPolicy func(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string)
|
||
|
||
type IDeliveryPlatformHandler interface {
|
||
CreateWaybill(order *model.GoodsOrder, policy CreateWaybillPolicy) (bill *model.Waybill, err error)
|
||
CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error)
|
||
|
||
GetVendorID() int
|
||
GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *WaybillFeeInfo, err error)
|
||
}
|
||
|
||
type IPrinterHandler interface {
|
||
GetVendorID() int
|
||
PrintMsg(ctx *jxcontext.Context, id1, id2, msgTitle, msgContent string) (printerStatus *PrinterStatus, err error)
|
||
GetPrinterStatus(ctx *jxcontext.Context, id1, id2 string) (printerStatus *PrinterStatus, err error)
|
||
|
||
RegisterPrinter(ctx *jxcontext.Context, id1, id2, printerName string) (newID1, newID2 string, err error)
|
||
UnregisterPrinter(ctx *jxcontext.Context, id1, id2 string) (err error)
|
||
|
||
PrintOrder(ctx *jxcontext.Context, store *model.Store, order *model.GoodsOrder) (printerStatus *PrinterStatus, err error)
|
||
}
|
||
|
||
type DeliveryPlatformHandlerInfo struct {
|
||
Handler IDeliveryPlatformHandler
|
||
Use4CreateWaybill bool
|
||
}
|
||
|
||
type BasePurchasePlatform struct {
|
||
}
|
||
|
||
func (p *BasePurchasePlatform) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams) {
|
||
return params
|
||
}
|
||
|
||
func init() {
|
||
PurchasePlatformHandlers = make(map[int]IPurchasePlatformHandler)
|
||
DeliveryPlatformHandlers = make(map[int]*DeliveryPlatformHandlerInfo)
|
||
PrinterPlatformHandlers = make(map[int]IPrinterHandler)
|
||
}
|
||
|
||
func InitOrderManager(curOrderManager IOrderManager) {
|
||
CurOrderManager = curOrderManager
|
||
}
|
||
|
||
func InitStoreManager(curStoreManager IStoreManager) {
|
||
CurStoreManager = curStoreManager
|
||
}
|
||
|
||
func RegisterPurchasePlatform(handler IPurchasePlatformHandler) {
|
||
vendorID := handler.GetVendorID()
|
||
if !(model.IsPurchaseVendorExist(vendorID)) {
|
||
panic(fmt.Sprintf("purchase vendor:%d is illegal", vendorID))
|
||
}
|
||
if _, ok := PurchasePlatformHandlers[vendorID]; ok {
|
||
panic(fmt.Sprintf("purchase vendor:%d, already exists", vendorID))
|
||
}
|
||
PurchasePlatformHandlers[vendorID] = handler
|
||
}
|
||
|
||
func RegisterDeliveryPlatform(handler IDeliveryPlatformHandler, isUse4CreateWaybill bool) {
|
||
vendorID := handler.GetVendorID()
|
||
if !(model.IsDeliveryVendorExist(vendorID)) {
|
||
panic(fmt.Sprintf("delivery vendor:%d is illegal", vendorID))
|
||
}
|
||
if _, ok := DeliveryPlatformHandlers[vendorID]; ok {
|
||
panic(fmt.Sprintf("delivery vendor:%d, already exists", vendorID))
|
||
}
|
||
DeliveryPlatformHandlers[vendorID] = &DeliveryPlatformHandlerInfo{
|
||
Handler: handler,
|
||
Use4CreateWaybill: isUse4CreateWaybill,
|
||
}
|
||
UseableDeliveryVendorIDs = append(UseableDeliveryVendorIDs, vendorID)
|
||
}
|
||
|
||
func RegisterPrinterPlatform(handler IPrinterHandler) {
|
||
vendorID := handler.GetVendorID()
|
||
if !(model.IsPrinterVendorExist(vendorID)) {
|
||
panic(fmt.Sprintf("printer vendor:%d is illegal", vendorID))
|
||
}
|
||
if _, ok := PrinterPlatformHandlers[vendorID]; ok {
|
||
panic(fmt.Sprintf("printer vendor:%d, already exists", vendorID))
|
||
}
|
||
PrinterPlatformHandlers[vendorID] = handler
|
||
}
|
||
|
||
func GetPurchasePlatformFromVendorID(vendorID int) IPurchasePlatformHandler {
|
||
return PurchasePlatformHandlers[vendorID]
|
||
}
|
||
|
||
func GetDeliveryPlatformFromVendorID(vendorID int) *DeliveryPlatformHandlerInfo {
|
||
return DeliveryPlatformHandlers[vendorID]
|
||
}
|
||
|
||
func GetPrinterPlatformFromVendorID(vendorID int) IPrinterHandler {
|
||
return PrinterPlatformHandlers[vendorID]
|
||
}
|