package controller import ( "fmt" "time" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/scheduler" "git.rosy.net.cn/jx-callback/globals" "github.com/astaxie/beego/orm" ) // 所有公共接口调用前,要求在order里或status中设置合适的Status type OrderController struct { } func NewOrderManager() *OrderController { return &OrderController{} } func (c *OrderController) LoadPendingOrders() []*model.GoodsOrder { db := orm.NewOrm() var orders []*model.GoodsOrder _, err := db.Raw(` SELECT * FROM goods_order WHERE order_created_at >= ? AND status < ? ORDER by order_created_at `, time.Now().Add(-pendingOrderGapMax), model.OrderStatusEndBegin).QueryRows(&orders) if err != nil { globals.SugarLogger.Warnf("LoadPendingOrders load pending orders error:%v", err) return nil } return orders } // msgVendorStatus的意思是事件本身的类型,类似有时收到NewOrder事件去取,订单状态不一定就是New的 // OnOrderAdjust也类似,而OrderStatus要记录的是消息,所以添加这个 func (c *OrderController) OnOrderNew(order *model.GoodsOrder, msgVendorStatus string) (err error) { db := orm.NewOrm() status := model.Order2Status(order) status.Status = model.OrderStatusNew status.VendorStatus = msgVendorStatus isDuplicated, err := addOrderOrWaybillStatus(status, db) if err == nil && !isDuplicated { if err = c.saveOrder(order, false, db); err == nil { err = scheduler.CurrentScheduler.OnOrderNew(order) weixinmsg.NotifyNewOrder(order) } } return err } // todo 调整单的处理可能还需要再细化一点,当前只是简单的删除重建 func (c *OrderController) OnOrderAdjust(order *model.GoodsOrder, msgVendorStatus string) (err error) { db := orm.NewOrm() 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 err = c.saveOrder(order, true, db); err == nil { // 因为订单调度器需要的是真实状态,所以用order的状态 err = scheduler.CurrentScheduler.OnOrderStatusChanged(model.Order2Status(order)) } } return err } func (c *OrderController) OnOrderStatusChanged(orderStatus *model.OrderStatus) (err error) { isDuplicated, err := c.addOrderStatus(orderStatus, nil) if err == nil && !isDuplicated { err = scheduler.CurrentScheduler.OnOrderStatusChanged(orderStatus) if globals.GenerateLegacyJxOrder { c.legacyJxOrderStatusChanged(orderStatus, nil) } } return err } // private func (c *OrderController) saveOrder(order *model.GoodsOrder, isAdjust bool, db orm.Ormer) (err error) { // 忽略查找JX信息错误 c.updateOrderOtherInfo(order, db) db.Begin() order.ID = 0 order.WaybillVendorID = model.VendorIDUnknown order.OrderFinishedAt = utils.DefaultTimeValue order.OrderCreatedAt = order.StatusTime globals.SugarLogger.Debugf("saveOrder isAdjust:%t, order:%v", isAdjust, order) 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 { 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 err } 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, t1.skuid 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("updateOrderSkuOtherInfo can not find sku map:%v", v) } } } else { globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku info for orderID:%s, num:%d, error:%v", 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 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.Errorf("updateOrderOtherInfo can not find store info for orderID:%s, store:%s, num:%d, error:%v", order.VendorOrderID, order.VendorStoreID, num, err) } err = c.updateOrderSkuOtherInfo(order.Skus, db) return err } 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 err == nil && !isDuplicated && orderStatus.Status > model.OrderStatusNew { params := orm.Params{ "status": orderStatus.Status, "vendor_status": orderStatus.VendorStatus, "status_time": orderStatus.StatusTime, } if orderStatus.Status >= model.OrderStatusEndBegin { params["order_finished_at"] = orderStatus.StatusTime } utils.CallFuncLogError(func() error { _, err = db.QueryTable("goods_order").Filter("vendor_order_id", orderStatus.VendorOrderID).Filter("vendor_id", orderStatus.VendorID).Update(params) return err }, "addOrderStatus update order, status:%v", orderStatus) } return isDuplicated, err } func (c *OrderController) 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 = db.QueryTable("order_sku").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).All(&order.Skus) } if err != nil { globals.SugarLogger.Warnf("LoadOrder orderID:%s failed with error:%v", vendorOrderID, err) } return order, err } //Waybill func (c *OrderController) UpdateWaybillVendorID(bill *model.Waybill) (err error) { db := orm.NewOrm() params := orm.Params{ "waybill_vendor_id": bill.WaybillVendorID, } // 如果运单被取消,则要保持在已拣货状态 if 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 }