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 ( 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 ) type StatusActionParams struct { TimerType int // 参见上面的相关常量定义 Timeout time.Duration // 超时时间,0在GetStatusActionConfig返回时表示不修改缺省 TimeoutGap int // 以秒为单位的随机时间,0在GetStatusActionConfig返回时表示不修改缺省 } type WaybillFeeInfo struct { ErrStr string `json:"errStr"` RefDeliveryFee int64 `json:"refDeliveryFee"` RefAddFee int64 `json:"refAddFee"` DeliveryFee int64 `json:"deliveryFee"` } func (s *StatusActionParams) GetRefTimeout(statusTime time.Time) (timeout time.Duration) { switch s.TimerType { case TimerTypeBaseNow: timeout = s.Timeout case TimerTypeBaseStatusTime: timeout = statusTime.Sub(time.Now()) + s.Timeout default: 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, msgVendorStatus string) (err error) OnOrderAdjust(order *model.GoodsOrder, msgVendorStatus string) (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) UpdateWaybillVendorID(bill *model.Waybill, revertStatus bool) (err error) UpdateOrderStatusAndFlag(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) } 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 { 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) //////// // 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) } // 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] }