initial commit 2

This commit is contained in:
Senad Uka
2018-04-25 13:16:36 +02:00
parent c1520d169c
commit 99c10b75fb
167 changed files with 25057 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
package applicationservice
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
Users *userService
Rides *rideService
Visits *visitService
Provider *providerService
Notification *notificationService
Profile *profileService
Organization *organizationService
}
// New returns a new domain Service instance
func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
once.Do(func() {
instance = &Service{
Users: newUserService(svc, mapper),
Rides: newRideService(svc, mapper),
Visits: newVisitService(svc, mapper),
Provider: newProviderService(svc, mapper),
Notification: newNotificationService(svc, mapper, notification, cfg),
Profile: newProfileService(svc, mapper),
Organization: newOrganizationService(svc, mapper),
}
})
return instance
}

View File

@@ -0,0 +1,640 @@
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 &notificationService{
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
}

View File

@@ -0,0 +1,131 @@
package applicationservice
const (
MessageSMSIAmReadyOrClick = "When you ready to go back to %s, click on the following link:\n %s\n or reply this message with I AM READY"
MessageEmailIAmReadyOrClick = "When you are ready to go back to %s, click on the following link:\n %s"
MessageSMSReplyOrCancel = "Reply CANCEL RIDE to cancel or DRIVER to contact driver"
MessageSMSPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageSMSPendingMemberTitle = "Ride Pending for %s"
MessageSMSPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageSMSPendingDispatcherTitle = "Ride Pending for %s on %s"
MessageEmailPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageEmailPendingMemberTitle = "Ride Pending for %s"
MessageEmailPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageEmailPendingDispatcherTitle = "Ride Pending for %s on %s"
MessageAppPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageAppPendingMemberTitle = "Pickup: %s | %s"
MessageAppPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageAppPendingDispatcherTitle = "Pickup: %s | %s"
MessageSMSWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
MessageSMSWillCallMemberTitle = "Ride Pending for %s"
MessageSMSWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
MessageSMSWillCallDispatcherTitle = "Ride Pending for %s"
MessageEmailWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
MessageEmailWillCallMemberTitle = "Ride Pending for %s"
MessageEmailWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
MessageEmailWillCallDispatcherTitle = "Ride Pending for %s"
MessageAppWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
MessageAppWillCallMemberTitle = "Pickup: %s | %s"
MessageAppWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
MessageAppWillCallDispatcherTitle = "Pickup: %s | %s"
MessageSMSScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageSMSScheduledMemberTitle = "Ride Scheduled for %s"
MessageSMSScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageSMSScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
MessageEmailScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageEmailScheduledMemberTitle = "Ride Scheduled for %s"
MessageEmailScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageEmailScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
MessageAppScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageAppScheduledMemberTitle = "Pickup: %s | %s"
MessageAppScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
MessageAppScheduledDispatcherTitle = "Pickup: %s | %s"
MessageSMSAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageSMSAcceptedMemberTitle = "Your Ride is on the way !"
MessageSMSAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageSMSAcceptedDispatcherTitle = "Ride Accepted for %s"
MessageEmailAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageEmailAcceptedMemberTitle = "Your Ride is on the way !"
MessageEmailAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageEmailAcceptedDispatcherTitle = "Ride Accepted for %s"
MessageAppAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageAppAcceptedMemberTitle = "ETA: %s at %s"
MessageAppAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
MessageAppAcceptedDispatcherTitle = "ETA: %s at %s"
MessageSMSArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageSMSArrivedMemberTitle = "Your Ride is HERE !"
MessageSMSArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageSMSArrivedDispatcherTitle = "Ride Arrived for %s"
MessageEmailArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageEmailArrivedMemberTitle = "Your Ride is HERE !"
MessageEmailArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageEmailArrivedDispatcherTitle = "Ride Arrived for %s"
MessageAppArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageAppArrivedMemberTitle = "Look for %s %s %s (%s)"
MessageAppArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
MessageAppArrivedDispatcherTitle = "Look for %s %s %s (%s)"
MessageSMSPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
MessageSMSPickedUpDispatcherTitle = "%s is in Transit"
MessageEmailPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
MessageEmailPickedUpDispatcherTitle = "%s is in Transit"
MessageAppPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
MessageAppPickedUpDispatcherTitle = "Actual Pickup Time: %s"
MessageSMSDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
MessageSMSDroppedOffDispatcherTitle = "%s has arrived"
MessageEmailDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
MessageEmailDroppedOffDispatcherTitle = "%s has arrived"
MessageAppDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
MessageAppDroppedOffDispatcherTitle = "Arrival Time: %s"
MessageSMSDroppedOffMember = "Your ride has been ended, Thank you."
MessageSMSDroppedOffMemberTitle = "Ride Ended"
MessageEmailDroppedOffMember = "Your ride has been ended, Thank you."
MessageEmailDroppedOffMemberTitle = "Ride Ended"
MessageAppDroppedOffMember = "Your ride has been ended, Thank you."
MessageAppDroppedOffMemberTitle = "Arrived to %s"
MessageSMSCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageSMSCanceledByDriverMemberTitle = "Your Ride has been Canceled"
MessageSMSCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageSMSCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
MessageEmailCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageEmailCanceledByDriverMemberTitle = "Your Ride has been Canceled"
MessageEmailCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageEmailCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
MessageAppCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageAppCanceledByDriverMemberTitle = "Canceled by Driver"
MessageAppCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
MessageAppCanceledByDriverDispatcherTitle = "Canceled by Driver"
MessageSMSCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
MessageSMSCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
MessageSMSCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
MessageSMSCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
MessageEmailCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
MessageEmailCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
MessageEmailCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
MessageEmailCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
MessageAppCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
MessageAppCanceledNoDriverMemberTitle = "No drivers available"
MessageAppCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
MessageAppCanceledNoDriverDispatcherTitle = "No drivers available"
MessageSMSCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
MessageSMSCanceledMemberTitle = "Your Ride has been Canceled"
MessageSMSCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
MessageSMSCanceledDispatcherTitle = "Ride for %s Canceled"
MessageEmailCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
MessageEmailCanceledMemberTitle = "Your Ride has been Canceled"
MessageEmailCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
MessageEmailCanceledDispatcherTitle = "Ride for %s Canceled"
MessageAppCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
MessageAppCanceledMemberTitle = "Canceled by Member"
MessageAppCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
MessageAppCanceledDispatcherTitle = "Canceled by Member"
)

View File

@@ -0,0 +1,230 @@
package applicationservice
import (
"fmt"
"strconv"
"strings"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"github.com/pquerna/ffjson/ffjson"
)
// providerService holds methods to provider application service
type organizationService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newProviderService returns a providerService instance
func newOrganizationService(svc *service.Service, mapper *entitymapping.Mapper) *organizationService {
return &organizationService{
svc: svc,
mapEntity: mapper,
}
}
func (s *organizationService) GetAllTypes() ([]viewmodel.OrganizationType, error) {
result, err := s.svc.Organization.GetAllTypes()
if err != nil {
return nil, err
}
return s.mapEntity.Organization.ToOrganizationTypeModelSlice(result), nil
}
func (s *organizationService) GetByType(organizationTypeKey string) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByType(organizationTypeKey)
if err != nil {
return nil, err
}
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
}
func (s *organizationService) GetByUUID(organizationUUID string) (viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByUUID(organizationUUID)
if err != nil {
return viewmodel.Organization{}, err
}
return s.mapEntity.Organization.ToOrganizationModel(result), nil
}
func (s *organizationService) GetByName(name string, searchType string) ([]viewmodel.Organization, error) {
result, err := s.svc.Organization.GetByName(name, searchType)
if err != nil {
return nil, err
}
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
}
func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string) (viewmodel.Organization, error) {
child, err := s.svc.Organization.GetByUUID(organizationUUID)
if err != nil {
return viewmodel.Organization{}, err
}
parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID)
if err != nil {
return viewmodel.Organization{}, err
}
if err := s.svc.Organization.SetParentOrganization(child.ID, parent.ID); err != nil {
return viewmodel.Organization{}, err
}
return s.GetByUUID(organizationUUID)
}
func (s *organizationService) InactivateOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) error {
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{
UUID: organizationUUID,
}
user, err := s.svc.Users.GetByUUID(address.UpdatedUser.ID, "")
if err != nil {
return err
}
entityAddress.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress); err != nil {
return err
} else {
return nil
}
}
func (s *organizationService) SetOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) (viewmodel.OrganizationAddress, error) {
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
entityAddress.Organization = &entity.Organization{
UUID: organizationUUID,
}
user, err := s.svc.Users.GetByUUID(address.CreatedUser.ID, "")
if err != nil {
return viewmodel.OrganizationAddress{}, err
}
entityAddress.CreatedUser = user
entityAddress.UpdatedUser = user
entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress)
if err != nil {
return viewmodel.OrganizationAddress{}, err
}
return s.mapEntity.Organization.ToOrganizationAddressModel(entityAddress), nil
}
func (s *organizationService) InactivateOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) error {
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{
UUID: organizationUUID,
}
user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
if err != nil {
return err
}
entityContact.UpdatedUser = user
if err := s.svc.Organization.InactivateOrganizationContact(entityContact); err != nil {
return err
} else {
return nil
}
}
func (s *organizationService) SetOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) (viewmodel.OrganizationContact, error) {
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
entityContact.Organization = &entity.Organization{
UUID: organizationUUID,
}
user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
if err != nil {
return viewmodel.OrganizationContact{}, err
}
entityContact.CreatedUser = user
entityContact.UpdatedUser = user
entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact)
if err != nil {
return viewmodel.OrganizationContact{}, err
}
return s.mapEntity.Organization.ToOrganizationContactModel(entityContact), nil
}
func (s *organizationService) AddOrganization(organization viewmodel.Organization, user viewmodel.User) (viewmodel.Organization, error) {
enOrg := s.mapEntity.Organization.ToOrganizationEntity(organization)
enUser := s.mapEntity.User.ToUserEntity(user)
author, err := s.svc.Users.GetByUUID(organization.Author.ID, "")
if err != nil {
return viewmodel.Organization{}, nil
}
enOrg.Author = author
enOrg.LastEditor = enOrg.Author
if organization.Reference != nil {
switch organization.Type.Key {
case "provider":
var provider npdmodel.ProviderResponse
bProvider, err := ffjson.Marshal(organization.Reference)
if err != nil {
fmt.Println("Error to marshal provider")
return viewmodel.Organization{}, nil
}
if err := ffjson.Unmarshal(bProvider, &provider); err != nil {
fmt.Println("Error to convert provider")
return viewmodel.Organization{}, nil
}
eProviders, err := s.svc.Provider.Save(s.mapEntity.Provider.ToProviderEntitySlice([]npdmodel.ProviderResponse{provider}), enUser)
if err != nil {
fmt.Println("Error to save provider")
return viewmodel.Organization{}, nil
}
respProvider := eProviders[0]
enOrg.ReferenceID = respProvider.ProviderID
lat, _ := strconv.ParseFloat(provider.Latitude, 64)
long, _ := strconv.ParseFloat(provider.Longitude, 64)
address := entity.OrganizationAddress{
InternalID: provider.MukID,
Name: "Main Address",
Address: fmt.Sprintf("%s %s - %s, %s (%s)", provider.StreetName1, provider.StreetName2, provider.CityName, provider.State, provider.ZipCode),
Latitude: lat,
Longitude: long,
CreatedUser: enOrg.Author,
UpdatedUser: enOrg.LastEditor,
}
enOrg.Addresses = append(enOrg.Addresses, address)
fmt.Println("Phone Number: ", provider.PhoneNumber)
if provider.PhoneNumber != "" {
formattedPhone := "+1" + strings.Replace(provider.PhoneNumber, "-", "", -1)
contact := entity.OrganizationContact{
Type: entity.ContactType{
Key: "phone",
},
Contact: formattedPhone,
Name: "Main Phone",
CreatedUser: enOrg.Author,
UpdatedUser: enOrg.LastEditor,
}
enOrg.Contacts = append(enOrg.Contacts, contact)
}
}
}
enOrg, err = s.svc.Organization.AddOrganization(enOrg)
if err != nil {
return viewmodel.Organization{}, nil
}
return s.GetByUUID(enOrg.UUID)
}

View File

@@ -0,0 +1,58 @@
package applicationservice
import (
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
)
// providerService holds methods to provider application service
type profileService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newProviderService returns a providerService instance
func newProfileService(svc *service.Service, mapper *entitymapping.Mapper) *profileService {
return &profileService{
svc: svc,
mapEntity: mapper,
}
}
func (s *profileService) GetAll() ([]viewmodel.Profile, error) {
result, err := s.svc.Profile.GetAll()
if err != nil {
return nil, err
}
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
}
func (s *profileService) GetByKey(key string) (viewmodel.Profile, error) {
result, err := s.svc.Profile.GetByKey(key)
if err != nil {
return viewmodel.Profile{}, err
}
return s.mapEntity.Profile.ToProfileModel(result), nil
}
func (s *profileService) GetVisibles(visible bool) ([]viewmodel.Profile, error) {
result, err := s.svc.Profile.GetVisibles(visible)
if err != nil {
return nil, err
}
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
}
func (s *profileService) GetByOrganizationType(organizationTypeKey string) ([]viewmodel.Profile, error) {
orgType, err := s.svc.Organization.GetTypeByKey(organizationTypeKey)
if err != nil {
return nil, err
}
result, err := s.svc.Profile.GetByOrganizationType(orgType.ID)
if err != nil {
return nil, err
}
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
}

View File

@@ -0,0 +1,50 @@
package applicationservice
import (
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
)
// providerService holds methods to provider application service
type providerService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newProviderService returns a providerService instance
func newProviderService(svc *service.Service, mapper *entitymapping.Mapper) *providerService {
return &providerService{
svc: svc,
mapEntity: mapper,
}
}
func (s *providerService) Save(providers []npdmodel.ProviderResponse, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
entities := s.mapEntity.Provider.ToProviderEntitySlice(providers)
result, err := s.svc.Provider.Save(entities, eUser)
if err != nil {
return nil, err
}
return s.mapEntity.Provider.ToProviderRespModelSlice(result), nil
}
func (s *providerService) GetAll(user viewmodel.User) ([]viewmodel.ProviderResp, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
providers, err := s.svc.Provider.GetAll(eUser)
if err != nil {
return nil, err
}
return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
}
func (s *providerService) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
providers, err := s.svc.Provider.Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, eUser)
if err != nil {
return nil, err
}
return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
}

View File

