package basesch import ( "fmt" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxcallback/orderman" "git.rosy.net.cn/jx-callback/business/jxcallback/scheduler" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "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" "strings" ) var ( ctx *jxcontext.Context ) var ( FixedBaseScheduler *BaseScheduler ) type BaseScheduler struct { IsReallyCallPlatformAPI bool } func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) { globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusNew || order.Status == model.OrderStatusWaitAccepted { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).AcceptOrRefuseOrder(order, isAcceptIt, userName) }, "AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt) } } else { return scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("AcceptOrRefuseOrder orderID:%s, status:%d is not suitable, isAcceptIt:%t", order.VendorOrderID, order.Status, isAcceptIt) } return err } func (c *BaseScheduler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) { globals.SugarLogger.Infof("PickupGoods orderID:%s,order :%v", order.VendorOrderID, utils.Format4Output(order, false)) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusAccepted { if c.IsReallyCallPlatformAPI { handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID) err = utils.CallFuncLogErrorWithInfo(func() (err error) { if err = handler.PickupGoods(order, isSelfDelivery, userName); err != nil { if status, err2 := handler.GetOrderStatus(order.VendorOrgCode, order.VendorOrderID); err2 == nil && status >= model.OrderStatusFinished { err = nil } } return err }, "PickupGoods orderID:%s", order.VendorOrderID) } } else { if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusAccepted { err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation globals.SugarLogger.Infof("PickupGoods orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } else { err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("PickupGoods orderID:%s status:%d already ok", order.VendorOrderID, order.Status) } } return err } func (c *BaseScheduler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s", order.VendorOrderID) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status >= model.OrderStatusFinishedPickup && order.Status <= model.OrderStatusDelivering { if order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled == 0 && c.IsReallyCallPlatformAPI { err = utils.CallFuncLogErrorWithInfo(func() error { return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).Swtich2SelfDeliver(order, userName) }, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID) } if err == nil { // 因为有些平台转自送后,不会再发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 order.Status = model.OrderStatusDelivering order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) } } else { if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusFinishedPickup || order.VendorID == order.WaybillVendorID { err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } else { err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("Swtich2SelfDeliver orderID:%s status:%d already ok", order.VendorOrderID, order.Status) } } return err } func (c *BaseScheduler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s", order.VendorOrderID) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusDelivering { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).Swtich2SelfDelivered(order, userName) }, "Swtich2SelfDelivered orderID:%s", order.VendorOrderID) } } else { if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusDelivering { err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } else { err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("Swtich2SelfDelivered orderID:%s status:%d already ok", order.VendorOrderID, order.Status) } } return err } func (c *BaseScheduler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Infof("SelfDeliverDelivering orderID:%s", order.VendorOrderID) if order.Status == model.OrderStatusFinishedPickup { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { // 下面这个写法暂存,可能会有问题 if err := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).SelfDeliverDelivering(order, userName); err != nil && (err != scheduler.ErrOrderStatusAlreadySatisfyCurOperation) { partner.CurOrderManager.OnOrderMsg(order, "SelfDeliverDelivering 调用[SelfDeliverDelivering]转自送", err.Error()) } if order.VendorID == model.VendorIDMTWM { // 转自送同时取消平台订单(美团才做这个操作) if _, err := partner.GetPurchasePlatformFromVendorID(order.VendorID).GetCancelDeliveryReason(order); err != nil { partner.CurOrderManager.OnOrderMsg(order, "订单转自送取消美团平台发单获取理由失败", err.Error()) } // 取消美团外卖配送,转自送 if err = partner.GetPurchasePlatformFromVendorID(order.VendorID).CancelLogisticsByWmOrderId(order, "101512", "已选择其他配送方式", order.VendorStoreID, order.VendorOrderID); err != nil { partner.CurOrderManager.OnOrderMsg(order, "取消美团外卖,转用三方配送", err.Error()) } // 查询订单状态, orderStatus, _ := partner.GetPurchasePlatformFromVendorID(order.VendorID).OrderLogisticsStatus(utils.Str2Int64(order.VendorOrderID)) if orderStatus == 100 { // 美团取消配送单 partner.CurOrderManager.OnOrderMsg(order, "美团外卖转自送成功.", "") return nil } else if strings.Contains(err.Error(), "包裹不存在") || strings.Contains(err.Error(), "运单不存在") || strings.Contains(err.Error(), "1071") || strings.Contains(err.Error(), "1014") || strings.Contains(err.Error(), "invalid character 'o' looking for beginning of value") { partner.CurOrderManager.OnOrderMsg(order, "美团外卖转自送可能成功,异常:", err.Error()) err = nil return nil } else { bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) err = c.CancelWaybill(bill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) partner.CurOrderManager.OnOrderMsg(order, "美团外卖运单无法取消,", err.Error()) return err } } return err }, "SelfDeliverDelivering orderID:%s", order.VendorOrderID) if err == nil { // 因为有些平台设置配送中后,不会发送订单在配送中消息过来,所以成功后就强制设置状态为配送中 order.Status = model.OrderStatusDelivering err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) } } } else { if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusFinishedPickup { err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation globals.SugarLogger.Infof("SelfDeliverDelivering orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } else { err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("SelfDeliverDelivering orderID:%s, status:%d already ok", order.VendorOrderID, order.Status) } } return err } func (c *BaseScheduler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) { globals.SugarLogger.Infof("SelfDeliverDelivered orderID:%s", order.VendorOrderID) if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status >= model.OrderStatusFinishedPickup && order.Status <= model.OrderStatusDelivering { if c.IsReallyCallPlatformAPI { err = utils.CallFuncLogError(func() error { if err = partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).SelfDeliverDelivered(order, userName); err != nil { bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID) c.CancelWaybill(bill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive) } return err }, "SelfDeliverDelivered orderID:%s", order.VendorOrderID) } } else { if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusDelivering { err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation globals.SugarLogger.Infof("SelfDeliverDelivered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status) } else { err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation globals.SugarLogger.Debugf("SelfDeliverDelivered orderID:%s, status:%d already ok", order.VendorOrderID, order.Status) } } return err } func (c *BaseScheduler) CreateWaybill(platformVendorID int, order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) { globals.SugarLogger.Infof("CreateWaybill to meituan orderID:%s, vendor:%s", order.VendorOrderID, jxutils.GetVendorName(platformVendorID)) if !model.IsOrderSolid(order) { // 如果订单是不完整的 globals.SugarLogger.Warnf("CreateWaybill orderID:%s, vendorID:%d is not solid!!!", order.VendorOrderID, platformVendorID) return nil, scheduler.ErrOrderIsNotSolid } // if order.DeliveryFlag&model.OrderDeliveryFlagMaskScheduleDisabled != 0 { // waybillList, err := partner.CurOrderManager.GetOrderWaybillInfo(jxcontext.AdminCtx, order.VendorOrderID, order.VendorID, true) // if err != nil { // return nil, err // } // if len(waybillList) > 0 { // return nil, fmt.Errorf("转商家自送的订单只允许有一个有效运单,当前已经有%s运单", jxutils.GetVendorName(waybillList[0].WaybillVendorID)) // } // } storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, order.VendorOrgCode) // 获取门店品牌余额 storeAcct, err := cms.GetStoreAcctBalance(ctx, jxutils.GetSaleStoreIDFromOrder(order)) // 获取门店余额 // 如果门店没钱,查看品牌,查询门店品牌id result, err := partner.CurStoreAcctManager.GetBrandBalance(storeDetail.BrandID) // 品牌余额 if err != nil { return nil, err } var balance int // 门店发单,如果是京西门店,直接使用京西余额,非京西门店使用门店余额,余额不足使用品牌余额! if order.CreateDeliveryType == model.YES { if storeDetail.BrandID == scheduler.JXC4B_SHOP || storeDetail.BrandID == scheduler.JXC4B_RAND_JXGY { // 京西品牌,扣门店 balance = storeAcct.AccountBalance } else { if storeAcct.AccountBalance >= model.BrandBalanceLimit { balance = storeAcct.AccountBalance } else if storeAcct.AccountBalance < model.BrandBalanceLimit && result >= model.BrandBalanceLimit { balance = result } else { balance = 0 } } } else { balance, _ = partner.CurStoreAcctManager.GetBrandBalance(storeDetail.BrandID) } handlerInfo := partner.GetDeliveryPlatformFromVendorID(platformVendorID) if handlerInfo != nil && handlerInfo.Use4CreateWaybill { //if model.DeliveryBrandMarkMap[platformVendorID]&storeDetail.BrandIsOpen != 0 && balance >= model.BrandBalanceLimit { if _, ok := model.DeliveryBrandMarkMap[platformVendorID]; ok && storeDetail.BrandIsOpen != 0 && balance >= model.BrandBalanceLimit { if c.IsReallyCallPlatformAPI { // 美团配送订单生成,配送费计算 bill, err = handlerInfo.Handler.CreateWaybill(order, maxDeliveryFee) if err != nil { globals.SugarLogger.Infof("CreateWaybill failed orderID:%s vendorID:%d with error:%v", order.VendorOrderID, platformVendorID, err) } else { order.DeliveryFlag |= model.WaybillVendorID2Mask(platformVendorID) err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order) } } } else { err = fmt.Errorf("CreateWaybill failed brand is close orderID: %s, isOpen: %d or store/brand money is enought ", order.VendorOrderID, storeDetail.BrandIsOpen) } } else { err = scheduler.ErrDeliverProviderWrong } return bill, err } func (c *BaseScheduler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) { globals.SugarLogger.Infof("CancelWaybill bill:%v, cancelReasonID:%d cancelReason:%s", bill, cancelReasonID, cancelReason) // 部分快递平台在取消成功后有时会不发运单取消消息过来(比如达达,904200512000442),为避免二次取消报错,添加状态判断 if c.IsReallyCallPlatformAPI && bill.OrderVendorID != bill.WaybillVendorID && bill.Status != model.WaybillStatusCanceled { if handlerInfo := partner.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID); handlerInfo != nil { if err = utils.CallFuncLogErrorWithInfo(func() error { if err := handlerInfo.Handler.CancelWaybill(bill, cancelReasonID, cancelReason); err != nil { return err } order, _ := partner.CurOrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID) return orderman.ResetCreateWaybillFee(nil, order) }, "CancelWaybill bill:%v", bill); err == nil { bill.Status = model.WaybillStatusCanceled bill.DeliveryFlag |= model.WaybillDeliveryFlagMaskActiveCancel _, err = dao.UpdateEntity(nil, bill, "Status", "DeliveryFlag") } globals.SugarLogger.Debugf("CancelWaybill bill:%v canceled by myself", bill) } } return err }