package tncroute import ( "fmt" "net/http" "strconv" "strings" "sync" "time" "bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/notificationservice" "bitbucket.org/nemt/nemt-portal-api/application/tncservice" "bitbucket.org/nemt/nemt-portal-api/application/viewmodel" "bitbucket.org/nemt/nemt-portal-api/infra/auth" "bitbucket.org/nemt/nemt-portal-api/infra/config" "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils" "github.com/labstack/echo" uuid "github.com/satori/go.uuid" "google.golang.org/api/googleapi/transport" urlshortener "google.golang.org/api/urlshortener/v1" "github.com/gorilla/websocket" ) var ( instance *controller once sync.Once upgrader = websocket.Upgrader{} ) type controller struct { cfg *config.Config svc *applicationservice.Service tnc *tncservice.Service notification *notificationservice.Service } func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller { once.Do(func() { instance = &controller{ cfg: cfg, svc: svc, tnc: tnc, notification: notification, } }) return instance } func (c *controller) handleSocket(ctx echo.Context) error { ws, err := upgrader.Upgrade(ctx.Response(), ctx.Request(), nil) if err != nil { return err } defer ws.Close() for { // Write err := ws.WriteMessage(websocket.TextMessage, []byte("Hello, Client!")) if err != nil { ctx.Logger().Error(err) } // Read _, msg, err := ws.ReadMessage() if err != nil { ctx.Logger().Error(err) } fmt.Printf("%s\n", msg) } } func (c *controller) handleMessage(ctx echo.Context) error { rideID := ctx.Param("ride_uuid") if rideID == "" { return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory") } message := make(map[string]string) err := ctx.Bind(&message) if err != nil || message["message"] == "" { return routeutils.ResponseAPIValidationError(ctx, "message body param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } notifications := make([]viewmodel.Notification, 0) notifications = append(notifications, c.svc.Notification.GetNotification(ride, "sms", "A message to member", message["message"], false, "message")) notifications = append(notifications, c.svc.Notification.GetNotification(ride, "app", "A message to member", message["message"], false, "message")) notifications, err = c.svc.Notification.SendNotifications(notifications) if err != nil { return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, notifications) } func (c *controller) getURLShortened(ride viewmodel.Ride) (string, error) { const ( url = "https://portal.bcbsinstitute.com/#/ride/%s/%s" ) svc, err := urlshortener.New(&http.Client{ Transport: &transport.APIKey{Key: c.cfg.GoogleShortener.APIKey}, }) if err != nil { return "", err } userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID) shortURL, err := svc.Url.Insert(&urlshortener.Url{ Kind: "urlshortener#url", // Not really needed LongUrl: userURL, }).Do() if err != nil { return "", err } return shortURL.Id, nil } func (c *controller) handleShare(ctx echo.Context) error { const ( message = "%s shared a link with you for an upcoming ride: %s" ) rideID := ctx.Param("ride_uuid") if rideID == "" { return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } url, err := c.getURLShortened(ride) if err != nil { fmt.Println("Error to short url: ", err) } notifications := make([]viewmodel.Notification, 0) notifications = append(notifications, c.svc.Notification.GetNotification(ride, "sms", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message")) notifications = append(notifications, c.svc.Notification.GetNotification(ride, "email", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message")) notifications = append(notifications, c.svc.Notification.GetNotification(ride, "app", "A ride was shared with you", fmt.Sprintf(message, ride.CreatedUser.Name, url), false, "message")) notifications, err = c.svc.Notification.SendNotifications(notifications) if err != nil { return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, notifications) } func (c *controller) handleMessageDriver(ctx echo.Context) error { rideID := ctx.Param("ride_uuid") if rideID == "" { return routeutils.ResponseAPIValidationError(ctx, "rideID param is mandatory") } message := make(map[string]string) err := ctx.Bind(&message) if err != nil || message["message"] == "" { return routeutils.ResponseAPIValidationError(ctx, "message body param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } notifications := make([]viewmodel.Notification, 0) if ride.Status.Key == "accepted" || ride.Status.Key == "arrived" || ride.Status.Key == "pickedUp" { notifications = append(notifications, c.getDriverNotification(ride, "sms", "A message to driver", message["message"], ride.Driver.PhoneNumber, *ride.CreatedUser.PhoneNumber)) notifications, err = c.svc.Notification.SendNotifications(notifications) if err != nil { return routeutils.HandleAPIError(ctx, err) } } return routeutils.ResponseAPIOK(ctx, notifications) } func (c *controller) handleList(ctx echo.Context) error { user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } entity, err := c.svc.Rides.GetAll(user) if err != nil { return routeutils.HandleAPIError(ctx, err) } ctx.Response().Header().Set("Content-Type", "application/json") return routeutils.ResponseAPIOK(ctx, entity) } func (c *controller) handle(ctx echo.Context) error { var requestRide viewmodel.RideRequest err := ctx.Bind(&requestRide) if err != nil { fmt.Println(err) return routeutils.ResponseAPIValidationError(ctx, "invalid parameters") } user, err := c.svc.Users.GetByUUID(requestRide.UserUUID, "US") if err != nil { return routeutils.HandleAPIError(ctx, err) } if user.ID == "" { return routeutils.ResponseAPIValidationError(ctx, "User not found") } createdUser, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } name := user.Name names := strings.Split(name, " ") requestRide.Passenger.FirstName = names[0] requestRide.Passenger.LastName = " " requestRide.Passenger.PhoneNumber = *user.PhoneNumber var resp viewmodel.RideRequest if requestRide.TripType.Key != "from_visit_call" { if requestRide.TripType.Key == "from_visit" { newOrigin := requestRide.Origin requestRide.Origin = requestRide.Destination requestRide.Destination = newOrigin } if c.cfg.LyftProd.UserUUID != createdUser.ID { resp, err = c.tnc.Lyft.RequestRide(requestRide) } else { fmt.Println("In Production") resp, err = c.tnc.LyftProd.RequestRide(requestRide) } if err != nil { return routeutils.HandleAPIError(ctx, err) } if requestRide.TripType.Key == "from_visit" { newOrigin := resp.Origin resp.Origin = resp.Destination resp.Destination = newOrigin } resp.RideID = strings.Replace(resp.RideID, "s_", "", -1) } else { resp = requestRide UUID, _ := uuid.NewV4() resp.RideID = UUID.String() } if resp.Status == "scheduled" || requestRide.TripType.Key == "from_visit_call" { if requestRide.PickupTime == nil { currentDate := time.Now() requestRide.PickupTime = ¤tDate } requestMS := (requestRide.PickupTime.UnixNano() / int64(time.Millisecond)) generateDate := time.Now() generateMS := (generateDate.UnixNano() / int64(time.Millisecond)) resp.RequestAt = requestRide.PickupTime resp.RequestAtMS = &requestMS resp.GeneratedAt = &generateDate resp.GeneratedAtMS = &generateMS } resp.Passenger.FirstName = names[0] resp.Passenger.LastName = names[len(names)-1] resp.Passenger.PhoneNumber = *user.PhoneNumber if resp.Passenger.ImageURL == nil { imageURL := " " resp.Passenger.ImageURL = &imageURL } resp.UserUUID = requestRide.UserUUID if requestRide.TripType.Key == "from_visit" { resp.Origin.Name = requestRide.Destination.Name resp.Origin.ID = requestRide.Destination.ID resp.Destination.Name = requestRide.Origin.Name resp.Destination.ID = requestRide.Origin.ID } else { resp.Origin.Name = requestRide.Origin.Name resp.Origin.ID = requestRide.Origin.ID resp.Destination.Name = requestRide.Destination.Name resp.Destination.ID = requestRide.Destination.ID } resp.Distance = requestRide.Distance resp.Duration = requestRide.Duration resp.ETA = requestRide.ETA resp.PickupTime = requestRide.PickupTime resp.VisitDate = requestRide.VisitDate resp.VisitTime = requestRide.VisitTime resp.VisitExternalID = requestRide.VisitExternalID resp.CreateUserUUID = createdUser.ID resp.Visit.TripType = requestRide.TripType if resp.TripType.Key == "from_visit_call" { resp.Status = "willCall" resp.Passenger.UserID = &resp.UserUUID } resp.TripType.Key = requestRide.TripType.Key if requestRide.TripType.Key == "roundtrip" || requestRide.TripType.Key == "roundtrip_call" { resp.TripType.Key = "to_visit" } else if requestRide.TripType.Key == "from_visit_call" { resp.TripType.Key = "from_visit_call" } entity, err := c.svc.Rides.Save(resp) if err != nil { return routeutils.HandleAPIError(ctx, err) } go func() { err = c.svc.Notification.SendNotification(resp.Status, entity, resp) if err != nil { fmt.Println("Error to notify user: ", err.Error()) } }() if requestRide.TripType.Key == "roundtrip" || requestRide.TripType.Key == "roundtrip_call" { newRide := requestRide if requestRide.TripType.Key == "roundtrip" { destination := newRide.Origin newRide.Origin = newRide.Destination newRide.Destination = destination if requestRide.ReturnTime != nil { newRide.PickupTime = requestRide.ReturnTime } scheduledRide := make(map[string]interface{}) scheduledRide["timestamp_ms"] = requestRide.PickupTime.Unix() newRide.ScheduledPickupRange = scheduledRide newRide.Passenger.FirstName = names[0] newRide.Passenger.LastName = " " newRide.Passenger.PhoneNumber = *user.PhoneNumber if c.cfg.LyftProd.UserUUID != createdUser.ID { newRide, err = c.tnc.Lyft.RequestRide(newRide) } else { fmt.Println("In Production") newRide, err = c.tnc.LyftProd.RequestRide(newRide) } if err != nil { return routeutils.HandleAPIError(ctx, err) } destination = newRide.Origin newRide.Origin = newRide.Destination newRide.Destination = destination if newRide.Error != "" { fmt.Println("Error to schedule a ride on lyft: ", newRide.Error, newRide.ErrorDescription) } else { fmt.Println("Ride Scheduled: ", newRide.Status) } newRide.TripType.Key = "from_visit" } else { newRide.TripType.Key = "from_visit_call" newRide.Status = "willCall" newRide.RideID = entity.UUID } newRide.Visit = entity.Visit newRide.PickupTime = requestRide.ReturnTime requestMS := (newRide.PickupTime.UnixNano() / int64(time.Millisecond)) generateDate := time.Now() generateMS := (generateDate.UnixNano() / int64(time.Millisecond)) newRide.RequestAt = newRide.PickupTime newRide.RequestAtMS = &requestMS newRide.GeneratedAt = &generateDate newRide.GeneratedAtMS = &generateMS newRide.Passenger.FirstName = names[0] newRide.Passenger.LastName = names[len(names)-1] newRide.Passenger.PhoneNumber = *user.PhoneNumber newRide.Passenger.UserID = &requestRide.UserUUID if newRide.Passenger.ImageURL == nil { imageURL := " " newRide.Passenger.ImageURL = &imageURL } newRide.UserUUID = requestRide.UserUUID newRide.Origin.Name = requestRide.Destination.Name newRide.Origin.ID = requestRide.Destination.ID newRide.Destination.Name = requestRide.Origin.Name newRide.Destination.ID = requestRide.Origin.ID newRide.Distance = requestRide.Distance newRide.Duration = requestRide.Duration newRide.ETA = requestRide.ETA newRide.VisitDate = requestRide.VisitDate newRide.VisitTime = requestRide.VisitTime newRide.VisitExternalID = requestRide.VisitExternalID newRide.CreateUserUUID = createdUser.ID roudtripRide, err := c.svc.Rides.Save(newRide) if err != nil { return routeutils.HandleAPIError(ctx, err) } go func() { err = c.svc.Notification.SendNotification(newRide.Status, roudtripRide, newRide) if err != nil { fmt.Println("Error to notify user: ", err.Error()) } }() } ctx.Response().Header().Set("Content-Type", "application/json") return routeutils.ResponseAPIOK(ctx, entity) } func (c *controller) getDriverNotification(ride viewmodel.Ride, notificationType string, subject string, message string, to string, from string) viewmodel.Notification { retVal := viewmodel.Notification{ Type: notificationType, Message: message, Subject: subject, Ride: ride, User: ride.User, CreatedUser: ride.CreatedUser, To: to, From: from, } return retVal } func (c *controller) handleRawLyft(ctx echo.Context) error { rideUUID := ctx.Param("ride_uuid") if rideUUID == "" { return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideUUID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } var lyftRide viewmodel.RideRequest if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID { lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } else { fmt.Println("In Production") lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } if err != nil { fmt.Println("Error getting lyft details: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, lyftRide) } func (c *controller) handleRideETA(ctx echo.Context) error { rideUUID := ctx.Param("ride_uuid") if rideUUID == "" { return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideUUID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" { var lyftRide viewmodel.RideRequest if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID { lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } else { fmt.Println("In Production") lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } if err != nil { fmt.Println("Error getting lyft details: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } ride.Route.Location = ride.Route.Origin ride.Route.Location.Address = "" ride.Route.Location.Name = "" switch lyftRide.Status { case "scheduled": ride.Route.ETA = ride.PickupTime.UnixNano() / int64(time.Second) case "accepted": if lyftRide.Origin.ETASeconds != nil { ride.Route.ETA = *lyftRide.Origin.ETASeconds } else { ride.Route.ETA = 0 if c.cfg.App.Debug { ride.Route.ETA = 350 } } case "arrived", "pickedUp": if lyftRide.Destination.ETASeconds != nil { ride.Route.ETA = *lyftRide.Destination.ETASeconds } else { ride.Route.ETA = 0 if c.cfg.App.Debug { ride.Route.ETA = 350 } } } if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 { ride.Route.Location = lyftRide.Location } } return routeutils.ResponseAPIOK(ctx, ride) } func (c *controller) handleCancel(ctx echo.Context) error { var requestRide viewmodel.RideRequest rideUUID := ctx.Param("ride_uuid") if rideUUID == "" { return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideUUID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } requestRide.RideID = ride.InternalID if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") { requestRide.RideID = "s_" + ride.InternalID } if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID { err = c.tnc.Lyft.CancelRide(requestRide) if err != nil && err.Error() == "ride_not_found" { err = nil } } else { fmt.Println("In Production") err = c.tnc.LyftProd.CancelRide(requestRide) } if err != nil { fmt.Println("Error: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } err = c.svc.Rides.UpdateStatus(rideUUID, "canceled") if err != nil { fmt.Println("Error: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } // ride.Status.Key = "canceled" // go func() { // err = c.svc.Notification.SendNotification(ride.Status.Key, ride, viewmodel.RideRequest{}) // if err != nil { // fmt.Println("Error: ", err.Error()) // } // }() ctx.Response().Header().Set("Content-Type", "application/json") return routeutils.ResponseNoContent(ctx, nil) } func (c *controller) handleETA(ctx echo.Context) error { sLat := ctx.Param("lat") if sLat == "" { return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory") } sLog := ctx.Param("log") if sLog == "" { return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory") } sDestLat := ctx.Param("destlat") if sLat == "" { return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory") } sDestLog := ctx.Param("destlong") if sLog == "" { return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory") } lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "lat invalid") } log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "log invalid") } destlat, err := strconv.ParseFloat(strings.TrimSpace(sDestLat), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "destination lat invalid") } destlog, err := strconv.ParseFloat(strings.TrimSpace(sDestLog), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "destination log invalid") } params := map[string]interface{}{} params["endLat"] = destlat params["endLng"] = destlog params["rideType"] = "lyft" resp, err := c.tnc.Lyft.GetCost(lat, log, params) if err != nil { return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, resp) } func (c *controller) handleRide(ctx echo.Context) error { rideUUID := ctx.Param("ride_uuid") if rideUUID == "" { return routeutils.ResponseAPIValidationError(ctx, "ride_uuid param is mandatory") } user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideUUID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" { var lyftRide viewmodel.RideRequest if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID { lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } else { fmt.Println("In Production") lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } if err != nil { fmt.Println("Error getting lyft details: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } ride.Route.Location = ride.Route.Origin ride.Route.Location.Address = "" ride.Route.Location.Name = "" switch lyftRide.Status { case "scheduled": ride.Route.ETA = ride.PickupTime.UnixNano() / int64(time.Second) case "accepted": if lyftRide.Origin.ETASeconds != nil { ride.Route.ETA = *lyftRide.Origin.ETASeconds } else { ride.Route.ETA = 0 if c.cfg.App.Debug { ride.Route.ETA = 350 } } case "arrived": if lyftRide.Destination.ETASeconds != nil { ride.Route.ETA = *lyftRide.Destination.ETASeconds } else { ride.Route.ETA = 0 } case "pickedUp": if lyftRide.Destination.ETASeconds != nil { ride.Route.ETA = *lyftRide.Destination.ETASeconds } else { ride.Route.ETA = 0 if c.cfg.App.Debug { ride.Route.ETA = 350 } } } if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 { ride.Route.Location = lyftRide.Location } } return routeutils.ResponseAPIOK(ctx, ride) } func (c *controller) handleDrivers(ctx echo.Context) error { sLat := ctx.Param("lat") if sLat == "" { return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory") } sLog := ctx.Param("log") if sLog == "" { return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory") } lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "lat invalid") } log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "log invalid") } resp, err := c.tnc.Lyft.GetDrivers(lat, log) if err != nil { return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, resp) } func (c *controller) handleTypes(ctx echo.Context) error { sLat := ctx.Param("lat") if sLat == "" { return routeutils.ResponseAPIValidationError(ctx, "lat param is mandatory") } sLog := ctx.Param("log") if sLog == "" { return routeutils.ResponseAPIValidationError(ctx, "log param is mandatory") } lat, err := strconv.ParseFloat(strings.TrimSpace(sLat), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "lat invalid") } log, err := strconv.ParseFloat(strings.TrimSpace(sLog), 64) if err != nil { return routeutils.ResponseAPIValidationError(ctx, "log invalid") } resp, err := c.tnc.Lyft.GetTypes(lat, log, nil) if err != nil { return routeutils.HandleAPIError(ctx, err) } return routeutils.ResponseAPIOK(ctx, resp) } func (c *controller) handleReady(ctx echo.Context) error { var rideUUID = ctx.Param("ride_uuid") user, err := auth.GetUserDetail(ctx, c.cfg) if err != nil { return routeutils.HandleAPIError(ctx, err) } ride, err := c.svc.Rides.GetByUUID(rideUUID, user) if err != nil { return routeutils.HandleAPIError(ctx, err) } var nextRide viewmodel.Ride if ride.TripType.Key == "from_visit_call" && ride.Status.Key == "willCall" { nextRide = ride } else if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" { roundTripRide, err := c.svc.Rides.GetByVisitUUIDAndTripType(ride.Visit.UUID, "from_visit_call", user) if err != nil { fmt.Println("Error to get next ride: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } nextRide = roundTripRide } else { fmt.Println("Error on get next ride ") return routeutils.ResponseAPINotFoundError(ctx) } var lyftRide viewmodel.RideRequest if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID { lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } else { fmt.Println("In Production") lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID}) } if err != nil { fmt.Println("Error: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } lyftRide.RideID = "" lyftRide.Destination = ride.Route.Destination lyftRide.Origin = ride.Route.Origin name := nextRide.User.Name names := strings.Split(name, " ") lyftRide.Passenger.FirstName = names[0] lyftRide.Passenger.LastName = " " lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber lyftRide.RideType = "lyft" if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID { lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide) } else { fmt.Println("In Production") lyftRide, err = c.tnc.LyftProd.RequestRide(lyftRide) } if err != nil { return routeutils.HandleAPIError(ctx, err) } currentTime := time.Now() lyftRide.PickupTime = ¤tTime lyftRide.ReturnTime = ¤tTime nextRide.PickupTime = ¤tTime nextRide, err = c.svc.Rides.UpdateNewRide(nextRide, lyftRide, user) if err != nil { fmt.Println("Error: ", err.Error()) return routeutils.HandleAPIError(ctx, err) } go func() { err = c.svc.Notification.SendNotification(lyftRide.Status, nextRide, lyftRide) if err != nil { fmt.Println("Error to notify user: ", err.Error()) } }() return routeutils.ResponseAPIOK(ctx, nextRide) }