diff --git a/business/controller/controller.go b/business/controller/controller.go index 5b5229c4f..e60231336 100644 --- a/business/controller/controller.go +++ b/business/controller/controller.go @@ -2,10 +2,13 @@ package controller import ( "fmt" + "math" "strings" "sync" "time" + "git.rosy.net.cn/baseapi/platformapi/autonavi" + "github.com/astaxie/beego/orm" "git.rosy.net.cn/jx-callback/business/model" @@ -14,6 +17,7 @@ import ( "git.rosy.net.cn/baseapi/utils/routinepool" _ "git.rosy.net.cn/jx-callback/business/scheduler/defsch" // 导入缺省定单调度器 "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" ) const ( @@ -21,9 +25,8 @@ const ( ) var ( - DefaultTimeValue = utils.Str2Time("1970-01-01 00:00:00") - OrderManager *OrderController - WaybillManager *WaybillController + OrderManager *OrderController + WaybillManager *WaybillController routinePool *routinepool.Pool ) @@ -64,7 +67,7 @@ func SplitUniversalOrderID(universalOrderID string) (orderID string, vendorID in vendorID = model.VendorIDELM } else { globals.SugarLogger.Errorf("unkown order type:%v", universalOrderID) - vendorID = model.VenderIDUnknown + vendorID = model.VendorIDUnknown } orderID = universalOrderID } @@ -72,7 +75,8 @@ func SplitUniversalOrderID(universalOrderID string) (orderID string, vendorID in } func ComposeUniversalOrderID(orderID string, vendorID int) string { - return fmt.Sprintf("%s|%d", orderID, vendorID) + // return fmt.Sprintf("%s|%d", orderID, vendorID) + return orderID // 当前用长度就能区分,先不加上vendorID } func StandardCoordinate2Int(value float64) int { @@ -83,6 +87,33 @@ func IntCoordinate2Standard(value int) float64 { return float64(value / 1000000) } +func IntCoordinate2MarsStandard(gpsLng, gpsLat int, coordinateType int) (marsLng, marsLat float64, err error) { + marsLng = IntCoordinate2Standard(gpsLng) + marsLat = IntCoordinate2Standard(gpsLat) + coordSys := "" + switch coordinateType { + case model.CoordinateTypeGPS: + coordSys = autonavi.CoordSysGPS + case model.CoordinateTypeMars: + coordSys = autonavi.CoordSysAutonavi + case model.CoordinateTypeBaiDu: + coordSys = autonavi.CoordSysBaidu + case model.CoordinateTypeMapbar: + coordSys = autonavi.CoordSysMapbar + default: + globals.SugarLogger.Errorf("known coordinate type:%d", coordinateType) + } + return api.AutonaviAPI.CoordinateConvert(marsLng, marsLat, coordSys) +} + +func IntPrice2Standard(value int64) float64 { + return float64(value) / 100 +} + +func StandardPrice2Int(value float64) int64 { + return int64(math.Round(value) * 100) +} + func addOrderOrWaybillStatus(status *model.OrderStatus, db orm.Ormer) (isDuplicated bool, err error) { status.ID = 0 created, _, err := db.ReadOrCreate(status, "VendorOrderID", "VendorID", "OrderType", "VendorStatus", "StatusTime") @@ -107,3 +138,35 @@ func CallMsgHandler(handler func(), primaryID string) { // handler() // }, primaryID) } + +func GetDataCityCodeFromOrder(order *model.GoodsOrder) (retVal string, err error) { + var sql string + if order.VendorID == model.VendorIDJD { + sql = ` + SELECT t2.tel_code + FROM jxstoremap t0 + JOIN jxstore t1 ON t0.jxstoreid = t1.storeid + JOIN city t2 ON t1.area = t2.citycode + WHERE t0.jdstoreid = ? + ` + } else if order.VendorID == model.VendorIDELM { + sql = ` + SELECT t2.tel_code + FROM jx_to_elm_store_map t0 + JOIN jxstore t1 ON t0.jx_store_id = t1.storeid + JOIN city t2 ON t1.area = t2.citycode + WHERE t0.elm_store_id = ? + ` + } else { + panic(fmt.Sprintf("wrong vendorid:%d", order.VendorID)) + } + db := orm.NewOrm() + var lists []orm.ParamsList + num, err := db.Raw(sql, utils.Str2Int64(order.VendorStoreID)).ValuesList(&lists) + if err != nil && num == 1 { + retVal = lists[0][0].(string) + } else { + globals.SugarLogger.Errorf("can not find store info for vendorID:%d, store:%s", order.VendorID, order.VendorStoreID) + } + return retVal, err +} diff --git a/business/controller/dada/waybill.go b/business/controller/dada/waybill.go index dca136f1e..1cc873683 100644 --- a/business/controller/dada/waybill.go +++ b/business/controller/dada/waybill.go @@ -6,6 +6,7 @@ import ( "git.rosy.net.cn/jx-callback/business/controller" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/scheduler" + "git.rosy.net.cn/jx-callback/globals/api" ) type WaybillController struct { @@ -57,8 +58,26 @@ func (c *WaybillController) callbackMsg2Waybill(msg *dadaapi.CallbackMsg) (retVa } // -func (c *WaybillController) CreateWaybill(bill *model.Waybill) (err error) { - return nil +func (c *WaybillController) CreateWaybill(order *model.GoodsOrder) (err error) { + billParams := &dadaapi.OperateOrderRequiredParams{ + ShopNo: utils.Int2Str(order.StoreID), // 当前达达的门店号与京西是一样的 + OriginID: controller.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), + CargoPrice: controller.IntPrice2Standard(order.SalePrice), + IsPrepay: 0, + ReceiverName: order.ConsigneeName, + ReceiverAddress: order.ConsigneeAddress, + ReceiverPhone: order.ConsigneeMobile, + } + if billParams.CityCode, err = controller.GetDataCityCodeFromOrder(order); err == nil { + billParams.ReceiverLng, billParams.ReceiverLat, _ = controller.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) + addParams := map[string]interface{}{ + "info": order.BuyerComment, + "origin_mark": model.VendorNames[order.VendorID], + "origin_mark_no": utils.Int2Str(order.VendorID), + } + _, err = api.DadaAPI.AddOrder(billParams, addParams) + } + return err } func (c *WaybillController) CancelWaybill(bill *model.Waybill) (err error) { diff --git a/business/controller/elm/order.go b/business/controller/elm/order.go index d2cf37f95..44c5f850a 100644 --- a/business/controller/elm/order.go +++ b/business/controller/elm/order.go @@ -59,7 +59,7 @@ func (c *OrderController) cancelRefundMsg2Status(msg *elmapi.CallbackOrderCancel VendorOrderID: msg.OrderID, VendorID: model.VendorIDELM, OrderType: model.OrderTypeOrder, - VendorStatus: utils.Int2Str(msg.MsgType), + VendorStatus: c.stateAndType2Str(msg.RefundStatus, msg.MsgType), StatusTime: utils.Timestamp2Time(msg.UpdateTime), } return orderStatus @@ -78,7 +78,11 @@ func (c *OrderController) onOrderStatusMsg(msg *elmapi.CallbackOrderStatusMsg) ( globals.SugarLogger.Warnf("elm msg:%d not handled", msg.MsgType) return elmapi.SuccessResponse } - return elmapi.Err2CallbackResponse(controller.OrderManager.OnOrderStatusChanged(status), status.VendorStatus) + err := controller.OrderManager.OnOrderStatusChanged(status) + if globals.HandleLegacyJxOrder && err == nil { + c.legacyElmOrderStatusChanged(status) + } + return elmapi.Err2CallbackResponse(err, status.VendorStatus) } func (c *OrderController) onOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancelRefundMsg) (retVal *elmapi.CallbackResponse) { @@ -94,28 +98,32 @@ func (c *OrderController) onOrderCancelRefundMsg(msg *elmapi.CallbackOrderCancel return elmapi.Err2CallbackResponse(controller.OrderManager.OnOrderStatusChanged(status), status.VendorStatus) } -func (c *OrderController) getOrderInfo(msg *elmapi.CallbackOrderStatusMsg) (order *model.GoodsOrder, orderSkus []*model.OrderSku, err error) { - result, err := api.ElmAPI.GetOrder(msg.OrderID) +func (c *OrderController) getOrderInfo(orderID string) (order *model.GoodsOrder, err error) { + result, err := api.ElmAPI.GetOrder(orderID) if err == nil { phoneList := result["phoneList"].([]interface{}) consigneeMobile := "" if len(phoneList) > 0 { - consigneeMobile = phoneList[0].(string) + consigneeMobile = utils.Interface2String(phoneList[0]) } // globals.SugarLogger.Debug(result) order = &model.GoodsOrder{ - VendorOrderID: msg.OrderID, - VendorID: model.VendorIDELM, - VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["shopId"])), - StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["openId"]), 0)), - StoreName: result["shopName"].(string), - ConsigneeName: result["consignee"].(string), - ConsigneeMobile: consigneeMobile, - ConsigneeAddress: result["address"].(string), - VendorStatus: msg.State, - OrderCreatedAt: utils.Str2Time(result["createdAt"].(string)), - OriginalData: string(utils.MustMarshal(result)), + VendorOrderID: orderID, + VendorID: model.VendorIDELM, + VendorStoreID: utils.Int64ToStr(utils.MustInterface2Int64(result["shopId"])), + StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["openId"]), 0)), + StoreName: result["shopName"].(string), + ConsigneeName: result["consignee"].(string), + ConsigneeMobile: consigneeMobile, + ConsigneeAddress: result["address"].(string), + BuyerComment: utils.Interface2String(result["description"]), + ExpectedDeliveredTime: utils.Str2TimeWithDefault(utils.Interface2String(result["deliverTime"]), utils.DefaultTimeValue), + // 这里已经做了elm VendorStatus的状态组合了 + VendorStatus: c.stateAndType2Str(utils.Interface2String(result["status"]), elmapi.MsgTypeOrderValid), + OrderCreatedAt: utils.Str2Time(result["createdAt"].(string)), + OriginalData: string(utils.MustMarshal(result)), + Skus: []*model.OrderSku{}, } deliveryGeo := strings.Split(utils.Interface2String(result["deliveryGeo"]), ",") if len(deliveryGeo) == 2 { @@ -124,23 +132,22 @@ func (c *OrderController) getOrderInfo(msg *elmapi.CallbackOrderStatusMsg) (orde order.ConsigneeLat = controller.StandardCoordinate2Int(utils.Str2Float64(deliveryGeo[1])) } - orderSkus = []*model.OrderSku{} for _, group2 := range result["groups"].([]interface{}) { group := group2.(map[string]interface{}) for _, product2 := range group["items"].([]interface{}) { product := product2.(map[string]interface{}) sku := &model.OrderSku{ - VendorOrderID: msg.OrderID, + VendorOrderID: orderID, VendorID: model.VendorIDELM, Count: int(utils.MustInterface2Int64(product["quantity"])), SkuID: int(utils.Str2Int64WithDefault(utils.Interface2String(product["extendCode"]), 0)), VendorSkuID: utils.Int64ToStr(utils.MustInterface2Int64(product["skuId"])), SkuName: product["name"].(string), - SalePrice: int64(math.Round(utils.MustInterface2Float64(product["userPrice"]) * 100)), - Weight: int(math.Round(utils.Interface2Float64(product["weight"]))), + SalePrice: controller.StandardPrice2Int(utils.MustInterface2Float64(product["userPrice"])), + Weight: int(math.Round(utils.Interface2FloatWithDefault(product["weight"], 0.0))), OrderCreatedAt: order.OrderCreatedAt, } - orderSkus = append(orderSkus, sku) + order.Skus = append(order.Skus, sku) order.SkuCount++ order.GoodsCount += sku.Count order.SalePrice += sku.SalePrice @@ -148,20 +155,19 @@ func (c *OrderController) getOrderInfo(msg *elmapi.CallbackOrderStatusMsg) (orde } } } - return order, orderSkus, err + return order, err } // func (c *OrderController) onOrderNew(msg map[string]interface{}) (response *elmapi.CallbackResponse) { // todo 这里应该可以直接用msg里的内容,而不用再次去查 - fakeOrderMsg := &elmapi.CallbackOrderStatusMsg{ - OrderID: msg["orderId"].(string), - State: c.stateAndType2Str(msg["status"].(string), elmapi.MsgTypeOrderValid), - } - order, orderSkus, err := c.getOrderInfo(fakeOrderMsg) + order, err := c.getOrderInfo(msg["orderId"].(string)) if err == nil { order.Status = model.OrderStatusNew - err = controller.OrderManager.OnOrderNew(order, orderSkus) + err = controller.OrderManager.OnOrderNew(order) + if globals.HandleLegacyJxOrder && err == nil { + c.legacyWriteElmOrder(order) + } } return elmapi.Err2CallbackResponse(err, "elm onOrderNew") } @@ -182,6 +188,18 @@ func (c *OrderController) stateAndType2Str(state string, msgType int) string { return fmt.Sprintf("%s-%d", state, msgType) } +func (c *OrderController) spliltCompositeState(compositeState string) (state string, msgType int) { + index := strings.Index(compositeState, "-") + if index >= 0 { + msgType = int(utils.Str2Int64(compositeState[index+1:])) + if msgType == 0 { + globals.SugarLogger.Debug(compositeState) + } + return compositeState[:index], msgType + } + return compositeState, 0 +} + // PurchasePlatformHandler func (c *OrderController) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool) (err error) { if isAcceptIt { diff --git a/business/controller/elm/order_legacy.go b/business/controller/elm/order_legacy.go new file mode 100644 index 000000000..4ead18f7b --- /dev/null +++ b/business/controller/elm/order_legacy.go @@ -0,0 +1,48 @@ +package elm + +import ( + "github.com/astaxie/beego/orm" + + "git.rosy.net.cn/jx-callback/business/legacyorder" + + "git.rosy.net.cn/jx-callback/globals" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" +) + +// 为了兼容之前的表,造出原来需要的数据 +func (c *OrderController) legacyWriteElmOrder(order *model.GoodsOrder) (err error) { + db := orm.NewOrm() + _, msgType := c.spliltCompositeState(order.VendorStatus) + legacyOrder := &legacyorder.Elemeorder2{ + Orderid: order.VendorOrderID, + Type: msgType, + Consignee: order.ConsigneeName, + Mobile: order.ConsigneeMobile, + OrderCreatedAt: utils.Time2Str(order.OrderCreatedAt), + } + _, err = db.Insert(legacyOrder) + if err != nil { + globals.SugarLogger.Infof("legacyWriteElmOrder orderID:%v insert error:%v", order.VendorOrderID, err) + } + return err +} + +func (c *OrderController) legacyElmOrderStatusChanged(status *model.OrderStatus) (err error) { + db := orm.NewOrm() + legacyOrder := &legacyorder.Elemeorder2{ + Orderid: status.VendorOrderID, + } + + if err = db.Read(legacyOrder, "Orderid"); err == nil { + _, legacyOrder.Type = c.spliltCompositeState(status.VendorStatus) + utils.CallFuncLogError(func() error { + _, err = db.Update(legacyOrder, "Type") + return err + }, "legacyWriteElmOrder") + } else { + globals.SugarLogger.Infof("read legacyElmOrder error:%v", err) + } + return err +} diff --git a/business/controller/jd/order.go b/business/controller/jd/order.go index e8c363847..002529663 100644 --- a/business/controller/jd/order.go +++ b/business/controller/jd/order.go @@ -1,11 +1,13 @@ package jd import ( + "git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/controller" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/scheduler" + "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) @@ -46,33 +48,52 @@ func (c *OrderController) onOrderMsg(msg *jdapi.CallbackOrderMsg) (retVal *jdapi default: status.Status = model.OrderStatusUnknown } - retVal = jdapi.Err2CallbackResponse(controller.OrderManager.OnOrderStatusChanged(status), status.VendorStatus) + err := controller.OrderManager.OnOrderStatusChanged(status) + if globals.HandleLegacyJxOrder && err == nil { + c.legacyJdOrderStatusChanged(status) + } + retVal = jdapi.Err2CallbackResponse(err, status.VendorStatus) } return retVal } -func (c *OrderController) getOrderInfo(msg *jdapi.CallbackOrderMsg) (order *model.GoodsOrder, orderSkus []*model.OrderSku, err error) { +func (c *OrderController) getOrderInfo(msg *jdapi.CallbackOrderMsg) (order *model.GoodsOrder, err error) { result, err := api.JdAPI.QuerySingleOrder(msg.BillID) // globals.SugarLogger.Info(result) if err == nil { order = &model.GoodsOrder{ - VendorOrderID: msg.BillID, - VendorID: model.VendorIDJD, - VendorStoreID: result["produceStationNo"].(string), - StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["produceStationNoIsv"]), 0)), - StoreName: result["produceStationName"].(string), - ConsigneeName: result["buyerFullName"].(string), - ConsigneeMobile: result["buyerMobile"].(string), - ConsigneeAddress: result["buyerFullAddress"].(string), - ConsigneeLat: controller.StandardCoordinate2Int(utils.MustInterface2Float64(result["buyerLat"])), - ConsigneeLng: controller.StandardCoordinate2Int(utils.MustInterface2Float64(result["buyerLng"])), - CoordinateType: model.CoordinateTypeMars, - VendorStatus: msg.StatusID, - OrderCreatedAt: utils.Str2Time(result["orderStartTime"].(string)), - OriginalData: string(utils.MustMarshal(result)), + VendorOrderID: msg.BillID, + VendorID: model.VendorIDJD, + VendorStoreID: result["produceStationNo"].(string), + StoreID: int(utils.Str2Int64WithDefault(utils.Interface2String(result["produceStationNoIsv"]), 0)), + StoreName: result["produceStationName"].(string), + ConsigneeName: result["buyerFullName"].(string), + ConsigneeMobile: result["buyerMobile"].(string), + ConsigneeAddress: result["buyerFullAddress"].(string), + CoordinateType: model.CoordinateTypeMars, + BuyerComment: utils.Interface2String(result["orderBuyerRemark"]), + ExpectedDeliveredTime: utils.Str2TimeWithDefault(utils.Interface2String(result["orderPreEndDeliveryTime"]), utils.DefaultTimeValue), + VendorStatus: msg.StatusID, + OrderCreatedAt: utils.Str2Time(result["orderStartTime"].(string)), + OriginalData: string(utils.MustMarshal(result)), + Skus: []*model.OrderSku{}, } + coordinateType := utils.Interface2Int64WithDefault(result["buyerCoordType"], 1) + originalLng := utils.MustInterface2Float64(result["buyerLng"]) + originalLat := utils.MustInterface2Float64(result["buyerLat"]) + if coordinateType == 1 { + lng, lat, err2 := api.AutonaviAPI.CoordinateConvert(originalLng, originalLat, autonavi.CoordSysGPS) + if err2 == nil { + originalLng = lng + originalLat = lat + } else { + // 如果没有转成功,保留原始数据 + order.CoordinateType = model.CoordinateTypeGPS + } + } + order.ConsigneeLng = controller.StandardCoordinate2Int(originalLng) + order.ConsigneeLat = controller.StandardCoordinate2Int(originalLat) // discounts := result["discount"].(map[string]interface{}) - orderSkus = []*model.OrderSku{} for _, product2 := range result["product"].([]interface{}) { product := product2.(map[string]interface{}) sku := &model.OrderSku{ @@ -84,33 +105,43 @@ func (c *OrderController) getOrderInfo(msg *jdapi.CallbackOrderMsg) (order *mode SkuName: product["skuName"].(string), Weight: int(utils.MustInterface2Float64(product["skuWeight"]) * 1000), SalePrice: utils.MustInterface2Int64(product["skuJdPrice"]), + PromotionType: int(utils.MustInterface2Int64(product["skuJdPrice"])), OrderCreatedAt: order.OrderCreatedAt, } - orderSkus = append(orderSkus, sku) + if product["isGift"].(bool) { + sku.SkuType = 1 + } + order.Skus = append(order.Skus, sku) order.SkuCount++ order.GoodsCount += sku.Count order.SalePrice += sku.SalePrice order.Weight += sku.Weight } } - return order, orderSkus, err + return order, err } // func (c *OrderController) onOrderNew(msg *jdapi.CallbackOrderMsg) (response *jdapi.CallbackResponse) { - order, orderSkus, err := c.getOrderInfo(msg) + order, err := c.getOrderInfo(msg) if err == nil { order.Status = model.OrderStatusNew - err = controller.OrderManager.OnOrderNew(order, orderSkus) + err = controller.OrderManager.OnOrderNew(order) + if err == nil { + c.legacyWriteJdOrder(order, false) + } } return jdapi.Err2CallbackResponse(err, "jd onOrderNew") } func (c *OrderController) onOrderAdjust(msg *jdapi.CallbackOrderMsg) *jdapi.CallbackResponse { - order, orderSkus, err := c.getOrderInfo(msg) + order, err := c.getOrderInfo(msg) if err == nil { order.Status = model.OrderStatusAdjust - err = controller.OrderManager.OnOrderAdjust(order, orderSkus) + err = controller.OrderManager.OnOrderAdjust(order) + if globals.HandleLegacyJxOrder && err == nil { + c.legacyWriteJdOrder(order, true) + } } return jdapi.Err2CallbackResponse(err, "jd onOrderAdjust") } diff --git a/business/controller/jd/order_legacy.go b/business/controller/jd/order_legacy.go new file mode 100644 index 000000000..abfd4098a --- /dev/null +++ b/business/controller/jd/order_legacy.go @@ -0,0 +1,49 @@ +package jd + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/legacyorder" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/globals" + "github.com/astaxie/beego/orm" +) + +// 为了兼容之前的表,造出原来需要的数据 +func (c *OrderController) legacyWriteJdOrder(order *model.GoodsOrder, delOldFirst bool) (err error) { + db := orm.NewOrm() + if delOldFirst { + db.Raw("DELETE FROM jdorder2 WHERE jdorderid = ?", utils.Str2Int64(order.VendorOrderID)).Exec() + } + legacyOrder := &legacyorder.Jdorder2{ + Code: "0", + Jdorderid: utils.Str2Int64(order.VendorOrderID), + Orderstatus: int(utils.Str2Int64(order.VendorStatus)), + Orderstatustime: utils.Time2Str(order.OrderCreatedAt), + Success: 1, + Cityname: "all", + } + _, err = db.Insert(legacyOrder) + if err != nil { + globals.SugarLogger.Infof("legacyWriteJdOrder orderID:%v insert error:%v", order.VendorOrderID, err) + } + return err +} + +func (c *OrderController) legacyJdOrderStatusChanged(status *model.OrderStatus) (err error) { + db := orm.NewOrm() + legacyOrder := &legacyorder.Jdorder2{ + Jdorderid: utils.Str2Int64(status.VendorOrderID), + } + + if err = db.Read(legacyOrder, "Jdorderid"); err == nil { + utils.CallFuncLogError(func() error { + legacyOrder.Orderstatus = int(utils.Str2Int64(status.VendorStatus)) + legacyOrder.Orderstatustime = utils.Time2Str(status.StatusTime) + _, err = db.Update(legacyOrder, "Orderstatus", "Orderstatustime") + return err + }, "legacyJdOrderStatusChanged") + } else { + globals.SugarLogger.Infof("read legacyJdOrder error:%v", err) + } + return err +} diff --git a/business/controller/mtps/waybill.go b/business/controller/mtps/waybill.go index efbd40d46..4a339cd31 100644 --- a/business/controller/mtps/waybill.go +++ b/business/controller/mtps/waybill.go @@ -4,9 +4,12 @@ import ( "git.rosy.net.cn/baseapi/platformapi/mtpsapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/controller" + "git.rosy.net.cn/jx-callback/business/legacyorder" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/scheduler" "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/jx-callback/globals/api" + "github.com/astaxie/beego/orm" ) type WaybillController struct { @@ -76,10 +79,69 @@ func (c *WaybillController) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) ( } // -func (c *WaybillController) CreateWaybill(bill *model.Waybill) (err error) { - return nil +func (c *WaybillController) CreateWaybill(order *model.GoodsOrder) (err error) { + db := orm.NewOrm() + // 忽略坐标转换错误,即使是转换出错,也只能当成转换成功来处理,底层会有错误日志输出 + lngFloat, latFloat, _ := controller.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) + billParams := &mtpsapi.CreateOrderByShopParam{ + OrderID: controller.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), + DeliveryServiceCode: mtpsapi.DeliveryServiceCodeRapid, + ReceiverName: order.ConsigneeName, + ReceiverAddress: order.ConsigneeAddress, + ReceiverPhone: order.ConsigneeMobile, + CoordinateType: model.CoordinateTypeMars, + ReceiverLng: controller.StandardCoordinate2Int(lngFloat), + ReceiverLat: controller.StandardCoordinate2Int(latFloat), + GoodsValue: controller.IntPrice2Standard(order.SalePrice), // todo 超价处理 + GoodsWeight: float64(order.Weight) / 1000, + ExpectedDeliveryTime: order.ExpectedDeliveredTime.Unix(), + OrderType: mtpsapi.OrderTypeASAP, + } + if billParams.DeliveryID, err = c.getDeliveryID(order, db); err == nil { + if billParams.ShopID, err = c.getMTPSShopID(order, db); err == nil { + goods := &mtpsapi.GoodsDetail{ + Goods: []*mtpsapi.GoodsItem{}, + } + for _, sku := range order.Skus { + goodItem := &mtpsapi.GoodsItem{ + GoodCount: sku.Count, + GoodName: sku.SkuName, + GoodPrice: controller.IntPrice2Standard(sku.SalePrice), + GoodUnit: "", //这个应该不是必须的,商品名里已经有UNIT的字样了 + } + goods.Goods = append(goods.Goods, goodItem) + } + addParams := utils.Params2Map("note", order.BuyerComment, "good_detail", string(utils.MustMarshal(goods))) + _, err = api.MtpsAPI.CreateOrderByShop(billParams, addParams) + } + } + return err } func (c *WaybillController) CancelWaybill(bill *model.Waybill) (err error) { return nil } + +// 生成mtps deliveryid,为了兼容,现在取jxorder中的id +func (c *WaybillController) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) (retVal int64, err error) { + jxorder := &legacyorder.Jxorder2{ + OrderId: utils.Str2Int64(order.VendorOrderID), + } + err = utils.CallFuncLogError(func() error { + err2 := db.Read(order, "OrderId") + return err2 + }, "getDeliveryID") + return int64(jxorder.Id), err +} + +func (c *WaybillController) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) { + sql := "SELECT zs_store_id FROM jx_to_zs_store_map WHERE jx_store_id = ?" + var lists []orm.ParamsList + num, err := db.Raw(sql, utils.Str2Int64(order.VendorStoreID)).ValuesList(&lists) + if err != nil && num == 1 { + retVal = lists[0][0].(string) + } else { + globals.SugarLogger.Errorf("can not find mtps store info for store:%d", order.JxStoreID) + } + return retVal, err +} diff --git a/business/controller/order.go b/business/controller/order.go index 4ea04473b..269c410f1 100644 --- a/business/controller/order.go +++ b/business/controller/order.go @@ -1,6 +1,8 @@ package controller import ( + "fmt" + "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" @@ -18,7 +20,7 @@ func NewOrderManager() *OrderController { return &OrderController{} } -func (c *OrderController) OnOrderNew(order *model.GoodsOrder, orderSkus []*model.OrderSku) (err error) { +func (c *OrderController) OnOrderNew(order *model.GoodsOrder) (err error) { db := orm.NewOrm() isDuplicated, err := addOrderOrWaybillStatus(c.order2Status(order), db) if !isDuplicated { @@ -30,46 +32,48 @@ func (c *OrderController) OnOrderNew(order *model.GoodsOrder, orderSkus []*model order.Status = model.OrderStatusFailed } }) - if err = c.updateOrderOtherInfo(order, db); err == nil { - if err = c.updateOrderSkuOtherInfo(orderSkus, db); err == nil { - db.Begin() - // globals.SugarLogger.Debugf("new order:%v", order) - order.OrderFinishedAt = 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, sku_id, vendor_sku_id, sku_name, shop_price, sale_price, weight, order_created_at) VALUES" - params := []interface{}{} - for _, sku := range orderSkus { - sql += "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)," - params = append(params, sku.VendorOrderID, sku.VendorID, sku.Count, sku.SkuID, sku.VendorSkuID, 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() - } - } 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) + + // 忽略查找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, orderSkus []*model.OrderSku) (err error) { +func (c *OrderController) OnOrderAdjust(order *model.GoodsOrder) (err error) { db := orm.NewOrm() isDuplicated, err := addOrderOrWaybillStatus(c.order2Status(order), db) if err == nil && !isDuplicated { @@ -89,23 +93,93 @@ func (c *OrderController) OnOrderAdjust(order *model.GoodsOrder, orderSkus []*mo return err } } - return c.OnOrderNew(order, orderSkus) + 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) { - return nil + 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) { - return nil + 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 { @@ -129,7 +203,7 @@ func (c *OrderController) handleAutoAcceptOrder(orderID string, vendorID int, us handleType = -1 } } else { - globals.SugarLogger.Infof("order:%s, vendorID:%d, mobile is empty, should accept it", orderID, vendorID) + globals.SugarLogger.Infof("order:%s, vendorID:%d, mobile is empty, should accept order", orderID, vendorID) handleType = 1 } diff --git a/business/controller/order_legacy.go b/business/controller/order_legacy.go new file mode 100644 index 000000000..c64fb6309 --- /dev/null +++ b/business/controller/order_legacy.go @@ -0,0 +1,119 @@ +package controller + +import ( + "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/legacyorder" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/globals" + "github.com/astaxie/beego/orm" +) + +// legacy +const ( + JX_ORDER_STATUS_WAIT_TO_ACCEPT = -1 //未接单(41000) + JX_ORDER_STATUS_PICKING = 0 //拣货(32000->或定时召唤达达) + JX_ORDER_STATUS_WAIT_FOR_DELIVERY = 1 //待配送(2->或转商家自送) + JX_ORDER_STATUS_DELIVERING = 2 //配送中(33040) + JX_ORDER_STATUS_DELIVERY_DONE = 3 //已完成(33060->90000) + JX_ORDER_STATUS_EXCEPTION_APPLY = 4 //异常申请 + JX_ORDER_STATUS_NOT_DELIVER = 5 //不配送 + JX_ORDER_STATUS_AFTER_SALE = 6 //售后单 + JX_ORDER_STATUS_CANCEL = 7 //已取消 + JX_ORDER_STATUS_ADJUST = 8 //调整单 + + JX_DELIVERY_STATUS_NOT_DELIVERY = -1 //尚未申请配送 + JX_DELIVERY_STATUS_WAIT_TO_GRAB = 0 //等待抢单 + JX_DELIVERY_STATUS_GRAB_DONE = 1 //已抢单 + JX_DELIVERY_STATUS_FAIL_TO_GET_GOODS = 2 //取货失败 + JX_DELIVERY_STATUS_FAIL_TO_GET_GOODS_WAIT_TO_CONFIRM = 3 //取货失败待审核 + JX_DELIVERY_STATUS_GET_GOODS_DONE = 4 //取货完成 + JX_DELIVERY_STATUS_DELIVERY_FAIL = 5 //投递失败 + JX_DELIVERY_STATUS_DELIVERY_DONE = 6 //已完成 + JX_DELIVERY_STATUS_DELIVERY_CANCEL = 7 //已取消 +) + +func (c *OrderController) legacyMapOrderStatus(orderStatus int) (retVal int8) { + switch orderStatus { + case model.OrderStatusNew: + retVal = JX_ORDER_STATUS_WAIT_TO_ACCEPT + case model.OrderStatusAccepted: + retVal = JX_ORDER_STATUS_PICKING + case model.OrderStatusDelivering: + retVal = JX_ORDER_STATUS_DELIVERING + case model.OrderStatusDelivered: + retVal = JX_ORDER_STATUS_DELIVERY_DONE + case model.OrderStatusAdjust: + retVal = JX_ORDER_STATUS_ADJUST + case model.OrderStatusApplyCancel: + retVal = JX_ORDER_STATUS_EXCEPTION_APPLY + } + return retVal +} + +func (c *OrderController) legacyWriteJxOrder(order *model.GoodsOrder, db orm.Ormer, isDelFirst bool) (err error) { + db.Begin() + if isDelFirst { + db.Raw("DELETE FROM jxorder2 WHERE order_id = ?", utils.Str2Int64(order.VendorOrderID)) + db.Raw("DELETE FROM jxordersku2 WHERE order_id = ?", utils.Str2Int64(order.VendorOrderID)) + } + + jxorder := &legacyorder.Jxorder2{ + VenderId: int8(order.VendorID), + OrderId: utils.Str2Int64(order.VendorOrderID), + JxStoreId: utils.Int2Str(order.JxStoreID), + JxStoreName: order.StoreName, + OrderNum: order.SkuCount, + OrderStatus: c.legacyMapOrderStatus(order.Status), + OrderStatusTime: utils.Time2Str(order.OrderCreatedAt), + BusinessTag: "", + SkuCount: order.SkuCount, + OrderBuyerRemark: order.BuyerComment, + BuyerFullName: order.ConsigneeName, + BuyerFullAddress: order.ConsigneeAddress, + BuyerMobile: order.ConsigneeMobile, + BuyerCoordType: order.CoordinateType, + BuyerLng: IntCoordinate2Standard(order.ConsigneeLng), + BuyerLat: IntCoordinate2Standard(order.ConsigneeLat), + } + + _, err = db.Insert(jxorder) + if err != nil { + db.Rollback() + return err + } + sql := "INSERT INTO jxordersku2(vender_id, order_id, jx_sku_id, sku_name, jx_store_id, sku_price, sku_count, is_gift, promotion_type, sku_plat_discount, sku_vender_discount) VALUES" + params := []interface{}{} + for _, sku := range order.Skus { + sql += "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)," + params = append(params, sku.VendorID, sku.VendorOrderID, sku.JxSkuID, sku.SkuName, order.JxStoreID, sku.SalePrice, sku.Count, sku.SkuType, sku.PromotionType, 0, 0) + } + sql = sql[:len(sql)-1] + ";" + if _, err = db.Raw(sql, params...).Exec(); err != nil { + db.Rollback() + baseapi.SugarLogger.Infof("insert jxordersku2 error:%v", err) + } else { + db.Commit() + } + return err +} + +func (c *OrderController) legacyJxOrderStatusChanged(status *model.OrderStatus, db orm.Ormer) (err error) { + if db == nil { + db = orm.NewOrm() + } + jxorder := &legacyorder.Jxorder2{ + OrderId: utils.Str2Int64(status.VendorOrderID), + } + if err = db.Read(jxorder, "OrderId"); err == nil { + utils.CallFuncLogError(func() error { + jxorder.OrderStatus = c.legacyMapOrderStatus(status.Status) + jxorder.OrderStatusTime = utils.Time2Str(status.StatusTime) + _, err = db.Update(jxorder, "OrderStatus", "OrderStatusTime") + return err + }, "legacyJxOrderStatusChanged") + } else { + globals.SugarLogger.Infof("read legacyJxOrder error:%v", err) + } + return err +} diff --git a/business/controller/waybill.go b/business/controller/waybill.go index 1691e10fc..f650af489 100644 --- a/business/controller/waybill.go +++ b/business/controller/waybill.go @@ -20,7 +20,7 @@ func (w *WaybillController) onWaybillNew(bill *model.Waybill) (err error) { db := orm.NewOrm() isDuplicated, err := addOrderOrWaybillStatus(w.waybill2Status(bill), db) if !isDuplicated { - bill.WaybillFinishedAt = DefaultTimeValue + bill.WaybillFinishedAt = utils.DefaultTimeValue bill.ID = 0 created, _, err2 := db.ReadOrCreate(bill, "VendorWaybillID", "WaybillVendorID") if err = err2; err == nil { diff --git a/business/legacyorder/elemeorder.go b/business/legacyorder/elemeorder.go new file mode 100644 index 000000000..c7e3b5ed0 --- /dev/null +++ b/business/legacyorder/elemeorder.go @@ -0,0 +1,15 @@ +package legacyorder + +type Elemeorder2 struct { + Id int `orm:"column(id);auto"` + Orderid string `orm:"column(orderid);size(50);null;unique"` + Data string `orm:"column(data);null"` + Type int `orm:"column(type);null"` + Consignee string `orm:"column(consignee);size(32)"` + Mobile string `orm:"column(mobile);size(32)"` + OrderCreatedAt string `orm:"column(order_created_at);size(50);index"` +} + +func (t *Elemeorder2) TableName() string { + return "elemeorder2" +} diff --git a/business/legacyorder/jdorder.go b/business/legacyorder/jdorder.go new file mode 100644 index 000000000..8af081e2a --- /dev/null +++ b/business/legacyorder/jdorder.go @@ -0,0 +1,17 @@ +package legacyorder + +type Jdorder2 struct { + Id int `orm:"column(id);auto"` + Code string `orm:"column(code);size(2);null"` + Msg string `orm:"column(msg);size(100);null"` + Data string `orm:"column(data);null"` + Success int8 `orm:"column(success);null"` + Jdorderid int64 `orm:"column(jdorderid);null;unique"` + Cityname string `orm:"column(cityname);size(20);null"` + Orderstatus int `orm:"column(orderstatus);null"` + Orderstatustime string `orm:"column(orderstatustime);size(50);null;index"` +} + +func (t *Jdorder2) TableName() string { + return "jdorder2" +} diff --git a/business/legacyorder/jxorder.go b/business/legacyorder/jxorder.go new file mode 100644 index 000000000..19e710cd5 --- /dev/null +++ b/business/legacyorder/jxorder.go @@ -0,0 +1,59 @@ +package legacyorder + +type Jxorder2 struct { + Id int `orm:"column(id);auto"` + VenderId int8 `orm:"column(vender_id);null"` + OrderId int64 `orm:"column(order_id);null;unique"` + JxStoreId string `orm:"column(jx_store_id);size(20);null"` + JxStoreName string `orm:"column(jx_store_name);size(100);null"` + OrderNum int `orm:"column(order_num);null"` + OrderStatus int8 `orm:"column(order_status);null"` + OrderStatusTime string `orm:"column(order_status_time);size(50);null"` + BusinessTag string `orm:"column(business_tag);size(100);null"` + SkuCount int `orm:"column(sku_count);null"` + OrderBuyerRemark string `orm:"column(order_buyer_remark);size(500);null"` + BuyerFullName string `orm:"column(buyer_full_name);size(100);null"` + BuyerFullAddress string `orm:"column(buyer_full_address);size(500);null"` + BuyerMobile string `orm:"column(buyer_mobile);size(100);null"` + BuyerCoordType int `orm:"column(buyer_coord_type);null"` + BuyerLng float64 `orm:"column(buyer_lng);null"` + BuyerLat float64 `orm:"column(buyer_lat);null"` + StoreLng float64 `orm:"column(store_lng);null;default(-1)"` + StoreLat float64 `orm:"column(store_lat);null;default(-1)"` + DeliveryPackageWeight float64 `orm:"column(delivery_package_weight);null"` + DeliveryCarrierNo string `orm:"column(delivery_carrier_no);size(20);null"` + DeliveryCarrierName string `orm:"column(delivery_carrier_name);size(100);null"` + DeliveryManNo string `orm:"column(delivery_man_no);size(20);null"` + DeliveryManName string `orm:"column(delivery_man_name);size(20);null"` + DeliveryManPhone string `orm:"column(delivery_man_phone);size(20);null"` + DeliveryBillNo string `orm:"column(delivery_bill_no);size(100);null"` + DeliveryStatus int8 `orm:"column(delivery_status);null"` + DeliveryConfirmTime string `orm:"column(delivery_confirm_time);size(50);null"` + AdjustIsExists int8 `orm:"column(adjust_is_exists);null"` + AdjustId int64 `orm:"column(adjust_id);null"` + OrderTotalMoney int `orm:"column(order_total_money);null"` + OrderDiscountMoney int `orm:"column(order_discount_money);null"` + OrderPlatDiscount int `orm:"column(order_plat_discount);null"` + OrderVenderDiscount int `orm:"column(order_vender_discount);null"` + OrderBuyerPayableMoney int `orm:"column(order_buyer_payable_money);null"` + OrderReceivableFreight int `orm:"column(order_receivable_freight);null"` + PlatFreightDis int `orm:"column(plat_freight_dis);null"` + VenderFreightDis int `orm:"column(vender_freight_dis);null"` + Tips int `orm:"column(tips);null"` + Percentage float64 `orm:"column(percentage);null"` + Allowance int `orm:"column(allowance);null"` + CityName string `orm:"column(city_name);size(20);null"` + OrderStartTime string `orm:"column(order_start_time);size(50);null"` + OrderPreEndDelivTime string `orm:"column(order_pre_end_deliv_time);size(50);null"` + OrderEndTime string `orm:"column(order_end_time);size(50);null"` + JdStoreId string `orm:"column(jd_store_id);size(20);null"` + DeliveryPrice float64 `orm:"column(delivery_price);null;digits(6);decimals(2);default(0.00)"` + DeliveryPrice1 float64 `orm:"column(delivery_price1);null;digits(6);decimals(2);default(0.00)"` + DeliveryStartTime string `orm:"column(delivery_start_time);size(50);null"` + DeliveryFinishTime string `orm:"column(delivery_finish_time);size(50);null"` + IsRecallDelivery int `orm:"column(is_recall_delivery);default(0)"` +} + +func (t *Jxorder2) TableName() string { + return "jxorder2" +} diff --git a/business/model/const.go b/business/model/const.go index a38965e4f..db323a2d7 100644 --- a/business/model/const.go +++ b/business/model/const.go @@ -1,7 +1,7 @@ package model const ( - VenderIDUnknown = -1 + VendorIDUnknown = -1 VendorIDPurchaseBegin = 0 VendorIDJD = 0 VendorIDMTWM = 1 @@ -14,14 +14,34 @@ const ( VendorIDDeliveryEnd = 102 ) +var ( + VendorNames = map[int]string{ + VendorIDJD: "JD", + VendorIDELM: "ELEME", + VendorIDMTWM: "MT", + } +) + const ( OrderTypeOrder = 1 OrderTypeWaybill = 2 ) +// https://blog.csdn.net/a13570320979/article/details/51366355 +// 美团配送: +// 坐标类型,0:火星坐标(高德,腾讯地图均采用火星坐标) 1:百度坐标 (默认值为0) +// 京东: +// 收货人地址定位类型(buyerCoordType值为空或为1时,定位类型为gps,如为其他值时,定位类型为非gps类型。) +// 饿了么: +// 只支持高德坐标 +// 达达: +// 只支持高德坐标 +// 如下定义与美团配送兼容 const ( - CoordinateTypeMars = 0 // 火星坐标 - CoordinateTypeReal = 1 // 真实坐标 + CoordinateTypeMars = 0 // 火星坐标,高德坐标,GCJ-02坐标系 + CoordinateTypeBaiDu = 1 // 百度坐标,bd-09,在GCJ-02坐标系上再次偏移加密的坐标 + CoordinateTypeMapbar = 2 + CoordinateTypeGPS = 84 // 真实坐标,WGS-84原始坐标系 ) const ( diff --git a/business/model/order.go b/business/model/order.go index 341eea865..8a3f75b75 100644 --- a/business/model/order.go +++ b/business/model/order.go @@ -8,38 +8,41 @@ type ModelTimeInfo struct { } type GoodsOrder struct { - ID int64 `orm:"column(id)"` - VendorOrderID string `orm:"column(vendor_order_id);size(48)"` - VendorID int `orm:"column(vendor_id)"` - VendorStoreID string `orm:"column(vendor_store_id);size(48)"` - StoreID int `orm:"column(store_id)"` // 外部系统里记录的 jxstoreid - JxStoreID int `orm:"column(jx_store_id)"` // 根据VendorStoreID在本地系统里查询出来的 jxstoreid - StoreName string `orm:"size(64)"` - SubStoreID int `orm:"column(sub_store_id)"` - SubStoreName string `orm:"size(64)"` - ShopPrice int64 // 单位为分 - SalePrice int64 // 单位为分 - Weight int // 单位为克 - ConsigneeName string `orm:"size(32)"` - ConsigneeMobile string `orm:"size(32)"` - ConsigneeAddress string `orm:"size(255)"` - ConsigneeLng int // 坐标 * (10的六次方) - ConsigneeLat int // 坐标 * (10的六次方) - CoordinateType int - SkuCount int // 商品类别数量,即有多少种商品(注意在某些情况下,相同SKU的商品由于售价不同,也会当成不同商品在这个值里) - GoodsCount int // 商品个数 - Status int // 参见相关常量定义 - VendorStatus string `orm:"size(16)"` - LockStatus int - CancelApplyReason string `orm:"size(255)"` // ""表示没有申请,不为null表示用户正在取消申请 - WaybillVendorID int `orm:"column(waybill_vendor_id)"` - WaybillStatus int - WaybillVendorStatus string `orm:"size(16)"` - DuplicatedCount int // 重复新定单消息数,这个一般不是由于消息重发赞成的(消息重发由OrderStatus过滤),一般是业务逻辑赞成的 - OriginalData string `orm:"type(text)"` - OrderCreatedAt time.Time `orm:"type(datetime);index"` - OrderFinishedAt time.Time `orm:"type(datetime)"` + ID int64 `orm:"column(id)"` + VendorOrderID string `orm:"column(vendor_order_id);size(48)"` + VendorID int `orm:"column(vendor_id)"` + VendorStoreID string `orm:"column(vendor_store_id);size(48)"` + StoreID int `orm:"column(store_id)"` // 外部系统里记录的 jxstoreid + JxStoreID int `orm:"column(jx_store_id)"` // 根据VendorStoreID在本地系统里查询出来的 jxstoreid + StoreName string `orm:"size(64)"` + SubStoreID int `orm:"column(sub_store_id)"` + SubStoreName string `orm:"size(64)"` + ShopPrice int64 // 单位为分 + SalePrice int64 // 单位为分 + Weight int // 单位为克 + ConsigneeName string `orm:"size(32)"` + ConsigneeMobile string `orm:"size(32)"` + ConsigneeAddress string `orm:"size(255)"` + ConsigneeLng int // 坐标 * (10的六次方) + ConsigneeLat int // 坐标 * (10的六次方) + CoordinateType int + SkuCount int // 商品类别数量,即有多少种商品(注意在某些情况下,相同SKU的商品由于售价不同,也会当成不同商品在这个值里) + GoodsCount int // 商品个数 + Status int // 参见相关常量定义 + VendorStatus string `orm:"size(16)"` + LockStatus int + BuyerComment string `orm:"size(255)"` + ExpectedDeliveredTime time.Time `orm:"type(datetime)"` // 预期送达时间 + CancelApplyReason string `orm:"size(255)"` // ""表示没有申请,不为null表示用户正在取消申请 + WaybillVendorID int `orm:"column(waybill_vendor_id)"` + WaybillStatus int + WaybillVendorStatus string `orm:"size(16)"` + DuplicatedCount int // 重复新定单消息数,这个一般不是由于消息重发赞成的(消息重发由OrderStatus过滤),一般是业务逻辑赞成的 + OrderCreatedAt time.Time `orm:"type(datetime);index"` + OrderFinishedAt time.Time `orm:"type(datetime)"` ModelTimeInfo + OriginalData string `orm:"type(text)"` + Skus []*OrderSku `orm:"-"` } func (o *GoodsOrder) TableUnique() [][]string { @@ -59,8 +62,10 @@ type OrderSku struct { SkuName string `orm:"size(255)"` ShopPrice int64 SalePrice int64 - Weight int // 单位为克 - OrderCreatedAt time.Time `orm:"type(datetime);index"` + Weight int // 单位为克 + SkuType int + PromotionType int + OrderCreatedAt time.Time `orm:"type(datetime);index"` // 分区考虑 } // 同样商品在一个定单中可能重复出现(比如搞活动时,相同商品价格不一样,第一个有优惠) @@ -87,6 +92,7 @@ type Waybill struct { WaybillCreatedAt time.Time `orm:"type(datetime);index"` WaybillFinishedAt time.Time `orm:"type(datetime)"` ModelTimeInfo + OriginalData string `orm:"type(text)"` } func (w *Waybill) TableUnique() [][]string { diff --git a/business/scheduler/scheduler.go b/business/scheduler/scheduler.go index 58aff3a22..39b431991 100644 --- a/business/scheduler/scheduler.go +++ b/business/scheduler/scheduler.go @@ -11,13 +11,14 @@ var ( CurrentScheduler Scheduler ) -type AutoStatusChangeConfig struct { - NextStatus int - Timeout time.Duration +type StatusTimeoutAction struct { + Action func(order *model.GoodsOrder) (err error) + Timeout time.Duration } type StatusConfig struct { - AutoStatusChange map[int][]*AutoStatusChangeConfig + handler PurchasePlatformHandler + AutoStatusChange map[int]*StatusTimeoutAction } type PurchasePlatformHandler interface { @@ -27,7 +28,7 @@ type PurchasePlatformHandler interface { } type DeliveryPlatformHandler interface { - CreateWaybill(bill *model.Waybill) (err error) + CreateWaybill(order *model.GoodsOrder) (err error) CancelWaybill(bill *model.Waybill) (err error) } diff --git a/conf/app.conf b/conf/app.conf index cf62a1a0d..245537992 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -12,6 +12,8 @@ routinePoolSize = 1000 dadaAppKey = "dada9623324449cd250" dadaAppSecret = "30c2abbfe8a8780ad5aace46300c64b9" +autonaviKey = "4427170f870af2110becb8852d36ab08" + callLegacy = true callNew = false diff --git a/globals/api/api.go b/globals/api/api.go index 37e7d4e5a..41f6aa5dd 100644 --- a/globals/api/api.go +++ b/globals/api/api.go @@ -1,6 +1,7 @@ package api import ( + "git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/platformapi/dadaapi" "git.rosy.net.cn/baseapi/platformapi/elmapi" "git.rosy.net.cn/baseapi/platformapi/jdapi" @@ -14,11 +15,12 @@ import ( ) var ( - JdAPI *jdapi.API - ElmAPI *elmapi.API - MtpsAPI *mtpsapi.API - DadaAPI *dadaapi.API - WeixinAPI *weixinapi.API + JdAPI *jdapi.API + ElmAPI *elmapi.API + MtpsAPI *mtpsapi.API + DadaAPI *dadaapi.API + WeixinAPI *weixinapi.API + AutonaviAPI *autonavi.API ) func init() { @@ -27,6 +29,7 @@ func init() { MtpsAPI = mtpsapi.New(beego.AppConfig.String("mtpsAppKey"), beego.AppConfig.String("mtpsSecret")) DadaAPI = dadaapi.New(beego.AppConfig.String("dadaAppKey"), beego.AppConfig.String("dadaAppSecret"), beego.AppConfig.String("dadaSourceID"), beego.AppConfig.String("dadaCallbackURL"), beego.AppConfig.DefaultBool("dadaIsProd", false)) WeixinAPI = weixinapi.New(beego.AppConfig.String("weixinAppID"), beego.AppConfig.String("weixinSecret")) + AutonaviAPI = autonavi.New(beego.AppConfig.String("autonaviKey")) } func initElm() { diff --git a/globals/globals.go b/globals/globals.go index 13788b19e..04ecee022 100644 --- a/globals/globals.go +++ b/globals/globals.go @@ -2,6 +2,7 @@ package globals import ( "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/jx-callback/business/legacyorder" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/legacy/models" "github.com/astaxie/beego" @@ -16,8 +17,9 @@ const ( ) var ( - CallLegacy bool - CallNew bool + CallLegacy bool + CallNew bool + HandleLegacyJxOrder bool SugarLogger *zap.SugaredLogger ) @@ -44,6 +46,10 @@ func initDB() { orm.RegisterModel(new(model.OrderSku)) orm.RegisterModel(new(model.Waybill)) orm.RegisterModel(new(model.OrderStatus)) + + orm.RegisterModel(new(legacyorder.Elemeorder2)) + orm.RegisterModel(new(legacyorder.Jdorder2)) + orm.RegisterModel(new(legacyorder.Jxorder2)) } // create table orm.RunSyncdb("default", false, true)