641 lines
33 KiB
Go
641 lines
33 KiB
Go
package applicationservice
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/pquerna/ffjson/ffjson"
|
|
|
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
|
"github.com/gorilla/websocket"
|
|
"google.golang.org/api/googleapi/transport"
|
|
urlshortener "google.golang.org/api/urlshortener/v1"
|
|
gomail "gopkg.in/gomail.v2"
|
|
redis "gopkg.in/redis.v5"
|
|
)
|
|
|
|
const (
|
|
NotificationTypeEmail = "email"
|
|
NOtificationTypeSMS = "sms"
|
|
NotificationTypeAPP = "app"
|
|
|
|
StatusPending = "pending"
|
|
StatusAccepted = "accepted"
|
|
StatusArrived = "arrived"
|
|
StatusPickedUp = "pickedUp"
|
|
StatusDroppedOff = "droppedOff"
|
|
StatusCanceled = "canceled"
|
|
StatusScheduled = "scheduled"
|
|
StatusWillCall = "willCall"
|
|
|
|
hourMinuteAMPM = "03:04 PM"
|
|
)
|
|
|
|
// providerService holds methods to provider application service
|
|
type notificationService struct {
|
|
svc *service.Service
|
|
mapEntity *entitymapping.Mapper
|
|
notification *notificationservice.Service
|
|
cfg *config.Config
|
|
store *Store
|
|
pubSub *redis.PubSub
|
|
redisConn *redis.Client
|
|
}
|
|
|
|
// newProviderService returns a providerService instance
|
|
func newNotificationService(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *notificationService {
|
|
redisClient := redis.NewFailoverClient(&redis.FailoverOptions{
|
|
MasterName: "master01",
|
|
SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
|
|
Password: cfg.Cache.Pass,
|
|
DB: cfg.Cache.DB,
|
|
})
|
|
|
|
pubSub, err := redisClient.Subscribe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return ¬ificationService{
|
|
svc: svc,
|
|
mapEntity: mapper,
|
|
notification: notification,
|
|
cfg: cfg,
|
|
redisConn: redisClient,
|
|
store: &Store{
|
|
Users: make(map[string]*UserNotification),
|
|
redisClient: redisClient,
|
|
pubSub: pubSub,
|
|
},
|
|
pubSub: pubSub,
|
|
}
|
|
}
|
|
|
|
func (s *notificationService) secondsToMinutes(inSeconds int64) string {
|
|
minutes := inSeconds / 60
|
|
seconds := inSeconds % 60
|
|
str := fmt.Sprintf("%v minutes", minutes)
|
|
|
|
if seconds > 0 {
|
|
str += fmt.Sprintf(" %v seconds", seconds)
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
func (s *notificationService) getReadyURLShortened(ride viewmodel.Ride) (string, error) {
|
|
const (
|
|
url = "https://portal.bcbsinstitute.com/#/ride/%s/%s/ready"
|
|
)
|
|
|
|
svc, err := urlshortener.New(&http.Client{
|
|
Transport: &transport.APIKey{Key: s.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 (s *notificationService) 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: s.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 (s *notificationService) SendNotification(state string, ride viewmodel.Ride, lyftRide viewmodel.RideRequest) error {
|
|
notifications := make([]viewmodel.Notification, 0)
|
|
url, err := s.getURLShortened(ride)
|
|
if err != nil {
|
|
fmt.Println("Error to short url: ", err)
|
|
}
|
|
|
|
loc, _ := time.LoadLocation("America/Chicago")
|
|
switch state {
|
|
case StatusWillCall:
|
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
|
|
|
messageMemberSMS := fmt.Sprintf(MessageSMSWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
|
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageMemberEmail := fmt.Sprintf(MessageEmailWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
|
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
urlReady, err := s.getReadyURLShortened(ride)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
|
|
messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSWillCallMemberTitle, messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSWillCallDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailWillCallMemberTitle, messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailWillCallDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallMemberTitle, ride.Status.Value, ride.Route.Destination.Address), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallDispatcherTitle, ride.Status.Value, ride.Route.Destination.Address), true, "ride"))
|
|
case StatusScheduled:
|
|
dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
|
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
|
|
|
if ride.TripType.Key == "from_visit" && lyftRide.ReturnTime != nil {
|
|
dateFormat = lyftRide.ReturnTime.In(loc).Format("01/02/2006 03:04 PM")
|
|
pickupTime = lyftRide.ReturnTime.In(loc).Format(hourMinuteAMPM)
|
|
}
|
|
|
|
messageMemberSMS := fmt.Sprintf(MessageSMSScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageMemberEmail := fmt.Sprintf(MessageEmailScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledMemberTitle, dateFormat), messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledMemberTitle, dateFormat), messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
|
|
|
|
// if ride.TripType.Key == "to_visit" {
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
|
|
// } else if ride.TripType.Key == "from_visit" {
|
|
// notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Destination.Name), false, "ride"))
|
|
// notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Destination.Name), true, "ride"))
|
|
// }
|
|
case StatusPending:
|
|
dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
|
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
|
|
|
messageMemberSMS := fmt.Sprintf(MessageSMSPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageMemberEmail := fmt.Sprintf(MessageEmailPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingMemberTitle, dateFormat), messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingMemberTitle, dateFormat), messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
|
|
case StatusAccepted:
|
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
|
|
|
messageMemberSMS := fmt.Sprintf(MessageSMSAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageMemberEmail := fmt.Sprintf(MessageEmailAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
//messageMemberApp := fmt.Sprintf(MessageAppAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSAcceptedMemberTitle, messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSAcceptedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailAcceptedMemberTitle, messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailAcceptedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedMemberTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedDispatcherTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), true, "ride"))
|
|
case StatusArrived:
|
|
messageMemberSMS := fmt.Sprintf(MessageSMSArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageMemberEmail := fmt.Sprintf(MessageEmailArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
//messageMemberApp := fmt.Sprintf(MessageAppArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSArrivedMemberTitle, messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSArrivedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailArrivedMemberTitle, messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailArrivedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", "Your ride is HERE", fmt.Sprintf(MessageAppArrivedMemberTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", "Waiting for member", fmt.Sprintf(MessageAppArrivedDispatcherTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), true, "ride"))
|
|
case StatusPickedUp:
|
|
dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
|
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
|
pickupTime := lyftRide.Pickup.Time.In(loc).Format(hourMinuteAMPM)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPickedUpDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPickedUpDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPickedUpDispatcherTitle, pickupTime), true, "ride"))
|
|
case StatusDroppedOff:
|
|
dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
|
|
dropOffTime := lyftRide.DropOff.Time.In(loc).Format(hourMinuteAMPM)
|
|
|
|
// messageMemberSMS := MessageSMSDroppedOffMember
|
|
// messageMemberEmail := MessageEmailDroppedOffMember
|
|
|
|
// if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" {
|
|
// entityRide, err := s.svc.Rides.GetByUUID(ride.UUID)
|
|
// if err != nil {
|
|
// fmt.Println(err)
|
|
// }
|
|
|
|
// var nextRide entity.Ride
|
|
// for _, r := range entityRide.Visit.Rides {
|
|
// fmt.Println("Ride Tryp Type: ", r.TripType.Key)
|
|
// if r.TripType.Key == "from_visit_call" {
|
|
// nextRide = r
|
|
// }
|
|
// }
|
|
|
|
// fmt.Println("NextRide Found: ", nextRide.UUID)
|
|
// if nextRide.UUID != "" {
|
|
// urlReady, err := s.getReadyURLShortened(nextRide)
|
|
// if err != nil {
|
|
// fmt.Println(err)
|
|
// }
|
|
|
|
// messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
|
|
// messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
|
|
// }
|
|
// }
|
|
|
|
// fmt.Println("SMS Message: ", messageMemberSMS)
|
|
|
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
|
//messageDispatcherApp := fmt.Sprintf(MessageAppDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
|
|
|
//notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSDroppedOffMemberTitle, messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
|
//notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailDroppedOffMemberTitle, messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
|
//notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppDroppedOffDispatcherTitle, dropOffTime), true, "ride"))
|
|
case StatusCanceled:
|
|
visitTime := ride.VisitDate.Format(hourMinuteAMPM)
|
|
visitDate := ride.VisitDate.Format("01/02/2006")
|
|
|
|
var messageMemberSMS string
|
|
var messageMemberSMSTitle string
|
|
var messageMemberEmail string
|
|
var messageMemberEmailTitle string
|
|
//var messageMemberApp string
|
|
var messageMemberAppTitle string
|
|
|
|
var messageDispatcherSMS string
|
|
var messageDispatcherSMSTitle string
|
|
var messageDispatcherEmail string
|
|
var messageDispatcherEmailTitle string
|
|
//var messageDispatcherApp string
|
|
var messageDispatcherAppTitle string
|
|
|
|
if lyftRide.CanceledBy == "driver" {
|
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberSMSTitle = MessageSMSCanceledByDriverMemberTitle
|
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberEmailTitle = MessageEmailCanceledByDriverMemberTitle
|
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberAppTitle = MessageAppCanceledByDriverMemberTitle
|
|
|
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledByDriverDispatcherTitle, ride.User.Name)
|
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledByDriverDispatcherTitle, ride.User.Name)
|
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherAppTitle = MessageAppCanceledByDriverDispatcherTitle
|
|
} else if lyftRide.CanceledBy == "no_drivers_available" {
|
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
|
messageMemberSMSTitle = MessageSMSCanceledNoDriverMemberTitle
|
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
|
messageMemberEmailTitle = MessageEmailCanceledNoDriverMemberTitle
|
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
|
messageMemberAppTitle = MessageAppCanceledNoDriverMemberTitle
|
|
|
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcherTitle, ride.User.Name)
|
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcherTitle, ride.User.Name)
|
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
|
messageDispatcherAppTitle = MessageAppCanceledNoDriverDispatcherTitle
|
|
} else {
|
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberSMSTitle = MessageSMSCanceledMemberTitle
|
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberEmailTitle = MessageEmailCanceledMemberTitle
|
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledMember, visitTime, ride.Visit.ExternalID)
|
|
messageMemberAppTitle = MessageAppCanceledMemberTitle
|
|
|
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledDispatcherTitle, ride.User.Name)
|
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledDispatcherTitle, ride.User.Name)
|
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
|
messageDispatcherAppTitle = MessageAppCanceledDispatcherTitle //fmt.Sprintf(MessageAppCanceledDispatcherTitle, ride.User.Name)
|
|
}
|
|
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", messageMemberSMSTitle, messageMemberSMS, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "sms", messageDispatcherSMSTitle, messageDispatcherSMS, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", messageMemberEmailTitle, messageMemberEmail, false, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "email", messageDispatcherEmailTitle, messageDispatcherEmail, true, ""))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageMemberAppTitle, false, "ride"))
|
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageDispatcherAppTitle, true, "ride"))
|
|
}
|
|
|
|
notifications, err = s.SendNotifications(notifications)
|
|
if err != nil {
|
|
fmt.Println("Error to notify")
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *notificationService) GetNotification(ride viewmodel.Ride, notificationType string, subject string, message string, isDispatcher bool, messageType string) viewmodel.Notification {
|
|
retVal := viewmodel.Notification{
|
|
Type: notificationType,
|
|
Message: message,
|
|
Subject: subject,
|
|
Ride: ride,
|
|
User: ride.User,
|
|
CreatedUser: ride.CreatedUser,
|
|
Read: false,
|
|
MessageType: messageType,
|
|
}
|
|
|
|
if isDispatcher {
|
|
retVal.User = ride.CreatedUser
|
|
retVal.CreatedUser = ride.User
|
|
}
|
|
|
|
switch notificationType {
|
|
case NotificationTypeEmail:
|
|
if isDispatcher {
|
|
retVal.To = *ride.CreatedUser.Email
|
|
} else {
|
|
retVal.To = *ride.User.Email
|
|
}
|
|
case NOtificationTypeSMS:
|
|
if isDispatcher {
|
|
retVal.To = *ride.CreatedUser.PhoneNumber
|
|
} else {
|
|
retVal.To = *ride.User.PhoneNumber
|
|
}
|
|
case NotificationTypeAPP:
|
|
if isDispatcher {
|
|
retVal.To = ride.CreatedUser.ID
|
|
} else {
|
|
retVal.To = ride.User.ID
|
|
}
|
|
}
|
|
|
|
return retVal
|
|
}
|
|
|
|
func (s *notificationService) SendMessage(message viewmodel.Message) error {
|
|
bMessage, err := ffjson.Marshal(message)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.store.redisClient.Publish(message.DeliveryID, string(bMessage)).Err()
|
|
}
|
|
|
|
func (s *notificationService) GetByUserUUIDAndReadStatus(user viewmodel.User, contactType string, isRead bool) ([]viewmodel.Notification, error) {
|
|
n, err := s.svc.Notification.GetByUserUUIDAndReadStatus(user.ID, contactType, isRead)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
authUser, err := s.svc.Users.GetByUUID(user.ID, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !isRead {
|
|
for i, _ := range n {
|
|
r, err := s.svc.Rides.GetByID(n[i].Ride.ID, authUser)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
n[i].Ride = r
|
|
}
|
|
}
|
|
|
|
return s.mapEntity.Notification.ToNotificationModelSlice(n), nil
|
|
}
|
|
|
|
func (s *notificationService) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
|
|
return s.store.Subscribe(user, conn)
|
|
}
|
|
|
|
func (s *notificationService) DeliverMessage() {
|
|
for {
|
|
v, _ := s.pubSub.Receive()
|
|
switch t := v.(type) {
|
|
case *redis.Message:
|
|
var m viewmodel.Message
|
|
ffjson.Unmarshal([]byte(t.Payload), &m)
|
|
s.store.FindAndDeliver(m)
|
|
case error:
|
|
fmt.Println("Error to delivery messages: ", t.Error())
|
|
return
|
|
default:
|
|
if t != nil {
|
|
fmt.Println("Unknown Event: ", t)
|
|
fmt.Println("Type: ", reflect.TypeOf(t))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//FindAndDeliver will send a message to an open channel
|
|
func (s *Store) FindAndDeliver(m viewmodel.Message) {
|
|
if s.Users[m.DeliveryID] != nil {
|
|
if s.Users[m.DeliveryID].ID != "" {
|
|
if len(s.Users[m.DeliveryID].Conn) > 0 {
|
|
for i, _ := range s.Users[m.DeliveryID].Conn {
|
|
if s.Users[m.DeliveryID].Conn[i] != nil {
|
|
if err := s.Users[m.DeliveryID].Conn[i].WriteJSON(m); err != nil {
|
|
s.Users[m.DeliveryID].Conn[i] = nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
//Subscribe add the user to a subscription
|
|
func (s *Store) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
|
|
u := s.Users[user.ID]
|
|
if u == nil {
|
|
u := &UserNotification{
|
|
ID: user.ID,
|
|
Conn: []*websocket.Conn{conn},
|
|
User: user,
|
|
}
|
|
s.Users[u.ID] = u
|
|
} else {
|
|
u.Conn = append(u.Conn, conn)
|
|
s.Users[u.ID] = u
|
|
}
|
|
|
|
err := s.pubSub.Subscribe(user.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
|
|
return u, nil
|
|
}
|
|
|
|
func (s *notificationService) ReadStatus(notificationUUID string, isRead bool) error {
|
|
return s.svc.Notification.ReadStatus(notificationUUID, isRead)
|
|
}
|
|
|
|
// SendNotifications will send all the notifications to email or SMS
|
|
func (s *notificationService) SendNotifications(notifications []viewmodel.Notification) ([]viewmodel.Notification, error) {
|
|
if len(notifications) > 0 {
|
|
retVal := make([]viewmodel.Notification, 0)
|
|
for _, n := range notifications {
|
|
if n.To != "" {
|
|
notification := s.mapEntity.Notification.ToNotificationEntity(n)
|
|
notification, err := s.svc.Notification.Create(notification)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch n.Type {
|
|
case NOtificationTypeSMS:
|
|
if n.From == "" {
|
|
if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, n.To, n.Message); err != nil {
|
|
fmt.Println("Error to send SMS: ", err.Error())
|
|
}
|
|
if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, "+17083038497", n.Message); err != nil {
|
|
fmt.Println("Error to send SMS: ", err.Error())
|
|
}
|
|
} else {
|
|
if err := s.notification.Twilio.SendSMS(n.From, n.To, n.Message); err != nil {
|
|
fmt.Println("Error to send SMS: ", err.Error())
|
|
}
|
|
if err := s.notification.Twilio.SendSMS(n.From, "+17083038497", n.Message); err != nil {
|
|
fmt.Println("Error to send SMS: ", err.Error())
|
|
}
|
|
}
|
|
case NotificationTypeEmail:
|
|
m := gomail.NewMessage()
|
|
m.SetHeader("From", s.cfg.Email.Sender)
|
|
m.SetHeader("To", n.To)
|
|
m.SetHeader("Subject", n.Subject)
|
|
m.SetBody("text/plain", n.Message)
|
|
d := gomail.NewDialer(s.cfg.Email.Server, s.cfg.Email.Port, s.cfg.Email.User, s.cfg.Email.Pass)
|
|
|
|
if err := d.DialAndSend(m); err != nil {
|
|
fmt.Println("Error to send Email: ", err.Error())
|
|
}
|
|
|
|
m = gomail.NewMessage()
|
|
m.SetHeader("From", s.cfg.Email.Sender)
|
|
m.SetHeader("To", "nemt@brighterdevelopment.com")
|
|
m.SetHeader("Subject", n.Subject)
|
|
m.SetBody("text/plain", n.Message)
|
|
|
|
if err := d.DialAndSend(m); err != nil {
|
|
fmt.Println("Error to send Email: ", err.Error())
|
|
}
|
|
case NotificationTypeAPP:
|
|
m := viewmodel.Message{
|
|
DeliveryID: n.To,
|
|
NotificationID: notification.UUID,
|
|
CreateDate: notification.Created,
|
|
Read: notification.Read,
|
|
Content: viewmodel.MessageContent{
|
|
Type: n.MessageType,
|
|
Subject: n.Subject,
|
|
Content: n.Message,
|
|
Payload: n.Ride,
|
|
},
|
|
}
|
|
|
|
if err := s.SendMessage(m); err != nil {
|
|
fmt.Println("Error to send notification to the users: ", err.Error())
|
|
}
|
|
}
|
|
retVal = append(retVal, s.mapEntity.Notification.ToNotificationModel(notification))
|
|
}
|
|
}
|
|
return retVal, nil
|
|
}
|
|
return notifications, nil
|
|
}
|
|
|
|
type UserNotification struct {
|
|
ID string
|
|
Conn []*websocket.Conn
|
|
User viewmodel.User
|
|
}
|
|
|
|
type Store struct {
|
|
Users map[string]*UserNotification
|
|
redisClient *redis.Client
|
|
pubSub *redis.PubSub
|
|
sync.Mutex
|
|
}
|