package controller import ( "fmt" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/legacy/models" "github.com/astaxie/beego/orm" ) // 所有公共接口调用前,要求在order里或status中设置合适的Status type OrderController struct { orderMap SyncMapWithTimeout } func NewOrderManager() *OrderController { return &OrderController{} } func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) { db := orm.NewOrm() isDuplicated, err := addOrderOrWaybillStatus(c.order2Status(order), db) if !isDuplicated { c.handleAutoAcceptOrder(order.VendorOrderID, order.VendorID, order.ConsigneeMobile, order.StoreID, db, func(isAccept bool) { // c.purchasePlatformHandlers[order.VendorID].AcceptOrRefuseOrder(order, isAccept) if isAccept { order.Status = model.OrderStatusAccepted } else { order.Status = model.OrderStatusFailed } }) // 忽略查找JX信息错误 c.updateOrderOtherInfo(order, db) db.Begin() // globals.SugarLogger.Debugf("new order:%v", order) order.OrderFinishedAt = utils.DefaultTimeValue order.ID = 0 created, _, err2 := db.ReadOrCreate(order, "VendorOrderID", "VendorID") if err = err2; err == nil { c.orderMap.Store(ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), order.ID) 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, 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, order.Weight, order.OrderCreatedAt) } sql = sql[:len(sql)-1] + ";" if _, err = db.Raw(sql, params...).Exec(); err != nil { db.Rollback() baseapi.SugarLogger.Infof("insert order_sku error:%v", err) } else { db.Commit() if globals.HandleLegacyJxOrder { c.legacyWriteJxOrder(order, db, false) } } } else { order.DuplicatedCount++ db.Update(order, "DuplicatedCount") db.Commit() baseapi.SugarLogger.Infof("duplicated order:%s vendorID:%d, msg received", order.VendorOrderID, order.VendorID) } } else { db.Rollback() globals.SugarLogger.Warnf("create order:%v, error:%v", order, err) } } return err } func (c *OrderController) OnOrderAdjust(order *model.GoodsOrder) (err error) { db := orm.NewOrm() isDuplicated, err := addOrderOrWaybillStatus(c.order2Status(order), 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") 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") if err != nil { return err } } err = c.OnOrderNew(order) if globals.HandleLegacyJxOrder && err == nil { c.legacyWriteJxOrder(order, db, true) } return err } func (c *OrderController) OnOrderStatusChanged(orderStatus *model.OrderStatus) (err error) { isDuplicated, err := c.addOrderStatus(orderStatus, nil) if err == nil && !isDuplicated { if globals.HandleLegacyJxOrder { c.legacyJxOrderStatusChanged(orderStatus, nil) } } return err } // private func (c *OrderController) updateOrderSkuOtherInfo(orderSkus []*model.OrderSku, db orm.Ormer) (err error) { var sql string if orderSkus[0].VendorID == model.VendorIDJD { sql = ` SELECT t1.jdskuid, t2.id FROM skumapper t1 JOIN jx_sku t2 ON t1.skuid = t2.id WHERE t1.jdskuid IN ( ` } else if orderSkus[0].VendorID == model.VendorIDELM { // 饿了么当前没有存映射关系 return nil } else { panic(fmt.Sprintf("wrong vendorid:%d", orderSkus[0].VendorID)) } jdskuids := []interface{}{} for _, v := range orderSkus { sql += "?," jdskuids = append(jdskuids, int(utils.Str2Int64(v.VendorSkuID))) } sql = sql[:len(sql)-1] + ")" var lists []orm.ParamsList if num, err := db.Raw(sql, jdskuids...).ValuesList(&lists); err == nil && num > 0 { skumapper := make(map[string]string) for _, v := range lists { skumapper[v[0].(string)] = v[1].(string) } globals.SugarLogger.Debug(skumapper) for _, v := range orderSkus { if jxskuid, ok := skumapper[v.VendorSkuID]; ok { v.JxSkuID = int(utils.Str2Int64(jxskuid)) } else { globals.SugarLogger.Infof("can not find %v", jxskuid) } } } else { globals.SugarLogger.Errorf("can not get sku info for vendorID:%d, vendorOrderID:%s, num:%d, error:%v", orderSkus[0].VendorID, orderSkus[0].VendorOrderID, num, err) } return err } func (c *OrderController) updateOrderOtherInfo(order *model.GoodsOrder, db orm.Ormer) (err error) { var sql string if order.VendorID == model.VendorIDJD { sql = ` SELECT t2.storeid FROM jxstoremap t1 JOIN jxstore t2 ON t1.jxstoreid = t2.storeid WHERE t1.jdstoreid = ? ` } else if order.VendorID == model.VendorIDELM { sql = ` SELECT t2.storeid 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.Errorf("can not find store info for vendorID:%d, store:%s, num:%d, error:%v", order.VendorID, order.VendorStoreID, num, err) } err = c.updateOrderSkuOtherInfo(order.Skus, db) return err } func (c *OrderController) handleAutoAcceptOrder(orderID string, vendorID int, userMobile string, jxStoreID int, db orm.Ormer, handler func(accepted bool)) int { handleType := 0 if userMobile != "" { if db == nil { db = orm.NewOrm() } user := &models.BlackClient{ Mobile: userMobile, } if err := db.Read(user, "Mobile"); err != nil { if err != orm.ErrNoRows { globals.SugarLogger.Errorf("read data error:%v, data:%v, vendorID:%d", err, user, vendorID) } // 在访问数据库出错的情况下,也需要自动接单 handleType = 1 } else { // 强制拒单 globals.SugarLogger.Infof("force reject order:%s, vendorID:%d", orderID, vendorID) handleType = -1 } } else { globals.SugarLogger.Infof("order:%s, vendorID:%d, mobile is empty, should accept order", orderID, vendorID) handleType = 1 } if handleType == 1 { handler(true) } else if handleType == -1 { handler(false) } return handleType } func (c *OrderController) addOrderStatus(orderStatus *model.OrderStatus, db orm.Ormer) (isDuplicated bool, err error) { if db == nil { db = orm.NewOrm() } isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db) if !isDuplicated && orderStatus.Status > model.OrderStatusUnknown { order := &model.GoodsOrder{ VendorOrderID: orderStatus.VendorOrderID, VendorID: orderStatus.VendorID, } if err = c.updateOrderPKID(order, db); err == nil { order.Status = orderStatus.Status order.VendorStatus = orderStatus.VendorStatus utils.CallFuncLogError(func() error { columns := []string{"Status", "VendorStatus"} if orderStatus.Status >= model.OrderStatusEndBegin { order.OrderFinishedAt = orderStatus.StatusTime columns = append(columns, "OrderFinishedAt") } _, err := db.Update(order, columns...) return err }, "update order") } } return isDuplicated, err } func (c *OrderController) updateOrderPKID(order *model.GoodsOrder, db orm.Ormer) (err error) { value, ok := c.orderMap.Load(ComposeUniversalOrderID(order.VendorOrderID, order.VendorID)) if !ok { err = db.Read(order, "VendorOrderID", "VendorID") // todo 这里应该要报警,但测试阶段先去掉 // utils.CallFuncLogError(func() error { // err = db.Read(order, "VendorOrderID", "VendorID") // return err // }, "can not get order info from db") } else { order.ID = value.(int64) } return err } func (c *OrderController) order2Status(order *model.GoodsOrder) (retVal *model.OrderStatus) { retVal = &model.OrderStatus{ VendorOrderID: order.VendorOrderID, VendorID: order.VendorID, OrderType: model.OrderTypeOrder, Status: order.Status, VendorStatus: order.VendorStatus, StatusTime: order.OrderCreatedAt, } return retVal } //Waybill func (c *OrderController) OnWaybillStatusChanged(bill *model.Waybill, db orm.Ormer) (err error) { return c.updateOrderByWaybill(bill, db) } func (c *OrderController) updateOrderByWaybill(bill *model.Waybill, db orm.Ormer) (err error) { if db == nil { db = orm.NewOrm() } order := &model.GoodsOrder{ VendorOrderID: bill.VendorOrderID, VendorID: bill.OrderVendorID, } if err = db.Read(order, "VendorOrderID", "VendorID"); err == nil { if order.Status < model.OrderStatusEndBegin { order.WaybillStatus = bill.Status order.WaybillVendorStatus = bill.VendorStatus db.Update(order, "WaybillStatus", "WaybillVendorStatus") } } return err }