- refactor file structure.

This commit is contained in:
gazebo
2018-08-17 13:59:15 +08:00
parent d872d4d0ec
commit d40186e930
25 changed files with 153 additions and 150 deletions

View File

@@ -0,0 +1,359 @@
package orderman
import (
"fmt"
"time"
"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/model"
"git.rosy.net.cn/jx-callback/globals"
"github.com/astaxie/beego/orm"
)
func (c *OrderManager) LoadPendingOrders() []*model.GoodsOrder {
db := orm.NewOrm()
var orders []*model.GoodsOrder
tillTime := time.Now().Add(-pendingOrderGapMax)
_, err := db.Raw(`
SELECT *
FROM goods_order
WHERE order_created_at >= ?
AND status < ?
`, tillTime, model.OrderStatusEndBegin).QueryRows(&orders)
if err != nil {
globals.SugarLogger.Warnf("LoadPendingOrders load pending orders error:%v", err)
return nil
}
for _, order := range orders {
utils.CallFuncLogError(func() error {
_, err = db.QueryTable("order_sku").Filter("vendor_order_id", order.VendorOrderID).Filter("vendor_id", order.VendorID).All(&order.Skus)
return err
}, "LoadPendingOrders order:%v", order)
}
return orders
}
// msgVendorStatus的意思是事件本身的类型类似有时收到NewOrder事件去取订单状态不一定就是New的
// OnOrderAdjust也类似而OrderStatus要记录的是消息所以添加这个
func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, msgVendorStatus string) (err error) {
// todo transaction
db := orm.NewOrm()
if order.Status == model.OrderStatusUnknown {
order.Status = model.OrderStatusNew
}
status := model.Order2Status(order)
status.Status = model.OrderStatusNew
status.VendorStatus = msgVendorStatus
isDuplicated, err := addOrderOrWaybillStatus(status, db)
if err == nil && !isDuplicated {
if isDuplicated, err = c.saveOrder(order, false, db); err == nil && !isDuplicated {
err = scheduler.CurrentScheduler.OnOrderNew(order, false)
}
}
return err
}
// todo 调整单的处理可能还需要再细化一点,当前只是简单的删除重建
func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, msgVendorStatus string) (err error) {
// todo transaction
db := orm.NewOrm()
if order.Status == model.OrderStatusUnknown {
order.Status = model.OrderStatusNew
}
status := model.Order2Status(order)
status.Status = model.OrderStatusAdjust
status.VendorStatus = msgVendorStatus
isDuplicated, err := addOrderOrWaybillStatus(status, db)
if err == nil && !isDuplicated {
err = utils.CallFuncLogError(func() error {
_, err = 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
}
err = utils.CallFuncLogError(func() error {
_, err = 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)
if err != nil {
return err
}
if isDuplicated, err = c.saveOrder(order, true, db); err == nil && !isDuplicated {
// 因为订单调度器需要的是真实状态所以用order的状态
err = scheduler.CurrentScheduler.OnOrderNew(order, false)
err = scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(order), false)
}
}
return err
}
func (c *OrderManager) OnOrderStatusChanged(orderStatus *model.OrderStatus) (err error) {
isDuplicated, err := c.addOrderStatus(orderStatus, nil)
if err == nil && !isDuplicated {
err = scheduler.CurrentScheduler.OnOrderStatusChanged(orderStatus, false)
if globals.GenerateLegacyJxOrder {
c.legacyJxOrderStatusChanged(orderStatus, nil)
}
}
return err
}
// private
func (c *OrderManager) saveOrder(order *model.GoodsOrder, isAdjust bool, db orm.Ormer) (isDuplicated bool, err error) {
// 忽略查找JX信息错误
c.updateOrderOtherInfo(order, db)
order.ID = 0
order.WaybillVendorID = model.VendorIDUnknown
order.OrderFinishedAt = utils.DefaultTimeValue
order.OrderCreatedAt = order.StatusTime
// hardcode 兼容京东消息错序问题
orderStatus := &model.OrderStatus{}
if db.Raw(`
SELECT *
FROM order_status
WHERE order_type = ? AND vendor_order_id = ? AND vendor_id = ?
ORDER BY status_time DESC
LIMIT 1
`, model.OrderTypeOrder, order.VendorOrderID, order.VendorID).QueryRow(orderStatus) == nil {
order.Status = orderStatus.Status
order.VendorStatus = orderStatus.VendorStatus
order.StatusTime = orderStatus.StatusTime
}
globals.SugarLogger.Debugf("saveOrder isAdjust:%t, order:%v", isAdjust, order)
db.Begin()
created, _, err2 := db.ReadOrCreate(order, "VendorOrderID", "VendorID")
if err = err2; err == nil {
if created {
sql := `INSERT INTO order_sku(vendor_order_id, vendor_id, count, vendor_sku_id, sku_id, jx_sku_id, sku_name,
shop_price, sale_price, weight, sku_type, promotion_type, order_created_at) VALUES`
params := []interface{}{}
for _, sku := range order.Skus {
sql += "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),"
params = append(params, sku.VendorOrderID, sku.VendorID, sku.Count, sku.VendorSkuID, sku.SkuID, sku.JxSkuID, sku.SkuName,
sku.ShopPrice, sku.SalePrice, sku.Weight, sku.SkuType, sku.PromotionType, order.StatusTime)
}
sql = sql[:len(sql)-1] + ";"
if _, err = db.Raw(sql, params...).Exec(); err != nil {
db.Rollback()
baseapi.SugarLogger.Infof("saveOrder insert order:%v, order_sku error:%v", order, err)
} else {
db.Commit()
if globals.GenerateLegacyJxOrder {
c.legacyWriteJxOrder(order, db, isAdjust)
}
}
} else {
isDuplicated = true
order.DuplicatedCount++
db.Update(order, "DuplicatedCount")
db.Commit()
baseapi.SugarLogger.Infof("saveOrder duplicated orderid:%s msg received", order.VendorOrderID)
}
} else {
db.Rollback()
globals.SugarLogger.Warnf("saveOrder create order:%v, error:%v", order, err)
}
return isDuplicated, err
}
func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db orm.Ormer) (err error) {
jxStoreID := jxutils.GetJxStoreIDFromOrder(order)
if jxStoreID == 0 {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营]订单在京西与平台都找不到京西门店信息orderID:%s, VendorStoreID:%s", order.VendorOrderID, order.VendorStoreID)
return nil
}
orderSkus := order.Skus
var sql string
if orderSkus[0].VendorID == model.VendorIDJD {
sql = `
SELECT t1.jdskuid, t1.skuid, t2.price
FROM skumapper t1
LEFT JOIN jx_sku_store_bind t2 ON t1.skuid = t2.jxskuid AND t2.jxstoreid = ?
WHERE t1.jdskuid IN (-1,`
} else if orderSkus[0].VendorID == model.VendorIDELM {
sql = `
SELECT t2.jxskuid, t2.jxskuid, t2.price
FROM jx_sku_store_bind t2
WHERE t2.jxstoreid = ? AND t2.jxskuid IN (-1,`
} else {
panic(fmt.Sprintf("wrong vendorid:%d", orderSkus[0].VendorID))
}
sqlParams := []interface{}{jxStoreID}
for _, v := range orderSkus {
if orderSkus[0].VendorID == model.VendorIDJD {
sql += "?,"
sqlParams = append(sqlParams, int(utils.Str2Int64(v.VendorSkuID)))
} else if v.SkuID != 0 {
sql += "?,"
sqlParams = append(sqlParams, v.SkuID)
}
}
sql = sql[:len(sql)-1] + ")"
var lists []orm.ParamsList
if num, err := db.Raw(sql, sqlParams...).ValuesList(&lists); err == nil {
skumapper := make(map[string]orm.ParamsList)
for _, v := range lists {
skumapper[v[0].(string)] = v
}
// globals.SugarLogger.Debug(skumapper)
for _, v := range orderSkus {
if orderSkus[0].VendorID == model.VendorIDJD {
if values, ok := skumapper[v.VendorSkuID]; ok {
v.JxSkuID = int(utils.Str2Int64(utils.Interface2String(values[1])))
v.ShopPrice = utils.Str2Int64WithDefault(utils.Interface2String(values[2]), 0)
order.ShopPrice += v.ShopPrice
if v.ShopPrice == 0 {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营2]京东订单sku门店价格为零一般原因为没有门店价格信息orderID:%s, StoreID:%d, SkuID:%d, sku:%v", order.VendorOrderID, jxStoreID, v.JxSkuID, v)
}
} else {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营2]京东订单sku找不到门店价格或商品映射orderID:%s, StoreID:%d, VendorSkuID:%s, sku:%v", order.VendorOrderID, jxStoreID, v.VendorSkuID, v)
}
} else {
if v.SkuID != 0 {
if values, ok := skumapper[utils.Int2Str(v.SkuID)]; ok {
v.ShopPrice = utils.Str2Int64WithDefault(utils.Interface2String(values[2]), 0)
order.ShopPrice += v.ShopPrice
if v.ShopPrice == 0 {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营2]饿了么订单sku门店价格为零orderID:%s, StoreID:%d, SkuID:%d, sku:%v", order.VendorOrderID, jxStoreID, v.SkuID, v)
}
} else {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营2]饿了么订单sku找不到门店价格orderID:%s, StoreID:%d, SkuID:%d, sku:%v", order.VendorOrderID, jxStoreID, v.SkuID, v)
}
} else {
globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营2]饿了么订单sku没有京西ID信息orderID:%s, VendorSkuID:%s, sku:%v", order.VendorOrderID, v.VendorSkuID, v)
}
}
}
} else {
globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku info for orderID:%s, num:%d, error:%v", order.VendorOrderID, num, err)
}
return err
}
func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db orm.Ormer) (err error) {
var sql string
if order.VendorID == model.VendorIDJD {
sql = `
SELECT t1.jxstoreid
FROM jxstoremap t1
/* JOIN jxstore t2 ON t1.jxstoreid = t2.storeid */
WHERE t1.jdstoreid = ?
`
} else if order.VendorID == model.VendorIDELM {
sql = `
SELECT t1.jx_store_id
FROM jx_to_elm_store_map t1
/* JOIN jxstore t2 ON t1.jx_store_id = t2.storeid */
WHERE t1.elm_store_id = ?
`
} else {
panic(fmt.Sprintf("wrong vendorid:%d", order.VendorID))
}
var lists []orm.ParamsList
if num, err := db.Raw(sql, utils.Str2Int64(order.VendorStoreID)).ValuesList(&lists); err == nil && num == 1 {
order.JxStoreID = int(utils.Str2Int64(lists[0][0].(string)))
} else {
globals.SugarLogger.Infof("updateOrderOtherInfo [运营]订单orderID:%s在京西找不到相应的京西门店信息请处理, VendorStoreID:%s, num:%d, error:%v", order.VendorOrderID, order.VendorStoreID, num, err)
}
err = c.updateOrderSkuOtherInfo(order, db)
return err
}
func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db orm.Ormer) (isDuplicated bool, err error) {
if db == nil {
db = orm.NewOrm()
}
isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db)
if err == nil && !isDuplicated &&
(orderStatus.Status > model.OrderStatusUnknown ||
(orderStatus.Status == model.OrderStatusUnlocked || orderStatus.Status == model.OrderStatusLocked || orderStatus.Status == model.OrderStatusApplyCancel)) {
order := &model.GoodsOrder{
VendorOrderID: orderStatus.VendorOrderID,
VendorID: orderStatus.VendorID,
}
if err = db.ReadForUpdate(order, "VendorOrderID", "VendorID"); err == nil {
if (orderStatus.Status == model.OrderStatusUnlocked || orderStatus.Status == model.OrderStatusLocked || orderStatus.Status == model.OrderStatusApplyCancel) ||
(orderStatus.Status > model.OrderStatusUnknown && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
order.VendorStatus = orderStatus.VendorStatus
order.StatusTime = orderStatus.StatusTime
updateFields := []string{
"VendorStatus", "StatusTime",
}
if orderStatus.Status > model.OrderStatusUnknown {
order.LockStatus = model.OrderStatusUnknown
order.Status = orderStatus.Status
updateFields = append(updateFields, "Status", "LockStatus")
} else {
if orderStatus.Status == model.OrderStatusUnlocked {
order.LockStatus = model.OrderStatusUnknown
updateFields = append(updateFields, "LockStatus")
} else if orderStatus.Status == model.OrderStatusLocked || orderStatus.Status == model.OrderStatusApplyCancel {
order.LockStatus = orderStatus.Status
updateFields = append(updateFields, "LockStatus")
}
}
if orderStatus.Status >= model.OrderStatusEndBegin {
order.OrderFinishedAt = orderStatus.StatusTime
updateFields = append(updateFields, "OrderFinishedAt")
}
utils.CallFuncLogError(func() error {
_, err = db.Update(order, updateFields...)
return err
}, "addOrderStatus update orderID:%s, status:%v", order.VendorOrderID, orderStatus)
} else {
isDuplicated = true
}
} else {
if err == orm.ErrNoRows { // todo 消息错序
err = nil
} else {
globals.SugarLogger.Warnf("addOrderStatus orderID:%s read failed with error:%v", order.VendorOrderID, err)
}
}
}
return isDuplicated, err
}
func (c *OrderManager) LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) {
db := orm.NewOrm()
order = &model.GoodsOrder{
VendorOrderID: vendorOrderID,
VendorID: vendorID,
}
if err = db.Read(order, "VendorOrderID", "VendorID"); err == nil {
err = utils.CallFuncLogError(func() error {
_, err = db.QueryTable("order_sku").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).All(&order.Skus)
return err
}, "LoadOrder orderID:%s", vendorOrderID)
}
if err != nil {
globals.SugarLogger.Infof("LoadOrder orderID:%s failed with error:%v", vendorOrderID, err)
}
return order, err
}
//Waybill
func (c *OrderManager) UpdateWaybillVendorID(bill *model.Waybill, revertStatus bool) (err error) {
globals.SugarLogger.Debugf("UpdateWaybillVendorID bill:%v", bill)
db := orm.NewOrm()
params := orm.Params{
"vendor_waybill_id": bill.VendorWaybillID,
"waybill_vendor_id": bill.WaybillVendorID,
}
// 如果运单被取消,则要保持在已拣货状态
if revertStatus && bill.WaybillVendorID == model.VendorIDUnknown {
params["status"] = model.OrderStatusFinishedPickup
}
utils.CallFuncLogError(func() error {
_, err = db.QueryTable("goods_order").Filter("vendor_order_id", bill.VendorOrderID).Filter("vendor_id", bill.OrderVendorID).Update(params)
return err
}, "UpdateWaybillVendorID update order, bill:%v", bill)
return err
}