@@ -0,0 +1,420 @@
package applicationservice
import (
"time"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
// rideService holds methods to user application service
type rideService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newUserService returns a userService instance
func newRideService(svc *service.Service, mapper *entitymapping.Mapper) *rideService {
return &rideService{
svc: svc,
mapEntity: mapper,
}
}
func (s *rideService) UpdateNewRide(ride viewmodel.Ride, lyftRide viewmodel.RideRequest, user viewmodel.User) (viewmodel.Ride, error) {
webhookModel := viewmodel.WebhookResponse{
Ride: ride,
Event: lyftRide,
}
webhook := s.mapEntity.Ride.ToWebhookEntity(webhookModel)
eUser := s.mapEntity.User.ToUserEntity(user)
oldRide, err := s.svc.Rides.GetByUUID(ride.UUID, eUser)
if err != nil {
return viewmodel.Ride{}, err
}
requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
generateDate := time.Now()
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
if webhook.Ride.RequestDate == nil {
webhook.Ride.RequestDate = oldRide.PickupTime
}
if webhook.Ride.RequestMiliseconds == nil {
webhook.Ride.RequestMiliseconds = &requestMS
}
if webhook.Ride.GenerateDate == nil {
webhook.Ride.GenerateDate = &generateDate
}
if webhook.Ride.GenerateMiliseconds == nil {
webhook.Ride.GenerateMiliseconds = &generateMS
}
switch webhook.Ride.Status.Key {
case "scheduled":
webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
case "accepted":
if lyftRide.Origin.ETASeconds != nil {
webhook.Ride.Route.ETA = *lyftRide.Origin.ETASeconds
} else {
webhook.Ride.Route.ETA = 0
}
case "arrived", "pickedUp":
if lyftRide.Destination.ETASeconds != nil {
webhook.Ride.Route.ETA = *lyftRide.Destination.ETASeconds
} else {
webhook.Ride.Route.ETA = 0
}
case "droppedOff":
webhook.Ride.Route.ETA = 0
}
webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
webhook.Ride.InternalID = lyftRide.RideID
webhook.Ride.ID = oldRide.ID
webhook.Ride.UUID = oldRide.UUID
webhook.Ride.Driver.ID = oldRide.Driver.ID
webhook.Ride.Passenger.ID = oldRide.Passenger.ID
webhook.Ride.Route.ID = oldRide.Route.ID
webhook.Ride.Type.ID = oldRide.Type.ID
webhook.Ride.User = oldRide.User
webhook.Ride.CreatedUser = oldRide.CreatedUser
webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
webhook.Ride.Visit = oldRide.Visit
webhook.Ride.VisitDate = oldRide.VisitDate
webhook.Ride.VisitTime = oldRide.VisitTime
//webhook.Ride.PickupTime = oldRide.PickupTime
entityRide, err := s.svc.Rides.Update(webhook)
if err != nil {
return viewmodel.Ride{}, err
}
return s.mapEntity.Ride.ToRideModel(entityRide), nil
}
func (s *rideService) Update(ride viewmodel.WebhookResponse) (viewmodel.Ride, error) {
webhook := s.mapEntity.Ride.ToWebhookEntity(ride)
oldRide, err := s.svc.Rides.GetByInternalID(ride.Event.RideID)
if err != nil {
oldRide, err = s.svc.Rides.GetByInternalPassengerID(*ride.Event.Passenger.UserID)
if err != nil {
return viewmodel.Ride{}, err
}
}
requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
generateDate := time.Now()
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
if webhook.Ride.RequestDate == nil {
webhook.Ride.RequestDate = oldRide.PickupTime
}
if webhook.Ride.RequestMiliseconds == nil {
webhook.Ride.RequestMiliseconds = &requestMS
}
if webhook.Ride.GenerateDate == nil {
webhook.Ride.GenerateDate = &generateDate
}
if webhook.Ride.GenerateMiliseconds == nil {
webhook.Ride.GenerateMiliseconds = &generateMS
}
switch webhook.Ride.Status.Key {
case "scheduled":
webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
case "accepted":
if ride.Event.Origin.ETASeconds != nil {
webhook.Ride.Route.ETA = *ride.Event.Origin.ETASeconds
} else {
webhook.Ride.Route.ETA = 0
}
case "arrived", "pickedUp":
if ride.Event.Destination.ETASeconds != nil {
webhook.Ride.Route.ETA = *ride.Event.Destination.ETASeconds
} else {
webhook.Ride.Route.ETA = 0
}
case "droppedOff":
webhook.Ride.Route.ETA = 0
}
webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
webhook.Ride.InternalID = ride.Event.RideID
webhook.Ride.ID = oldRide.ID
webhook.Ride.UUID = oldRide.UUID
webhook.Ride.Driver.ID = oldRide.Driver.ID
webhook.Ride.Passenger.ID = oldRide.Passenger.ID
webhook.Ride.Route.ID = oldRide.Route.ID
webhook.Ride.Type.ID = oldRide.Type.ID
webhook.Ride.User = oldRide.User
webhook.Ride.CreatedUser = oldRide.CreatedUser
webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
webhook.Ride.Visit = oldRide.Visit
webhook.Ride.VisitDate = oldRide.VisitDate
webhook.Ride.VisitTime = oldRide.VisitTime
webhook.Ride.PickupTime = oldRide.PickupTime
entityRide, err := s.svc.Rides.Update(webhook)
if err != nil {
return viewmodel.Ride{}, err
}
return s.mapEntity.Ride.ToRideModel(entityRide), nil
}
// Save a new ride
func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
rideEntity := s.mapEntity.Ride.ToRideEntity(ride)
if ride.Visit.UUID == "" {
visit := entity.Visit{}
visit.User = rideEntity.User
visit.Pickup = rideEntity.Route.Origin
visit.Notes = &rideEntity.Note
visit.PickupDatetime = *rideEntity.PickupTime
visit.VisitDatetime = *rideEntity.VisitTime
visit.CreatedUser.UUID = ride.CreateUserUUID
visit.ExternalID = ride.VisitExternalID
visit.TripType = rideEntity.Visit.TripType
visit.ReturnDate = ride.ReturnTime
address, _ := s.svc.Users.GetAddressByUUID(rideEntity.Route.Destination.ID)
createdUser, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if address.ID > 0 {
visit.DestinationAddressID = address.ID
provider, err := s.svc.Provider.GetByMukID(address.InternalID, createdUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
visit.Provider = provider
} else {
provider, err := s.svc.Provider.GetByMukID(rideEntity.Route.Destination.ID, createdUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
visit.Provider = provider
}
visit, err = s.svc.Visits.Create(visit)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
rideEntity.Visit = visit
} else {
user, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
visit, err := s.svc.Visits.GetByUUID(ride.Visit.UUID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
rideEntity.Visit = visit
}
retVal, err := s.svc.Rides.Save(rideEntity)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}
// GetAll returns a list of users
func (s *rideService) GetAll(user viewmodel.User) ([]viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetAll(eUser)
if err != nil {
return nil, errors.Wrap(err)
}
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
}
// GetByUUID returns a specific Ride
func (s *rideService) GetByUUID(uuid string, user viewmodel.User) (viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetByUUID(uuid, eUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if retVal.Visit.ID > 0 {
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, eUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}
func (s *rideService) GetByVisitUUID(visitUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetByVisitUUID(visitUUID, eUser)
if err != nil {
return nil, errors.Wrap(err)
}
visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
if err != nil {
return nil, errors.Wrap(err)
}
for i, _ := range retVal {
retVal[i].Visit = visit
}
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
}
func (s *rideService) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user viewmodel.User) (viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetByVisitUUIDAndTripType(visitUUID, tripTypeKey, eUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
retVal.Visit = visit
return s.mapEntity.Ride.ToRideModel(retVal), err
}
// GetByUUID returns a specific Ride
func (s *rideService) GetByUUIDAndUserUUID(uuid string, user_uuid string) (viewmodel.Ride, error) {
retVal, err := s.svc.Rides.GetByUUIDAndUserUUID(uuid, user_uuid)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if retVal.Visit.ID > 0 {
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}
// GetByInternalID returns a specific Ride
func (s *rideService) GetByInternalID(internalID string) (viewmodel.Ride, error) {
retVal, err := s.svc.Rides.GetByInternalID(internalID)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if retVal.Visit.ID > 0 {
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}
// GetByUserID returns a list of rides for an user
func (s *rideService) GetByUserID(userID int64, user viewmodel.User) ([]viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetByUserID(userID, eUser)
if err != nil {
return []viewmodel.Ride{}, errors.Wrap(err)
}
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
}
// UpdateStatus change the status of the ride
func (s *rideService) UpdateStatus(rideUUID string, status string) error {
err := s.svc.Rides.UpdateStatus(rideUUID, status)
if err != nil {
return errors.Wrap(err)
}
return nil
}
// GetByUserID returns a list of rides for an user
func (s *rideService) GetByUserUUID(userUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Rides.GetByUserUUID(userUUID, eUser)
if err != nil {
return []viewmodel.Ride{}, errors.Wrap(err)
}
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
}
func (s *rideService) GetLastRideByPhoneNumber(phoneNumber string, notificationType string, status string) (viewmodel.Ride, error) {
// if notificationType == ""{
// notificationType = "message"
// }
if status == "" {
status = "sms"
}
notification, err := s.svc.Notification.GetLastNotificationFromPhoneNumber(notificationType, phoneNumber, status)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
user, err := s.svc.Users.GetByID(notification.CreatedUser.ID)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
retVal, err := s.svc.Rides.GetByID(notification.Ride.ID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if retVal.Visit.ID > 0 {
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}
func (s *rideService) GetLastRideByDriversNumber(phoneNumber string) (viewmodel.Ride, error) {
retVal, err := s.svc.Rides.GetLastRideByDriversNumber(phoneNumber)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
if retVal.Visit.ID > 0 {
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
if err != nil {
return viewmodel.Ride{}, errors.Wrap(err)
}
}
return s.mapEntity.Ride.ToRideModel(retVal), err
}

View File

@@ -0,0 +1,149 @@
package applicationservice
import (
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
// userService holds methods to user application service
type userService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newUserService returns a userService instance
func newUserService(svc *service.Service, mapper *entitymapping.Mapper) *userService {
return &userService{
svc: svc,
mapEntity: mapper,
}
}
// GetAll returns a list of users
func (s *userService) GetAll(quantity int64, page int64) (retVal []viewmodel.User, err error) {
users, err := s.svc.Users.GetAll()
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModelSlice(users), nil
}
// GetByID returns a specific user by its ID
func (s *userService) GetByID(id int64) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.GetByID(id)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(user), nil
}
// GetByID returns a specific user by its ID
func (s *userService) GetByUUID(uuid string, profile string) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.GetByUUID(uuid, profile)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(user), nil
}
// Login returns a specific user by email and pass
func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.FullLogin(loginType, key, pass, profile)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(user), nil
}
// Login returns a specific user by email and pass
func (s *userService) Login(email string, pass string) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.Login(email, pass)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(user), nil
}
func (s *userService) Create(user viewmodel.User) (retVal viewmodel.User, err error) {
entity := s.mapEntity.User.ToUserEntity(user)
for i, _ := range entity.Organizations {
entity.Organizations[i], err = s.svc.Organization.GetByUUID(entity.Organizations[i].UUID)
if err != nil {
return retVal, err
}
}
entity, err = s.svc.Users.Create(entity)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(entity), nil
}
func (s *userService) CreateBulk(users []viewmodel.User) (retVal []viewmodel.User, err error) {
entities := s.mapEntity.User.ToUserEntitySlice(users)
organizations := make([]entity.Organization, 0)
for i, _ := range entities {
if i == 0 {
for o, _ := range entities[i].Organizations {
org, err := s.svc.Organization.GetByUUID(entities[i].Organizations[o].UUID)
if err != nil {
return nil, err
}
organizations = append(organizations, org)
}
}
entities[i].Organizations = organizations
}
entities, err = s.svc.Users.CreateBulk(entities)
if err != nil {
return nil, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModelSlice(entities), nil
}
// GetUsersByProfile returns a list of users by profile
func (s *userService) GetUsersByProfile(profile string) (retVal []viewmodel.User, err error) {
users, err := s.svc.Users.GetUsersByProfile(profile)
if err != nil {
return retVal, errors.Wrap(err)
}
list := s.mapEntity.User.ToUserModelSlice(users)
return list, nil
}
func (s *userService) RemoveAddress(addressUUID string) error {
return s.svc.Users.RemoveAddress(addressUUID)
}
func (s *userService) SaveAddress(address viewmodel.Address) (retVal viewmodel.Address, err error) {
entity := s.mapEntity.Address.ToAddressEntity(address)
entity, err = s.svc.Users.SaveAddress(entity)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.Address.ToAddressModel(entity), err
}
func (s *userService) GetContactType() (retVal []viewmodel.ContactType, err error) {
entity, err := s.svc.Users.GetContactType()
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToContactTypeModelSlice(entity), nil
}

View File

@@ -0,0 +1,38 @@
package applicationservice
import (
"math"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
// getTakeSkipPaging return the take and skip from page number and item quantity
func getTakeSkipPaging(quantity int64, page int64) (take int64, skip int64) {
if page < 1 {
page = 1
}
if quantity < 1 {
quantity = 10
} else if quantity > 1000 {
quantity = 1000
}
take = quantity // itens per page
skip = (page - 1) * quantity
return take, skip
}
// buildPaginatedResult returns a paginatedResult instance
func buildPaginatedResult(list interface{}, skip int64, take int64, totalRecords int64) viewmodel.PaginatedResult {
return viewmodel.PaginatedResult{
List: list,
Pagination: viewmodel.ReturnPagination{
CurrentPage: (skip / take) + 1,
RecordsPerPage: take,
TotalRecords: totalRecords,
TotalPages: int64(math.Ceil(float64(totalRecords) / float64(take))),
},
}
}

View File

@@ -0,0 +1,55 @@
package applicationservice
import (
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
// rideService holds methods to user application service
type visitService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newUserService returns a userService instance
func newVisitService(svc *service.Service, mapper *entitymapping.Mapper) *visitService {
return &visitService{
svc: svc,
mapEntity: mapper,
}
}
// Save a new ride
func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) {
entity := s.mapEntity.Visit.ToVisitEntity(visit)
retVal, err := s.svc.Visits.Create(entity)
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
return s.mapEntity.Visit.ToVisitModel(retVal), err
}
// Save a new ride
func (s *visitService) GetAll(user viewmodel.User) ([]viewmodel.Visit, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Visits.GetAll(eUser)
if err != nil {
return nil, errors.Wrap(err)
}
return s.mapEntity.Visit.ToVisitModelSlice(retVal), err
}
// Save a new ride
func (s *visitService) GetByUUID(visitUUID string, user viewmodel.User) (viewmodel.Visit, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
retVal, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
return s.mapEntity.Visit.ToVisitModel(retVal), err
}

View File

@@ -0,0 +1,74 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// rideMapping has method to map ride entities to view models
type addressMapping struct {
mapper *Mapper
}
// ToVisitEntity maps a User entity to User view model
func (mapping *addressMapping) ToAddressEntity(item viewmodel.Address) entity.Address {
return entity.Address{
UUID: item.UUID,
InternalID: item.InternalID,
Name: item.Name,
Address: item.Address,
AddressType: mapping.ToParamEntity(item.AddressType),
Latitude: item.Latitude,
Longitude: item.Longitude,
Origin: mapping.ToParamEntity(item.Type),
User: mapping.mapper.User.ToUserEntity(item.User),
CreatedUser: entity.User{
UUID: item.CreatedUserUUID,
},
}
}
func (mapping *addressMapping) ToParamEntity(item string) entity.Params {
return entity.Params{
Key: item,
}
}
// ToVisitEntity maps a User entity to User view model
func (mapping *addressMapping) ToAddressModel(item entity.Address) viewmodel.Address {
return viewmodel.Address{
UUID: item.UUID,
InternalID: item.InternalID,
Name: item.Name,
Address: item.Address,
AddressType: item.AddressType.Key,
AddressTypeName: item.AddressType.Name,
Latitude: item.Latitude,
Longitude: item.Longitude,
Type: item.Origin.Key,
User: mapping.mapper.User.ToUserModel(item.User),
CreatedUserUUID: item.CreatedUser.UUID,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *addressMapping) ToAddressEntitySlice(list []viewmodel.Address) (retVal []entity.Address) {
retVal = make([]entity.Address, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToAddressEntity(item))
}
return retVal
}
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
func (mapping *addressMapping) ToAddressModelSlice(list []entity.Address) (retVal []viewmodel.Address) {
retVal = make([]viewmodel.Address, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToAddressModel(item))
}
return retVal
}

View File

@@ -0,0 +1,51 @@
package entitymapping
import (
"strings"
"sync"
)
var (
instance *Mapper
once sync.Once
)
// Mapper has mapping methods to map entities to view models
type Mapper struct {
User *userMapping
Ride *rideMapping
Visit *visitMapping
Address *addressMapping
Provider *providerMapping
Notification *notificationMapping
Profile *profileMapping
Organization *organizationMapping
}
// New returns an EntityMapper for fluent mapping
func New() *Mapper {
once.Do(func() {
instance = &Mapper{}
instance.User = &userMapping{instance}
instance.Ride = &rideMapping{instance}
instance.Visit = &visitMapping{instance}
instance.Address = &addressMapping{instance}
instance.Provider = &providerMapping{instance}
instance.Notification = &notificationMapping{instance}
instance.Profile = &profileMapping{instance}
instance.Organization = &organizationMapping{instance}
})
return instance
}
// isEmpty returns the alternative option in case the first is empty
func ifEmpty(firstOption string, alternativeOption string) string {
if strings.TrimSpace(firstOption) == "" {
return alternativeOption
}
return firstOption
}

View File

@@ -0,0 +1,69 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// providerMapping has method to map provider entities to view models
type notificationMapping struct {
mapper *Mapper
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *notificationMapping) ToNotificationEntitySlice(list []viewmodel.Notification) (retVal []entity.Notification) {
retVal = make([]entity.Notification, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToNotificationEntity(item))
}
return retVal
}
func (mapping *notificationMapping) ToNotificationEntity(model viewmodel.Notification) entity.Notification {
return entity.Notification{
UUID: model.UUID,
To: model.To,
From: model.From,
Type: model.Type,
Subject: model.Subject,
Message: model.Message,
Created: model.Created,
Ride: entity.Ride{
UUID: model.Ride.UUID,
},
User: mapping.mapper.User.ToUserEntity(model.User),
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
Read: model.Read,
MessageType: model.MessageType,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *notificationMapping) ToNotificationModelSlice(list []entity.Notification) (retVal []viewmodel.Notification) {
retVal = make([]viewmodel.Notification, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToNotificationModel(item))
}
return retVal
}
func (mapping *notificationMapping) ToNotificationModel(model entity.Notification) viewmodel.Notification {
return viewmodel.Notification{
UUID: model.UUID,
To: model.To,
From: model.From,
Type: model.Type,
Subject: model.Subject,
Message: model.Message,
Created: model.Created,
Ride: mapping.mapper.Ride.ToRideModel(model.Ride),
User: mapping.mapper.User.ToUserModel(model.User),
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
Read: model.Read,
MessageType: model.MessageType,
}
}

View File

@@ -0,0 +1,256 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// providerMapping has method to map provider entities to view models
type organizationMapping struct {
mapper *Mapper
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationTypeEntitySlice(list []viewmodel.OrganizationType) (retVal []entity.OrganizationType) {
retVal = make([]entity.OrganizationType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationTypeEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationEntitySlice(list []viewmodel.Organization) (retVal []entity.Organization) {
retVal = make([]entity.Organization, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationEntity(item))
}
return retVal
}
func (mapping *organizationMapping) ToOrganizationEntity(model viewmodel.Organization) entity.Organization {
return entity.Organization{
ID: model.ID,
UUID: model.UUID,
Type: mapping.ToOrganizationTypeEntity(model.Type),
Name: model.Name,
Description: model.Description,
ReferenceID: model.ReferenceID,
ParentID: model.ParentID,
Main: model.Main,
Created: model.Created,
Updated: model.Updated,
Active: model.Active,
Blocked: model.Blocked,
Suspended: model.Suspended,
Author: mapping.mapper.User.ToUserEntity(model.Author),
LastEditor: mapping.mapper.User.ToUserEntity(model.LastEditor),
Contacts: mapping.ToOrganizationContactEntitySlice(model.Contacts),
Addresses: mapping.ToOrganizationAddressEntitySlice(model.Addresses),
ChildOrgs: mapping.ToOrganizationEntitySlice(model.ChildOrgs),
Parent: mapping.ToOrganizationEntityPointer(model.Parent),
}
}
func (mapping *organizationMapping) ToOrganizationEntityPointer(model *viewmodel.Organization) *entity.Organization {
if model != nil {
convertibleModel := *model
convertibleEntity := mapping.ToOrganizationEntity(convertibleModel)
return &convertibleEntity
} else {
return nil
}
}
func (mapping *organizationMapping) ToOrganizationModelPointer(model *entity.Organization) *viewmodel.Organization {
if model != nil {
convertibleModel := *model
convertibleEntity := mapping.ToOrganizationModel(convertibleModel)
return &convertibleEntity
} else {
return nil
}
}
func (mapping *organizationMapping) ToOrganizationTypeEntity(model viewmodel.OrganizationType) entity.OrganizationType {
return entity.OrganizationType{
ID: model.ID,
Name: model.Name,
Key: model.Key,
Description: model.Description,
Created: model.Created,
Updated: model.Updated,
}
}
func (mapping *organizationMapping) ToOrganizationTypeModelSlice(list []entity.OrganizationType) (retVal []viewmodel.OrganizationType) {
retVal = make([]viewmodel.OrganizationType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationTypeModel(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationModelSlice(list []entity.Organization) (retVal []viewmodel.Organization) {
retVal = make([]viewmodel.Organization, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationModel(item))
}
return retVal
}
func (mapping *organizationMapping) ToOrganizationModel(model entity.Organization) viewmodel.Organization {
return viewmodel.Organization{
ID: model.ID,
UUID: model.UUID,
Type: mapping.ToOrganizationTypeModel(model.Type),
Name: model.Name,
Description: model.Description,
ReferenceID: model.ReferenceID,
ParentID: model.ParentID,
Main: model.Main,
Created: model.Created,
Updated: model.Updated,
Active: model.Active,
Blocked: model.Blocked,
Suspended: model.Suspended,
Author: mapping.mapper.User.ToUserModel(model.Author),
LastEditor: mapping.mapper.User.ToUserModel(model.LastEditor),
Contacts: mapping.ToOrganizationContactModelSlice(model.Contacts),
Addresses: mapping.ToOrganizationAddressModelSlice(model.Addresses),
ChildOrgs: mapping.ToOrganizationModelSlice(model.ChildOrgs),
Parent: mapping.ToOrganizationModelPointer(model.Parent),
}
}
func (mapping *organizationMapping) ToOrganizationTypeModel(model entity.OrganizationType) viewmodel.OrganizationType {
return viewmodel.OrganizationType{
ID: model.ID,
Name: model.Name,
Key: model.Key,
Description: model.Description,
Created: model.Created,
Updated: model.Updated,
}
}
func (mapping *organizationMapping) ToOrganizationContactModel(model entity.OrganizationContact) viewmodel.OrganizationContact {
return viewmodel.OrganizationContact{
ID: model.ID,
UUID: model.UUID,
Type: mapping.mapper.User.ToContactTypeModel(model.Type),
Contact: model.Contact,
Name: model.Name,
Description: model.Description,
Created: model.Created,
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
Updated: model.Updated,
UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
Active: model.Active,
}
}
func (mapping *organizationMapping) ToOrganizationContactEntity(model viewmodel.OrganizationContact) entity.OrganizationContact {
return entity.OrganizationContact{
ID: model.ID,
UUID: model.UUID,
Type: mapping.mapper.User.ToContactTypeEntity(model.Type),
Contact: model.Contact,
Name: model.Name,
Description: model.Description,
Created: model.Created,
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
Updated: model.Updated,
UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
Active: model.Active,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationContactModelSlice(list []entity.OrganizationContact) (retVal []viewmodel.OrganizationContact) {
retVal = make([]viewmodel.OrganizationContact, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationContactModel(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationContactEntitySlice(list []viewmodel.OrganizationContact) (retVal []entity.OrganizationContact) {
retVal = make([]entity.OrganizationContact, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationContactEntity(item))
}
return retVal
}
func (mapping *organizationMapping) ToOrganizationAddressModel(model entity.OrganizationAddress) viewmodel.OrganizationAddress {
return viewmodel.OrganizationAddress{
ID: model.ID,
UUID: model.UUID,
InternalID: model.InternalID,
Address: model.Address,
Name: model.Name,
Description: model.Description,
Latitude: model.Latitude,
Longitude: model.Longitude,
Created: model.Created,
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
Updated: model.Updated,
UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
Active: model.Active,
}
}
func (mapping *organizationMapping) ToOrganizationAddressEntity(model viewmodel.OrganizationAddress) entity.OrganizationAddress {
return entity.OrganizationAddress{
ID: model.ID,
UUID: model.UUID,
InternalID: model.InternalID,
Address: model.Address,
Name: model.Name,
Description: model.Description,
Latitude: model.Latitude,
Longitude: model.Longitude,
Created: model.Created,
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
Updated: model.Updated,
UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
Active: model.Active,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationAddressModelSlice(list []entity.OrganizationAddress) (retVal []viewmodel.OrganizationAddress) {
retVal = make([]viewmodel.OrganizationAddress, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationAddressModel(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *organizationMapping) ToOrganizationAddressEntitySlice(list []viewmodel.OrganizationAddress) (retVal []entity.OrganizationAddress) {
retVal = make([]entity.OrganizationAddress, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToOrganizationAddressEntity(item))
}
return retVal
}

View File

@@ -0,0 +1,65 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// providerMapping has method to map provider entities to view models
type profileMapping struct {
mapper *Mapper
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *profileMapping) ToProfileEntitySlice(list []viewmodel.Profile) (retVal []entity.Profile) {
retVal = make([]entity.Profile, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProfileEntity(item))
}
return retVal
}
func (mapping *profileMapping) ToProfileEntity(model viewmodel.Profile) entity.Profile {
return entity.Profile{
ID: model.ID,
Key: model.Key,
Name: model.Name,
Description: model.Description,
Created: model.Created,
Updated: model.Updated,
Active: model.Active,
Visible: model.Visible,
Blocked: model.Blocked,
Suspended: model.Suspended,
Organization: mapping.mapper.Organization.ToOrganizationEntity(model.Organization),
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *profileMapping) ToProfileModelSlice(list []entity.Profile) (retVal []viewmodel.Profile) {
retVal = make([]viewmodel.Profile, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProfileModel(item))
}
return retVal
}
func (mapping *profileMapping) ToProfileModel(model entity.Profile) viewmodel.Profile {
return viewmodel.Profile{
ID: model.ID,
Key: model.Key,
Name: model.Name,
Description: model.Description,
Created: model.Created,
Updated: model.Updated,
Active: model.Active,
Visible: model.Visible,
Blocked: model.Blocked,
Suspended: model.Suspended,
Organization: mapping.mapper.Organization.ToOrganizationModel(model.Organization),
}
}

View File

@@ -0,0 +1,375 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// providerMapping has method to map provider entities to view models
type providerMapping struct {
mapper *Mapper
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderRespEntitySlice(list []viewmodel.ProviderResp) (retVal []entity.Provider) {
retVal = make([]entity.Provider, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderRespEntity(item))
}
return retVal
}
func (mapping *providerMapping) ToProviderRespEntity(item viewmodel.ProviderResp) entity.Provider {
return entity.Provider{
ProviderUUID: item.ProviderUUID,
InternalID: item.InternalID,
InternalSuffixID: item.InternalSuffixID,
MukID: item.MukID,
OrganizatioName: item.OrganizatioName,
Gender: item.Gender,
AcceptNewPatients: item.AcceptNewPatients,
Name: item.Name,
FirstName: item.FirstName,
MiddleName: item.MiddleName,
LastName: item.LastName,
Title: item.Title,
Distance: item.Distance,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderRespModelSlice(list []entity.Provider) (retVal []viewmodel.ProviderResp) {
retVal = make([]viewmodel.ProviderResp, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderRespModel(item))
}
return retVal
}
func (mapping *providerMapping) ToProviderRespModel(item entity.Provider) viewmodel.ProviderResp {
return viewmodel.ProviderResp{
ProviderUUID: item.ProviderUUID,
InternalID: item.InternalID,
InternalSuffixID: item.InternalSuffixID,
MukID: item.MukID,
OrganizatioName: item.OrganizatioName,
Gender: item.Gender,
AcceptNewPatients: item.AcceptNewPatients,
Name: item.Name,
FirstName: item.FirstName,
MiddleName: item.MiddleName,
LastName: item.LastName,
Title: item.Title,
Keys: mapping.ToProviderKeyModelSlice(item.Keys),
Address: mapping.ToProviderRespAddressModel(item.Address),
Distance: item.Distance,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderKeyModelSlice(list []entity.ProviderKey) (retVal []viewmodel.ProviderKey) {
retVal = make([]viewmodel.ProviderKey, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderKeyModel(item))
}
return retVal
}
func (mapping *providerMapping) ToProviderKeyModel(item entity.ProviderKey) viewmodel.ProviderKey {
return viewmodel.ProviderKey{
InternalID: item.InternalID,
InternalSuffixID: item.InternalSuffixID,
LocationSeqNumber: item.LocationSeqNumber,
PlanCode: item.PlanCode,
ProductID: item.ProductID,
TreatmentCategoryCode: item.TreatmentCategoryCode,
}
}
func (mapping *providerMapping) ToProviderRespAddressModel(item entity.ProviderAddress) viewmodel.ProviderAddress {
return viewmodel.ProviderAddress{
StreetAddress1: item.StreetAddress1,
StreetAddress2: item.StreetAddress2,
CityName: item.CityName,
State: item.State,
ZipCode: item.ZipCode,
Country: item.Country,
Latitude: item.Latitude,
Longitude: item.Longitude,
PhoneNumber: item.PhoneNumber,
}
}
func (mapping *providerMapping) ToProviderEntity(item npdmodel.ProviderResponse) entity.ProviderResponse {
return entity.ProviderResponse{
MukID: item.MukID,
FivePartKeyGroups: mapping.ToPartKeyGroupEntitySlice(item.FivePartKeyGroups),
OrgName: item.OrgName,
Gender: item.Gender,
AcceptNewPatients: item.AcceptNewPatients,
ProviderName: item.ProviderName,
FirstName: item.FirstName,
LastName: item.LastName,
MiddleName: item.MiddleName,
ProviderTitle: item.ProviderTitle,
StreetName1: item.StreetName1,
StreetName2: item.StreetName2,
CityName: item.CityName,
State: item.State,
ZipCode: item.ZipCode,
Country: item.Country,
Latitude: item.Latitude,
Longitude: item.Longitude,
PhoneNumber: item.PhoneNumber,
ProviderEntityName: item.ProviderEntityName,
ProviderEntityCode: item.ProviderEntityCode,
ProviderTypeCode: mapping.ToProviderTypeCodeEntitySlice(item.ProviderTypeCode),
Distance: item.Distance,
AvailabilityOfCost: item.AvailabilityOfCost,
TDDPhoneNumber: item.TDDPhoneNumber,
ExtendedOfficeHours: item.ExtendedOfficeHours,
ProviderCountyCode: item.ProviderCountyCode,
ProviderCountyName: item.ProviderCountyName,
HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesEntitySlice(item.HospitalAffiliationNames),
ProviderAffiliationNumber: item.ProviderAffiliationNumber,
ProviderAffiliationName: item.ProviderAffiliationName,
LanguagesSpoken: mapping.ToLanguagesEntitySlice(item.LanguagesSpoken),
OfficeLanguagesSpoken: mapping.ToLanguagesEntitySlice(item.OfficeLanguagesSpoken),
MedSchool: item.MedSchool,
MedSchoolYear: item.MedSchoolYear,
Internship: item.Internship,
Residence: item.Residence,
Specialty1: item.Specialty1,
Specialty2: item.Specialty2,
Specialty3: item.Specialty3,
Specialty4: item.Specialty4,
Certification1: item.Certification1,
Certification2: item.Certification2,
Certification3: item.Certification3,
Certification4: item.Certification4,
}
}
func (mapping *providerMapping) ToProviderModel(item entity.ProviderResponse) npdmodel.ProviderResponse {
return npdmodel.ProviderResponse{
MukID: item.MukID,
FivePartKeyGroups: mapping.ToPartKeyGroupModelSlice(item.FivePartKeyGroups),
OrgName: item.OrgName,
Gender: item.Gender,
AcceptNewPatients: item.AcceptNewPatients,
ProviderName: item.ProviderName,
FirstName: item.FirstName,
LastName: item.LastName,
MiddleName: item.MiddleName,
ProviderTitle: item.ProviderTitle,
StreetName1: item.StreetName1,
StreetName2: item.StreetName2,
CityName: item.CityName,
State: item.State,
ZipCode: item.ZipCode,
Country: item.Country,
Latitude: item.Latitude,
Longitude: item.Longitude,
PhoneNumber: item.PhoneNumber,
ProviderEntityName: item.ProviderEntityName,
ProviderEntityCode: item.ProviderEntityCode,
ProviderTypeCode: mapping.ToProviderTypeCodeModelSlice(item.ProviderTypeCode),
Distance: item.Distance,
AvailabilityOfCost: item.AvailabilityOfCost,
TDDPhoneNumber: item.TDDPhoneNumber,
ExtendedOfficeHours: item.ExtendedOfficeHours,
ProviderCountyCode: item.ProviderCountyCode,
ProviderCountyName: item.ProviderCountyName,
HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesModelSlice(item.HospitalAffiliationNames),
ProviderAffiliationNumber: item.ProviderAffiliationNumber,
ProviderAffiliationName: item.ProviderAffiliationName,
LanguagesSpoken: mapping.ToLanguagesModelSlice(item.LanguagesSpoken),
OfficeLanguagesSpoken: mapping.ToLanguagesModelSlice(item.OfficeLanguagesSpoken),
MedSchool: item.MedSchool,
MedSchoolYear: item.MedSchoolYear,
Internship: item.Internship,
Residence: item.Residence,
Specialty1: item.Specialty1,
Specialty2: item.Specialty2,
Specialty3: item.Specialty3,
Specialty4: item.Specialty4,
Certification1: item.Certification1,
Certification2: item.Certification2,
Certification3: item.Certification3,
Certification4: item.Certification4}
}
func (mapping *providerMapping) ToHospitalAffiliationNamesEntity(item npdmodel.HospitalAffiliationNames) entity.HospitalAffiliationNames {
return entity.HospitalAffiliationNames{
HospAffProvOrgName: item.HospAffProvOrgName,
}
}
func (mapping *providerMapping) ToHospitalAffiliationNamesModel(item entity.HospitalAffiliationNames) npdmodel.HospitalAffiliationNames {
return npdmodel.HospitalAffiliationNames{
HospAffProvOrgName: item.HospAffProvOrgName,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToHospitalAffiliationNamesEntitySlice(list []npdmodel.HospitalAffiliationNames) (retVal []entity.HospitalAffiliationNames) {
retVal = make([]entity.HospitalAffiliationNames, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToHospitalAffiliationNamesEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToHospitalAffiliationNamesModelSlice(list []entity.HospitalAffiliationNames) (retVal []npdmodel.HospitalAffiliationNames) {
retVal = make([]npdmodel.HospitalAffiliationNames, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToHospitalAffiliationNamesModel(item))
}
return retVal
}
func (mapping *providerMapping) ToLanguagesEntity(item npdmodel.Languages) entity.Languages {
return entity.Languages{
Code: item.Code,
}
}
func (mapping *providerMapping) ToLanguagesModel(item entity.Languages) npdmodel.Languages {
return npdmodel.Languages{
Code: item.Code,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToLanguagesEntitySlice(list []npdmodel.Languages) (retVal []entity.Languages) {
retVal = make([]entity.Languages, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToLanguagesEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToLanguagesModelSlice(list []entity.Languages) (retVal []npdmodel.Languages) {
retVal = make([]npdmodel.Languages, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToLanguagesModel(item))
}
return retVal
}
func (mapping *providerMapping) ToProviderTypeCodeEntity(item npdmodel.ProviderTypeCode) entity.ProviderTypeCode {
return entity.ProviderTypeCode{
Code: item.Code,
}
}
func (mapping *providerMapping) ToProviderTypeCodeModel(item entity.ProviderTypeCode) npdmodel.ProviderTypeCode {
return npdmodel.ProviderTypeCode{
Code: item.Code,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderTypeCodeEntitySlice(list []npdmodel.ProviderTypeCode) (retVal []entity.ProviderTypeCode) {
retVal = make([]entity.ProviderTypeCode, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderTypeCodeEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderTypeCodeModelSlice(list []entity.ProviderTypeCode) (retVal []npdmodel.ProviderTypeCode) {
retVal = make([]npdmodel.ProviderTypeCode, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderTypeCodeModel(item))
}
return retVal
}
func (mapping *providerMapping) ToPartKeyGroupEntity(item npdmodel.PartKeyGroup) entity.PartKeyGroup {
return entity.PartKeyGroup{
ProviderNum: item.ProviderNum,
ProviderNumSuffix: item.ProviderNumSuffix,
LocationSeqNum: item.LocationSeqNum,
PlanCode: item.PlanCode,
ProductID: item.ProductID,
TreatmentCategoryCode: item.TreatmentCategoryCode,
}
}
func (mapping *providerMapping) ToPartKeyGroupModel(item entity.PartKeyGroup) npdmodel.PartKeyGroup {
return npdmodel.PartKeyGroup{
ProviderNum: item.ProviderNum,
ProviderNumSuffix: item.ProviderNumSuffix,
LocationSeqNum: item.LocationSeqNum,
PlanCode: item.PlanCode,
ProductID: item.ProductID,
TreatmentCategoryCode: item.TreatmentCategoryCode,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToPartKeyGroupEntitySlice(list []npdmodel.PartKeyGroup) (retVal []entity.PartKeyGroup) {
retVal = make([]entity.PartKeyGroup, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToPartKeyGroupEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToPartKeyGroupModelSlice(list []entity.PartKeyGroup) (retVal []npdmodel.PartKeyGroup) {
retVal = make([]npdmodel.PartKeyGroup, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToPartKeyGroupModel(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderEntitySlice(list []npdmodel.ProviderResponse) (retVal []entity.ProviderResponse) {
retVal = make([]entity.ProviderResponse, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *providerMapping) ToProviderModelSlice(list []entity.ProviderResponse) (retVal []npdmodel.ProviderResponse) {
retVal = make([]npdmodel.ProviderResponse, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToProviderModel(item))
}
return retVal
}

View File

@@ -0,0 +1,254 @@
package entitymapping
import (
"time"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// rideMapping has method to map ride entities to view models
type rideMapping struct {
mapper *Mapper
}
func (mapping *rideMapping) ToRideModel(item entity.Ride) viewmodel.Ride {
return viewmodel.Ride{
User: mapping.mapper.User.ToUserModel(item.User),
Status: mapping.ToRideStatusModel(item.Status),
Type: mapping.ToRideTypeModel(item.Type),
UUID: item.UUID,
Note: item.Note,
Driver: mapping.ToDriverUserModel(item.Driver),
Passenger: mapping.ToPassengerUserModel(item.Passenger),
Vehicle: mapping.ToVehicleModel(item.Vehicle),
Route: mapping.ToRouteModel(item.Route),
PickupTime: item.PickupTime,
VisitDate: item.VisitDate,
VisitTime: item.VisitTime,
InternalID: item.InternalID,
Visit: mapping.mapper.Visit.ToVisitModel(item.Visit),
CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
CreateAt: item.Created,
UpdateAt: item.Updated,
TripType: mapping.mapper.Visit.ToTripTypeModel(item.TripType),
}
}
func (mapping *rideMapping) ToRideInternalEntity(item viewmodel.Ride) entity.Ride {
return entity.Ride{
User: mapping.mapper.User.ToUserEntity(item.User),
UUID: item.UUID,
Note: item.Note,
PickupTime: item.PickupTime,
VisitDate: item.VisitDate,
VisitTime: item.VisitTime,
InternalID: item.InternalID,
TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
}
}
func (mapping *rideMapping) ToRouteModel(item entity.RideRoute) viewmodel.RideRoute {
return viewmodel.RideRoute{
Origin: mapping.ToLocationModel(item.Origin),
Destination: mapping.ToLocationModel(item.Destination),
RouteKML: item.RouteKML,
ETA: item.ETA,
Distance: item.Distance,
Duration: item.Duration,
}
}
func (mapping *rideMapping) ToLocationModel(item entity.Location) viewmodel.Location {
return viewmodel.Location{
ID: item.ID,
Name: item.Name,
Address: item.Address,
Latitude: item.Latitude,
Longitude: item.Longitude,
}
}
func (mapping *rideMapping) ToVehicleModel(item entity.RideVehicle) viewmodel.Vehicle {
return viewmodel.Vehicle{
Color: item.Color,
Make: item.Make,
LicensePlate: item.LicensePlate,
ImageURL: item.ImageURL,
Year: item.Year,
LicensePlateState: item.LicensePlateState,
Model: item.Model,
}
}
func (mapping *rideMapping) ToDriverUserModel(item entity.RideDriver) viewmodel.UserLyft {
return viewmodel.UserLyft{
FirstName: item.Name,
ImageURL: item.ImageURL,
PhoneNumber: item.PhoneNumber,
Rating: item.Rating,
}
}
func (mapping *rideMapping) ToPassengerUserModel(item entity.RidePassenger) viewmodel.UserLyft {
return viewmodel.UserLyft{
FirstName: item.FirstName,
LastName: item.LastName,
ImageURL: item.ImageURL,
PhoneNumber: item.PhoneNumber,
UserID: item.InternalID,
}
}
func (mapping *rideMapping) ToRideStatusModel(item entity.RideStatus) viewmodel.RideStatus {
return viewmodel.RideStatus{
Value: item.Value,
Key: item.Key,
}
}
func (mapping *rideMapping) ToRideTypeModel(item entity.RideType) viewmodel.RideType {
return viewmodel.RideType{
Value: item.Value,
Key: item.Key,
}
}
func (mapping *rideMapping) ToWebhookEntity(item viewmodel.WebhookResponse) entity.WebhookResponse {
occurredAt, _ := time.Parse(time.RFC3339Nano, item.OccurredAt)
return entity.WebhookResponse{
EventID: item.EventID,
HREF: item.HREF,
OccurredAt: occurredAt,
EventType: item.EventType,
Ride: mapping.ToRideEntity(item.Event),
}
}
// ToUserModel maps a User entity to User view model
func (mapping *rideMapping) ToRideEntity(item viewmodel.RideRequest) entity.Ride {
return entity.Ride{
User: entity.User{
UUID: item.UserUUID,
},
Status: mapping.ToRideStatusEntity(item),
Type: mapping.ToRideTypeEntity(item),
InternalID: item.RideID,
RequestDate: item.RequestAt,
RequestMiliseconds: item.RequestAtMS,
GenerateDate: item.GeneratedAt,
GenerateMiliseconds: item.GeneratedAtMS,
Note: item.Notes,
PrimetimePercentage: item.PrimetimePercentage,
Passenger: mapping.ToRidePassengerEntity(item),
Driver: mapping.ToRideDriverEntity(item),
Vehicle: mapping.ToRideVehicleEntity(item),
Route: mapping.ToRideRouteEntity(item),
PickupTime: item.PickupTime,
VisitDate: item.VisitDate,
VisitTime: item.VisitTime,
Visit: mapping.mapper.Visit.ToVisitEntity(item.Visit),
TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
CreatedUser: entity.User{
UUID: item.CreateUserUUID,
},
}
}
func (mapping *rideMapping) ToRideRouteEntity(item viewmodel.RideRequest) entity.RideRoute {
return entity.RideRoute{
Origin: mapping.ToLocationEntity(item.Origin),
Destination: mapping.ToLocationEntity(item.Destination),
RouteKML: &item.RouteURL,
ETA: item.ETA,
Distance: item.Distance,
Duration: item.Duration,
}
}
func (mapping *rideMapping) ToLocationEntity(item viewmodel.Location) entity.Location {
return entity.Location{
ID: item.ID,
Name: item.Name,
Address: item.Address,
Latitude: item.Latitude,
Longitude: item.Longitude,
}
}
func (mapping *rideMapping) ToRideVehicleEntity(item viewmodel.RideRequest) entity.RideVehicle {
return entity.RideVehicle{
Color: item.Vehicle.Color,
Make: item.Vehicle.Make,
LicensePlate: item.Vehicle.LicensePlate,
LicensePlateState: item.Vehicle.LicensePlateState,
ImageURL: item.Vehicle.ImageURL,
Model: item.Vehicle.Model,
Year: item.Vehicle.Year,
}
}
func (mapping *rideMapping) ToRideDriverEntity(item viewmodel.RideRequest) entity.RideDriver {
return entity.RideDriver{
Name: item.Driver.FirstName,
ImageURL: item.Driver.ImageURL,
PhoneNumber: item.Driver.PhoneNumber,
Rating: item.Driver.Rating,
}
}
func (mapping *rideMapping) ToRidePassengerEntity(item viewmodel.RideRequest) entity.RidePassenger {
return entity.RidePassenger{
FirstName: item.Passenger.FirstName,
LastName: item.Passenger.LastName,
ImageURL: item.Passenger.ImageURL,
PhoneNumber: item.Passenger.PhoneNumber,
InternalID: item.Passenger.UserID,
}
}
func (mapping *rideMapping) ToRideStatusEntity(item viewmodel.RideRequest) entity.RideStatus {
return entity.RideStatus{
Key: item.Status,
}
}
func (mapping *rideMapping) ToRideTypeEntity(item viewmodel.RideRequest) entity.RideType {
return entity.RideType{
Key: item.RideType,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *rideMapping) ToRideEntitySlice(list []viewmodel.RideRequest) (retVal []entity.Ride) {
retVal = make([]entity.Ride, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToRideEntity(item))
}
return retVal
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *rideMapping) ToRideInternalEntitySlice(list []viewmodel.Ride) (retVal []entity.Ride) {
retVal = make([]entity.Ride, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToRideInternalEntity(item))
}
return retVal
}
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
func (mapping *rideMapping) ToRideModelSlice(list []entity.Ride) (retVal []viewmodel.Ride) {
retVal = make([]viewmodel.Ride, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToRideModel(item))
}
return retVal
}

View File

@@ -0,0 +1,194 @@
package entitymapping
import (
"fmt"
"strings"
"time"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// userMapping has method to map User entities to view models
type userMapping struct {
mapper *Mapper
}
// ToUserModel maps a User entity to User view model
func (mapping *userMapping) ToUserModel(item entity.User) viewmodel.User {
var birthDate *time.Time
if !item.BirthDate.IsZero() {
birthDate = &item.BirthDate
}
first := ""
last := ""
fullName := strings.Split(item.Name, " ")
if len(fullName) > 0 {
first = fullName[0]
if len(fullName) > 1 {
last = fullName[len(fullName)-1]
}
}
return viewmodel.User{
ID: item.UUID,
Name: item.Name,
First: first,
Last: last,
Email: &item.Email,
PhoneNumber: &item.PhoneNumber,
Gender: &item.Gender,
Member: &item.Member,
BirthDate: birthDate,
Active: item.Active,
Created: item.Created,
Updated: item.Updated,
Contacts: mapping.ToContactModelSlice(item.Contacts),
Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
Addresses: mapping.mapper.Address.ToAddressModelSlice(item.Addresses),
Profiles: mapping.mapper.Profile.ToProfileModelSlice(item.Profiles),
Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
}
}
// ToUserModelSlice maps a User entity slice to User view model slice
func (mapping *userMapping) ToUserModelSlice(list []entity.User) (retVal []viewmodel.User) {
retVal = make([]viewmodel.User, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToUserModel(item))
}
return retVal
}
// ToUserModel maps a User entity to User view model
func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
user := entity.User{
UUID: item.ID,
Name: item.Name,
Pass: item.Pass,
Active: item.Active,
Created: item.Created,
Updated: item.Updated,
Contacts: mapping.ToContactEntitySlice(item.Contacts),
Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
}
if user.Name == "" {
user.Name = fmt.Sprintf("%s %s", item.First, item.Last)
}
if item.Email != nil {
user.Email = *item.Email
}
if item.PhoneNumber != nil {
user.PhoneNumber = *item.PhoneNumber
}
if item.Gender != nil {
user.Gender = *item.Gender
}
if item.Member != nil {
user.Member = *item.Member
}
if item.BirthDate != nil {
user.BirthDate = *item.BirthDate
}
return user
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *userMapping) ToUserEntitySlice(list []viewmodel.User) (retVal []entity.User) {
retVal = make([]entity.User, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToUserEntity(item))
}
return retVal
}
// ToContactTypeEntity maps a Contact type entity to Contact Type view model
func (mapping *userMapping) ToContactTypeEntity(item viewmodel.ContactType) entity.ContactType {
return entity.ContactType{
Key: item.Key,
Value: item.Value,
}
}
// ToContactTypeEntitySlice maps a User entity slice to Contact Type view model slice
func (mapping *userMapping) ToContactTypeEntitySlice(list []viewmodel.ContactType) (retVal []entity.ContactType) {
retVal = make([]entity.ContactType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToContactTypeEntity(item))
}
return retVal
}
// ToContactTypeModel maps a Contact type entity to Contact Type view model
func (mapping *userMapping) ToContactTypeModel(item entity.ContactType) viewmodel.ContactType {
return viewmodel.ContactType{
Key: item.Key,
Value: item.Value,
}
}
// ToContactTypeModelSlice maps a User entity slice to Contact Type view model slice
func (mapping *userMapping) ToContactTypeModelSlice(list []entity.ContactType) (retVal []viewmodel.ContactType) {
retVal = make([]viewmodel.ContactType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToContactTypeModel(item))
}
return retVal
}
// ToContactModel maps a Contact entity to Contact view model
func (mapping *userMapping) ToContactModel(item entity.ContactInfo) viewmodel.Contact {
return viewmodel.Contact{
Type: mapping.ToContactTypeModel(item.Type),
Value: item.Value,
}
}
// ToContactModelSlice maps a Contact entity slice to Contact view model slice
func (mapping *userMapping) ToContactModelSlice(list []entity.ContactInfo) (retVal []viewmodel.Contact) {
retVal = make([]viewmodel.Contact, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToContactModel(item))
}
return retVal
}
// ToContactEntity maps a Contact entity to Contact view model
func (mapping *userMapping) ToContactEntity(item viewmodel.Contact) entity.ContactInfo {
return entity.ContactInfo{
Type: mapping.ToContactTypeEntity(item.Type),
Value: item.Value,
}
}
// ToContactEntitySlice maps a Contact entity slice to Contact view model slice
func (mapping *userMapping) ToContactEntitySlice(list []viewmodel.Contact) (retVal []entity.ContactInfo) {
retVal = make([]entity.ContactInfo, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToContactEntity(item))
}
return retVal
}

View File

@@ -0,0 +1,131 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// rideMapping has method to map ride entities to view models
type visitMapping struct {
mapper *Mapper
}
// ToVisitEntity maps a User entity to User view model
func (mapping *visitMapping) ToVisitEntity(item viewmodel.Visit) entity.Visit {
return entity.Visit{
UUID: item.UUID,
Status: mapping.ToVisitStatusEntity(item.Status),
User: mapping.mapper.User.ToUserEntity(item.User),
VisitDuration: item.VisitDuration,
VisitDatetime: item.VisitDatetime,
PickupDatetime: item.PickupDatetime,
Notes: item.Notes,
PickupAddressID: item.PickupAddressID,
DestinationAddressID: item.DestinationAddressID,
Pickup: mapping.mapper.Ride.ToLocationEntity(item.Pickup),
Provider: mapping.mapper.Provider.ToProviderRespEntity(item.Provider),
CreatedUser: mapping.mapper.User.ToUserEntity(item.CreatedUser),
Created: item.CreatedDate,
Updated: item.UpdatedDate,
ReturnDate: item.ReturnDate,
ExternalID: item.ExternalID,
TripType: mapping.ToTripTypeEntity(item.TripType),
Rides: mapping.mapper.Ride.ToRideInternalEntitySlice(item.Rides),
}
}
func (mapping *visitMapping) ToVisitStatusEntity(item viewmodel.VisitStatus) entity.VisitStatus {
return entity.VisitStatus{
Value: item.Value,
Key: item.Key,
}
}
// ToVisitEntity maps a User entity to User view model
func (mapping *visitMapping) ToVisitModel(item entity.Visit) viewmodel.Visit {
return viewmodel.Visit{
UUID: item.UUID,
Status: mapping.ToVisitStatusModel(item.Status),
User: mapping.mapper.User.ToUserModel(item.User),
VisitDuration: item.VisitDuration,
VisitDatetime: item.VisitDatetime,
PickupDatetime: item.PickupDatetime,
Notes: item.Notes,
PickupAddressID: item.PickupAddressID,
DestinationAddressID: item.DestinationAddressID,
Pickup: mapping.mapper.Ride.ToLocationModel(item.Pickup),
Provider: mapping.mapper.Provider.ToProviderRespModel(item.Provider),
CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
CreatedDate: item.Created,
UpdatedDate: item.Updated,
ReturnDate: item.ReturnDate,
ExternalID: item.ExternalID,
TripType: mapping.ToTripTypeModel(item.TripType),
Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
}
}
func (mapping *visitMapping) ToVisitStatusModel(item entity.VisitStatus) viewmodel.VisitStatus {
return viewmodel.VisitStatus{
Value: item.Value,
Key: item.Key,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *visitMapping) ToVisitEntitySlice(list []viewmodel.Visit) (retVal []entity.Visit) {
retVal = make([]entity.Visit, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToVisitEntity(item))
}
return retVal
}
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
func (mapping *visitMapping) ToVisitModelSlice(list []entity.Visit) (retVal []viewmodel.Visit) {
retVal = make([]viewmodel.Visit, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToVisitModel(item))
}
return retVal
}
func (mapping *visitMapping) ToTripTypeModel(item entity.TripType) viewmodel.TripType {
return viewmodel.TripType{
Value: item.Value,
Key: item.Key,
}
}
func (mapping *visitMapping) ToTripTypeEntity(item viewmodel.TripType) entity.TripType {
return entity.TripType{
Value: item.Value,
Key: item.Key,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *visitMapping) ToTripTypeEntitySlice(list []viewmodel.TripType) (retVal []entity.TripType) {
retVal = make([]entity.TripType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToTripTypeEntity(item))
}
return retVal
}
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
func (mapping *visitMapping) ToTripTypeModelSlice(list []entity.TripType) (retVal []viewmodel.TripType) {
retVal = make([]viewmodel.TripType, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToTripTypeModel(item))
}
return retVal
}

View File

@@ -0,0 +1,31 @@
package notificationservice
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
Twilio *twilioService
}
// New returns a new domain Service instance
func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *Service {
once.Do(func() {
instance = &Service{
Twilio: newTwilioService(svc, mapper, cfg, cache),
}
})
return instance
}

View File

@@ -0,0 +1,259 @@
package notificationservice
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain"
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
const (
twilioMessageURL = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json"
twilioNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/AvailablePhoneNumbers/US/Local.json"
twiliActualNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/IncomingPhoneNumbers.json"
)
// twilioService holds methods to twillio application service
type twilioService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
cfg *config.Config
urlMessage string
urlNumber string
urlActualNumber string
cache contract.CacheManager
}
// newTwilioService returns a twilioService instance
func newTwilioService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *twilioService {
return &twilioService{
svc: svc,
mapEntity: mapper,
cfg: cfg,
urlMessage: fmt.Sprintf(twilioMessageURL, cfg.Twilio.Account),
urlNumber: fmt.Sprintf(twilioNumbersURL, cfg.Twilio.Account),
urlActualNumber: fmt.Sprintf(twiliActualNumbersURL, cfg.Twilio.Account),
cache: cache,
}
}
func (s twilioService) GetProxyNumber(to string) (viewmodel.ProxyNumber, error) {
key := "proxy" + to
var number viewmodel.ProxyNumber
err := s.cache.GetStruct(key, &number)
if err != nil || err == domain.ErrCacheMiss {
return number, err
} else {
return number, nil
}
}
func (s twilioService) GetAvaliableNumbers(to string) (viewmodel.ListNumbers, error) {
if to != "" {
if strings.Contains(to, "+1") {
to = strings.Replace(to, "+1", "", -1)
}
area := to[0:3]
msgData := url.Values{}
msgData.Set("PhoneNumber", area)
client := &http.Client{}
req, _ := http.NewRequest("GET", s.urlActualNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Twilio: ", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
var data viewmodel.ListNumbers
decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(&data)
if err != nil {
return viewmodel.ListNumbers{}, err
}
return data, nil
} else {
return viewmodel.ListNumbers{}, errors.New(resp.Status)
}
}
return viewmodel.ListNumbers{}, nil
}
func (s twilioService) GetAvaliableNewNumbers(to string) (viewmodel.ListNumbers, error) {
if to != "" {
if strings.Contains(to, "+1") {
to = strings.Replace(to, "+1", "", -1)
}
area := to[0:3]
msgData := url.Values{}
msgData.Set("AreaCode", area)
client := &http.Client{}
req, _ := http.NewRequest("GET", s.urlNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Twilio: ", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
var data viewmodel.ListNumbers
decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(&data)
if err != nil {
return viewmodel.ListNumbers{}, err
}
return data, nil
} else {
return viewmodel.ListNumbers{}, errors.New(resp.Status)
}
}
return viewmodel.ListNumbers{}, nil
}
func (s twilioService) SaveNewNumber(number viewmodel.Number) (viewmodel.Number, error) {
phoneNumber := number.PhoneNumber
if strings.Contains(phoneNumber, "+1") {
phoneNumber = strings.Replace(phoneNumber, "+1", "", -1)
}
area := phoneNumber[0:3]
msgData := url.Values{}
msgData.Set("PhoneNumber", number.PhoneNumber)
msgData.Set("AreaCode", area)
msgData.Set("FriendlyName", number.FriendlyName)
msgData.Set("SmsApplicationSid", s.cfg.Twilio.TwiMLSID)
msgDataReader := *strings.NewReader(msgData.Encode())
client := &http.Client{}
req, _ := http.NewRequest("POST", s.urlActualNumber, &msgDataReader)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Twilio: ", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(&number)
if err != nil {
return viewmodel.Number{}, err
}
return number, nil
} else {
return viewmodel.Number{}, errors.New(resp.Status)
}
}
func (s twilioService) GetValidNumber(from string, to string) (viewmodel.Number, error) {
list, err := s.GetAvaliableNumbers(to)
if err != nil {
return viewmodel.Number{}, err
}
if len(list.IncomingPhones) > 0 {
return list.IncomingPhones[0], nil
}
list, err = s.GetAvaliableNewNumbers(to)
if err != nil {
return viewmodel.Number{}, err
}
if len(list.AvailableNumbers) > 0 {
number, err := s.SaveNewNumber(list.AvailableNumbers[0])
if err != nil {
fmt.Println("Error on GetValidNumber: ", err.Error())
return viewmodel.Number{}, err
}
return number, nil
} else {
return viewmodel.Number{}, errors.New("No new number available")
}
}
func (s twilioService) GetNumber(from string, to string) (string, error) {
number, err := s.GetValidNumber(from, to)
if err != nil {
return from, err
}
return number.PhoneNumber, nil
}
func (s twilioService) SendSMS(from string, to string, message string) error {
if from == "" {
return errors.New("TwilioService.SendSMS: from parameter is mandatory")
}
if to == "" {
return errors.New("TwilioService.SendSMS: to parameter is mandatory")
}
if message == "" {
return errors.New("TwilioService.SendSMS: message parameter is mandatory")
}
senderNumber, err := s.GetNumber(from, to)
if err != nil {
return err
}
msgData := url.Values{}
msgData.Set("To", to)
msgData.Set("From", senderNumber)
msgData.Set("Body", message)
msgDataReader := *strings.NewReader(msgData.Encode())
client := &http.Client{}
req, _ := http.NewRequest("POST", s.urlMessage, &msgDataReader)
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Twilio: ", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
var data map[string]interface{}
decoder := json.NewDecoder(resp.Body)
err := decoder.Decode(&data)
if err != nil {
return err
}
} else {
fmt.Println("Error on Twilio Response: ", resp.Status)
return errors.New(resp.Status)
}
return nil
}

View File

@@ -0,0 +1,28 @@
package bcbsi
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
BXE *bxeService
}
// New returns a new domain Service instance
func New(cfg *config.Config) *Service {
once.Do(func() {
instance = &Service{
BXE: newBXEService(cfg),
}
})
return instance
}

View File

@@ -0,0 +1,150 @@
package bcbsimodel
import (
"encoding/xml"
"time"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func GetEnvelope(eligibility viewmodel.Eligibility) Envelope {
soapEnvelope := Envelope{}
soapEnvelope.Namespace = "http://schemas.xmlsoap.org/soap/envelope/"
soapEnvelope.Body.MemberEligibilityRequest = GetEligibilityRequest(eligibility)
soapEnvelope.Body.MemberEligibilityRequest.Namespace = "http://v30.bx.services.bcbsa.com/eligibility-ext"
return soapEnvelope
}
func GetEligibilityRequest(eligibility viewmodel.Eligibility) MemberEligibilityRequest {
retVal := MemberEligibilityRequest{}
retVal.Version.MajorVersion = 3
retVal.Version.MinorVersion = 0
retVal.QueryHeader.TimeSent = time.Now().Format("2006-01-02T15:04:05")
retVal.QueryHeader.TrackingID = eligibility.TrackingID
retVal.Query.PayerInfo.PayerID = eligibility.Payer.PayerID
retVal.Query.PayerInfo.PayerName = eligibility.Payer.PayerName
retVal.Query.ProviderInfo.ProviderID = eligibility.Provider.ProviderID
retVal.Query.ProviderInfo.ProviderNPI = eligibility.Provider.ProviderNPI
retVal.Query.ProviderInfo.Provider.Organization = eligibility.Provider.ProviderName
retVal.Query.ProviderInfo.Provider.Name.First = eligibility.Provider.Name.First
retVal.Query.ProviderInfo.Provider.Name.Last = eligibility.Provider.Name.Last
retVal.Query.ProviderInfo.Provider.Name.Middle = eligibility.Provider.Name.Middle
retVal.Query.SubscriberInfo.SubscriberID = eligibility.Subscriber.SubscriberID
retVal.Query.SubscriberInfo.PatientType = eligibility.Subscriber.PatientType
retVal.Query.SubscriberInfo.Name.First = eligibility.Subscriber.Name.First
retVal.Query.SubscriberInfo.Name.Last = eligibility.Subscriber.Name.Last
retVal.Query.SubscriberInfo.Name.Middle = eligibility.Subscriber.Name.Middle
retVal.Query.SubscriberInfo.DemographicInfo.DateOfBirth = eligibility.Subscriber.DemographicInfo.DateOfBirth.Format("20060102")
retVal.Query.SubscriberInfo.DemographicInfo.GenderCode = eligibility.Subscriber.DemographicInfo.Gender
var dependents []Dependent
for _, d := range eligibility.Subscriber.Dependents {
dependent := Dependent{}
dependent.PatientAccountNumber = d.PatientAccountNumber
dependent.DemographicInfo.DateOfBirth = d.DemographicInfo.DateOfBirth.Format("20060102")
dependent.DemographicInfo.GenderCode = d.DemographicInfo.Gender
dependent.Name.First = d.Name.First
dependent.Name.Last = d.Name.Last
dependent.Name.Middle = d.Name.Middle
dependents = append(dependents, dependent)
}
if len(dependents) == 0 {
dependents = append(dependents, Dependent{})
}
retVal.Query.SubscriberInfo.DependentInfo.Dependents = dependents
retVal.Query.ServiceInfo.DateOfService = eligibility.ServiceInfo.DateOfService.Format("20060102")
retVal.Query.ServiceInfo.ServiceTypeCodes.ServiceTypeCode = eligibility.ServiceInfo.ServiceTypeCodes
return retVal
}
type Envelope struct {
XMLName xml.Name `xml:"soap:Envelope"`
Body EnvelopeBody `xml:"soap:Body"`
Namespace string `xml:"xmlns:soap,attr"`
}
type EnvelopeBody struct {
MemberEligibilityRequest MemberEligibilityRequest `xml:"elig:MemberEligibilityRequest"`
}
type MemberEligibilityRequest struct {
Version Version `xml:"version"`
QueryHeader QueryHeader `xml:"elig:eligibility-benefits-query-header"`
Query Query `xml:"elig:eligibility-benefits-query"`
Namespace string `xml:"xmlns:elig,attr"`
}
type Version struct {
MajorVersion int64 `xml:"majorVersion"`
MinorVersion int64 `xml:"minorVersion"`
}
type QueryHeader struct {
TrackingID string `xml:"tracking-id"`
TimeSent string `xml:"time-sent"`
}
type Query struct {
PayerInfo PayerInfo `xml:"elig:payer-info"`
ProviderInfo ProviderInfo `xml:"elig:provider-info"`
SubscriberInfo SubscriberInfo `xml:"elig:subscriber-info"`
ServiceInfo ServiceInfo `xml:"elig:service-info"`
}
type ServiceInfo struct {
DateOfService string `xml:"elig:date-of-service"`
ServiceTypeCodes ServiceTypeCodes `xml:"elig:service-type-codes"`
}
type ServiceTypeCodes struct {
ServiceTypeCode []string `xml:"elig:service-type-code"`
}
type SubscriberInfo struct {
PatientType string `xml:"elig:patient-type"`
SubscriberID string `xml:"elig:subscriber-id"`
Name Name `xml:"elig:name"`
DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
DependentInfo DependentInfo `xml:"elig:dependent-info"`
}
type DependentInfo struct {
Dependents []Dependent `xml:"elig:dependent"`
}
type Dependent struct {
PatientAccountNumber string `xml:"elig:patient-account-number"`
Name Name `xml:"elig:name"`
DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
}
type DemographicInfo struct {
DateOfBirth string `xml:"elig:date-of-birth"`
GenderCode string `xml:"elig:gender-code"`
}
type ProviderInfo struct {
ProviderID string `xml:"elig:provider-id"`
ProviderNPI string `xml:"elig:provider-npi"`
Provider Provider `xml:"elig:provider-name"`
}
type Provider struct {
Organization string `xml:"organization"`
Name Name `xml:"elig:name"`
}
type Name struct {
First string `xml:"elig:first"`
Last string `xml:"elig:last"`
Middle string `xml:"elig:middle"`
}
type PayerInfo struct {
PayerName string `xml:"elig:payer-name"`
PayerID string `xml:"elig:payer-id"`
}

View File

@@ -0,0 +1,44 @@
package bcbsimodel
import (
"encoding/xml"
)
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Body EnvelopeBodyResponse `xml:"Body"`
}
type EnvelopeBodyResponse struct {
MemberEligibilityResponse MemberEligibilityResponse `xml:"MemberEligibilityResponse"`
}
type MemberEligibilityResponse struct {
Version Version `xml:"version" json:"-"`
QueryResult QueryResult `xml:"eligibility-benefits-query-results" json:"results"`
}
type QueryResult struct {
HIPPA271 HIPAA271 `xml:"vcml-271" json:"raw"`
QueryResultSummary QueryResultSummary `xml:"query-result-summary" json:"summary"`
}
type HIPAA271 struct {
T271 string `xml:"t271" json:"t271"`
}
type QueryResultSummary struct {
BenefitsFound bool `xml:"benefits-found" json:"benefits_found"`
ProcessingInfo ProcessingInfo `xml:"processing-info" json:"-"`
}
type ProcessingInfo struct {
Message string `xml:"message" json:"-"`
}
type EntityResponse struct {
EntityID int64 `json:"entity_id"`
ID string `json:"id"`
Name string `json:"name"`
Status bool `json:"status"`
}

View File

@@ -0,0 +1,126 @@
package bcbsi
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/pquerna/ffjson/ffjson"
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi/bcbsimodel"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
type bxeService struct {
cfg *config.Config
}
func newBXEService(cfg *config.Config) *bxeService {
return &bxeService{
cfg: cfg,
}
}
func (s bxeService) getSignature(APIKey string, secretKey string) string {
rawKey := fmt.Sprintf("%s%s%v", APIKey, secretKey, time.Now().Unix())
hasher := md5.New()
hasher.Write([]byte(rawKey))
key := hex.EncodeToString(hasher.Sum(nil))
return strings.ToLower(key)
}
func (s bxeService) GetPayerDetails(subscriberID string) ([]bcbsimodel.EntityResponse, error) {
apiKey := s.cfg.Blue365.APIKey
secretKey := s.cfg.Blue365.Secret
URL := s.cfg.Blue365.URL
prefix := subscriberID[:3]
client := &http.Client{}
req, _ := http.NewRequest("GET", URL+"/"+prefix, bytes.NewBuffer([]byte{}))
req.Header.Add("X-Api-Key", apiKey)
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
defer resp.Body.Close()
bReturn, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
var response []bcbsimodel.EntityResponse
err = ffjson.Unmarshal(bReturn, &response)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
return response, nil
}
func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimodel.MemberEligibilityResponse, error) {
payer, err := s.GetPayerDetails(eligibility.Subscriber.SubscriberID)
if err != nil {
return bcbsimodel.MemberEligibilityResponse{}, err
}
eligibility.Payer.PayerID = payer[0].ID
eligibility.Payer.PayerName = payer[0].Name
envelope := bcbsimodel.GetEnvelope(eligibility)
apiKey := s.cfg.BXE.APIKey
secretKey := s.cfg.BXE.Secret
bObj, err := xml.Marshal(envelope)
if err != nil {
return bcbsimodel.MemberEligibilityResponse{}, err
}
client := &http.Client{}
req, _ := http.NewRequest("POST", s.cfg.BXE.URL, bytes.NewBuffer(bObj))
req.Header.Add("Soapaction", "CheckEligibility")
req.Header.Add("Content-Type", "text/xml")
req.Header.Add("X-Api-Key", apiKey)
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
defer resp.Body.Close()
bReturn, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
sResponse := string(bReturn)
sResponse = strings.Replace(sResponse, "soapenv:Envelope", "Envelope", -1)
sResponse = strings.Replace(sResponse, "soapenv:Body", "Body", -1)
sResponse = strings.Replace(sResponse, "ns2:", "", -1)
var result bcbsimodel.EnvelopeResponse
err = xml.Unmarshal([]byte(sResponse), &result)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
return result.Body.MemberEligibilityResponse, nil
}

View File

@@ -0,0 +1,28 @@
package npd
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
Provider *providerService
}
// New returns a new domain Service instance
func New(cfg *config.Config) *Service {
once.Do(func() {
instance = &Service{
Provider: newProviderService(cfg),
}
})
return instance
}

View File

@@ -0,0 +1,124 @@
package npdmodel
type ProviderHeaderResponse struct {
ResultStatus string `json:"resultStatus"`
Count CountResponse `json:"counts"`
Providers []ProviderResponse `json:"providers"`
FacetFields []FacetField `json:"facetEntries"`
}
type CountResponse struct {
Total string `json:"total"`
Groups string `json:"groups"`
}
type FacetField struct {
Name string `json:"name"`
FacetEntries []map[string]string `json:"facetEntries"`
}
type ProviderResponse struct {
MukID string `json:"mukId"`
FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
OrgName string `json:"orgName"`
Gender string `json:"gender"`
AcceptNewPatients string `json:"acceptNewPatients"`
ProviderName string `json:"providerName"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
MiddleName string `json:"middleName"`
ProviderTitle string `json:"providerTitle"`
StreetName1 string `json:"streetName_1"`
StreetName2 string `json:"streetName_2"`
CityName string `json:"cityName"`
State string `json:"state"`
ZipCode string `json:"zipCode"`
Country string `json:"country"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
PhoneNumber string `json:"phoneNumber"`
ProviderEntityName string `json:"providerEntityName"`
ProviderEntityCode string `json:"providerEntityCode"`
ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
Distance string `json:"distance"`
AvailabilityOfCost string `json:"availabilityOfCost"`
TDDPhoneNumber string `json:"tddPhoneNumber"`
ExtendedOfficeHours string `json:"extendedOfficeHours"`
ProviderCountyCode string `json:"providerCountyCode"`
ProviderCountyName string `json:"providerCountyName"`
HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
ProviderAffiliationName string `json:"providerAffiliationName"`
LanguagesSpoken []Languages `json:"languagesSpoken"`
OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
MedSchool string `json:"medSchool"`
MedSchoolYear string `json:"medSchoolYear"`
Internship string `json:"internship"`
Residence string `json:"residency"`
Specialty1 string `json:"specialty1"`
Specialty2 string `json:"specialty2"`
Specialty3 string `json:"specialty3"`
Specialty4 string `json:"specialty4"`
Certification1 string `json:"certification1"`
Certification2 string `json:"certification2"`
Certification3 string `json:"certification3"`
Certification4 string `json:"certification4"`
}
type HospitalAffiliationNames struct {
HospAffProvOrgName string `json:"hospAffProvOrgName"`
}
type Languages struct {
Code string `json:"code"`
}
type ProviderTypeCode struct {
Code string `json:"code"`
}
type PartKeyGroup struct {
ProviderNum string `json:"providerNum"`
ProviderNumSuffix string `json:"providerNumSuffix"`
LocationSeqNum string `json:"locationSeqNum"`
PlanCode string `json:"planCode"`
ProductID string `json:"productId"`
TreatmentCategoryCode string `json:"treatmentCategoryCode"`
}
// ProviderSearchParams entity data
type ProviderSearchParams struct {
Name string
AlphaPrefix string
SearchBy string
Specialty string
Languages string
OfficeLanguages string
Gender string
AcceptNewPatients string
TreatmentCategoryCode string
SummaryScore string
AvailabilityOfCost string
AvailabilityOfQuality string
ExtendedOfficeHours string
HospitalAffiliation string
ProviderAffiliation string
ProviderEntityName string
NameRange string
BluPhyRcgIndicator string
Latitude float64
Longitude float64
Distance int64
Offset int64
Limit int64
SortBy string
FacetAcceptNewPatients string
FacetGender string
FacetExtendedOfficeHours string
FacetProviderEntityName string
FacetSummaryScore string
FacetLanguage string
FacetOfficeLanguages string
FacetHospitalAffiliations string
FacetProviderAffiliations string
}

View File

@@ -0,0 +1,56 @@
package npd
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"github.com/pquerna/ffjson/ffjson"
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
type providerService struct {
cfg *config.Config
}
func newProviderService(cfg *config.Config) *providerService {
return &providerService{
cfg: cfg,
}
}
func (c *providerService) GetProviders(searchParams npdmodel.ProviderSearchParams) (npdmodel.ProviderHeaderResponse, error) {
providerURL := "https://api-pve.bcbs.com/Providers/V30%s"
params := "?name=%s&alphaPrefix=BCB&lat=%v&long=%v&distance=%v&offset=%v&limit=%v&sortBy=%s&facetAcceptNewPatients=%s&facetGender=%s&facetExtendedOfficeHours=%s&facetProviderEntityName=%s&facetSummaryScore=%s&facetlanguage=%s&facetOfficelanguages=%s&facetHospitalAffiliations=%s&facetProviderAffiliations=%s"
params = fmt.Sprintf(params, url.QueryEscape(searchParams.Name), searchParams.Latitude, searchParams.Longitude, searchParams.Distance, searchParams.Offset, searchParams.Limit, url.QueryEscape(searchParams.SortBy), url.QueryEscape(searchParams.FacetAcceptNewPatients), url.QueryEscape(searchParams.FacetGender), url.QueryEscape(searchParams.FacetExtendedOfficeHours), url.QueryEscape(searchParams.FacetProviderEntityName), url.QueryEscape(searchParams.FacetSummaryScore), url.QueryEscape(searchParams.FacetLanguage), url.QueryEscape(searchParams.FacetOfficeLanguages), url.QueryEscape(searchParams.FacetHospitalAffiliations), url.QueryEscape(searchParams.FacetProviderAffiliations))
providerURL = fmt.Sprintf(providerURL, params)
req, err := http.NewRequest("GET", providerURL, nil)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
req.Header.Add("X-Api-Key", "sv6fs4dyh8macvuyyzgqs45w")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
defer resp.Body.Close()
bObject, err := ioutil.ReadAll(resp.Body)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
var providers npdmodel.ProviderHeaderResponse
if err := ffjson.Unmarshal(bObject, &providers); err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
return providers, nil
}

View File

@@ -0,0 +1,305 @@
package tncservice
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net/http"
"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/lyft/lyft-go-sdk/lyft"
"github.com/pquerna/ffjson/ffjson"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
)
const (
lyftURL = "https://api.lyft.com/v1/"
)
// lyftService holds methods to lyft application service
type lyftService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
client *lyft.APIClient
httpClient *http.Client
cfg *config.Config
notification *notificationservice.Service
lyftConfig clientcredentials.Config
refreshToken string
}
// newLyftProdService returns a lyftService instance with production info
func newLyftProdService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
config := clientcredentials.Config{
ClientID: cfg.LyftProd.Lyft.Client,
ClientSecret: cfg.LyftProd.Lyft.Secret,
TokenURL: "https://api.lyft.com/oauth/token",
Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
}
httpClient := config.Client(context.Background())
return &lyftService{
svc: svc,
mapEntity: mapper,
client: lyft.NewAPIClient(httpClient, "nemt"),
httpClient: httpClient,
cfg: cfg,
notification: notificationService,
lyftConfig: config,
refreshToken: cfg.LyftProd.Lyft.RefreshToken,
}
}
// newLyftService returns a lyftService instance
func newLyftService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
config := clientcredentials.Config{
ClientID: cfg.Lyft.Client,
ClientSecret: cfg.Lyft.Secret,
TokenURL: "https://api.lyft.com/oauth/token",
Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
}
httpClient := config.Client(context.Background())
return &lyftService{
svc: svc,
mapEntity: mapper,
client: lyft.NewAPIClient(httpClient, "nemt"),
httpClient: httpClient,
cfg: cfg,
notification: notificationService,
lyftConfig: config,
refreshToken: cfg.Lyft.RefreshToken,
}
}
func (s *lyftService) getToken() string {
token, err := s.lyftConfig.Token(context.Background())
if err != nil {
fmt.Println("Error to get token: ", err)
return ""
}
return "Bearer " + token.AccessToken
}
func (s *lyftService) setTokenHeader(req *http.Request) string {
type Token struct {
GrantType string `json:"grant_type"`
RefreshToken string `json:"refresh_token"`
}
token := Token{
GrantType: "refresh_token",
RefreshToken: s.refreshToken,
}
bObject, err := ffjson.Marshal(token)
if err != nil {
return ""
}
tokenReq, err := http.NewRequest("POST", s.lyftConfig.TokenURL, bytes.NewBuffer(bObject))
if err != nil {
return ""
}
tokenReq.Header.Set("Content-Type", "application/json")
tokenReq.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", s.lyftConfig.ClientID, s.lyftConfig.ClientSecret))))
tokenReq.Header.Add("cache-control", "no-cache")
resp, err := http.DefaultClient.Do(tokenReq)
if err != nil {
fmt.Println("Error to refresh token: ", err.Error())
return ""
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var returnToken oauth2.Token
err = ffjson.Unmarshal(body, &returnToken)
if err != nil {
fmt.Println("Error to parse token: ", err.Error())
return ""
}
returnToken.SetAuthHeader(req)
return "Bearer " + returnToken.AccessToken
}
func (s *lyftService) GetRideDetails(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
url := lyftURL + "dispatches/" + rideRequest.RideID
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return viewmodel.RideRequest{}, err
}
s.setTokenHeader(req)
req.Header.Add("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return viewmodel.RideRequest{}, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var raw viewmodel.RideRequest
err = ffjson.Unmarshal(body, &raw)
if err != nil {
return viewmodel.RideRequest{}, err
}
return raw, nil
}
func (s *lyftService) GetRideStatus(rideRequest viewmodel.RideRequest, param string) (viewmodel.RideRequest, error) {
params := make(map[string]string)
params["status"] = param
bObject, err := ffjson.Marshal(params)
if err != nil {
return viewmodel.RideRequest{}, err
}
fmt.Println("STATUS CHANGE REQUEST ON LYFT")
fmt.Println("Ride ID: ", rideRequest.RideID)
fmt.Println("Status: ", param)
url := lyftURL + "sandbox/dispatches/" + rideRequest.RideID
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(bObject))
if err != nil {
return viewmodel.RideRequest{}, err
}
req.Header.Add("Content-Type", "application/json")
resp, err := s.httpClient.Do(req)
if err != nil {
return viewmodel.RideRequest{}, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("STATUS CHANGE RESPONSE ON LYFT")
fmt.Println(string(body))
var raw viewmodel.RideRequest
err = ffjson.Unmarshal(body, &raw)
if err != nil {
return viewmodel.RideRequest{}, err
}
rideRequest.Status = raw.Status
return s.GetRideDetails(rideRequest)
}
func (s *lyftService) CancelRide(rideRequest viewmodel.RideRequest) error {
finalURL := lyftURL + "dispatches/" + rideRequest.RideID + "/cancel"
req, err := http.NewRequest("POST", finalURL, bytes.NewBuffer([]byte{}))
if err != nil {
return err
}
s.setTokenHeader(req)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode == 204 || resp.StatusCode == 404 {
if err != nil {
fmt.Println("Error: ", err)
}
return nil
} else {
fmt.Println("Response Body: ", string(body))
raw := map[string]interface{}{}
err = ffjson.Unmarshal(body, &raw)
if err != nil {
return err
} else {
return errors.New(raw["error_description"].(string))
}
}
}
func (s *lyftService) RequestRide(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
bObject, err := ffjson.Marshal(rideRequest)
if err != nil {
return viewmodel.RideRequest{}, err
}
req, err := http.NewRequest("POST", lyftURL+"dispatches", bytes.NewBuffer(bObject))
if err != nil {
return viewmodel.RideRequest{}, err
}
s.setTokenHeader(req)
req.Header.Add("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return viewmodel.RideRequest{}, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var raw viewmodel.RideRequest
err = ffjson.Unmarshal(body, &raw)
if err != nil {
return viewmodel.RideRequest{}, err
}
if raw.Error != "" {
fmt.Println("Error to call Lyft: ", raw.Error+" - "+raw.ErrorDescription)
return viewmodel.RideRequest{}, errors.New("Lyft Error: " + raw.Error + " - " + raw.ErrorDescription)
}
return s.GetRideDetails(raw)
}
func (s *lyftService) GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
resp, _, err := s.client.PublicApi.GetETA(lag, log, params)
if err != nil {
return nil, err
}
return resp, nil
}
func (s *lyftService) GetCost(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
resp, _, err := s.client.PublicApi.GetCost(lag, log, params)
if err != nil {
return nil, err
}
return resp, nil
}
func (s *lyftService) GetDrivers(lag float64, log float64) (interface{}, error) {
resp, _, err := s.client.PublicApi.GetDrivers(lag, log)
if err != nil {
return nil, err
}
return resp, nil
}
func (s *lyftService) GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
resp, _, err := s.client.PublicApi.GetRideTypes(lag, log, params)
if err != nil {
return nil, err
}
return resp, nil
}

View File

@@ -0,0 +1,33 @@
package tncservice
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
Lyft *lyftService
LyftProd *lyftService
}
// New returns a new domain Service instance
func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *Service {
once.Do(func() {
instance = &Service{
Lyft: newLyftService(svc, mapper, cfg, notificationService),
LyftProd: newLyftProdService(svc, mapper, cfg, notificationService),
}
})
return instance
}

View File

@@ -0,0 +1,15 @@
package viewmodel
type Address struct {
UUID string `json:"address_uuid,omitempty"`
InternalID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Address string `json:"address,omitempty"`
AddressType string `json:"address_type,omitempty"`
AddressTypeName string `json:"address_type_name,omitempty"`
Latitude float64 `json:"lat,omitempty"`
Longitude float64 `json:"lng,omitempty"`
Type string `json:"type,omitempty"`
User User `json:"user,omitempty"`
CreatedUserUUID string `json:"-"`
}

View File

@@ -0,0 +1,9 @@
package viewmodel
// AuthResponse has data from authentication routes
type AuthResponse struct {
Token string `json:"token"`
ValidTime int64 `json:"valid_time"`
ServerTime int64 `json:"server_time"`
User User `json:"user"`
}

View File

@@ -0,0 +1,55 @@
package viewmodel
import (
"time"
)
type Eligibility struct {
TrackingID string `json:"tracking_id,omitempty"`
Payer Payer `json:"payer,omitempty"`
Provider Provider `json:"provider,omitempty"`
Subscriber Subscriber `json:"subscriber,omitempty"`
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
}
type Payer struct {
PayerID string `json:"payer_id,omitempty"`
PayerName string `json:"payer_name,omitempty"`
}
type Provider struct {
ProviderID string `json:"provider_id,omitempty"`
ProviderNPI string `json:"provider_npi,omitempty"`
ProviderName string `json:"provider_name,omitempty"`
Name Name `json:"name,omitempty"`
}
type Name struct {
First string `json:"first,omitempty"`
Last string `json:"last,omitempty"`
Middle string `json:"middle,omitempty"`
}
type Subscriber struct {
PatientType string `json:"patient_type,omitempty"`
SubscriberID string `json:"subscriber_id,omitempty"`
Name Name `json:"name,omitempty"`
DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
Dependents []Dependent `json:"dependents,omitempty"`
}
type DemographicInfo struct {
DateOfBirth time.Time `json:"date_of_birth,omitempty"`
Gender string `json:"gender,omitempty"`
}
type Dependent struct {
PatientAccountNumber string `json:"patient_account_number,omitempty"`
Name Name `json:"name,omitempty"`
DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
}
type ServiceInfo struct {
DateOfService time.Time `json:"date_of_service,omitempty"`
ServiceTypeCodes []string `json:"service_type_codes,omitempty"`
}

View File

@@ -0,0 +1,34 @@
package viewmodel
import "time"
type Notification struct {
UUID string `json:"uuid"`
To string `json:"to"`
From string `json:"from"`
Type string `json:"type"`
Subject string `json:"subject"`
Message string `json:"message"`
Ride Ride `json:"ride"`
User User `json:"user"`
CreatedUser User `json:"created_user"`
Created time.Time `json:"create_at"`
MessageType string `json:"message_type"`
Read bool `json:"read"`
}
type Message struct {
DeliveryID string `json:"id"`
NotificationID string `json:"nid"`
CreateDate time.Time `json:"date"`
Read bool `json:"readed"`
Content MessageContent `json:"content"`
}
type MessageContent struct {
Type string `json:"type"`
Subject string `json:"subject"`
Content string `json:"body,omitempty"`
Payload interface{} `json:"payload,omitempty"`
RedirectLink string `json:"redirect,omitempty"`
}

View File

@@ -0,0 +1,69 @@
package viewmodel
import (
"time"
)
type OrganizationType struct {
ID int64 `json:"-"`
Name string `json:"name"`
Key string `json:"key"`
Description string `json:"desc,omitempty"`
Created time.Time `json:"-"`
Updated time.Time `json:"-"`
}
type Organization struct {
ID int64 `json:"-"`
UUID string `json:"id"`
Type OrganizationType `json:"type"`
Name string `json:"name"`
Description string `json:"desc,omitempty"`
ReferenceID int64 `json:"-"`
ParentID int64 `json:"-"`
Main bool `json:"main"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Active bool `json:"active"`
Blocked bool `json:"blocked"`
Suspended bool `json:"suspended"`
Author User `json:"author"`
LastEditor User `json:"last_editor"`
Contacts []OrganizationContact `json:"contacts"`
Addresses []OrganizationAddress `json:"addresses"`
ChildOrgs []Organization `json:"childs,omitempty"`
Parent *Organization `json:"parent,omitempty"`
Reference interface{} `json:"reference,omitempty"`
}
type OrganizationContact struct {
ID int64 `json:"-"`
UUID string `json:"id"`
Organization *Organization `json:"organization,omitempty"`
Type ContactType `json:"type"`
Contact string `json:"contact"`
Name string `json:"name"`
Description string `json:"desc"`
Created time.Time `json:"created"`
CreatedUser User `json:"author"`
Updated time.Time `json:"updated"`
UpdatedUser User `json:"last_editor"`
Active bool `json:"active"`
}
type OrganizationAddress struct {
ID int64 `json:"-"`
UUID string `json:"id"`
Organization *Organization `json:"organization,omitempty"`
InternalID string `json:"internal_id"`
Name string `json:"name"`
Address string `json:"address"`
Description string `json:"desc"`
Latitude float64 `json:"lat"`
Longitude float64 `json:"long"`
Created time.Time `json:"created"`
CreatedUser User `json:"author"`
Updated time.Time `json:"updated"`
UpdatedUser User `json:"last_editor"`
Active bool `json:"active"`
}

View File

@@ -0,0 +1,15 @@
package viewmodel
// ReturnPagination holds the pagination data result
type ReturnPagination struct {
TotalRecords int64 `json:"total_records"`
RecordsPerPage int64 `json:"records_per_page"`
TotalPages int64 `json:"total_pages"`
CurrentPage int64 `json:"current_page"`
}
// PaginatedResult is the standard paginated list result
type PaginatedResult struct {
Pagination ReturnPagination `json:"pagination,omitempty"`
List interface{} `json:"data,omitempty"`
}

View File

@@ -0,0 +1,17 @@
package viewmodel
import "time"
type Profile struct {
ID int64 `json:"-"`
Name string `json:"name"`
Key string `json:"key"`
Description string `json:"desc"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Active bool `json:"active"`
Blocked bool `json:"blocked"`
Suspended bool `json:"suspended"`
Visible bool `json:"visible"`
Organization Organization `json:"organization"`
}

View File

@@ -0,0 +1,119 @@
package viewmodel
type ProviderResp struct {
ProviderUUID string `json:"provider_uuid,omitempty"`
InternalID string `json:"internal_id,omitempty"`
InternalSuffixID string `json:"internal_suffix_id,omitempty"`
MukID string `json:"muk_id,omitempty"`
OrganizatioName string `json:"org_name,omitempty"`
Gender string `json:"gender,omitempty"`
AcceptNewPatients string `json:"accept_new_patients,omitempty"`
Name string `json:"name,omitempty"`
FirstName string `json:"first,omitempty"`
MiddleName string `json:"middle,omitempty"`
LastName string `json:"last,omitempty"`
Title string `json:"title,omitempty"`
Keys []ProviderKey `json:"keys,omitempty"`
Address ProviderAddress `json:"address,omitempty"`
Distance float64 `json:"distance,omitempty"`
}
type ProviderKey struct {
InternalID string `json:"internal_id"`
InternalSuffixID string `json:"internal_suffix_id"`
LocationSeqNumber string `json:"location_seq_number"`
PlanCode string `json:"plan_code"`
ProductID string `json:"product_id"`
TreatmentCategoryCode string `json:"treatment_category_code"`
}
type ProviderAddress struct {
StreetAddress1 string `json:"street_address_1,omitempty"`
StreetAddress2 string `json:"street_address_2,omitempty"`
CityName string `json:"city,omitempty"`
State string `json:"state,omitempty"`
ZipCode string `json:"zipcode,omitempty"`
Country string `json:"country,omitempty"`
Latitude float64 `json:"lat,omitempty"`
Longitude float64 `json:"long,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
}
// ProviderSearchParams entity data
type ProviderSearchParams struct {
Name string
SearchBy string
Latitude float64
Longitude float64
Distance int64
Limit int64
}
type ProviderResponse struct {
MukID string `json:"mukId"`
FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
OrgName string `json:"orgName"`
Gender string `json:"gender"`
AcceptNewPatients string `json:"acceptNewPatients"`
ProviderName string `json:"providerName"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
MiddleName string `json:"middleName"`
ProviderTitle string `json:"providerTitle"`
StreetName1 string `json:"streetName_1"`
StreetName2 string `json:"streetName_2"`
CityName string `json:"cityName"`
State string `json:"state"`
ZipCode string `json:"zipCode"`
Country string `json:"country"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
PhoneNumber string `json:"phoneNumber"`
ProviderEntityName string `json:"providerEntityName"`
ProviderEntityCode string `json:"providerEntityCode"`
ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
Distance string `json:"distance"`
AvailabilityOfCost string `json:"availabilityOfCost"`
TDDPhoneNumber string `json:"tddPhoneNumber"`
ExtendedOfficeHours string `json:"extendedOfficeHours"`
ProviderCountyCode string `json:"providerCountyCode"`
ProviderCountyName string `json:"providerCountyName"`
HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
ProviderAffiliationName string `json:"providerAffiliationName"`
LanguagesSpoken []Languages `json:"languagesSpoken"`
OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
MedSchool string `json:"medSchool"`
MedSchoolYear string `json:"medSchoolYear"`
Internship string `json:"internship"`
Residence string `json:"residency"`
Specialty1 string `json:"specialty1"`
Specialty2 string `json:"specialty2"`
Specialty3 string `json:"specialty3"`
Specialty4 string `json:"specialty4"`
Certification1 string `json:"certification1"`
Certification2 string `json:"certification2"`
Certification3 string `json:"certification3"`
Certification4 string `json:"certification4"`
}
type HospitalAffiliationNames struct {
HospAffProvOrgName string `json:"hospAffProvOrgName"`
}
type Languages struct {
Code string `json:"code"`
}
type ProviderTypeCode struct {
Code string `json:"code"`
}
type PartKeyGroup struct {
ProviderNum string `json:"providerNum"`
ProviderNumSuffix string `json:"providerNumSuffix"`
LocationSeqNum string `json:"locationSeqNum"`
PlanCode string `json:"planCode"`
ProductID string `json:"productId"`
TreatmentCategoryCode string `json:"treatmentCategoryCode"`
}

View File

@@ -0,0 +1,161 @@
package viewmodel
import "time"
//WebhookResponse has the data and events from the webhook
type WebhookResponse struct {
EventID string `json:"event_id,omitempty"`
HREF string `json:"href,omitempty"`
OccurredAt string `json:"occurred_at,omitempty"`
EventType string `json:"event_type,omitempty"`
Event RideRequest `json:"event,omitempty"`
Ride Ride `json:"-"`
}
//RideRequest has the data to dispatch a ride
type RideRequest struct {
UserUUID string `json:"user_uuid,omitempty"`
Status string `json:"status,omitempty"`
RideID string `json:"ride_id,omitempty"`
RideType string `json:"ride_type,omitempty"`
Origin Location `json:"origin,omitempty"`
Location Location `json:"location,omitempty"`
Destination Location `json:"destination,omitempty"`
Passenger UserLyft `json:"passenger,omitempty"`
Notes string `json:"external_note,omitempty"`
RouteURL string `json:"route_url,omitempty"`
ScheduledPickupRange interface{} `json:"scheduled_pickup_range,omitempty"`
PrimetimePercentage string `json:"primetime_percentage,omitempty"`
Pickup Location `json:"pickup,omitempty"`
DropOff Location `json:"dropoff,omitempty"`
Vehicle Vehicle `json:"vehicle,omitempty"`
Price Price `json:"price,omitempty"`
Driver UserLyft `json:"driver,omitempty"`
GeneratedAtMS *int64 `json:"generated_at_ms,omitempty"`
GeneratedAt *time.Time `json:"generated_at,omitempty"`
RequestAtMS *int64 `json:"requested_at_ms,omitempty"`
RequestAt *time.Time `json:"requested_at,omitempty"`
LineItems []Price `json:"line_items,omitempty"`
BeaconColor string `json:"beacon_color,omitempty"`
Charges []Charge `json:"charges,omitempty"`
VisitDate *time.Time `json:"visit_date,omitempty"`
VisitTime *time.Time `json:"visit_time,omitempty"`
PickupTime *time.Time `json:"pickup_time,omitempty"`
ReturnTime *time.Time `json:"return_time,omitempty"`
Distance float64 `json:"distance,omitempty"`
ETA int64 `json:"eta,omitempty"`
Duration int64 `json:"duration,omitempty"`
Visit Visit `json:"visit,omitempty"`
CreateUserUUID string `json:"created_user_uuid,omitempty"`
VisitExternalID string `json:"visit_external_id,omitempty"`
CanCancel []string `json:"can_cancel,omitempty"`
PricingDetailsURL string `json:"pricing_details_url,omitempty"`
RideProfile string `json:"ride_profile,omitempty"`
DistanceInMiles float64 `json:"distance_miles,omitempty"`
DurationInSeconds float64 `json:"duration_seconds,omitempty"`
CanceledBy string `json:"canceled_by,omitempty"`
TripType TripType `json:"trip_type,omitempty"`
Error string `json:"error,omitempty"`
ErrorDescription string `json:"error_description,omitempty"`
}
//Charge information
type Charge struct {
Currency string `json:"currency,omitempty"`
PaymentMethod string `json:"payment_method,omitempty"`
Amount int64 `json:"amount,omitempty"`
}
//Price information
type Price struct {
Currency string `json:"currency,omitempty"`
Amount float64 `json:"amount,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
}
//Vehicle information
type Vehicle struct {
Color string `json:"color,omitempty"`
Make string `json:"make,omitempty"`
LicensePlate string `json:"license_plate,omitempty"`
ImageURL string `json:"image_url,omitempty"`
Year int64 `json:"year,omitempty"`
LicensePlateState string `json:"license_plate_state,omitempty"`
Model string `json:"model,omitempty"`
}
//Location has the coordinates from the user
type Location struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Latitude float64 `json:"lat,omitempty"`
Longitude float64 `json:"lng,omitempty"`
Address string `json:"address,omitempty"`
ETASeconds *int64 `json:"eta_seconds,omitempty"`
TimeMS *int64 `json:"time_ms,omitempty"`
Time *time.Time `json:"time,omitempty"`
Bearing *float64 `json:"bearing,omitempty"`
}
//UserLyft has the personal information
type UserLyft struct {
UserID *string `json:"user_id,omitempty"`
Rating *string `json:"rating,omitempty"`
ImageURL *string `json:"image_url,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
}
// Ride entity data
type Ride struct {
UUID string `json:"ride_uuid,omitempty"`
InternalID string `json:"internal_id,omitempty"`
User User `json:"user,omitempty"`
Status RideStatus `json:"status,omitempty"`
Type RideType `json:"type,omitempty"`
Note string `json:"notes,omitempty"`
Passenger UserLyft `json:"passenger,omitempty"`
Driver UserLyft `json:"driver,omitempty"`
Vehicle Vehicle `json:"vehicle,omitempty"`
Route RideRoute `json:"route,omitempty"`
VisitDate *time.Time `json:"visit_date,omitempty"`
VisitTime *time.Time `json:"visit_time,omitempty"`
PickupTime *time.Time `json:"pickup_time,omitempty"`
Visit Visit `json:"visit,omitempty"`
CreatedUser User `json:"created_user,omitempty"`
CreateAt time.Time `json:"create_at,omitempty"`
UpdateAt time.Time `json:"update_at,omitempty"`
TripType TripType `json:"trip_type,omitempty"`
}
// RideStatus entity data
type RideStatus struct {
Key string `json:"key,omitempty"`
Value string `json:"value,omitempty"`
}
// TripType entity data
type TripType struct {
Key string `json:"key"`
Value string `json:"value"`
}
// RideType entity data
type RideType struct {
Key string `json:"key,omitempty"`
Value string `json:"value,omitempty"`
}
// RideRoute entity data
type RideRoute struct {
Origin Location `json:"origin,omitempty"`
Destination Location `json:"destination,omitempty"`
Location Location `json:"location,omitempty"`
RouteKML *string `json:"route_kml,omitempty"`
Distance float64 `json:"distance,omitempty"`
Duration int64 `json:"duration,omitempty"`
ETA int64 `json:"eta,omitempty"`
Bearing int64 `json:"bearing,omitempty"`
}

View File

@@ -0,0 +1,87 @@
package viewmodel
type ListNumbers struct {
AvailableNumbers []Number `json:"available_phone_numbers,omitempty"`
Page int64 `json:"page,omitempty"`
PageSize int64 `json:"page_size,omitempty"`
URI string `json:"uri,omitempty"`
FirstPageURI string `json:"first_page_uri,omitempty"`
PreviousPageURI string `json:"previous_page_uri,omitempty"`
NextPageURI string `json:"next_page_uri,omitempty"`
IncomingPhones []Number `json:"incoming_phone_numbers,omitempty"`
}
type Number struct {
SID *string `json:"sid,omitempty"`
AccountSID *string `json:"account_sid,omitempty"`
FriendlyName string `json:"friendly_name,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
Lata string `json:"lata,omitempty"`
RateCenter string `json:"rate_center,omitempty"`
Latitude string `json:"latitude,omitempty"`
Longitude string `json:"longitude,omitempty"`
Region string `json:"region,omitempty"`
PostalCode string `json:"postal_code,omitempty"`
ISOCountry string `json:"iso_country,omitempty"`
Beta bool `json:"beta,omitempty"`
Capabilities Capabilities `json:"capabilities,omitempty"`
VoiceURL *string `json:"voice_url,omitempty"`
VoiceMethod *string `json:"voice_method,omitempty"`
VoiceFallbackURL *string `json:"voice_fallback_url,omitempty"`
VoiceFallbackMethod *string `json:"voice_fallback_method,omitempty"`
VoiceCallerIDLookup bool `json:"voice_caller_id_lookup,omitempty"`
VoiceApplicationSID *string `json:"voice_application_sid,omitempty"`
DateCreated *string `json:"date_created,omitempty"`
DateUpdated *string `json:"date_updated,omitempty"`
SmsURL *string `json:"sms_url,omitempty"`
SmsMethod *string `json:"sms_method,omitempty"`
SmsFallbackURL *string `json:"sms_fallback_url,omitempty"`
SmsFallbackMethod *string `json:"sms_fallback_method,omitempty"`
SmsApplicationID *string `json:"sms_application_sid,omitempty"`
StatusCallback *string `json:"status_callback,omitempty"`
StatusCallbackMethod *string `json:"status_callback_method,omitempty"`
APIVersion *string `json:"api_version,omitempty"`
}
type Capabilities struct {
Voice bool `json:"voice,omitempty"`
SMS bool `json:"SMS,omitempty"`
MMS bool `json:"MMS,omitempty"`
}
type ProxyNumber struct {
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Proxy string `json:"proxy,omitempty"`
Number Number `json:"details,omitempty"`
}
type SocketMessage struct {
From string `json:"from"`
To string `json:"to"`
Message string `json:"message"`
Filled bool `json:"-"`
}
type TwilioWebhook struct {
ToCountry string `json:"ToCountry,omitempty"`
ToState string `json:"ToState,omitempty"`
SMSMessageSID string `json:"SmsMessageSid,omitempty"`
NumMedia string `json:"NumMedia,omitempty"`
ToCity string `json:"ToCity,omitempty"`
FromZip string `json:"FromZip,omitempty"`
SMSSID string `json:"SmsSid,omitempty"`
FromState string `json:"FromState,omitempty"`
SMSStatus string `json:"SmsStatus,omitempty"`
FromCity string `json:"FromCity,omitempty"`
Body string `json:"Body,omitempty"`
FromCountry string `json:"FromCountry,omitempty"`
To string `json:"To,omitempty"`
ToZip string `json:"ToZip,omitempty"`
AddOns string `json:"AddOns,omitempty"`
NumSegments string `json:"NumSegments,omitempty"`
MessageSID string `json:"MessageSid,omitempty"`
AccountSID string `json:"AccountSid,omitempty"`
From string `json:"From,omitempty"`
APIVersion string `json:"ApiVersion,omitempty"`
}

View File

@@ -0,0 +1,36 @@
package viewmodel
import "time"
// User model for API binding
type User struct {
ID string `json:"useruuid"`
Name string `json:"name,omitempty"`
First string `json:"first,omitempty"`
Last string `json:"last,omitempty"`
Gender *string `json:"gender,omitempty"`
Member *string `json:"member,omitempty"`
BirthDate *time.Time `json:"birthdate,omitempty"`
Email *string `json:"email,omitempty"`
PhoneNumber *string `json:"phonenumber,omitempty"`
Pass string `json:"pass,omitempty"`
Active bool `json:"active,omitempty"`
Created time.Time `json:"created,omitempty"`
Updated time.Time `json:"updated,omitempty"`
Contacts []Contact `json:"contacts,omitempty"`
Rides []Ride `json:"rides,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
Profiles []Profile `json:"profiles,omitempty"`
Types []OrganizationType `json:"types,omitempty"`
Organizations []Organization `json:"organizations,omitempty"`
}
type Contact struct {
Type ContactType `json:"type,omitempty"`
Value string `json:"contact,omitempty"`
}
type ContactType struct {
Key string `json:"key,omitempty"`
Value string `json:"value,omitempty"`
}

View File

@@ -0,0 +1,33 @@
package viewmodel
import (
"time"
)
// VisitStatus entity data
type VisitStatus struct {
Key string `json:"key,omitempty"`
Value string `json:"value,omitempty"`
}
// Visit entity data
type Visit struct {
UUID string `json:"visit_uuid,omitempty"`
Status VisitStatus `json:"visit_status,omitempty"`
User User `json:"user,omitempty"`
VisitDatetime time.Time `json:"visit_datetime,omitempty"`
VisitDuration int64 `json:"visit_duration,omitempty"`
PickupDatetime time.Time `json:"pickup_datetime,omitempty"`
Notes *string `json:"notes,omitempty"`
PickupAddressID int64 `json:"pickup_address_id,omitempty"`
DestinationAddressID int64 `json:"destination_address_id,omitempty"`
Pickup Location `json:"pickup,omitempty"`
Provider ProviderResp `json:"provider,omitempty"`
CreatedUser User `json:"created_user,omitempty"`
CreatedDate time.Time `json:"created,omitempty"`
UpdatedDate time.Time `json:"updated,omitempty"`
ReturnDate *time.Time `json:"return_date,omitempty"`
TripType TripType `json:"trip_type,omitempty"`
ExternalID string `json:"visit_external_id,omitempty"`
Rides []Ride `json:"rides,omitempty"`
}