Files
jx-callback/business/jxcallback/orderman/order.go
2019-12-31 13:31:29 +08:00

834 lines
32 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package orderman
import (
"errors"
"fmt"
"math"
"strings"
"time"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/baseapi"
"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"
"github.com/astaxie/beego/orm"
)
type tStoreSkuBindAndVendorSkuID struct {
VendorSkuID int64 `orm:"column(vendor_sku_id)"`
SkuID int `orm:"column(sku_id)"`
Weight int
Price int
}
func init() {
}
// msgVendorStatus的意思是事件本身的类型类似有时收到NewOrder事件去取订单状态不一定就是New的
// OnOrderAdjust也类似而OrderStatus要记录的是消息所以添加这个
func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
globals.SugarLogger.Debugf("OnOrderNew orderID:%s", order.VendorOrderID)
if order.ConsigneeMobile2 == "" && jxutils.IsStringLikeMobile(order.ConsigneeMobile) {
order.ConsigneeMobile2 = order.ConsigneeMobile
}
db := dao.GetDB()
dao.Begin(db)
defer func() {
globals.SugarLogger.Debugf("OnOrderNew exit orderID:%s", order.VendorOrderID)
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if order.Status == model.OrderStatusUnknown {
order.Status = model.OrderStatusNew
}
var isDuplicated bool
if order.Status == model.OrderStatusNew && order.VendorID == model.VendorIDJX && !model.IsOrderJXTemp(order) {
isDuplicated, _, err = c.addOrderStatus(orderStatus, db)
} else {
isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db)
if err == nil && !isDuplicated {
isDuplicated, err = c.SaveOrder(order, false, db)
}
}
if err == nil {
dao.Commit(db)
if !isDuplicated {
err = scheduler.CurrentScheduler.OnOrderNew(order, false)
}
} else {
dao.Rollback(db)
}
return err
}
// todo 调整单的处理可能还需要再细化一点,当前只是简单的删除重建
func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
globals.SugarLogger.Debugf("OnOrderAdjust orderID:%s, status:%d", order.VendorOrderID, order.Status)
if order.ConsigneeMobile2 == "" && jxutils.IsStringLikeMobile(order.ConsigneeMobile) {
order.ConsigneeMobile2 = order.ConsigneeMobile
}
db := dao.GetDB()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
// 出现过调整单后状态回到新订单状态比如911350836000622
// 不完全确定,加一个处理
if order.Status < model.OrderStatusAccepted {
order.Status = model.OrderStatusAccepted
}
isDuplicated, err := addOrderOrWaybillStatus(orderStatus, db)
if err == nil && !isDuplicated {
err = utils.CallFuncLogError(func() error {
_, err = db.Db.Raw("DELETE FROM order_sku WHERE vendor_order_id = ? AND vendor_id = ?", order.VendorOrderID, order.VendorID).Exec()
return err
}, "OnAdjustOrder delete order, orderID:%s", order.VendorOrderID)
if err != nil {
return err
}
adjustCount := int8(0)
previousOrder := &model.GoodsOrder{
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
}
if err = dao.GetEntity(db, previousOrder, model.FieldVendorOrderID, model.FieldVendorID); err != nil && !dao.IsNoRowsError(err) {
globals.SugarLogger.Warnf("OnOrderAdjust, order:%s GetEntity failed with error:%v", order.VendorOrderID, err)
return err
}
if err == nil {
adjustCount = previousOrder.AdjustCount
if _, err = dao.DeleteEntity(db, previousOrder); err != nil {
return err
}
order.VendorWaybillID = previousOrder.VendorWaybillID
order.WaybillVendorID = previousOrder.WaybillVendorID
} else {
globals.SugarLogger.Warnf("OnOrderAdjust, but previous order:%s doesn't exist", order.VendorOrderID)
}
// err = utils.CallFuncLogError(func() error {
// _, err = db.Db.Raw("DELETE FROM goods_order WHERE vendor_order_id = ? AND vendor_id = ?", order.VendorOrderID, order.VendorID).Exec()
// return err
// }, "OnAdjustOrder delete order_sku, orderID:%s", order.VendorOrderID)
order.AdjustCount = adjustCount + 1
isDuplicated, err = c.SaveOrder(order, true, db)
}
if err == nil {
dao.Commit(db)
if !isDuplicated {
// 因为订单调度器需要的是真实状态所以用order的状态
_ = scheduler.CurrentScheduler.OnOrderNew(order, false)
_ = scheduler.CurrentScheduler.OnOrderStatusChanged(order, orderStatus, false)
}
} else {
dao.Rollback(db)
}
return err
}
func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *model.OrderStatus) (err error) {
// 有些平台(比如美团外卖),在新订单事件没有成功返回,但在重发订单消息前,订单状态转换,则不会再重发新订单事件,特殊处理一下
if orderStatus.Status == model.OrderStatusAccepted {
if _, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == ErrCanNotFindOrder {
if handler := partner.GetPurchaseOrderHandlerFromVendorID(orderStatus.VendorID); handler != nil {
if order, err2 := handler.GetOrder(vendorOrgCode, orderStatus.VendorOrderID); err2 == nil {
c.OnOrderNew(order, orderStatus)
}
}
}
}
db := dao.GetDB()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
isDuplicated, order, err := c.addOrderStatus(orderStatus, db)
if err == nil {
dao.Commit(db)
if orderStatus.Status == model.OrderStatusWaybillTipChanged {
if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
if handler := partner.GetWaybillTipUpdater(orderStatus.RefVendorID); handler != nil {
tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, vendorOrgCode, order.VendorStoreID, orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, "")
if err2 == nil {
order.WaybillTipMoney = tipFee
c.UpdateOrderFields(order, []string{"WaybillTipMoney"})
}
}
}
} else if orderStatus.Status == model.OrderStatusFinished {
if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
// 当前只针对三方运单更新配送费信息
if order.WaybillVendorID >= 0 && order.VendorWaybillID != "" && order.WaybillVendorID != order.VendorID {
if waybill, err2 := c.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID); err2 == nil {
if handler := partner.GetWaybillTipUpdater(waybill.WaybillVendorID); handler != nil {
tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, waybill.VendorOrgCode, "", order.VendorOrderID, waybill.VendorWaybillID, waybill.VendorWaybillID2)
if err2 == nil && waybill.TipFee != tipFee {
waybill.ActualFee += tipFee - waybill.TipFee
waybill.TipFee = tipFee
dao.UpdateEntity(db, waybill, "TipFee", "ActualFee")
}
}
}
}
}
}
if !isDuplicated {
if order != nil {
order.Skus = c.loadOrderSku(db, order.VendorOrderID, order.VendorID)
_ = scheduler.CurrentScheduler.OnOrderStatusChanged(order, orderStatus, false)
}
}
} else {
dao.Rollback(db)
}
return err
}
func (c *OrderManager) OnOrderMsg(order *model.GoodsOrder, vendorStatus, remark string) (err error) {
_, _, err = c.addOrderStatus(&model.OrderStatus{
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
OrderType: model.OrderTypeOrder,
RefVendorOrderID: order.VendorOrderID,
RefVendorID: order.VendorID,
VendorStatus: vendorStatus,
Status: model.OrderStatusMsg,
StatusTime: time.Now(),
Remark: utils.LimitUTF8StringLen(remark, 255),
}, nil)
return err
}
func setFakeOrderFlag(db *dao.DaoDB, order *model.GoodsOrder) {
if order.DeliveryType == model.OrderDeliveryTypeSelfTake {
if realMobile := jxutils.GetRealMobile4Order(order); realMobile != "" {
if configList, err := dao.QueryConfigs(db, model.ConfigSysFakeOrderMobiles, model.ConfigTypeSys, ""); err == nil && len(configList) > 0 {
isMatch := false
mobileList := strings.Split(configList[0].Value, ",")
for _, v := range mobileList {
if jxutils.TrimDecorationChar(v) == realMobile {
isMatch = true
break
}
}
if isMatch {
order.Flag |= model.OrderFlagMaskFake
}
}
}
}
}
func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error) {
globals.SugarLogger.Debugf("SaveOrder orderID:%s, VendorStoreID:%s, status:%d", order.VendorOrderID, order.VendorStoreID, order.Status)
// 忽略查找JX信息错误
c.updateOrderOtherInfo(order, db)
order.ID = 0
order.WaybillVendorID = model.VendorIDUnknown
order.OrderFinishedAt = utils.DefaultTimeValue
setFakeOrderFlag(db, order)
// cms.HandleOrder4Consignee(order)
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
// todo hardcode 兼容京东消息错序问题
if true { //order.VendorID == model.VendorIDJD {
orderStatus := &model.OrderStatus{}
if dao.GetRow(db, orderStatus, `
SELECT *
FROM order_status
WHERE order_type = ? AND vendor_order_id = ? AND vendor_id = ? AND status > 0
ORDER BY status_time DESC
LIMIT 1
`, model.OrderTypeOrder, order.VendorOrderID, order.VendorID) == nil {
if orderStatus.Status > order.Status {
order.Status = orderStatus.Status
order.VendorStatus = orderStatus.VendorStatus
order.StatusTime = orderStatus.StatusTime
// jxutils.RefreshOrderSkuRelated(order)
}
}
}
order.ConsigneeName = utils.LimitUTF8StringLen(order.ConsigneeName, 32)
created, _, err2 := db.Db.ReadOrCreate(order, "VendorOrderID", "VendorID")
if err = err2; err == nil {
originalOrder := &model.GoodsOrderOriginal{
VendorOrderID: order.VendorOrderID,
VendorID: order.VendorID,
OrderCreatedAt: order.OrderCreatedAt,
OriginalData: order.OriginalData,
}
if _, _, err = db.Db.ReadOrCreate(originalOrder, "VendorOrderID", "VendorID"); err == nil {
if created {
if err = dao.CreateMultiEntities(db, order.Skus); err != nil {
baseapi.SugarLogger.Warnf("saveOrder orderID:%s, save order_sku failed with error:%v", order.VendorOrderID, err)
}
} else {
isDuplicated = true
order.DuplicatedCount++
db.Db.Update(order, "DuplicatedCount")
baseapi.SugarLogger.Infof("saveOrder duplicated orderid:%s msg received", order.VendorOrderID)
}
}
} else {
globals.SugarLogger.Warnf("saveOrder create order:%v, error:%v", order, err)
}
if err == nil {
dao.Commit(db)
}
return isDuplicated, err
}
func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.DaoDB, storePayPercentage, changePriceType int) (err error) {
globals.SugarLogger.Debugf("updateOrderSkuOtherInfo orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
jxStoreID := jxutils.GetShowStoreIDFromOrder(order)
var opNumStr string
if time.Now().Sub(order.OrderCreatedAt) < 1*time.Hour && order.VendorID != model.VendorIDJD {
opNumStr = "2"
} else {
opNumStr = "2"
}
if jxStoreID == 0 {
return nil
}
orderSkus := order.Skus
vendorSkuIDs := make([]int64, 0)
for _, v := range orderSkus {
intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0)
if intVendorSkuID != 0 {
vendorSkuIDs = append(vendorSkuIDs, intVendorSkuID)
}
}
if len(vendorSkuIDs) > 0 {
tableName := "t2"
if model.MultiStoresVendorMap[order.VendorID] == 1 {
tableName = "t1"
}
fieldPrefix := dao.ConvertDBFieldPrefix(model.VendorNames[order.VendorID])
sql := `
SELECT %s.%s_id vendor_sku_id, t1.id sku_id, t2.price, t1.weight
FROM sku t1
LEFT JOIN store_sku_bind t2 ON t1.id = t2.sku_id AND t2.deleted_at = ? AND t2.store_id = ?
WHERE t1.deleted_at = ? AND %s.%s_id IN (-1, ` + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")"
sql = fmt.Sprintf(sql, tableName, fieldPrefix, tableName, fieldPrefix)
if order.VendorID == model.VendorIDJX {
sql = `
SELECT t1.id vendor_sku_id, t1.id sku_id, t2.price, t1.weight
FROM sku t1
LEFT JOIN store_sku_bind t2 ON t1.id = t2.sku_id AND t2.deleted_at = ? AND t2.store_id = ?
WHERE t1.deleted_at = ? AND t1.id IN (-1, ` + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")"
}
var skuInfos []*tStoreSkuBindAndVendorSkuID
if err = dao.GetRows(db, &skuInfos, sql, utils.DefaultTimeValue, jxStoreID, utils.DefaultTimeValue, vendorSkuIDs); err != nil {
globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku info for orderID:%s, error:%v", order.VendorOrderID, err)
return err
}
skumapper := make(map[int64]*tStoreSkuBindAndVendorSkuID)
for _, v := range skuInfos {
skumapper[v.VendorSkuID] = v
}
for _, v := range orderSkus {
v.VendorOrderID = order.VendorOrderID
v.VendorID = order.VendorID
intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0)
if intVendorSkuID != 0 && v.VendorSkuID != "-70000" { // todo hard code
skuBindInfo := skumapper[intVendorSkuID]
if skuBindInfo == nil {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku找不到门店价格或商品映射orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.VendorSkuID, v)
} else {
v.JxSkuID = skuBindInfo.SkuID
v.ShopPrice = int64(skuBindInfo.Price)
v.Weight = skuBindInfo.Weight // 以本地信息中的WEIGHT为准
if skuBindInfo.Price == 0 {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku门店价格为零一般原因为没有门店价格信息orderID:%s, StoreID:%d, SkuID:%d, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.JxSkuID, v)
}
}
}
// 直营店始终按比例结算,不考虑活动与结算表
salePrice := v.SalePrice
if changePriceType == model.StoreChangePriceTypeManagedStore && v.ShopPrice != 0 {
salePrice = 0
}
v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, salePrice, storePayPercentage)
}
// 直营店始终按比例结算,不考虑活动与结算表
if changePriceType != model.StoreChangePriceTypeManagedStore {
updateSingleOrderEarningPrice(order, db)
}
}
return nil
}
func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) {
jxStoreID := jxutils.GetShowStoreIDFromOrder(order)
skuIDMap := make(map[int]int)
for _, v := range order.Skus {
skuIDMap[v.SkuID] = 1
}
if len(skuIDMap) > 0 {
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, model.ActTypeAll, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt)
if err != nil {
globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err)
}
if actStoreSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false); actStoreSkuMap != nil {
for _, v := range order.Skus {
if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 {
if actStoreSku := actStoreSkuMap.GetActStoreSku(jxStoreID, skuID, order.VendorID); actStoreSku != nil {
v.EarningPrice = actStoreSku.EarningPrice
if true { //v.StoreSubName != "" { // 之前这里为什么要加判断?
v.StoreSubID = actStoreSku.ActID
}
}
}
}
}
}
}
func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.DaoDB) (err error) {
globals.SugarLogger.Debugf("updateOrderOtherInfo orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
payPercentage := 0
changePriceType := model.StoreChangePriceTypeDirect
storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID)
if err != nil {
if !dao.IsNoRowsError(err) {
globals.SugarLogger.Warnf("updateOrderOtherInfo GetStoreDetailByVendorStoreID orderID:%s, VendorStoreID:%s, error:%v", order.VendorOrderID, order.VendorStoreID, err)
return err
}
if time.Now().Sub(order.OrderCreatedAt) < 1*time.Hour {
globals.SugarLogger.Infof("updateOrderOtherInfo [运营]订单在京西与平台都找不到京西门店信息,订单:%s,平台门店ID:%s,平台:%s", order.VendorOrderID, order.VendorStoreID, model.VendorChineseNames[order.VendorID])
}
err = nil
} else {
order.JxStoreID = storeDetail.Store.ID
payPercentage = storeDetail.PayPercentage
changePriceType = int(storeDetail.ChangePriceType)
}
if err = c.updateOrderSkuOtherInfo(order, db, payPercentage, changePriceType); err == nil {
jxutils.RefreshOrderSkuRelated(order)
// caculateOrderEarningPrice(order, payPercentage)
}
return err
}
// 计算结算给门店的金额
// func caculateOrderEarningPrice(order *model.GoodsOrder, storePayPercentage int) {
// order.EarningPrice = 0
// for _, v := range order.Skus {
// skuEarningPrice := v.EarningPrice
// if skuEarningPrice == 0 {
// skuEarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage)
// }
// order.EarningPrice += skuEarningPrice * int64(v.Count)
// }
// }
func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) {
globals.SugarLogger.Debugf("addOrderStatus refOrderID:%s, orderID:%s", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID)
if db == nil {
db = dao.GetDB()
}
isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db)
if err == nil && !isDuplicated && (orderStatus.Status != model.OrderStatusUnknown && orderStatus.Status != model.OrderStatusMsg) {
order = &model.GoodsOrder{
VendorOrderID: orderStatus.VendorOrderID,
VendorID: orderStatus.VendorID,
}
if err = db.Db.ReadForUpdate(order, "VendorOrderID", "VendorID"); err == nil {
// todo 美团在订单完成后还可能收到订单取消应该当成售后单处理才合适强制忽略这种情况比如订单80662201436073600
// 后来又发现有订单81710104014426376在完成后直接再被取消的情况不能生成售后单还是再允许完成后取消。。。
// if orderStatus.VendorID == model.VendorIDMTWM && model.IsOrderFinalStatus(order.Status) {
// return false, order, nil
// }
if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) ||
(model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
order.VendorStatus = orderStatus.VendorStatus
updateFields := []string{
"VendorStatus",
"UpdatedAt",
}
if model.IsOrderMainStatus(orderStatus.Status) {
order.Status = orderStatus.Status
order.StatusTime = orderStatus.StatusTime
updateFields = append(updateFields, "Status", "StatusTime")
if model.IsOrderFinalStatus(orderStatus.Status) {
order.OrderFinishedAt = orderStatus.StatusTime
updateFields = append(updateFields, "OrderFinishedAt")
if order.LockStatus != model.OrderStatusUnknown {
order.LockStatus = model.OrderStatusUnknown
updateFields = append(updateFields, "LockStatus")
}
}
} else {
if model.IsOrderUnlockStatus(orderStatus.Status) {
order.LockStatus = model.OrderStatusUnknown
updateFields = append(updateFields, "LockStatus")
} else if model.IsOrderLockStatus(orderStatus.Status) {
if order.LockStatus != model.OrderStatusUnknown {
globals.SugarLogger.Warnf("addOrderStatus refOrderID:%s, orderID:%s, order.LockStatus:%d, status.LockStatus:%d", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, order.LockStatus, orderStatus.Status)
}
order.Flag &= ^model.OrderFlagMaskUserApplyCancel
order.LockStatus = orderStatus.Status
order.LockStatusTime = orderStatus.StatusTime
updateFields = append(updateFields, "LockStatus", "LockStatusTime", "Flag")
}
}
utils.CallFuncLogError(func() error {
_, err = db.Db.Update(order, updateFields...)
return err
}, "addOrderStatus update orderID:%s, status:%v", order.VendorOrderID, orderStatus)
} else {
isDuplicated = true
}
} else {
order = nil
if dao.IsNoRowsError(err) { // todo 消息错序
err = nil
} else {
globals.SugarLogger.Warnf("addOrderStatus orderID:%s read failed with error:%v", order.VendorOrderID, err)
}
}
}
return isDuplicated, order, err
}
func (c *OrderManager) loadOrderSku(db *dao.DaoDB, vendorOrderID string, vendorID int) (orderSkus []*model.OrderSku) {
utils.CallFuncLogError(func() (err error) {
_, err = db.Db.QueryTable("order_sku").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).All(&orderSkus)
return err
}, "loadOrderSku orderID:%s", vendorOrderID)
return orderSkus
}
func (c *OrderManager) loadOrder(vendorOrderID, vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) {
db1 := dao.GetDB()
db := db1.Db
order = &model.GoodsOrder{
VendorOrderID: vendorOrderID,
VendorOrderID2: vendorOrderID2,
VendorID: vendorID,
}
keyFields := []string{
model.FieldVendorID,
}
if vendorOrderID != "" {
keyFields = append(keyFields, model.FieldVendorOrderID)
}
if vendorOrderID2 != "" {
keyFields = append(keyFields, model.FieldVendorOrderID2)
}
if err = db.Read(order, keyFields...); err == nil {
vendorOrderID = order.VendorOrderID
order.Skus = c.loadOrderSku(db1, vendorOrderID, vendorID)
}
if err != nil {
order = nil
if err == orm.ErrNoRows {
err = ErrCanNotFindOrder
}
globals.SugarLogger.Infof("LoadOrder orderID:%s failed with error:%v", vendorOrderID, err)
}
return order, err
}
func (c *OrderManager) LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) {
return c.loadOrder(vendorOrderID, "", vendorID)
}
func (c *OrderManager) LoadOrder2(vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) {
return c.loadOrder("", vendorOrderID2, vendorID)
}
func (c *OrderManager) LoadOrderFinancial(vendorOrderID string, vendorID int) (order *model.OrderFinancial, err error) {
return c.loadOrderFinancial(vendorOrderID, "", vendorID)
}
func (c *OrderManager) LoadOrderFinancial2(vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error) {
return c.loadOrderFinancial("", vendorOrderID2, vendorID)
}
func (c *OrderManager) loadOrderFinancial(vendorOrderID, vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error) {
db := orm.NewOrm()
order = &model.OrderFinancial{
VendorOrderID: vendorOrderID,
VendorOrderID2: vendorOrderID2,
VendorID: vendorID,
}
keyFields := []string{
model.FieldVendorID,
}
if vendorOrderID != "" {
keyFields = append(keyFields, model.FieldVendorOrderID)
}
if vendorOrderID2 != "" {
keyFields = append(keyFields, model.FieldVendorOrderID2)
}
// 这块不知道怎么写了、、、标注一下
if err = db.Read(order, keyFields...); err == nil {
vendorOrderID = order.VendorOrderID
err = utils.CallFuncLogError(func() error {
_, err = db.QueryTable("order_sku_financial").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).Filter("is_afs_order", 0).All(&order.Skus)
return err
}, "LoadOrder orderID:%s", vendorOrderID)
}
if err != nil {
order = nil
if err == orm.ErrNoRows {
err = ErrCanNotFindOrder
}
globals.SugarLogger.Infof("LoadOrderFinancial orderID:%s failed with error:%v", vendorOrderID, err)
}
return order, err
}
func (c *OrderManager) UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error) {
return c.UpdateOrderFields(order, []string{"Status", "DeliveryFlag"})
}
func (c *OrderManager) UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error) {
db := dao.GetDB()
utils.CallFuncLogError(func() error {
if order.ID == 0 {
order2 := *order
if err = dao.GetEntity(db, &order2, model.FieldVendorOrderID, model.FieldVendorID); err == nil {
order.ID = order2.ID
} else if dao.IsNoRowsError(err) {
err = nil // 强制忽略订单不存在错误
}
}
if err == nil && order.ID != 0 {
_, err = db.Db.Update(order, fieldList...)
}
return err
}, "UpdateOrderFields orderID:%s failed with error:%v", order.VendorOrderID, err)
return err
}
func (c *OrderManager) RefreshHistoryOrdersEarningPrice(ctx *jxcontext.Context, vendorOrderID string, actID int, vendorIDs []int, storeID int, fromDate, toDate string, isAsync, isContinueWhenError bool) (hint string, errCode string, err error) {
var (
orderList []*model.GoodsOrder
fromDateParam time.Time
toDateParam time.Time
beginAt time.Time
endAt time.Time
)
db := dao.GetDB()
if actID > 0 {
if fromDate != "" && toDate != "" {
fromDateParam = utils.Str2Time(fromDate)
toDateParam = utils.Str2Time(toDate)
actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, 0, 0, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue)
if len(actList.Data) > 0 {
actBeginAt := actList.Data[0].BeginAt
actEndAt := actList.Data[0].EndAt
if fromDateParam.Sub(actBeginAt) > 0 && fromDateParam.Sub(actEndAt) > 0 {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致!,活动时间范围:[%v] 至 [%v] ,订单创建时间范围 [%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam))
}
if actBeginAt.Sub(toDateParam) > 0 && actEndAt.Sub(toDateParam) > 0 {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致!,活动时间范围:[%v] 至 [%v] ,订单创建时间范围 [%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam))
}
if fromDateParam.Sub(actBeginAt) > 0 {
beginAt = fromDateParam
if toDateParam.Sub(actEndAt) > 0 {
endAt = actEndAt
} else {
endAt = toDateParam
}
} else {
beginAt = actBeginAt
if toDateParam.Sub(actEndAt) > 0 {
endAt = actEndAt
} else {
endAt = toDateParam
}
}
orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, beginAt, endAt)
} else {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("未查询到相关结算活动活动ID[%d]", actID))
}
} else if fromDate == "" && toDate == "" {
actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, 0, 0, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue)
if len(actList.Data) > 0 {
orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, actList.Data[0].BeginAt, actList.Data[0].EndAt)
} else {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("未查询到相关结算活动活动ID[%d]", actID))
}
} else {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("间隔时间必须完整!时间范围:[%v] 至 [%v]", fromDate, toDate))
}
} else {
if fromDate != "" && toDate != "" {
fromDateParam = utils.Str2Time(fromDate)
toDateParam = utils.Str2Time(toDate)
//若未传入活动ID,且时间间隔大于10天则不允许查询
if math.Ceil(toDateParam.Sub(fromDateParam).Hours()/24) > 10 {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("查询间隔时间不允许大于10天时间范围[%v] 至 [%v]", fromDate, toDate))
}
orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, fromDateParam, toDateParam)
} else {
return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("若不按活动查询则间隔时间必须完整!时间范围:[%v] 至 [%v]", fromDate, toDate))
}
}
if len(orderList) <= 0 {
return "", model.ErrCodePoint, errors.New(fmt.Sprintf("所选活动没有要更新结算价的订单!,vendorOrderID : %s, actID : %d, 时间范围:[%v] 至 [%v]", vendorOrderID, actID, fromDate, toDate))
}
task := tasksch.NewParallelTask("刷新历史订单结算价", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
order := batchItemList[0].(*model.GoodsOrder)
db := dao.GetDB()
updateSingleOrderEarningPrice(order, db)
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
for _, value := range order.Skus {
if _, err = dao.UpdateEntity(db, value, "EarningPrice", "StoreSubID"); err != nil {
return nil, err
}
}
jxutils.RefreshOrderSkuRelated(order)
num, err := dao.UpdateEntity(db, order, "EarningPrice")
if err != nil {
return nil, err
}
dao.Commit(db)
retVal = []string{utils.Int64ToStr(num)}
return retVal, err
}, orderList)
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
resultNum, err2 := task.GetResult(0)
if err = err2; err == nil {
hint = resultNum[0].(string)
}
} else {
hint = task.GetID()
}
return hint, model.ErrCodeSuccess, err
}
func RefreshOrdersWithoutJxStoreID(ctx *jxcontext.Context, fromDate, toDate string, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
fromDateParam time.Time
toDateParam time.Time
)
if fromDate != "" {
fromDateParam = utils.Str2Time(fromDate)
}
if toDate != "" {
toDateParam = utils.Str2Time(toDate)
}
db := dao.GetDB()
task := tasksch.NewParallelTask("订单门店归属补漏", tasksch.NewParallelConfig().SetParallelCount(1), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
_, err = dao.UpdateOrdersWithoutJxStoreID(db, fromDateParam, toDateParam)
return retVal, err
}, []int{0})
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
_, err = task.GetResult(0)
hint = "1"
} else {
hint = task.GetID()
}
return hint, err
}
func GetOrdersSupplement(ctx *jxcontext.Context, storIDs, vendorIDs []int, vendorOrderID, fromTime, toTime string, status, stype, IsReverse, offset, pageSize int) (pageInfo *model.PagedInfo, err error) {
var (
db = dao.GetDB()
fromTimeP time.Time
toTimeP time.Time
)
if fromTime != "" {
fromTimeP = utils.Str2Time(fromTime)
}
if toTime != "" {
toTimeP = utils.Str2Time(toTime)
}
if fromTimeP.After(toTimeP) {
return nil, fmt.Errorf("时间范围不合法!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP)
}
result, totalCount, err := dao.GetOrdersSupplement(db, storIDs, vendorIDs, vendorOrderID, fromTimeP, toTimeP, status, stype, IsReverse, offset, pageSize)
pageInfo = &model.PagedInfo{
Data: result,
TotalCount: totalCount,
}
return pageInfo, err
}
func AddUpdateOrdersSupplement(ctx *jxcontext.Context, ordersSupplement *model.OrderSupplementFee) (num int64, err error) {
var (
db = dao.GetDB()
id = ordersSupplement.ID
)
now := time.Now()
ordersSupplement.SupplementTime = &now
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
if id > 0 {
if ordersSupplement.Status == 1 {
return 0, fmt.Errorf("已结账的扣款信息不允许修改门店ID:[%v],订单号:[%v]", ordersSupplement.StoreID, ordersSupplement.VendorOrderID)
}
ordersSupplement.UpdatedAt = time.Now()
ordersSupplement.LastOperator = ctx.GetUserName()
if ordersSupplement.Status == -1 {
ordersSupplement.DeletedAt = time.Now()
} else {
ordersSupplement.DeletedAt = utils.DefaultTimeValue
}
num, err = dao.UpdateEntity(db, ordersSupplement)
} else {
dao.WrapAddIDCULDEntity(ordersSupplement, ctx.GetUserName())
err = dao.CreateEntity(db, ordersSupplement)
}
dao.Commit(db)
return num, err
}