Compare commits
7 Commits
verify-eli
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f22af46a26 | ||
|
|
79f39b32c9 | ||
|
|
dfa43d09e4 | ||
|
|
69853b026b | ||
|
|
f1ac874276 | ||
|
|
756d84359d | ||
|
|
806e2b1f3b |
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
)
|
)
|
||||||
@@ -16,30 +17,34 @@ var (
|
|||||||
|
|
||||||
// Service holds the domain service repositories
|
// Service holds the domain service repositories
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Users *userService
|
Users *userService
|
||||||
Rides *rideService
|
Rides *rideService
|
||||||
Visits *visitService
|
Visits *visitService
|
||||||
Provider *providerService
|
Provider *providerService
|
||||||
Notification *notificationService
|
Notification *notificationService
|
||||||
Profile *profileService
|
Profile *profileService
|
||||||
Organization *organizationService
|
Organization *organizationService
|
||||||
Zipcodes *zipcodeService
|
Zipcodes *zipcodeService
|
||||||
Plan *planService
|
Plan *planService
|
||||||
|
PasswordReset *passwordResetService
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new domain Service instance
|
// New returns a new domain Service instance
|
||||||
func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
|
func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
|
bcbsi := bcbsi.New(cfg)
|
||||||
|
|
||||||
instance = &Service{
|
instance = &Service{
|
||||||
Users: newUserService(svc, mapper),
|
Users: newUserService(svc, mapper, bcbsi, cfg),
|
||||||
Rides: newRideService(svc, mapper),
|
Rides: newRideService(svc, mapper),
|
||||||
Visits: newVisitService(svc, mapper),
|
Visits: newVisitService(svc, mapper),
|
||||||
Provider: newProviderService(svc, mapper),
|
Provider: newProviderService(svc, mapper),
|
||||||
Notification: newNotificationService(svc, mapper, notification, cfg),
|
Notification: newNotificationService(svc, mapper, notification, cfg),
|
||||||
Profile: newProfileService(svc, mapper),
|
Profile: newProfileService(svc, mapper),
|
||||||
Organization: newOrganizationService(svc, mapper),
|
Organization: newOrganizationService(svc, mapper),
|
||||||
Zipcodes: newZipcodeService(svc, mapper),
|
Zipcodes: newZipcodeService(svc, mapper),
|
||||||
Plan: newPlanService(svc, mapper),
|
Plan: newPlanService(svc, mapper),
|
||||||
|
PasswordReset: newPasswordResetService(svc, mapper),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -550,6 +550,56 @@ func (s *notificationService) ReadStatus(notificationUUID string, isRead bool) e
|
|||||||
return s.svc.Notification.ReadStatus(notificationUUID, isRead)
|
return s.svc.Notification.ReadStatus(notificationUUID, isRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SendNotificationWithoutWritingToDatabase will send notification directly
|
||||||
|
func (s *notificationService) SendNotificationWithoutWritingToDatabase(n viewmodel.Notification) (viewmodel.Notification, error) {
|
||||||
|
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())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, "+17083038497", n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := s.notification.Twilio.SendSMS(n.From, n.To, n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
if err := s.notification.Twilio.SendSMS(n.From, "+17083038497", n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
return viewmodel.Notification{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SendNotifications will send all the notifications to email or SMS
|
// SendNotifications will send all the notifications to email or SMS
|
||||||
func (s *notificationService) SendNotifications(notifications []viewmodel.Notification) ([]viewmodel.Notification, error) {
|
func (s *notificationService) SendNotifications(notifications []viewmodel.Notification) ([]viewmodel.Notification, error) {
|
||||||
if len(notifications) > 0 {
|
if len(notifications) > 0 {
|
||||||
|
|||||||
62
application/applicationservice/passwordresetservice.go
Normal file
62
application/applicationservice/passwordresetservice.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// zipcodeService holds methods to participating zipcode application service
|
||||||
|
type passwordResetService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newZipcodeService returns a zipcodeService instance
|
||||||
|
func newPasswordResetService(svc *service.Service, mapper *entitymapping.Mapper) *passwordResetService {
|
||||||
|
return &passwordResetService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetAll() ([]viewmodel.PasswordReset, error) {
|
||||||
|
result, err := s.svc.PasswordReset.GetAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.PasswordReset.ToPasswordResetModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) CreatePasswordResetEntry(passwordResetEntry viewmodel.PasswordReset) (viewmodel.PasswordReset, error) {
|
||||||
|
passwordResetEntity := s.mapEntity.PasswordReset.ToPasswordResetEntity(passwordResetEntry)
|
||||||
|
result, err := s.svc.PasswordReset.CreatePasswordResetEntry(passwordResetEntity)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.PasswordReset{}, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.PasswordReset.ToPasswordResetModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetByID(ID int64) (viewmodel.PasswordReset, error) {
|
||||||
|
result, err := s.svc.PasswordReset.GetByID(ID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.PasswordReset{}, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.PasswordReset.ToPasswordResetModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetByToken(token string) (viewmodel.PasswordReset, error) {
|
||||||
|
result, err := s.svc.PasswordReset.GetByToken(token)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.PasswordReset{}, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.PasswordReset.ToPasswordResetModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) SetTokenOpened(token string) error {
|
||||||
|
return s.svc.PasswordReset.SetTokenOpened(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) SetTokenUsed(token string) error {
|
||||||
|
return s.svc.PasswordReset.SetTokenUsed(token)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package applicationservice
|
package applicationservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
@@ -183,6 +184,7 @@ func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
|
|||||||
address, _ := s.svc.Users.GetAddressByUUID(rideEntity.Route.Destination.ID)
|
address, _ := s.svc.Users.GetAddressByUUID(rideEntity.Route.Destination.ID)
|
||||||
createdUser, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
createdUser, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error to get User: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,12 +192,14 @@ func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
|
|||||||
visit.DestinationAddressID = address.ID
|
visit.DestinationAddressID = address.ID
|
||||||
provider, err := s.svc.Provider.GetByMukID(address.InternalID, createdUser)
|
provider, err := s.svc.Provider.GetByMukID(address.InternalID, createdUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error to get Provider: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
visit.Provider = provider
|
visit.Provider = provider
|
||||||
} else {
|
} else {
|
||||||
provider, err := s.svc.Provider.GetByMukID(rideEntity.Route.Destination.ID, createdUser)
|
provider, err := s.svc.Provider.GetByMukID(rideEntity.Route.Destination.ID, createdUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error to get Provider by Route: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
visit.Provider = provider
|
visit.Provider = provider
|
||||||
@@ -203,17 +207,20 @@ func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
|
|||||||
|
|
||||||
visit, err = s.svc.Visits.Create(visit)
|
visit, err = s.svc.Visits.Create(visit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error creating visit: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
rideEntity.Visit = visit
|
rideEntity.Visit = visit
|
||||||
} else {
|
} else {
|
||||||
user, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
user, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error getting User: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
visit, err := s.svc.Visits.GetByUUID(ride.Visit.UUID, user)
|
visit, err := s.svc.Visits.GetByUUID(ride.Visit.UUID, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error getting Visit: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
rideEntity.Visit = visit
|
rideEntity.Visit = visit
|
||||||
@@ -221,6 +228,7 @@ func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
|
|||||||
|
|
||||||
retVal, err := s.svc.Rides.Save(rideEntity)
|
retVal, err := s.svc.Rides.Save(rideEntity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Application.Save: Error saving ride: ", err.Error())
|
||||||
return viewmodel.Ride{}, errors.Wrap(err)
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,40 @@
|
|||||||
package applicationservice
|
package applicationservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"html"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||||
|
"googlemaps.github.io/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// userService holds methods to user application service
|
// userService holds methods to user application service
|
||||||
type userService struct {
|
type userService struct {
|
||||||
svc *service.Service
|
svc *service.Service
|
||||||
mapEntity *entitymapping.Mapper
|
mapEntity *entitymapping.Mapper
|
||||||
|
bcbsi *bcbsi.Service
|
||||||
|
cfg *config.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// newUserService returns a userService instance
|
// newUserService returns a userService instance
|
||||||
func newUserService(svc *service.Service, mapper *entitymapping.Mapper) *userService {
|
func newUserService(svc *service.Service, mapper *entitymapping.Mapper, bcbsi *bcbsi.Service, cfg *config.Config) *userService {
|
||||||
return &userService{
|
return &userService{
|
||||||
svc: svc,
|
svc: svc,
|
||||||
mapEntity: mapper,
|
mapEntity: mapper,
|
||||||
|
bcbsi: bcbsi,
|
||||||
|
cfg: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +77,16 @@ func (s *userService) GetByMemberID(memberID string) (retVal viewmodel.User, err
|
|||||||
return s.mapEntity.User.ToUserModel(user), nil
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetByEmail returns a specific user by its email
|
||||||
|
func (s *userService) GetByEmail(email string) (retVal viewmodel.User, err error) {
|
||||||
|
user, err := s.svc.Users.GetByEmail(email)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Login returns a specific user by email and pass
|
// 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) {
|
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)
|
user, err := s.svc.Users.FullLogin(loginType, key, pass, profile)
|
||||||
@@ -184,3 +210,220 @@ func (s *userService) RemoveContact(contact viewmodel.Contact) (retVal viewmodel
|
|||||||
|
|
||||||
return s.mapEntity.User.ToContactModel(entity), err
|
return s.mapEntity.User.ToContactModel(entity), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *userService) rangeIn(low, hi int) string {
|
||||||
|
result := low + rand.Intn(hi-low)
|
||||||
|
return fmt.Sprintf("%v", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) generatePassword(n int) string {
|
||||||
|
const (
|
||||||
|
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
)
|
||||||
|
|
||||||
|
return s.stringWithCharset(n, charset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) stringWithCharset(length int, charset string) string {
|
||||||
|
b := make([]byte, length)
|
||||||
|
var seededRand *rand.Rand = rand.New(
|
||||||
|
rand.NewSource(time.Now().UnixNano()))
|
||||||
|
for i := range b {
|
||||||
|
b[i] = charset[seededRand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) CheckAndCreateMember(user viewmodel.User, provider viewmodel.ProviderResp, authorUser viewmodel.User) (viewmodel.User, error) {
|
||||||
|
if validationErrors := validation.ValidateEligibility(&user); len(validationErrors) > 0 {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: "Eligibility validation failed", Errors: validationErrors}
|
||||||
|
}
|
||||||
|
|
||||||
|
entityUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
entityAuthorUser := s.mapEntity.User.ToUserEntity(authorUser)
|
||||||
|
entityProvider := s.mapEntity.Provider.ToProviderRespEntity(provider)
|
||||||
|
|
||||||
|
newEmail := entityUser.Email
|
||||||
|
newPhoneNumber := entityUser.PhoneNumber
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if entityUser.UUID != "" {
|
||||||
|
entityUser, err = s.svc.Users.GetByUUID(entityUser.UUID, "US")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error finding user by UUID: %s", err.Error())}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entityUser, err = s.svc.Users.GetByMemberID(entityUser.Member)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error finding user by Subscriber ID: %s", err.Error())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if entityUser.UUID == "" {
|
||||||
|
entityUser = s.mapEntity.User.ToUserEntity(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
var eligibility viewmodel.Eligibility
|
||||||
|
loc, _ := time.LoadLocation("America/Chicago")
|
||||||
|
eligibility.TrackingID = s.rangeIn(1000000, 9999999)
|
||||||
|
eligibility.ServiceInfo.DateOfService = time.Now().In(loc)
|
||||||
|
eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
|
||||||
|
|
||||||
|
if entityProvider.InternalID == "" && entityProvider.ProviderUUID != "" {
|
||||||
|
entityProvider, err = s.svc.Provider.GetByUUID(entityProvider.ProviderUUID, entityAuthorUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error finding provider by UUID: %s", err.Error())}
|
||||||
|
}
|
||||||
|
} else if entityProvider.InternalID != "" {
|
||||||
|
entityProvider, err = s.svc.Provider.GetByNPI(entityProvider.InternalID, entityAuthorUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error finding provider by NPI: %s", err.Error())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if entityProvider.InternalID == "" {
|
||||||
|
eligibility.Provider.ProviderNPI = "1699849786"
|
||||||
|
eligibility.Provider.ProviderName = "LITHOLINK CORPORATION"
|
||||||
|
} else {
|
||||||
|
eligibility.Provider.ProviderNPI = entityProvider.InternalID
|
||||||
|
eligibility.Provider.ProviderName = entityProvider.OrganizatioName
|
||||||
|
}
|
||||||
|
|
||||||
|
plan, err := s.svc.Plans.GetByAlphaPrefix(entityUser.Member[:3])
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error finding Plan: %s", err.Error())}
|
||||||
|
}
|
||||||
|
eligibility.Payer.PayerID = fmt.Sprintf("%v", plan.PayerID)
|
||||||
|
eligibility.Payer.PayerName = plan.PayerName
|
||||||
|
|
||||||
|
eligibility.Subscriber.SubscriberID = entityUser.Member
|
||||||
|
eligibility.Subscriber.PatientType = entityUser.Type
|
||||||
|
eligibility.Subscriber.Name.First = strings.Split(entityUser.Name, " ")[0]
|
||||||
|
eligibility.Subscriber.Name.Last = strings.Split(entityUser.Name, " ")[1]
|
||||||
|
eligibility.Subscriber.DemographicInfo.DateOfBirth = entityUser.BirthDate
|
||||||
|
eligibility.Subscriber.DemographicInfo.Gender = entityUser.Gender
|
||||||
|
|
||||||
|
ret, err := s.bcbsi.BXE.CheckEligibility(eligibility)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error checking eligibility: %s", err.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret.QueryResult.QueryResultSummary.BenefitsFound {
|
||||||
|
xmlString := html.UnescapeString(ret.QueryResult.HIPPA271.T271)
|
||||||
|
xmlReader := strings.NewReader(xmlString)
|
||||||
|
|
||||||
|
var f viewmodel.Interchange271
|
||||||
|
err = xml.NewDecoder(xmlReader).Decode(&f)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error unmarshaling 271 response: %s", err.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
header := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
||||||
|
body := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
||||||
|
zipCode := strings.TrimSpace(body.N403)
|
||||||
|
|
||||||
|
if len(strings.TrimSpace(zipCode)) > 5 {
|
||||||
|
zipCode = strings.TrimSpace(zipCode)[:5]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.cfg.App.DisableZipValidation {
|
||||||
|
_, err = s.svc.Zipcodes.GetByParticipatingZipcode(zipCode)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Member's Home zipcode, %s, is not currently eligible for participation in this program", zipCode)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if entityUser.ID == 0 {
|
||||||
|
profile, err := s.svc.Profile.GetByKey("US")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error getting user profile: %s", err.Error())}
|
||||||
|
}
|
||||||
|
entityUser.Profiles = append(entityUser.Profiles, profile)
|
||||||
|
|
||||||
|
if len(entityUser.PhoneNumber) == 10 && !strings.Contains(entityUser.PhoneNumber, "+1") {
|
||||||
|
phoneNumber := fmt.Sprintf("+1%s", entityUser.PhoneNumber)
|
||||||
|
entityUser.PhoneNumber = phoneNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
entityUser.Test = false
|
||||||
|
entityUser, err = s.svc.Users.Create(entityUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error creating user: %s", err.Error())}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(newEmail) > 0 && newEmail != entityUser.Email {
|
||||||
|
entityUser.Email = newEmail
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(newPhoneNumber) > 0 && len(newPhoneNumber) == 10 && !strings.Contains(newPhoneNumber, "+1") {
|
||||||
|
newPhoneNumber = fmt.Sprintf("+1%s", newPhoneNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(newPhoneNumber) > 0 && len(newPhoneNumber) == 12 && strings.Contains(newPhoneNumber, "+1") {
|
||||||
|
entityUser.PhoneNumber = newPhoneNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.svc.Users.UpdateLogin(entityUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error updating login data: %s", err.Error())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address := entity.Address{}
|
||||||
|
address.AddressType = entity.Params{
|
||||||
|
Key: "home",
|
||||||
|
Name: "Home",
|
||||||
|
}
|
||||||
|
address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
||||||
|
address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
|
||||||
|
address.CreatedUser = entityAuthorUser
|
||||||
|
address.User = entityUser
|
||||||
|
address.Origin = entity.Params{
|
||||||
|
Key: "provider",
|
||||||
|
Name: "Provider",
|
||||||
|
}
|
||||||
|
|
||||||
|
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error instanciating google maps: %s", err.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &maps.GeocodingRequest{
|
||||||
|
Address: address.Address + " " + body.N402 + ", " + zipCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := googleMapsAPI.Geocode(context.Background(), r)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error getting geocode info: %s", err.Error())}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(result) > 0 {
|
||||||
|
address.Latitude = result[0].Geometry.Location.Lat
|
||||||
|
address.Longitude = result[0].Geometry.Location.Lng
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user.Addresses) > 0 {
|
||||||
|
for _, a := range user.Addresses {
|
||||||
|
if a.AddressType == "home" {
|
||||||
|
err := s.svc.Users.RemoveAddress(a.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error removing old address: %s", err.Error())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address, err = s.svc.Users.SaveAddress(address)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: fmt.Sprintf("Error saving new address: %s", err.Error())}
|
||||||
|
}
|
||||||
|
entityUser.Addresses = append(entityUser.Addresses, address)
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(entityUser), nil
|
||||||
|
} else {
|
||||||
|
return viewmodel.User{}, &viewmodel.ValidationError{Message: "No benefits found for the member"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewmodel.User{}, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,16 +13,17 @@ var (
|
|||||||
|
|
||||||
// Mapper has mapping methods to map entities to view models
|
// Mapper has mapping methods to map entities to view models
|
||||||
type Mapper struct {
|
type Mapper struct {
|
||||||
User *userMapping
|
User *userMapping
|
||||||
Ride *rideMapping
|
Ride *rideMapping
|
||||||
Visit *visitMapping
|
Visit *visitMapping
|
||||||
Address *addressMapping
|
Address *addressMapping
|
||||||
Provider *providerMapping
|
Provider *providerMapping
|
||||||
Notification *notificationMapping
|
Notification *notificationMapping
|
||||||
Profile *profileMapping
|
Profile *profileMapping
|
||||||
Organization *organizationMapping
|
Organization *organizationMapping
|
||||||
Zipcode *zipcodeMapping
|
Zipcode *zipcodeMapping
|
||||||
Plan *planMapping
|
Plan *planMapping
|
||||||
|
PasswordReset *passwordResetMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns an EntityMapper for fluent mapping
|
// New returns an EntityMapper for fluent mapping
|
||||||
@@ -40,6 +41,7 @@ func New() *Mapper {
|
|||||||
instance.Organization = &organizationMapping{instance}
|
instance.Organization = &organizationMapping{instance}
|
||||||
instance.Zipcode = &zipcodeMapping{instance}
|
instance.Zipcode = &zipcodeMapping{instance}
|
||||||
instance.Plan = &planMapping{instance}
|
instance.Plan = &planMapping{instance}
|
||||||
|
instance.PasswordReset = &passwordResetMapping{instance}
|
||||||
})
|
})
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|||||||
59
application/entitymapping/passwordreset.go
Normal file
59
application/entitymapping/passwordreset.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// zipcodeMapping has method to map zipcode entities to view models
|
||||||
|
type passwordResetMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *passwordResetMapping) ToPasswordResetEntitySlice(list []viewmodel.PasswordReset) (retVal []entity.PasswordReset) {
|
||||||
|
retVal = make([]entity.PasswordReset, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToPasswordResetEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *passwordResetMapping) ToPasswordResetEntity(model viewmodel.PasswordReset) entity.PasswordReset {
|
||||||
|
return entity.PasswordReset{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
User: mapping.mapper.User.ToUserEntity(model.User),
|
||||||
|
Token: model.Token,
|
||||||
|
Created: model.Created,
|
||||||
|
Expires: model.Expires,
|
||||||
|
Used: model.Used,
|
||||||
|
Opened: model.Opened,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *passwordResetMapping) ToPasswordResetModelSlice(list []entity.PasswordReset) (retVal []viewmodel.PasswordReset) {
|
||||||
|
retVal = make([]viewmodel.PasswordReset, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToPasswordResetModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *passwordResetMapping) ToPasswordResetModel(model entity.PasswordReset) viewmodel.PasswordReset {
|
||||||
|
return viewmodel.PasswordReset{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
User: mapping.mapper.User.ToUserModel(model.User),
|
||||||
|
Token: model.Token,
|
||||||
|
Created: model.Created,
|
||||||
|
Expires: model.Expires,
|
||||||
|
Used: model.Used,
|
||||||
|
Opened: model.Opened,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,6 +50,8 @@ func (mapping *userMapping) ToUserModel(item entity.User) viewmodel.User {
|
|||||||
Profiles: mapping.mapper.Profile.ToProfileModelSlice(item.Profiles),
|
Profiles: mapping.mapper.Profile.ToProfileModelSlice(item.Profiles),
|
||||||
Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
|
Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
|
||||||
Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
|
Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
|
||||||
|
Type: &item.Type,
|
||||||
|
Test: item.Test,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +79,13 @@ func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
|
|||||||
Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
|
Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
|
||||||
Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
|
Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
|
||||||
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
|
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
|
||||||
|
Test: item.Test,
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Type == nil {
|
||||||
|
user.Type = "S"
|
||||||
|
} else {
|
||||||
|
user.Type = *item.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Name == "" {
|
if user.Name == "" {
|
||||||
|
|||||||
@@ -119,11 +119,14 @@ func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimo
|
|||||||
req.Header.Add("X-Api-Key", apiKey)
|
req.Header.Add("X-Api-Key", apiKey)
|
||||||
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
|
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
|
||||||
|
|
||||||
|
eligibilityCall := time.Now()
|
||||||
|
fmt.Println(fmt.Sprintf("Start eligibility call %s at %s", eligibility.TrackingID, eligibilityCall.Format("2006-01-02 15:04:05 PM")))
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error WebService Request: ", err)
|
fmt.Println("Error WebService Request: ", err)
|
||||||
return bcbsimodel.MemberEligibilityResponse{}, err
|
return bcbsimodel.MemberEligibilityResponse{}, err
|
||||||
}
|
}
|
||||||
|
fmt.Println(fmt.Sprintf("Getting Response from eligibility call %s at %s, duration %f seconds", eligibility.TrackingID, time.Now().Format("2006-01-02 15:04:05 PM"), time.Since(eligibilityCall).Seconds()))
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
bReturn, err := ioutil.ReadAll(resp.Body)
|
bReturn, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Eligibility struct {
|
type Eligibility struct {
|
||||||
TrackingID string `json:"tracking_id,omitempty"`
|
TrackingID string `json:"tracking_id,omitempty"`
|
||||||
Payer Payer `json:"payer,omitempty"`
|
Payer Payer `json:"payer,omitempty"`
|
||||||
Provider Provider `json:"provider,omitempty"`
|
Provider Provider `json:"provider,omitempty"`
|
||||||
Subscriber Subscriber `json:"subscriber,omitempty"`
|
Subscriber Subscriber `json:"subscriber,omitempty"`
|
||||||
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
|
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
|
||||||
User User `json:"user,omitempty"`
|
User User `json:"user,omitempty"`
|
||||||
|
RawProvider ProviderResponse `json:"raw_provider,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Payer struct {
|
type Payer struct {
|
||||||
|
|||||||
16
application/viewmodel/error.go
Normal file
16
application/viewmodel/error.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidationError struct {
|
||||||
|
Errors []errors.ValidationError
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ve *ValidationError) Error() string {
|
||||||
|
return fmt.Sprintf("Error: %s", ve.Message)
|
||||||
|
}
|
||||||
14
application/viewmodel/passwordreset.go
Normal file
14
application/viewmodel/passwordreset.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type PasswordReset struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
User User `json:"user"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
Created time.Time `json:"create_date"`
|
||||||
|
Expires time.Time `json:"expire_date"`
|
||||||
|
Used bool `json:"used"`
|
||||||
|
Opened bool `json:"opened"`
|
||||||
|
}
|
||||||
@@ -14,50 +14,53 @@ type WebhookResponse struct {
|
|||||||
|
|
||||||
//RideRequest has the data to dispatch a ride
|
//RideRequest has the data to dispatch a ride
|
||||||
type RideRequest struct {
|
type RideRequest struct {
|
||||||
UserUUID string `json:"user_uuid,omitempty"`
|
UserUUID string `json:"user_uuid,omitempty"`
|
||||||
UserConsent bool `json:"user_consent,omitempty"`
|
UserConsent bool `json:"user_consent,omitempty"`
|
||||||
Status string `json:"status,omitempty"`
|
Status string `json:"status,omitempty"`
|
||||||
RideID string `json:"ride_id,omitempty"`
|
RideID string `json:"ride_id,omitempty"`
|
||||||
RideType string `json:"ride_type,omitempty"`
|
RideType string `json:"ride_type,omitempty"`
|
||||||
Origin Location `json:"origin,omitempty"`
|
Origin Location `json:"origin,omitempty"`
|
||||||
Location Location `json:"location,omitempty"`
|
Location Location `json:"location,omitempty"`
|
||||||
Destination Location `json:"destination,omitempty"`
|
Destination Location `json:"destination,omitempty"`
|
||||||
Passenger UserLyft `json:"passenger,omitempty"`
|
Passenger UserLyft `json:"passenger,omitempty"`
|
||||||
Notes string `json:"external_note,omitempty"`
|
Notes string `json:"external_note,omitempty"`
|
||||||
RouteURL string `json:"route_url,omitempty"`
|
RouteURL string `json:"route_url,omitempty"`
|
||||||
ScheduledPickupRange interface{} `json:"scheduled_pickup_range,omitempty"`
|
ScheduledPickupRange interface{} `json:"scheduled_pickup_range,omitempty"`
|
||||||
PrimetimePercentage string `json:"primetime_percentage,omitempty"`
|
PrimetimePercentage string `json:"primetime_percentage,omitempty"`
|
||||||
Pickup Location `json:"pickup,omitempty"`
|
Pickup Location `json:"pickup,omitempty"`
|
||||||
DropOff Location `json:"dropoff,omitempty"`
|
DropOff Location `json:"dropoff,omitempty"`
|
||||||
Vehicle Vehicle `json:"vehicle,omitempty"`
|
Vehicle Vehicle `json:"vehicle,omitempty"`
|
||||||
Price Price `json:"price,omitempty"`
|
Price Price `json:"price,omitempty"`
|
||||||
Driver UserLyft `json:"driver,omitempty"`
|
Driver UserLyft `json:"driver,omitempty"`
|
||||||
GeneratedAtMS *int64 `json:"generated_at_ms,omitempty"`
|
GeneratedAtMS *int64 `json:"generated_at_ms,omitempty"`
|
||||||
GeneratedAt *time.Time `json:"generated_at,omitempty"`
|
GeneratedAt *time.Time `json:"generated_at,omitempty"`
|
||||||
RequestAtMS *int64 `json:"requested_at_ms,omitempty"`
|
RequestAtMS *int64 `json:"requested_at_ms,omitempty"`
|
||||||
RequestAt *time.Time `json:"requested_at,omitempty"`
|
RequestAt *time.Time `json:"requested_at,omitempty"`
|
||||||
LineItems []Price `json:"line_items,omitempty"`
|
LineItems []Price `json:"line_items,omitempty"`
|
||||||
BeaconColor string `json:"beacon_color,omitempty"`
|
BeaconColor string `json:"beacon_color,omitempty"`
|
||||||
Charges []Charge `json:"charges,omitempty"`
|
Charges []Charge `json:"charges,omitempty"`
|
||||||
VisitDate *time.Time `json:"visit_date,omitempty"`
|
VisitDate *time.Time `json:"visit_date,omitempty"`
|
||||||
VisitTime *time.Time `json:"visit_time,omitempty"`
|
VisitTime *time.Time `json:"visit_time,omitempty"`
|
||||||
PickupTime *time.Time `json:"pickup_time,omitempty"`
|
PickupTime *time.Time `json:"pickup_time,omitempty"`
|
||||||
ReturnTime *time.Time `json:"return_time,omitempty"`
|
ReturnTime *time.Time `json:"return_time,omitempty"`
|
||||||
Distance float64 `json:"distance,omitempty"`
|
Distance float64 `json:"distance,omitempty"`
|
||||||
ETA int64 `json:"eta,omitempty"`
|
ETA int64 `json:"eta,omitempty"`
|
||||||
Duration int64 `json:"duration,omitempty"`
|
Duration int64 `json:"duration,omitempty"`
|
||||||
Visit Visit `json:"visit,omitempty"`
|
Visit Visit `json:"visit,omitempty"`
|
||||||
CreateUserUUID string `json:"created_user_uuid,omitempty"`
|
CreateUserUUID string `json:"created_user_uuid,omitempty"`
|
||||||
VisitExternalID string `json:"visit_external_id,omitempty"`
|
VisitExternalID string `json:"visit_external_id,omitempty"`
|
||||||
CanCancel []string `json:"can_cancel,omitempty"`
|
CanCancel []string `json:"can_cancel,omitempty"`
|
||||||
PricingDetailsURL string `json:"pricing_details_url,omitempty"`
|
PricingDetailsURL string `json:"pricing_details_url,omitempty"`
|
||||||
RideProfile string `json:"ride_profile,omitempty"`
|
RideProfile string `json:"ride_profile,omitempty"`
|
||||||
DistanceInMiles float64 `json:"distance_miles,omitempty"`
|
DistanceInMiles float64 `json:"distance_miles,omitempty"`
|
||||||
DurationInSeconds float64 `json:"duration_seconds,omitempty"`
|
DurationInSeconds float64 `json:"duration_seconds,omitempty"`
|
||||||
CanceledBy string `json:"canceled_by,omitempty"`
|
CanceledBy string `json:"canceled_by,omitempty"`
|
||||||
TripType TripType `json:"trip_type,omitempty"`
|
TripType TripType `json:"trip_type,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
ErrorDescription string `json:"error_description,omitempty"`
|
ErrorDescription string `json:"error_description,omitempty"`
|
||||||
|
User User `json:"user,omitempty"`
|
||||||
|
Provider ProviderResp `json:"provider,omitempty"`
|
||||||
|
RawProvider ProviderResponse `json:"raw_provider,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//Charge information
|
//Charge information
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type User struct {
|
|||||||
Organizations []Organization `json:"organizations,omitempty"`
|
Organizations []Organization `json:"organizations,omitempty"`
|
||||||
Provider *ProviderResp `json:"provider,omitempty"`
|
Provider *ProviderResp `json:"provider,omitempty"`
|
||||||
Consent bool `json:"consent,omitempty"`
|
Consent bool `json:"consent,omitempty"`
|
||||||
|
Test bool `json:"test,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Contact struct {
|
type Contact struct {
|
||||||
|
|||||||
@@ -113,3 +113,10 @@ p, BCBSIAD, *, bcbsi, *, *, *, /v1/nemt/eligibility, POST
|
|||||||
p, BDCAD, *, techsupport, *, *, *, /v1/nemt/eligibility, POST
|
p, BDCAD, *, techsupport, *, *, *, /v1/nemt/eligibility, POST
|
||||||
p, PLANAD, *, plan, *, *, *, /v1/nemt/eligibility, POST
|
p, PLANAD, *, plan, *, *, *, /v1/nemt/eligibility, POST
|
||||||
p, AD, *, *, *, *, *, /v1/nemt/eligibility, POST
|
p, AD, *, *, *, *, *, /v1/nemt/eligibility, POST
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/users/member, POST
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/users/member, GET
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/eligibility, POST
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/visits, POST
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/rides/eta, GET
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/nemt/provider, GET
|
||||||
|
p, VIRPT, *, *, *, *, *, /v1/selfregister, POST
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
[app]
|
[app]
|
||||||
name = "nemt"
|
name = "nemt"
|
||||||
debug = true
|
debug = true
|
||||||
|
disable-zip-validation = true
|
||||||
|
|
||||||
[app.docs]
|
[app.docs]
|
||||||
swagger-path = "./static/swagger-ui"
|
swagger-path = "./static/swagger-ui"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[app]
|
[app]
|
||||||
name = "nemt"
|
name = "nemt"
|
||||||
debug = true
|
debug = true
|
||||||
|
disable-zip-validation = true
|
||||||
|
|
||||||
[app.docs]
|
[app.docs]
|
||||||
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||||
@@ -9,7 +10,7 @@ debug = true
|
|||||||
[db]
|
[db]
|
||||||
host = "db01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
host = "db01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
||||||
port = 3306
|
port = 3306
|
||||||
name = "nemt_clean"
|
name = "nemt"
|
||||||
user = "nemt-user"
|
user = "nemt-user"
|
||||||
pass = "OL&!n#p6J8Lu"
|
pass = "OL&!n#p6J8Lu"
|
||||||
max-life-minutes = 5
|
max-life-minutes = 5
|
||||||
@@ -74,8 +75,8 @@ user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
|
|||||||
|
|
||||||
[bxe]
|
[bxe]
|
||||||
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
||||||
key = "dacg7jtsmb6ajr3z553jbczg"
|
key = "c63z7gv9a5qz2zgx7zcm3253"
|
||||||
secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
|
secret = "hK4Yc9jtBrxaZTr4UU2VsfX9"
|
||||||
|
|
||||||
[blue365]
|
[blue365]
|
||||||
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[app]
|
[app]
|
||||||
name = "nemt"
|
name = "nemt"
|
||||||
debug = true
|
debug = true
|
||||||
|
disable-zip-validation = true
|
||||||
|
|
||||||
[app.docs]
|
[app.docs]
|
||||||
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||||
|
|||||||
@@ -20,16 +20,17 @@ var (
|
|||||||
|
|
||||||
// Conn is the MySQL connection manager
|
// Conn is the MySQL connection manager
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
users *userRepo
|
users *userRepo
|
||||||
rides *rideRepo
|
rides *rideRepo
|
||||||
visit *visitRepo
|
visit *visitRepo
|
||||||
provider *providerRepo
|
provider *providerRepo
|
||||||
notification *notificationRepo
|
notification *notificationRepo
|
||||||
profile *profileRepo
|
profile *profileRepo
|
||||||
organization *organizationRepo
|
organization *organizationRepo
|
||||||
zipcodes *zipcodeRepo
|
zipcodes *zipcodeRepo
|
||||||
plan *planRepo
|
plan *planRepo
|
||||||
|
passwordReset *passwordResetRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin starts a transaction
|
// Begin starts a transaction
|
||||||
@@ -90,6 +91,10 @@ func (c *Conn) Plans() contract.PlanRepo {
|
|||||||
return c.plan
|
return c.plan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Conn) PasswordReset() contract.PasswordResetRepo {
|
||||||
|
return c.passwordReset
|
||||||
|
}
|
||||||
|
|
||||||
// Instance returns an instance of a DataManager
|
// Instance returns an instance of a DataManager
|
||||||
func Instance(cfg *config.Config) (contract.DataManager, error) {
|
func Instance(cfg *config.Config) (contract.DataManager, error) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
@@ -123,6 +128,7 @@ func Instance(cfg *config.Config) (contract.DataManager, error) {
|
|||||||
instance.organization = newOrganizationRepo(db)
|
instance.organization = newOrganizationRepo(db)
|
||||||
instance.zipcodes = newZipcodeRepo(db)
|
instance.zipcodes = newZipcodeRepo(db)
|
||||||
instance.plan = newPlanRepo(db)
|
instance.plan = newPlanRepo(db)
|
||||||
|
instance.passwordReset = newPasswordResetRepo(db)
|
||||||
})
|
})
|
||||||
|
|
||||||
return instance, connErr
|
return instance, connErr
|
||||||
|
|||||||
144
data/datamysql/passwordreset.go
Normal file
144
data/datamysql/passwordreset.go
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideRepo maps methods to database
|
||||||
|
type passwordResetRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPasswordResetRepo(conn executor) *passwordResetRepo {
|
||||||
|
return &passwordResetRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) getQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.password_reset_id,
|
||||||
|
a.password_reset_uuid,
|
||||||
|
a.user_id,
|
||||||
|
b.user_uuid,
|
||||||
|
a.token,
|
||||||
|
a.create_date,
|
||||||
|
a.expire_date,
|
||||||
|
(IFNULL(a.used, b'0') = b'1') used,
|
||||||
|
(IFNULL(a.opened, b'0') = b'1') opened
|
||||||
|
FROM
|
||||||
|
tab_password_reset a
|
||||||
|
INNER JOIN tab_user b
|
||||||
|
ON a.user_id = b.user_id`
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *passwordResetRepo) parseSet(rows *sql.Rows, err error) ([]entity.PasswordReset, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.PasswordReset, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseEntity(rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result = append(result, entity)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseEntity parses a result to an entity
|
||||||
|
func (c *passwordResetRepo) parseEntity(row scanner) (retVal entity.PasswordReset, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.User.ID, &retVal.User.UUID, &retVal.Token, &retVal.Created, &retVal.Expires, &retVal.Used, &retVal.Opened)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) GetAll() ([]entity.PasswordReset, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) CreatePasswordResetEntry(passwordResetEntry entity.PasswordReset) (entity.PasswordReset, error) {
|
||||||
|
const (
|
||||||
|
insertQuery = `INSERT INTO tab_password_reset(password_reset_uuid, user_id, token, expire_date, used, opened) VALUES(?, ?, ?, ?, 0, 0);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal := passwordResetEntry
|
||||||
|
guid, _ := uuid.NewV4()
|
||||||
|
|
||||||
|
userRepo := newUserRepo(c.conn)
|
||||||
|
|
||||||
|
fullUser, err := userRepo.GetByEmail(passwordResetEntry.User.Email)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fullUser.Email != passwordResetEntry.User.Email {
|
||||||
|
return retVal, fmt.Errorf("User not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := c.conn.Exec(insertQuery, guid, fullUser.ID, passwordResetEntry.Token, passwordResetEntry.Expires)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.GetByID(retVal.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) GetByID(ID int64) (entity.PasswordReset, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.password_reset_id = ?; ", ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) GetByToken(token string) (entity.PasswordReset, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.token = ? AND a.used = 0; ", token))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) SetTokenOpened(token string) error {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_password_reset a
|
||||||
|
SET a.opened = 1
|
||||||
|
WHERE a.token = ? AND a.used = 0 AND a.expire_date > CURRENT_TIMESTAMP`
|
||||||
|
)
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, token)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if updateCount, err := result.RowsAffected(); err != nil || updateCount == 0 {
|
||||||
|
return fmt.Errorf("Invalid token")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *passwordResetRepo) SetTokenUsed(token string) error {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_password_reset a
|
||||||
|
SET a.opened = 1,
|
||||||
|
a.used = 1
|
||||||
|
WHERE a.token = ? AND a.used = 0`
|
||||||
|
)
|
||||||
|
|
||||||
|
if _, err := c.conn.Exec(query, token); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ func (c *rideRepo) getQuery() string {
|
|||||||
b.user_id,
|
b.user_id,
|
||||||
b.user_uuid,
|
b.user_uuid,
|
||||||
b.name,
|
b.name,
|
||||||
b.member,
|
b.subscriber_id,
|
||||||
c.ride_status_id,
|
c.ride_status_id,
|
||||||
c.ride_status,
|
c.ride_status,
|
||||||
c.key ride_status_key,
|
c.key ride_status_key,
|
||||||
@@ -514,14 +514,14 @@ func (c *rideRepo) saveHeader(ride entity.Ride) (retVal entity.Ride, err error)
|
|||||||
dataQuery = `SELECT
|
dataQuery = `SELECT
|
||||||
a.user_id user_id,
|
a.user_id user_id,
|
||||||
a.name,
|
a.name,
|
||||||
a.member,
|
a.subscriber_id,
|
||||||
b.ride_status_id,
|
b.ride_status_id,
|
||||||
b.ride_status,
|
b.ride_status,
|
||||||
c.ride_type_id,
|
c.ride_type_id,
|
||||||
c.value ride_type,
|
c.value ride_type,
|
||||||
d.user_id created_user_id,
|
d.user_id created_user_id,
|
||||||
d.name created_name,
|
d.name created_name,
|
||||||
IFNULL(d.member, '') created_member,
|
IFNULL(d.subscriber_id, '') created_member,
|
||||||
e.trip_type_id,
|
e.trip_type_id,
|
||||||
e.trip_type_key,
|
e.trip_type_key,
|
||||||
e.trip_type
|
e.trip_type
|
||||||
|
|||||||
@@ -8,16 +8,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type transaction struct {
|
type transaction struct {
|
||||||
tx *sql.Tx
|
tx *sql.Tx
|
||||||
users *userRepo
|
users *userRepo
|
||||||
rides *rideRepo
|
rides *rideRepo
|
||||||
visits *visitRepo
|
visits *visitRepo
|
||||||
provider *providerRepo
|
provider *providerRepo
|
||||||
notification *notificationRepo
|
notification *notificationRepo
|
||||||
profile *profileRepo
|
profile *profileRepo
|
||||||
organization *organizationRepo
|
organization *organizationRepo
|
||||||
zipcodes *zipcodeRepo
|
zipcodes *zipcodeRepo
|
||||||
plan *planRepo
|
plan *planRepo
|
||||||
|
passwordReset *passwordResetRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTransaction(tx *sql.Tx) *transaction {
|
func newTransaction(tx *sql.Tx) *transaction {
|
||||||
@@ -34,6 +35,7 @@ func newTransaction(tx *sql.Tx) *transaction {
|
|||||||
t.organization = newOrganizationRepo(tx)
|
t.organization = newOrganizationRepo(tx)
|
||||||
t.zipcodes = newZipcodeRepo(tx)
|
t.zipcodes = newZipcodeRepo(tx)
|
||||||
t.plan = newPlanRepo(tx)
|
t.plan = newPlanRepo(tx)
|
||||||
|
t.passwordReset = newPasswordResetRepo(tx)
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
@@ -81,6 +83,10 @@ func (t transaction) Plans() contract.PlanRepo {
|
|||||||
return t.plan
|
return t.plan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t transaction) PasswordReset() contract.PasswordResetRepo {
|
||||||
|
return t.passwordReset
|
||||||
|
}
|
||||||
|
|
||||||
func (t *transaction) Commit() error {
|
func (t *transaction) Commit() error {
|
||||||
|
|
||||||
err := t.tx.Commit()
|
err := t.tx.Commit()
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func newUserRepo(conn executor) *userRepo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *userRepo) GetByMemberID(memberID string) (entity.User, error) {
|
func (c *userRepo) GetByMemberID(memberID string) (entity.User, error) {
|
||||||
finalQuery := c.getQuery() + " AND a.member = ? AND e.key = 'US'"
|
finalQuery := c.getQuery() + " AND a.subscriber_id = ? AND e.key = 'US'"
|
||||||
|
|
||||||
user, err := c.parseSet(c.conn.Query(finalQuery, memberID))
|
user, err := c.parseSet(c.conn.Query(finalQuery, memberID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -48,6 +48,32 @@ func (c *userRepo) GetByMemberID(memberID string) (entity.User, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetByEmail(email string) (entity.User, error) {
|
||||||
|
finalQuery := c.getQuery() + " AND b.email = ?"
|
||||||
|
|
||||||
|
user, err := c.parseSet(c.conn.Query(finalQuery, email))
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user) > 0 {
|
||||||
|
retVal := user[0]
|
||||||
|
retVal.Contacts, err = c.GetContacts(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Addresses = nil
|
||||||
|
retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
} else {
|
||||||
|
return entity.User{}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) {
|
func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) {
|
||||||
params := make([]interface{}, 0)
|
params := make([]interface{}, 0)
|
||||||
params = append(params, uuid)
|
params = append(params, uuid)
|
||||||
@@ -192,7 +218,7 @@ func (c *userRepo) parseEntity(row scanner) (retVal entity.User, err error) {
|
|||||||
|
|
||||||
err = row.Scan(&retVal.ID, &retVal.UUID, &retVal.Name, &retVal.Member, &birthDate, &retVal.LoginID, &retVal.LoginUUID, &retVal.Email, &retVal.PhoneNumber, &retVal.LoginKey, &retVal.Gender, &retVal.Active, &retVal.Created, &retVal.Updated, &profile.ID, &profile.Name, &profile.Key, &profile.Active, &profile.Blocked, &profile.Suspended, &profile.Created, &profile.Updated, &profile.Organization.ID, &profile.Organization.UUID, &profile.Organization.Type.ID, &profile.Organization.Type.Name, &profile.Organization.Type.Key, &profile.Organization.Type.Description, &profile.Organization.Name, &profile.Organization.Description, &profile.Organization.ReferenceID, &profile.Organization.ParentID, &profile.Organization.Main,
|
err = row.Scan(&retVal.ID, &retVal.UUID, &retVal.Name, &retVal.Member, &birthDate, &retVal.LoginID, &retVal.LoginUUID, &retVal.Email, &retVal.PhoneNumber, &retVal.LoginKey, &retVal.Gender, &retVal.Active, &retVal.Created, &retVal.Updated, &profile.ID, &profile.Name, &profile.Key, &profile.Active, &profile.Blocked, &profile.Suspended, &profile.Created, &profile.Updated, &profile.Organization.ID, &profile.Organization.UUID, &profile.Organization.Type.ID, &profile.Organization.Type.Name, &profile.Organization.Type.Key, &profile.Organization.Type.Description, &profile.Organization.Name, &profile.Organization.Description, &profile.Organization.ReferenceID, &profile.Organization.ParentID, &profile.Organization.Main,
|
||||||
&homeAddress.ID, &homeAddress.UUID, &homeAddress.AddressType.ID, &homeAddress.AddressType.Key, &homeAddress.AddressType.Name, &homeAddress.Name, &homeAddress.Address, &homeAddress.Latitude, &homeAddress.Longitude,
|
&homeAddress.ID, &homeAddress.UUID, &homeAddress.AddressType.ID, &homeAddress.AddressType.Key, &homeAddress.AddressType.Name, &homeAddress.Name, &homeAddress.Address, &homeAddress.Latitude, &homeAddress.Longitude,
|
||||||
&workAddress.ID, &workAddress.UUID, &workAddress.AddressType.ID, &workAddress.AddressType.Key, &workAddress.AddressType.Name, &workAddress.Name, &workAddress.Address, &workAddress.Latitude, &workAddress.Longitude)
|
&workAddress.ID, &workAddress.UUID, &workAddress.AddressType.ID, &workAddress.AddressType.Key, &workAddress.AddressType.Name, &workAddress.Name, &workAddress.Address, &workAddress.Latitude, &workAddress.Longitude, &retVal.Type, &retVal.Test)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != sql.ErrNoRows {
|
if err != sql.ErrNoRows {
|
||||||
return retVal, errors.Wrap(err)
|
return retVal, errors.Wrap(err)
|
||||||
@@ -230,7 +256,7 @@ func (c *userRepo) getQuery() string {
|
|||||||
a.user_id,
|
a.user_id,
|
||||||
a.user_uuid,
|
a.user_uuid,
|
||||||
a.name,
|
a.name,
|
||||||
IFNULL(a.member, '') member,
|
IFNULL(a.subscriber_id, '') subscriber_id,
|
||||||
a.birth_date,
|
a.birth_date,
|
||||||
b.login_id,
|
b.login_id,
|
||||||
b.login_uuid,
|
b.login_uuid,
|
||||||
@@ -260,24 +286,26 @@ func (c *userRepo) getQuery() string {
|
|||||||
IFNULL(f.organization_reference_id, 0) organization_reference_id,
|
IFNULL(f.organization_reference_id, 0) organization_reference_id,
|
||||||
IFNULL(f.organization_parent_id, 0) organization_parent_id,
|
IFNULL(f.organization_parent_id, 0) organization_parent_id,
|
||||||
(IFNULL(f.main_organization, b'0') = b'1') main_organization,
|
(IFNULL(f.main_organization, b'0') = b'1') main_organization,
|
||||||
IFNULL(h.address_id, 0) home_address_id,
|
IFNULL(h.address_id, 0) home_address_id,
|
||||||
IFNULL(h.address_uuid, '') home_address_uuid,
|
IFNULL(h.address_uuid, '') home_address_uuid,
|
||||||
IFNULL(h.address_type_id, 0) home_address_type_id,
|
IFNULL(h.address_type_id, 0) home_address_type_id,
|
||||||
IFNULL(h.address_type_key, '') home_address_type_key,
|
IFNULL(h.address_type_key, '') home_address_type_key,
|
||||||
IFNULL(h.address_type_name, '') home_address_type_name,
|
IFNULL(h.address_type_name, '') home_address_type_name,
|
||||||
IFNULL(h.name, '') home_name,
|
IFNULL(h.name, '') home_name,
|
||||||
IFNULL(h.address, '') home_address,
|
IFNULL(h.address, '') home_address,
|
||||||
IFNULL(h.lat, 0) home_lat,
|
IFNULL(h.lat, 0) home_lat,
|
||||||
IFNULL(h.long, 0) home_long,
|
IFNULL(h.long, 0) home_long,
|
||||||
IFNULL(i.address_id, 0) work_address_id,
|
IFNULL(i.address_id, 0) work_address_id,
|
||||||
IFNULL(i.address_uuid, '') work_address_uuid,
|
IFNULL(i.address_uuid, '') work_address_uuid,
|
||||||
IFNULL(i.address_type_id, 0) work_address_type_id,
|
IFNULL(i.address_type_id, 0) work_address_type_id,
|
||||||
IFNULL(i.address_type_key, '') work_address_type_key,
|
IFNULL(i.address_type_key, '') work_address_type_key,
|
||||||
IFNULL(i.address_type_name, '') work_address_type_name,
|
IFNULL(i.address_type_name, '') work_address_type_name,
|
||||||
IFNULL(i.name, '') work_name,
|
IFNULL(i.name, '') work_name,
|
||||||
IFNULL(i.address, '') work_address,
|
IFNULL(i.address, '') work_address,
|
||||||
IFNULL(i.lat, 0) work_lat,
|
IFNULL(i.lat, 0) work_lat,
|
||||||
IFNULL(i.long, 0) work_long
|
IFNULL(i.long, 0) work_long,
|
||||||
|
IFNULL(a.member_type, 'S') member_type,
|
||||||
|
user_test
|
||||||
FROM
|
FROM
|
||||||
tab_user a
|
tab_user a
|
||||||
INNER JOIN
|
INNER JOIN
|
||||||
@@ -521,7 +549,7 @@ func (c *userRepo) addProfileToUser(loginID int64, profileID int64, organization
|
|||||||
|
|
||||||
func (c *userRepo) getUserByMember(u entity.User) (user entity.User, err error) {
|
func (c *userRepo) getUserByMember(u entity.User) (user entity.User, err error) {
|
||||||
user = u
|
user = u
|
||||||
users, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.active = 1 AND e.key = 'US' AND IFNULL(a.member, '') = ?;", u.Member))
|
users, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.active = 1 AND e.key = 'US' AND IFNULL(a.subscriber_id, '') = ?;", u.Member))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, errors.Wrap(err)
|
return user, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
@@ -586,11 +614,11 @@ func (c *userRepo) createLogin(user entity.User) (int64, string, error) {
|
|||||||
|
|
||||||
func (c *userRepo) createUser(user entity.User) (int64, string, error) {
|
func (c *userRepo) createUser(user entity.User) (int64, string, error) {
|
||||||
const (
|
const (
|
||||||
query = "INSERT INTO tab_user(user_uuid, `name`, member, birth_date, gender) VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE user_uuid = ?, `name` = ?, member = ?, birth_date = ?, gender = ?;"
|
query = "INSERT INTO tab_user(user_uuid, `name`, subscriber_id, birth_date, gender, member_type, user_hash, user_test) VALUES(?, ?, ?, ?, ?, ?, SHA2(CONCAT_WS('-',?,?,?,?,?), 512), ?) ON DUPLICATE KEY UPDATE user_uuid = ?, `name` = ?, subscriber_id = ?, birth_date = ?, gender = ?, user_test = ?;"
|
||||||
)
|
)
|
||||||
guid, _ := uuid.NewV4()
|
guid, _ := uuid.NewV4()
|
||||||
|
|
||||||
result, err := c.conn.Exec(query, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender))
|
result, err := c.conn.Exec(query, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), user.Type, user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), user.Type, user.Test, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), user.Test)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, "", err
|
return 0, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func (c *visitRepo) getQuery() string {
|
|||||||
a.user_id,
|
a.user_id,
|
||||||
c.user_uuid,
|
c.user_uuid,
|
||||||
c.name user_name,
|
c.name user_name,
|
||||||
c.member user_member,
|
c.subscriber_id user_member,
|
||||||
c.birth_date user_birth_date,
|
c.birth_date user_birth_date,
|
||||||
c.gender user_gender,
|
c.gender user_gender,
|
||||||
a.visit_datetime,
|
a.visit_datetime,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type repoManager interface {
|
|||||||
Organization() OrganizationRepo
|
Organization() OrganizationRepo
|
||||||
Zipcodes() ZipcodeRepo
|
Zipcodes() ZipcodeRepo
|
||||||
Plans() PlanRepo
|
Plans() PlanRepo
|
||||||
|
PasswordReset() PasswordResetRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserRepo defines the data set for users
|
// UserRepo defines the data set for users
|
||||||
@@ -22,6 +23,7 @@ type UserRepo interface {
|
|||||||
GetByID(userID int64) (retVal entity.User, err error)
|
GetByID(userID int64) (retVal entity.User, err error)
|
||||||
GetByUUID(uuid string, profile string) (entity.User, error)
|
GetByUUID(uuid string, profile string) (entity.User, error)
|
||||||
GetByMemberID(memberID string) (entity.User, error)
|
GetByMemberID(memberID string) (entity.User, error)
|
||||||
|
GetByEmail(email string) (entity.User, error)
|
||||||
Login(email string, pass string) (entity.User, error)
|
Login(email string, pass string) (entity.User, error)
|
||||||
FullLogin(loginType string, key string, pass string, profile string) (entity.User, error)
|
FullLogin(loginType string, key string, pass string, profile string) (entity.User, error)
|
||||||
Create(user entity.User) (entity.User, error)
|
Create(user entity.User) (entity.User, error)
|
||||||
@@ -124,3 +126,12 @@ type ZipcodeRepo interface {
|
|||||||
GetAll() ([]entity.Zipcode, error)
|
GetAll() ([]entity.Zipcode, error)
|
||||||
GetByParticipatingZipcode(zipcode string) (entity.Zipcode, error)
|
GetByParticipatingZipcode(zipcode string) (entity.Zipcode, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PasswordResetRepo interface {
|
||||||
|
GetAll() ([]entity.PasswordReset, error)
|
||||||
|
CreatePasswordResetEntry(passwordResetEntry entity.PasswordReset) (entity.PasswordReset, error)
|
||||||
|
GetByID(ID int64) (entity.PasswordReset, error)
|
||||||
|
GetByToken(token string) (entity.PasswordReset, error)
|
||||||
|
SetTokenOpened(token string) error
|
||||||
|
SetTokenUsed(token string) error
|
||||||
|
}
|
||||||
|
|||||||
14
domain/entity/passwordreset.go
Normal file
14
domain/entity/passwordreset.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type PasswordReset struct {
|
||||||
|
ID int64 `db:"password_reset_id" json:"-"`
|
||||||
|
UUID string `db:"password_reset_uuid" json:"uuid"`
|
||||||
|
User User `db:"-" json:"user"`
|
||||||
|
Token string `db:"token" json:"token"`
|
||||||
|
Created time.Time `db:"create_date" json:"create_date"`
|
||||||
|
Expires time.Time `db:"expire_date" json:"expire_date"`
|
||||||
|
Used bool `db:"used" json:"used"`
|
||||||
|
Opened bool `db:"opend" json:"opened"`
|
||||||
|
}
|
||||||
@@ -30,6 +30,8 @@ type User struct {
|
|||||||
Profiles []Profile `json:"profiles,omitempty"`
|
Profiles []Profile `json:"profiles,omitempty"`
|
||||||
Types []OrganizationType `json:"types,omitempty"`
|
Types []OrganizationType `json:"types,omitempty"`
|
||||||
Organizations []Organization `json:"organizations,omitempty"`
|
Organizations []Organization `json:"organizations,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Test bool `json:"test,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContactInfo struct {
|
type ContactInfo struct {
|
||||||
|
|||||||
41
domain/service/passwordreset.go
Normal file
41
domain/service/passwordreset.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type passwordResetService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newPasswordResetService(svc *Service) *passwordResetService {
|
||||||
|
return &passwordResetService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetAll() ([]entity.PasswordReset, error) {
|
||||||
|
return s.svc.db.PasswordReset().GetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetByID(ID int64) (entity.PasswordReset, error) {
|
||||||
|
return s.svc.db.PasswordReset().GetByID(ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) GetByToken(token string) (entity.PasswordReset, error) {
|
||||||
|
return s.svc.db.PasswordReset().GetByToken(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) CreatePasswordResetEntry(passwordResetEntry entity.PasswordReset) (entity.PasswordReset, error) {
|
||||||
|
return s.svc.db.PasswordReset().CreatePasswordResetEntry(passwordResetEntry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) SetTokenOpened(token string) error {
|
||||||
|
return s.svc.db.PasswordReset().SetTokenOpened(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *passwordResetService) SetTokenUsed(token string) error {
|
||||||
|
return s.svc.db.PasswordReset().SetTokenUsed(token)
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,11 +22,13 @@ func newRideService(svc *Service) *rideService {
|
|||||||
func (s *rideService) Save(ride entity.Ride) (entity.Ride, error) {
|
func (s *rideService) Save(ride entity.Ride) (entity.Ride, error) {
|
||||||
ride, err := s.svc.db.Rides().Save(ride)
|
ride, err := s.svc.db.Rides().Save(ride)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Service.Save: Error saving Ride: ", err.Error())
|
||||||
return ride, err
|
return ride, err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := s.svc.db.Users().GetByID(ride.CreatedUser.ID)
|
user, err := s.svc.db.Users().GetByID(ride.CreatedUser.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Service.Save: Error getting User: ", err.Error())
|
||||||
return ride, err
|
return ride, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +62,8 @@ func (s *rideService) GetByID(id int64, user entity.User) (entity.Ride, error) {
|
|||||||
func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
|
func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
|
||||||
ride, err := s.svc.db.Rides().GetByUUID(uuid, user)
|
ride, err := s.svc.db.Rides().GetByUUID(uuid, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Ride Service.GetByUUID: Ride UUID: ", uuid)
|
||||||
|
fmt.Println("Ride Service.GetByUUID: Error getting Ride: ", err.Error())
|
||||||
return entity.Ride{}, err
|
return entity.Ride{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,19 @@ var (
|
|||||||
|
|
||||||
// Service holds the domain service repositories
|
// Service holds the domain service repositories
|
||||||
type Service struct {
|
type Service struct {
|
||||||
db contract.DataManager
|
db contract.DataManager
|
||||||
cache contract.CacheManager
|
cache contract.CacheManager
|
||||||
tnc contract.TNCManager
|
tnc contract.TNCManager
|
||||||
Users *userService
|
Users *userService
|
||||||
Rides *rideService
|
Rides *rideService
|
||||||
Visits *visitService
|
Visits *visitService
|
||||||
Provider *providerService
|
Provider *providerService
|
||||||
Notification *notificationService
|
Notification *notificationService
|
||||||
Profile *profileService
|
Profile *profileService
|
||||||
Organization *organizationService
|
Organization *organizationService
|
||||||
Zipcodes *zipcodeService
|
Zipcodes *zipcodeService
|
||||||
Plans *planService
|
Plans *planService
|
||||||
|
PasswordReset *passwordResetService
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new domain Service instance
|
// New returns a new domain Service instance
|
||||||
@@ -43,6 +44,7 @@ func New(db contract.DataManager, cache contract.CacheManager, cfg *config.Confi
|
|||||||
instance.Organization = newOrganizationService(instance)
|
instance.Organization = newOrganizationService(instance)
|
||||||
instance.Zipcodes = newZipcodeService(instance)
|
instance.Zipcodes = newZipcodeService(instance)
|
||||||
instance.Plans = newPlanService(instance)
|
instance.Plans = newPlanService(instance)
|
||||||
|
instance.PasswordReset = newPasswordResetService(instance)
|
||||||
})
|
})
|
||||||
|
|
||||||
return instance, nil
|
return instance, nil
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ func (s *userService) GetByMemberID(memberID string) (entity.User, error) {
|
|||||||
return s.svc.db.Users().GetByMemberID(memberID)
|
return s.svc.db.Users().GetByMemberID(memberID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *userService) GetByEmail(email string) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().GetByEmail(email)
|
||||||
|
}
|
||||||
|
|
||||||
// Login returns a specific user by email and pass
|
// Login returns a specific user by email and pass
|
||||||
func (s *userService) Login(email string, pass string) (entity.User, error) {
|
func (s *userService) Login(email string, pass string) (entity.User, error) {
|
||||||
return s.svc.db.Users().Login(email, pass)
|
return s.svc.db.Users().Login(email, pass)
|
||||||
@@ -72,7 +76,7 @@ func (s *userService) CreateBulk(users []entity.User) ([]entity.User, error) {
|
|||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *userService) UpdateLogin(user entity.User) error {
|
func (s *userService) UpdateLogin(user entity.User) error {
|
||||||
return s.svc.db.Users().UpdateLogin(user)
|
return s.svc.db.Users().UpdateLogin(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ type Config struct {
|
|||||||
Blue365 Blue365Config
|
Blue365 Blue365Config
|
||||||
Email EmailConfig
|
Email EmailConfig
|
||||||
GoogleShortener GoogleShortenerConfig
|
GoogleShortener GoogleShortenerConfig
|
||||||
Eligibility EligibilityConfig
|
Eligibility EligibilityConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppConfig represents the configuration values about the application.
|
// AppConfig represents the configuration values about the application.
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
Name string
|
Name string
|
||||||
Debug bool
|
Debug bool
|
||||||
Docs DocsConfig
|
Docs DocsConfig
|
||||||
|
DisableZipValidation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TwilioConfig represents the configuration values about the twilio.
|
// TwilioConfig represents the configuration values about the twilio.
|
||||||
@@ -139,7 +140,7 @@ type GoogleShortenerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EligibilityConfig struct {
|
type EligibilityConfig struct {
|
||||||
Url string
|
Url string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read returns the configuration values,
|
// Read returns the configuration values,
|
||||||
@@ -160,8 +161,9 @@ func Read() (*Config, error) {
|
|||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
App: AppConfig{
|
App: AppConfig{
|
||||||
Name: viper.GetString("app.name"),
|
Name: viper.GetString("app.name"),
|
||||||
Debug: viper.GetBool("app.debug"),
|
Debug: viper.GetBool("app.debug"),
|
||||||
|
DisableZipValidation: viper.GetBool("app.disable-zip-validation"),
|
||||||
Docs: DocsConfig{
|
Docs: DocsConfig{
|
||||||
YAMLPath: viper.GetString("app.docs.yaml-path"),
|
YAMLPath: viper.GetString("app.docs.yaml-path"),
|
||||||
SwaggerPath: viper.GetString("app.docs.swagger-path"),
|
SwaggerPath: viper.GetString("app.docs.swagger-path"),
|
||||||
@@ -243,8 +245,8 @@ func Read() (*Config, error) {
|
|||||||
ClientID: viper.GetString("google-shortener.client-id"),
|
ClientID: viper.GetString("google-shortener.client-id"),
|
||||||
SecretKey: viper.GetString("google-shortener.secret-key"),
|
SecretKey: viper.GetString("google-shortener.secret-key"),
|
||||||
},
|
},
|
||||||
Eligibility : EligibilityConfig{
|
Eligibility: EligibilityConfig{
|
||||||
Url : viper.GetString("eligibility.url"),
|
Url: viper.GetString("eligibility.url"),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package eligibilityroute
|
package eligibilityroute
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -17,7 +13,6 @@ import (
|
|||||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"googlemaps.github.io/maps"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -77,181 +72,53 @@ func (c *controller) handleEligibility(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if eligibility.Provider.ProviderNPI == "" {
|
var provider viewmodel.ProviderResp
|
||||||
provider, err := c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, authUser)
|
provider, err = c.svc.Provider.GetByNPI(eligibility.RawProvider.FivePartKeyGroups[0].ProviderNum, authUser)
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
eligibility.Provider.ProviderNPI = provider.InternalID
|
|
||||||
eligibility.Provider.ProviderName = provider.OrganizatioName
|
|
||||||
}
|
|
||||||
|
|
||||||
loc, _ := time.LoadLocation("America/Chicago")
|
|
||||||
eligibility.TrackingID = c.rangeIn(1000000, 9999999)
|
|
||||||
eligibility.ServiceInfo.DateOfService = time.Now().In(loc)
|
|
||||||
eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
|
|
||||||
|
|
||||||
var plan viewmodel.Plan
|
|
||||||
if eligibility.Subscriber.SubscriberID != "" {
|
|
||||||
plan, err = c.svc.Plan.GetByAlphaPrefix(eligibility.Subscriber.SubscriberID[:3])
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
eligibility.Payer.PayerID = fmt.Sprintf("%v", plan.PayerID)
|
|
||||||
eligibility.Payer.PayerName = plan.PayerName
|
|
||||||
} else {
|
|
||||||
return routeutils.ResponseAPIFieldValidationError(ctx, "subscriber_id", "member # is required.")
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, err := c.bcbsi.BXE.CheckEligibility(eligibility)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error Here: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ret.QueryResult.QueryResultSummary.BenefitsFound {
|
if provider.ProviderUUID == "" {
|
||||||
xmlString := html.UnescapeString(ret.QueryResult.HIPPA271.T271)
|
org := viewmodel.Organization{
|
||||||
xmlReader := strings.NewReader(xmlString)
|
Type: viewmodel.OrganizationType{
|
||||||
|
Key: "provider",
|
||||||
var f viewmodel.Interchange271
|
Name: "Provider",
|
||||||
err = xml.NewDecoder(xmlReader).Decode(&f)
|
},
|
||||||
if err != nil {
|
Name: eligibility.RawProvider.OrgName,
|
||||||
fmt.Println("Error to unmarshal: ", err.Error())
|
Description: eligibility.RawProvider.OrgName,
|
||||||
|
Main: false,
|
||||||
|
Author: authUser,
|
||||||
|
LastEditor: authUser,
|
||||||
|
Reference: eligibility.RawProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := c.svc.Users.GetByMemberID(eligibility.Subscriber.SubscriberID)
|
org, err = c.svc.Organization.AddOrganization(org, authUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.ID == "" {
|
provider, err = c.svc.Provider.GetByOrganization(org.UUID, authUser)
|
||||||
user.Pass = c.generatePassword(8)
|
if err != nil {
|
||||||
user.BirthDate = &eligibility.Subscriber.DemographicInfo.DateOfBirth
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
user.Member = &eligibility.Subscriber.SubscriberID
|
}
|
||||||
user.Gender = &eligibility.Subscriber.DemographicInfo.Gender
|
}
|
||||||
user.First = eligibility.Subscriber.Name.First
|
|
||||||
user.Last = eligibility.Subscriber.Name.Last
|
|
||||||
user.Active = true
|
|
||||||
user.Type = &eligibility.Subscriber.PatientType
|
|
||||||
user.PhoneNumber = eligibility.User.PhoneNumber
|
|
||||||
user.Email = eligibility.User.Email
|
|
||||||
|
|
||||||
profile, err := c.svc.Profile.GetByKey("US")
|
user, err := c.svc.Users.CheckAndCreateMember(eligibility.User, provider, authUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||||
}
|
if len(validationError.Errors) > 0 {
|
||||||
user.Profiles = append(user.Profiles, profile)
|
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||||
|
|
||||||
if user.BirthDate == nil || user.BirthDate.IsZero() {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "birthdate is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Member == nil || len(*user.Member) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "member is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Gender == nil || len(*user.Gender) == 0 || (*user.Gender != "M" && *user.Gender != "F" && *user.Gender != "U") {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "gender is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
|
||||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.PhoneNumber != nil && len(*user.PhoneNumber) == 10 && !strings.Contains(*user.PhoneNumber, "+1") {
|
|
||||||
phoneNumber := fmt.Sprintf("+1%s", *user.PhoneNumber)
|
|
||||||
user.PhoneNumber = &phoneNumber
|
|
||||||
} else {
|
} else {
|
||||||
return routeutils.ResponseAPIFieldValidationError(ctx, "phonenumber", "Phone number is required")
|
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||||
}
|
|
||||||
|
|
||||||
user, err = c.svc.Users.Create(user, authUser)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if eligibility.User.Email != nil && len(*eligibility.User.Email) > 0 {
|
|
||||||
user.Email = eligibility.User.Email
|
|
||||||
}
|
|
||||||
|
|
||||||
if eligibility.User.PhoneNumber != nil {
|
|
||||||
if len(*eligibility.User.PhoneNumber) == 10 && !strings.Contains(*eligibility.User.PhoneNumber, "+1") {
|
|
||||||
phoneNumber := fmt.Sprintf("+1%s", *eligibility.User.PhoneNumber)
|
|
||||||
eligibility.User.PhoneNumber = &phoneNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*eligibility.User.PhoneNumber) > 0 {
|
|
||||||
user.PhoneNumber = eligibility.User.PhoneNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.svc.Users.UpdateLogin(user)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
address := viewmodel.Address{}
|
|
||||||
header := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
||||||
body := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
||||||
zipCode := strings.TrimSpace(body.N403)
|
|
||||||
|
|
||||||
address.AddressTypeName = "Home"
|
|
||||||
address.AddressType = "home"
|
|
||||||
address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
||||||
address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
|
|
||||||
address.CreatedUserUUID = authUser.ID
|
|
||||||
address.User = user
|
|
||||||
address.Type = "provider"
|
|
||||||
|
|
||||||
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r := &maps.GeocodingRequest{
|
if authUser.Profiles[0].Key == "VIRPT" {
|
||||||
Address: address.Address + " " + body.N402 + ", " + zipCode,
|
return ctx.JSON(204, nil)
|
||||||
}
|
|
||||||
|
|
||||||
result, err := googleMapsAPI.Geocode(context.Background(), r)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(result) > 0 {
|
|
||||||
address.Latitude = result[0].Geometry.Location.Lat
|
|
||||||
address.Longitude = result[0].Geometry.Location.Lng
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Addresses) > 0 {
|
|
||||||
for _, a := range user.Addresses {
|
|
||||||
if a.AddressType == "home" {
|
|
||||||
err := c.svc.Users.RemoveAddress(a.UUID)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to remove old address: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
address, err = c.svc.Users.SaveAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to save address: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
user.Addresses = append(user.Addresses, address)
|
|
||||||
|
|
||||||
return ctx.JSON(200, user)
|
|
||||||
} else {
|
} else {
|
||||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "No benefits found for member")
|
return ctx.JSON(200, user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,12 +63,17 @@ func (c *controller) handleCancel(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
lyftRide := viewmodel.RideRequest{RideID: ride.InternalID}
|
lyftRide := viewmodel.RideRequest{RideID: ride.InternalID}
|
||||||
if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") {
|
if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") {
|
||||||
lyftRide.RideID = "s_" + ride.InternalID
|
lyftRide.RideID = "s_" + ride.InternalID
|
||||||
}
|
}
|
||||||
|
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if authUser.Test {
|
||||||
if err = c.tnc.Lyft.CancelRide(lyftRide); err != nil {
|
if err = c.tnc.Lyft.CancelRide(lyftRide); err != nil {
|
||||||
if err.Error() != "ride_not_found" {
|
if err.Error() != "ride_not_found" {
|
||||||
fmt.Println("Error to cancel with Lyft: ", err.Error())
|
fmt.Println("Error to cancel with Lyft: ", err.Error())
|
||||||
@@ -144,13 +149,18 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: ", err.Error())
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
var err error
|
var err error
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if authUser.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
|
||||||
lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,7 +246,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if authUser.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -258,7 +268,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
|||||||
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
||||||
lyftRide.RideType = "lyft"
|
lyftRide.RideType = "lyft"
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
|
if authUser.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
|
|||||||
@@ -57,8 +57,14 @@ func (c *controller) handleStateChange(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: ", err.Error())
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
// var lyftRide viewmodel.RideRequest
|
// var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if authUser.Test {
|
||||||
_, err = c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
|
_, err = c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
|
||||||
go func() {
|
go func() {
|
||||||
secondCall := func() {
|
secondCall := func() {
|
||||||
|
|||||||
168
server/router/passwordresetroute/controller.go
Normal file
168
server/router/passwordresetroute/controller.go
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package passwordresetroute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
tokenExpirationTime = 90 // in minutes
|
||||||
|
randomStringLength = 15
|
||||||
|
baseURL = "http://localhost:5000"
|
||||||
|
passwordResetEmailSubject = "Reset Your Password"
|
||||||
|
passwordResetEmailMainBody = "To reset your password click here or copy the following link and paste it into your browser: \n\n " + baseURL + "/#/reset-password/"
|
||||||
|
passwordResetEmailFooter = "\nThis link expires in 90 minutes"
|
||||||
|
passwordResetCompleteEmailSubject = "Your Password Has been Reset"
|
||||||
|
passwordResetCompleteEmailBody = "Your password has been reset. To login click here or copy the following link and paste it into your browser: \n\n" + baseURL + "/#/login"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *controller
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
type controller struct {
|
||||||
|
svc *applicationservice.Service
|
||||||
|
cfg *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *controller {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &controller{
|
||||||
|
svc: svc,
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
|
})
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) handleResetRequest(ctx echo.Context) error {
|
||||||
|
userEmail, err := routeutils.GetAndValidateStringParam(ctx, "email", "mandatory field")
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//find if user with email exists
|
||||||
|
user, err := c.svc.Users.GetByEmail(userEmail)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Email == nil || (*user.Email != userEmail) {
|
||||||
|
return routeutils.ResponseAPIOK(ctx, nil) //more secure, don't inform user (attacker) that email doesn't exists
|
||||||
|
}
|
||||||
|
|
||||||
|
//create and store reset token
|
||||||
|
|
||||||
|
timeNow := time.Now()
|
||||||
|
expirationTime := timeNow.Add(time.Minute * tokenExpirationTime)
|
||||||
|
|
||||||
|
randomArray := make([]byte, randomStringLength)
|
||||||
|
rand.Read(randomArray)
|
||||||
|
token := fmt.Sprintf("%x", sha256.Sum256(randomArray))
|
||||||
|
|
||||||
|
passwordResetEntry := viewmodel.PasswordReset{
|
||||||
|
User: user,
|
||||||
|
Token: token,
|
||||||
|
Expires: expirationTime,
|
||||||
|
Opened: false,
|
||||||
|
Used: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.svc.PasswordReset.CreatePasswordResetEntry(passwordResetEntry)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send email with reset link
|
||||||
|
notification := viewmodel.Notification{
|
||||||
|
Type: applicationservice.NotificationTypeEmail,
|
||||||
|
From: c.cfg.Email.Sender,
|
||||||
|
To: *user.Email,
|
||||||
|
Subject: passwordResetEmailSubject,
|
||||||
|
Message: passwordResetEmailMainBody + token + passwordResetEmailFooter,
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routeutils.ResponseAPIOK(ctx, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) handleResetComplete(ctx echo.Context) error {
|
||||||
|
userToken, err := routeutils.GetAndValidateStringParam(ctx, "token", "mandatory field")
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var user viewmodel.User
|
||||||
|
if err = ctx.Bind(&user); err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(strings.TrimSpace(user.Pass)) < 1 {
|
||||||
|
routeutils.ResponseAPIPasswordResetFailed(ctx, "No password")
|
||||||
|
}
|
||||||
|
|
||||||
|
passwordResetEntry, err := c.svc.PasswordReset.GetByToken(userToken)
|
||||||
|
if err != nil || len(passwordResetEntry.Token) < 1 || passwordResetEntry.Expires.Before(time.Now()) || passwordResetEntry.Used == true {
|
||||||
|
routeutils.ResponseAPIPasswordResetFailed(ctx, "Token error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fullUserData, err := c.svc.Users.GetByUUID(passwordResetEntry.User.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
routeutils.ResponseAPIPasswordResetFailed(ctx, "User problem")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(fullUserData)
|
||||||
|
|
||||||
|
//write new password in database
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
if err := c.svc.PasswordReset.SetTokenUsed(userToken); err != nil {
|
||||||
|
routeutils.ResponseAPIPasswordResetFailed(ctx, "Reset failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send email with reset link
|
||||||
|
notification := viewmodel.Notification{
|
||||||
|
Type: applicationservice.NotificationTypeEmail,
|
||||||
|
From: c.cfg.Email.Sender,
|
||||||
|
To: *user.Email,
|
||||||
|
Subject: passwordResetCompleteEmailSubject,
|
||||||
|
Message: passwordResetCompleteEmailBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routeutils.ResponseAPIOK(ctx, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) handleTokenOpen(ctx echo.Context) error {
|
||||||
|
token, err := routeutils.GetAndValidateStringParam(ctx, "token", "mandatory field")
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.svc.PasswordReset.SetTokenOpened(token); err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return routeutils.ResponseAPIOK(ctx, nil)
|
||||||
|
}
|
||||||
21
server/router/passwordresetroute/router.go
Normal file
21
server/router/passwordresetroute/router.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package passwordresetroute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
resetRequest = "/request/:email"
|
||||||
|
resetComplete = "/complete/:token"
|
||||||
|
tokenOpen = "/open/:token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) {
|
||||||
|
ctrl := controllerInstance(svc, cfg)
|
||||||
|
|
||||||
|
r.POST(resetRequest, ctrl.handleResetRequest)
|
||||||
|
r.POST(resetComplete, ctrl.handleResetComplete)
|
||||||
|
r.POST(tokenOpen, ctrl.handleTokenOpen)
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/lyfthookroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/lyfthookroute"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/notificationroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/notificationroute"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/organizationroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/organizationroute"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/server/router/passwordresetroute"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/placesroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/placesroute"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/profileroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/profileroute"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/providerroute"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/providerroute"
|
||||||
@@ -39,6 +40,7 @@ func Register(e *echo.Echo, cfg *config.Config, svc *applicationservice.Service,
|
|||||||
externalroute.Register(prefixGroup.Group("/ext"), cfg, svc, tnc, notification)
|
externalroute.Register(prefixGroup.Group("/ext"), cfg, svc, tnc, notification)
|
||||||
authenticateroute.Register(prefixGroup.Group("/authenticate"), cfg, svc)
|
authenticateroute.Register(prefixGroup.Group("/authenticate"), cfg, svc)
|
||||||
selfregisterroute.Register(prefixGroup.Group("/selfregister"), cfg, svc)
|
selfregisterroute.Register(prefixGroup.Group("/selfregister"), cfg, svc)
|
||||||
|
passwordresetroute.Register(prefixGroup.Group("/passwordreset"), cfg, svc)
|
||||||
|
|
||||||
appGroup := prefixGroup.Group("/" + cfg.App.Name)
|
appGroup := prefixGroup.Group("/" + cfg.App.Name)
|
||||||
usersroute.Register(appGroup.Group("/users"), cfg, svc)
|
usersroute.Register(appGroup.Group("/users"), cfg, svc)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func ResponseAPIErrorWithData(c echo.Context, status int, message string, redire
|
|||||||
Error: true,
|
Error: true,
|
||||||
Message: message,
|
Message: message,
|
||||||
Redirect: redirect,
|
Redirect: redirect,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(status, returnValue)
|
return c.JSON(status, returnValue)
|
||||||
@@ -92,15 +92,21 @@ func ResponseAPINotFoundError(c echo.Context) error {
|
|||||||
return ResponseAPIError(c, http.StatusNotFound, "Not Found", false)
|
return ResponseAPIError(c, http.StatusNotFound, "Not Found", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
//ResponseAPINotEligible returns a standard API not eligible to the response
|
//ResponseAPINotEligibleError returns a standard API not eligible to the response
|
||||||
func ResponseAPINotEligibleError(c echo.Context) error {
|
func ResponseAPINotEligibleError(c echo.Context) error {
|
||||||
return ResponseAPIError(c, http.StatusForbidden, "Eligibility Not Found or Error", false)
|
return ResponseAPIError(c, http.StatusForbidden, "Member does not have active insurance coverage", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ResponseAPINotEligibleWithMessageError returns a standard API not eligible to the response with custom message
|
||||||
func ResponseAPINotEligibleWithMessageError(c echo.Context, message string) error {
|
func ResponseAPINotEligibleWithMessageError(c echo.Context, message string) error {
|
||||||
return ResponseAPIError(c, http.StatusForbidden, message, false)
|
return ResponseAPIError(c, http.StatusForbidden, message, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ResponseAPIPasswordResetFailed returns a standard API error when password reset fails
|
||||||
|
func ResponseAPIPasswordResetFailed(c echo.Context, message string) error {
|
||||||
|
return ResponseAPIError(c, http.StatusForbidden, message, false)
|
||||||
|
}
|
||||||
|
|
||||||
func ignoreDefaultWrappedErrors(c echo.Context, errorToHandle *errors.WrappedError, handler func(echo.Context, error) error) error {
|
func ignoreDefaultWrappedErrors(c echo.Context, errorToHandle *errors.WrappedError, handler func(echo.Context, error) error) error {
|
||||||
err := errorToHandle.GetOriginalError()
|
err := errorToHandle.GetOriginalError()
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package selfregisterroute
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
b64 "encoding/base64"
|
b64 "encoding/base64"
|
||||||
@@ -16,6 +17,16 @@ import (
|
|||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
notificationEmailSubject = "Registration sucessful"
|
||||||
|
notificationEmailBody = "You have registered as a Visit Reporter for CHM NEMT.\nLogin: https://portal.bcbsinstitute.com\nReset PW: https://portal.bcbsinstitute.com/forgot"
|
||||||
|
notificationSmsBody = "You have registered as a Visit Reporter for CHM NEMT. Login: https://portal.bcbsinstitute.com Reset PW: https://portal.bcbsinstitute.com/forgot"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
phoneNumberMaxLength = 12
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
instance *controller
|
instance *controller
|
||||||
once sync.Once
|
once sync.Once
|
||||||
@@ -38,55 +49,53 @@ func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *co
|
|||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeNonNumberChars(input string) string {
|
||||||
|
result := ""
|
||||||
|
for _, char := range input {
|
||||||
|
if char >= '0' && char <= '9' {
|
||||||
|
result += string(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controller) handle(ctx echo.Context) error {
|
func (c *controller) handle(ctx echo.Context) error {
|
||||||
var user viewmodel.User
|
var user viewmodel.User
|
||||||
if err := ctx.Bind(&user); err != nil {
|
if err := ctx.Bind(&user); err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//format phone number - max length in database is 12 chars
|
||||||
|
formatedPhoneNumber := strings.TrimSpace(*user.PhoneNumber)
|
||||||
|
formatedPhoneNumber = strings.Replace(formatedPhoneNumber, "+1", "", -1)
|
||||||
|
formatedPhoneNumber = removeNonNumberChars(formatedPhoneNumber)
|
||||||
|
|
||||||
|
if len(formatedPhoneNumber) > phoneNumberMaxLength {
|
||||||
|
formatedPhoneNumber = formatedPhoneNumber[:phoneNumberMaxLength]
|
||||||
|
}
|
||||||
|
|
||||||
|
*user.PhoneNumber = formatedPhoneNumber
|
||||||
|
|
||||||
authUser, err := c.svc.Users.GetByUUID("573c70ff-733d-11e7-ba8f-0a6ad3fcdeaa", "")
|
authUser, err := c.svc.Users.GetByUUID("573c70ff-733d-11e7-ba8f-0a6ad3fcdeaa", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.PhoneNumber == nil || len(*user.PhoneNumber) == 0 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "phonenumber is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Email == nil || len(*user.Email) == 0 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "email is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Pass) == 0 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "password is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
pass, err := b64.StdEncoding.DecodeString(user.Pass)
|
pass, err := b64.StdEncoding.DecodeString(user.Pass)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "Invalid password")
|
return routeutils.ResponseAPIValidationError(ctx, "Invalid password")
|
||||||
}
|
}
|
||||||
user.Pass = string(pass)
|
user.Pass = string(pass)
|
||||||
|
|
||||||
if passwordValidationErrors := validation.ValidatePassword(&user); len(passwordValidationErrors) > 0 {
|
if validationErrors := validation.ValidateSelfregistration(&user); len(validationErrors) > 0 {
|
||||||
return routeutils.ResponseAPICustomValidationError(ctx, "Password not strong enough", passwordValidationErrors)
|
return routeutils.ResponseAPICustomValidationError(ctx, "Self registration failed", validationErrors)
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "name is required")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
if len(user.First) != 0 && len(user.Last) != 0 {
|
||||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(user.Provider.InternalID) == 0 || len(user.Provider.InternalID) > 10 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "Provider NPI is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Provider.OrganizatioName) == 0 {
|
|
||||||
return routeutils.ResponseAPIValidationError(ctx, "Provider Organization Name is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
provider, err := c.svc.Provider.GetByNPI(user.Provider.InternalID, authUser)
|
provider, err := c.svc.Provider.GetByNPI(user.Provider.InternalID, authUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error to create organization", err)
|
fmt.Println("Error to create organization", err)
|
||||||
@@ -139,5 +148,36 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Send email notification to Authorized user
|
||||||
|
notification := viewmodel.Notification{
|
||||||
|
Type: applicationservice.NotificationTypeEmail,
|
||||||
|
From: c.cfg.Email.Sender,
|
||||||
|
To: *user.Email,
|
||||||
|
Subject: notificationEmailSubject,
|
||||||
|
Message: notificationEmailBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||||
|
if err != nil {
|
||||||
|
logger := ctx.Logger()
|
||||||
|
logger.Warnf("Application Error: Could not send email notification to user email : %s", *user.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send sms notification to Authorized user
|
||||||
|
|
||||||
|
formatedPhoneNumber = *user.PhoneNumber
|
||||||
|
|
||||||
|
notification = viewmodel.Notification{
|
||||||
|
Type: applicationservice.NOtificationTypeSMS,
|
||||||
|
To: *user.PhoneNumber,
|
||||||
|
Message: notificationSmsBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||||
|
if err != nil {
|
||||||
|
logger := ctx.Logger()
|
||||||
|
logger.Warnf("Application Error: Could not send sms notification to user mobile : %s", *user.PhoneNumber)
|
||||||
|
}
|
||||||
|
|
||||||
return routeutils.ResponseAPIOK(ctx, user)
|
return routeutils.ResponseAPIOK(ctx, user)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,6 +239,42 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var provider viewmodel.ProviderResp
|
||||||
|
provider, err = c.svc.Provider.GetByNPI(requestRide.RawProvider.FivePartKeyGroups[0].ProviderNum, createdUser)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Provider Found: ", provider.ProviderUUID)
|
||||||
|
if provider.ProviderUUID == "" {
|
||||||
|
org := viewmodel.Organization{
|
||||||
|
Type: viewmodel.OrganizationType{
|
||||||
|
Key: "provider",
|
||||||
|
Name: "Provider",
|
||||||
|
},
|
||||||
|
Name: requestRide.RawProvider.OrgName,
|
||||||
|
Description: requestRide.RawProvider.OrgName,
|
||||||
|
Main: false,
|
||||||
|
Author: createdUser,
|
||||||
|
LastEditor: createdUser,
|
||||||
|
Reference: requestRide.RawProvider,
|
||||||
|
}
|
||||||
|
|
||||||
|
org, err = c.svc.Organization.AddOrganization(org, createdUser)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
fmt.Println("Organization Created: ", org.UUID)
|
||||||
|
|
||||||
|
provider, err = c.svc.Provider.GetByOrganization(org.UUID, createdUser)
|
||||||
|
if err != nil {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
|
}
|
||||||
|
fmt.Println("Provider Found: ", provider.ProviderUUID)
|
||||||
|
}
|
||||||
|
requestRide.Provider = provider
|
||||||
|
requestRide.Destination.ID = provider.MukID
|
||||||
|
|
||||||
name := user.Name
|
name := user.Name
|
||||||
names := strings.Split(name, " ")
|
names := strings.Split(name, " ")
|
||||||
requestRide.Passenger.FirstName = names[0]
|
requestRide.Passenger.FirstName = names[0]
|
||||||
@@ -253,7 +289,7 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
requestRide.Destination = newOrigin
|
requestRide.Destination = newOrigin
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != createdUser.ID {
|
if createdUser.Test {
|
||||||
resp, err = c.tnc.Lyft.RequestRide(requestRide)
|
resp, err = c.tnc.Lyft.RequestRide(requestRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -304,14 +340,14 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
|
|
||||||
if requestRide.TripType.Key == "from_visit" {
|
if requestRide.TripType.Key == "from_visit" {
|
||||||
resp.Origin.Name = requestRide.Destination.Name
|
resp.Origin.Name = requestRide.Destination.Name
|
||||||
resp.Origin.ID = requestRide.Destination.ID
|
resp.Origin.ID = requestRide.Provider.MukID
|
||||||
resp.Destination.Name = requestRide.Origin.Name
|
resp.Destination.Name = requestRide.Origin.Name
|
||||||
resp.Destination.ID = requestRide.Origin.ID
|
resp.Destination.ID = requestRide.Origin.ID
|
||||||
} else {
|
} else {
|
||||||
resp.Origin.Name = requestRide.Origin.Name
|
resp.Origin.Name = requestRide.Origin.Name
|
||||||
resp.Origin.ID = requestRide.Origin.ID
|
resp.Origin.ID = requestRide.Origin.ID
|
||||||
resp.Destination.Name = requestRide.Destination.Name
|
resp.Destination.Name = requestRide.Destination.Name
|
||||||
resp.Destination.ID = requestRide.Destination.ID
|
resp.Destination.ID = requestRide.Provider.MukID
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Distance = requestRide.Distance
|
resp.Distance = requestRide.Distance
|
||||||
@@ -338,6 +374,7 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
|
|
||||||
entity, err := c.svc.Rides.Save(resp)
|
entity, err := c.svc.Rides.Save(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("Error to save rides: ", err.Error())
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +404,7 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
newRide.Passenger.LastName = " "
|
newRide.Passenger.LastName = " "
|
||||||
newRide.Passenger.PhoneNumber = *user.PhoneNumber
|
newRide.Passenger.PhoneNumber = *user.PhoneNumber
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != createdUser.ID {
|
if createdUser.Test {
|
||||||
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -477,7 +514,7 @@ func (c *controller) handleRawLyft(ctx echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if user.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -509,7 +546,7 @@ func (c *controller) handleRideETA(ctx echo.Context) error {
|
|||||||
|
|
||||||
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if user.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -577,7 +614,7 @@ func (c *controller) handleCancel(ctx echo.Context) error {
|
|||||||
requestRide.RideID = "s_" + ride.InternalID
|
requestRide.RideID = "s_" + ride.InternalID
|
||||||
}
|
}
|
||||||
|
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if user.Test {
|
||||||
err = c.tnc.Lyft.CancelRide(requestRide)
|
err = c.tnc.Lyft.CancelRide(requestRide)
|
||||||
if err != nil && err.Error() == "ride_not_found" {
|
if err != nil && err.Error() == "ride_not_found" {
|
||||||
err = nil
|
err = nil
|
||||||
@@ -682,7 +719,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
|||||||
|
|
||||||
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if user.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -821,7 +858,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if user.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -843,7 +880,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
|||||||
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
||||||
lyftRide.RideType = "lyft"
|
lyftRide.RideType = "lyft"
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
|
if user.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
|
|||||||
@@ -128,6 +128,13 @@ func (c *controller) handleTwilio(ctx echo.Context) error {
|
|||||||
message = fmt.Sprintf("We received a request to cancel a ride from you at %s, but cannot find a ride for this mobile number.", libphonenumber.Format(num, libphonenumber.NATIONAL))
|
message = fmt.Sprintf("We received a request to cancel a ride from you at %s, but cannot find a ride for this mobile number.", libphonenumber.Format(num, libphonenumber.NATIONAL))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authUser, err := c.svc.Users.GetByUUID(lastRide.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to author of the ride: ", err.Error())
|
||||||
|
message = "There was a problem to call your ride"
|
||||||
|
}
|
||||||
|
|
||||||
if !isDriver {
|
if !isDriver {
|
||||||
if requestMessage == "I AM READY" && lastRide.UUID != "" {
|
if requestMessage == "I AM READY" && lastRide.UUID != "" {
|
||||||
if (lastRide.Visit.TripType.Key == "roundtrip_call" && (lastRide.TripType.Key == "to_visit" || lastRide.TripType.Key == "from_visit_call")) || lastRide.Visit.TripType.Key == "from_visit_call" {
|
if (lastRide.Visit.TripType.Key == "roundtrip_call" && (lastRide.TripType.Key == "to_visit" || lastRide.TripType.Key == "from_visit_call")) || lastRide.Visit.TripType.Key == "from_visit_call" {
|
||||||
@@ -161,7 +168,7 @@ func (c *controller) handleTwilio(ctx echo.Context) error {
|
|||||||
lyftRide.Passenger.PhoneNumber = *readyRide.User.PhoneNumber
|
lyftRide.Passenger.PhoneNumber = *readyRide.User.PhoneNumber
|
||||||
lyftRide.RideType = "lyft"
|
lyftRide.RideType = "lyft"
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != readyRide.CreatedUser.ID {
|
if authUser.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -209,7 +216,7 @@ func (c *controller) handleTwilio(ctx echo.Context) error {
|
|||||||
|
|
||||||
if requestMessage == "YES" && lastRide.UUID != "" {
|
if requestMessage == "YES" && lastRide.UUID != "" {
|
||||||
var lyftRide viewmodel.RideRequest
|
var lyftRide viewmodel.RideRequest
|
||||||
if lastRide.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
if authUser.Test {
|
||||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: lastRide.InternalID})
|
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: lastRide.InternalID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error: ", err.Error())
|
fmt.Println("Error: ", err.Error())
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"net/http"
|
|
||||||
"encoding/json"
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
||||||
@@ -19,11 +15,9 @@ import (
|
|||||||
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
|
"bitbucket.org/nemt/nemt-portal-api/infra/cache"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/authorization"
|
"bitbucket.org/nemt/nemt-portal-api/server/authorization"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"googlemaps.github.io/maps"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -345,11 +339,6 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Validate member
|
|
||||||
if validationErrors := validation.ValidateEligibility(&user) ; len(validationErrors) > 0 {
|
|
||||||
return routeutils.ResponseAPICustomValidationError(ctx, "eligibility validation failed", validationErrors)
|
|
||||||
}
|
|
||||||
|
|
||||||
authUser, err := auth.GetUserDetail(ctx, c.cfg)
|
authUser, err := auth.GetUserDetail(ctx, c.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
@@ -359,151 +348,18 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
|||||||
return routeutils.ResponseAPIAuthError(ctx, "phonenumber or email is required", false)
|
return routeutils.ResponseAPIAuthError(ctx, "phonenumber or email is required", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(user.Pass) == 0 {
|
provider := viewmodel.ProviderResp{}
|
||||||
user.Pass = c.generatePassword(8)
|
user, err = c.svc.Users.CheckAndCreateMember(user, provider, authUser)
|
||||||
} else {
|
if err != nil {
|
||||||
pass, err := b64.StdEncoding.DecodeString(user.Pass)
|
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||||
if err != nil {
|
if len(validationError.Errors) > 0 {
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "Invalid password", false)
|
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||||
|
} else {
|
||||||
|
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
user.Pass = string(pass)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.BirthDate == nil || user.BirthDate.IsZero() {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "birthdate is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Member == nil || len(*user.Member) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "member is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Gender == nil || len(*user.Gender) == 0 || (*user.Gender != "M" && *user.Gender != "F" && *user.Gender != "U") {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "gender is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
|
||||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
|
||||||
}
|
|
||||||
|
|
||||||
profile, err := c.svc.Profile.GetByKey("US")
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
user.Profiles = append(user.Profiles, profile)
|
|
||||||
|
|
||||||
eligibility := viewmodel.Eligibility{}
|
|
||||||
eligibility.Provider.ProviderNPI = "1699849786"
|
|
||||||
eligibility.Provider.ProviderName = "LITHOLINK CORPORATION"
|
|
||||||
eligibility.TrackingID = user.ID
|
|
||||||
eligibility.Subscriber.SubscriberID = *user.Member
|
|
||||||
eligibility.Subscriber.PatientType = "S"
|
|
||||||
eligibility.Subscriber.Name.First = user.First
|
|
||||||
eligibility.Subscriber.Name.Last = user.Last
|
|
||||||
eligibility.Subscriber.DemographicInfo.DateOfBirth = *user.BirthDate
|
|
||||||
eligibility.Subscriber.DemographicInfo.Gender = *user.Gender
|
|
||||||
eligibility.ServiceInfo.DateOfService = time.Now()
|
|
||||||
eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
|
|
||||||
|
|
||||||
/*
|
|
||||||
resp, err := c.bcbsi.BXE.Get271(eligibility)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Eligibility Not Found or Error: ", err.Error())
|
|
||||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//This part is emulating eligibility check for testing purposes
|
|
||||||
client := &http.Client{}
|
|
||||||
eligibilityJson, err := json.Marshal(eligibility)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
req, _ := http.NewRequest("POST", c.cfg.Eligibility.Url, bytes.NewBuffer(eligibilityJson))
|
|
||||||
req.Header.Add("App", c.cfg.HTTP.Auth.AppKey)
|
|
||||||
req.Header.Add("Token", ctx.Request().Header.Get("Token"))
|
|
||||||
req.Header.Add("Content-Type", "application/json")
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 300 {
|
|
||||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility")
|
|
||||||
}
|
|
||||||
|
|
||||||
eligibilityResponse := viewmodel.Interchange271{}
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
|
||||||
err = decoder.Decode(&eligibilityResponse)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility")
|
|
||||||
}
|
|
||||||
//================================================================
|
|
||||||
|
|
||||||
if len(eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030) < 1 {
|
|
||||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility")
|
|
||||||
}
|
|
||||||
|
|
||||||
address := viewmodel.Address{}
|
|
||||||
//header := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
||||||
//body := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
||||||
header := eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
||||||
body := eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
||||||
|
|
||||||
address.AddressTypeName = "Home"
|
|
||||||
address.AddressType = "home"
|
|
||||||
address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
||||||
address.Address = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
||||||
address.CreatedUserUUID = authUser.ID
|
|
||||||
address.User = user
|
|
||||||
|
|
||||||
cleanZipcode := strings.TrimSpace(body.N403)
|
|
||||||
trimmedZipcode := cleanZipcode
|
|
||||||
if len(cleanZipcode) > zipcodeTrimLength {
|
|
||||||
trimmedZipcode = cleanZipcode[:zipcodeTrimLength]
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.svc.Zipcodes.GetByParticipatingZipcode(trimmedZipcode)
|
|
||||||
|
|
||||||
if err != nil{
|
|
||||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Member's Home zipcode, " + trimmedZipcode + ", is not currently eligible for participation in this program")
|
|
||||||
}
|
|
||||||
|
|
||||||
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx,err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &maps.GeocodingRequest{
|
|
||||||
Address: address.Address + " " + body.N402 + ", " + body.N403,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := googleMapsAPI.Geocode(context.Background(), r)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx,err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(result) > 0 {
|
|
||||||
address.Latitude = result[0].Geometry.Location.Lat
|
|
||||||
address.Longitude = result[0].Geometry.Location.Lng
|
|
||||||
|
|
||||||
_, err := c.svc.Users.SaveAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to save address: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx,err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err = c.svc.Users.Create(user, authUser)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return routeutils.ResponseAPIOK(ctx, user)
|
return routeutils.ResponseAPIOK(ctx, user)
|
||||||
@@ -547,6 +403,7 @@ func (c *controller) handleBulkPortal(ctx echo.Context) error {
|
|||||||
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
users[i].Test = true
|
||||||
if len(users[i].First) != 0 && len(users[i].Last) != 0 {
|
if len(users[i].First) != 0 && len(users[i].Last) != 0 {
|
||||||
users[i].Name = fmt.Sprintf("%s %s", users[i].First, users[i].Last)
|
users[i].Name = fmt.Sprintf("%s %s", users[i].First, users[i].Last)
|
||||||
}
|
}
|
||||||
@@ -597,7 +454,7 @@ func (c *controller) handlePortal(ctx echo.Context) error {
|
|||||||
}
|
}
|
||||||
user.Pass = string(pass)
|
user.Pass = string(pass)
|
||||||
|
|
||||||
if passwordValidationErrors := validation.ValidatePassword(&user) ; len(passwordValidationErrors) > 0 {
|
if passwordValidationErrors := validation.ValidatePassword(&user); len(passwordValidationErrors) > 0 {
|
||||||
return routeutils.ResponseAPICustomValidationError(ctx, "Password not strong enough", passwordValidationErrors)
|
return routeutils.ResponseAPICustomValidationError(ctx, "Password not strong enough", passwordValidationErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,6 +465,7 @@ func (c *controller) handlePortal(ctx echo.Context) error {
|
|||||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
if len(user.First) != 0 && len(user.Last) != 0 {
|
||||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
||||||
}
|
}
|
||||||
|
user.Test = true
|
||||||
|
|
||||||
user, err = c.svc.Users.Create(user, authUser)
|
user, err = c.svc.Users.Create(user, authUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
package visitroute
|
package visitroute
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
b64 "encoding/base64"
|
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
|
"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
|
||||||
@@ -20,7 +17,6 @@ import (
|
|||||||
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"googlemaps.github.io/maps"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -81,98 +77,39 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
ride.Visit = visit
|
|
||||||
|
|
||||||
user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
|
visit.User.PhoneNumber = ride.User.PhoneNumber
|
||||||
if err != nil {
|
visit.User.Email = ride.User.Email
|
||||||
fmt.Println(err)
|
visit.User.Consent = true
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
ride.Visit = visit
|
||||||
ride.Visit.User = user
|
|
||||||
subscriber := "S"
|
|
||||||
ride.Visit.User.Type = &subscriber
|
|
||||||
|
|
||||||
var provider viewmodel.ProviderResp
|
var provider viewmodel.ProviderResp
|
||||||
provider, err = c.svc.Provider.GetByUUID(ride.Visit.Provider.ProviderUUID, authUser)
|
provider, err = c.svc.Provider.GetByUUID(ride.Visit.Provider.ProviderUUID, authUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
visit.Provider = provider
|
ride.Visit.Provider = provider
|
||||||
|
|
||||||
eligibility := viewmodel.Eligibility{}
|
// user, err := c.svc.Users.GetByUUID(ride.User.ID, "US")
|
||||||
eligibility.Provider.ProviderNPI = provider.InternalID
|
// if err != nil {
|
||||||
eligibility.Provider.ProviderName = provider.OrganizatioName
|
// return routeutils.HandleAPIError(ctx, err)
|
||||||
eligibility.TrackingID = c.rangeIn(1000000, 9999999)
|
// }
|
||||||
eligibility.Subscriber.SubscriberID = *ride.Visit.User.Member
|
user, err := c.svc.Users.CheckAndCreateMember(ride.Visit.User, provider, authUser)
|
||||||
eligibility.Subscriber.PatientType = *ride.Visit.User.Type
|
|
||||||
eligibility.Subscriber.Name.First = ride.Visit.User.First
|
|
||||||
eligibility.Subscriber.Name.Last = ride.Visit.User.Last
|
|
||||||
eligibility.Subscriber.DemographicInfo.DateOfBirth = *ride.Visit.User.BirthDate
|
|
||||||
eligibility.Subscriber.DemographicInfo.Gender = *ride.Visit.User.Gender
|
|
||||||
loc, _ := time.LoadLocation("America/Chicago")
|
|
||||||
eligibility.ServiceInfo.DateOfService = time.Now().In(loc)
|
|
||||||
eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
|
|
||||||
|
|
||||||
resp271, err := c.bcbsi.BXE.Get271(eligibility)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||||
return routeutils.ResponseAPIValidationError(ctx, err.Error())
|
if len(validationError.Errors) > 0 {
|
||||||
}
|
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||||
|
} else {
|
||||||
address := viewmodel.Address{}
|
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||||
header := resp271.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
||||||
body := resp271.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
||||||
zipCode := strings.TrimSpace(body.N403)
|
|
||||||
|
|
||||||
address.AddressTypeName = "Home"
|
|
||||||
address.AddressType = "home"
|
|
||||||
address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
||||||
address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
|
|
||||||
address.CreatedUserUUID = authUser.ID
|
|
||||||
address.User = user
|
|
||||||
address.Type = "provider"
|
|
||||||
|
|
||||||
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &maps.GeocodingRequest{
|
|
||||||
Address: address.Address + " " + body.N402 + ", " + zipCode,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := googleMapsAPI.Geocode(context.Background(), r)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(result) > 0 {
|
|
||||||
address.Latitude = result[0].Geometry.Location.Lat
|
|
||||||
address.Longitude = result[0].Geometry.Location.Lng
|
|
||||||
}
|
|
||||||
|
|
||||||
if address.Latitude != 0 && address.Longitude != 0 {
|
|
||||||
if len(user.Addresses) > 0 {
|
|
||||||
for _, a := range user.Addresses {
|
|
||||||
if a.AddressType == "home" {
|
|
||||||
err := c.svc.Users.RemoveAddress(a.UUID)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to remove old address: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
address, err = c.svc.Users.SaveAddress(address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to save address: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
user.Addresses = append(user.Addresses, address)
|
|
||||||
}
|
}
|
||||||
|
ride.Visit.User = user
|
||||||
|
ride.User = user
|
||||||
|
visit.User = user
|
||||||
|
|
||||||
homeAddress := viewmodel.Address{}
|
homeAddress := viewmodel.Address{}
|
||||||
for _, a := range visit.User.Addresses {
|
for _, a := range visit.User.Addresses {
|
||||||
@@ -189,20 +126,29 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
|||||||
Longitude: visit.Provider.Address.Longitude,
|
Longitude: visit.Provider.Address.Longitude,
|
||||||
Address: visit.Provider.Address.StreetAddress1,
|
Address: visit.Provider.Address.StreetAddress1,
|
||||||
}
|
}
|
||||||
ride.Origin = viewmodel.Location{
|
|
||||||
ID: homeAddress.UUID,
|
if len(ride.Origin.ID) == 0 {
|
||||||
Name: homeAddress.AddressTypeName,
|
ride.Origin = viewmodel.Location{
|
||||||
Latitude: homeAddress.Latitude,
|
ID: homeAddress.UUID,
|
||||||
Longitude: homeAddress.Longitude,
|
Name: homeAddress.AddressTypeName,
|
||||||
Address: homeAddress.Address,
|
Latitude: homeAddress.Latitude,
|
||||||
|
Longitude: homeAddress.Longitude,
|
||||||
|
Address: homeAddress.Address,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ride.Notes = ride.Notes
|
ride.Notes = ride.Notes
|
||||||
ride.Passenger.FirstName = visit.User.First
|
ride.Passenger.FirstName = ride.Visit.User.First
|
||||||
ride.Passenger.LastName = " "
|
ride.Passenger.LastName = " "
|
||||||
ride.Passenger.PhoneNumber = *visit.User.PhoneNumber
|
ride.Passenger.PhoneNumber = *ride.Visit.User.PhoneNumber
|
||||||
ride.RideType = "lyft"
|
ride.RideType = "lyft"
|
||||||
ride.VisitDate = &visit.VisitDatetime
|
ride.VisitDate = &visit.VisitDatetime
|
||||||
ride.VisitTime = &visit.VisitDatetime
|
ride.VisitTime = &visit.VisitDatetime
|
||||||
|
ride.UserConsent = true
|
||||||
|
|
||||||
|
if validationErrors := validation.ValidateVisitRide(&ride, &user); len(validationErrors) > 0 {
|
||||||
|
return routeutils.ResponseAPICustomValidationError(ctx, "ride validation failed", validationErrors)
|
||||||
|
}
|
||||||
|
|
||||||
var resp viewmodel.RideRequest
|
var resp viewmodel.RideRequest
|
||||||
if ride.TripType.Key != "from_visit_call" {
|
if ride.TripType.Key != "from_visit_call" {
|
||||||
@@ -212,7 +158,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
|||||||
ride.Destination = newOrigin
|
ride.Destination = newOrigin
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != authUser.ID {
|
if authUser.Test {
|
||||||
resp, err = c.tnc.Lyft.RequestRide(ride)
|
resp, err = c.tnc.Lyft.RequestRide(ride)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -326,7 +272,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
|||||||
newRide.Passenger.LastName = " "
|
newRide.Passenger.LastName = " "
|
||||||
newRide.Passenger.PhoneNumber = *visit.User.PhoneNumber
|
newRide.Passenger.PhoneNumber = *visit.User.PhoneNumber
|
||||||
|
|
||||||
if c.cfg.LyftProd.UserUUID != authUser.ID {
|
if authUser.Test {
|
||||||
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("In Production")
|
fmt.Println("In Production")
|
||||||
@@ -457,154 +403,19 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
return routeutils.ResponseAPICustomValidationError(ctx, "visit validation failed", validationErrors)
|
return routeutils.ResponseAPICustomValidationError(ctx, "visit validation failed", validationErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
// eligibility := viewmodel.Eligibility{}
|
user, err := c.svc.Users.CheckAndCreateMember(visit.User, provider, authUser)
|
||||||
// eligibility.Provider.ProviderNPI = provider.InternalID
|
|
||||||
// eligibility.Provider.ProviderName = provider.OrganizatioName
|
|
||||||
// eligibility.TrackingID = c.rangeIn(1000000, 9999999)
|
|
||||||
// eligibility.Subscriber.SubscriberID = *visit.User.Member
|
|
||||||
// eligibility.Subscriber.PatientType = *visit.User.Type
|
|
||||||
// eligibility.Subscriber.Name.First = visit.User.First
|
|
||||||
// eligibility.Subscriber.Name.Last = visit.User.Last
|
|
||||||
// eligibility.Subscriber.DemographicInfo.DateOfBirth = *visit.User.BirthDate
|
|
||||||
// eligibility.Subscriber.DemographicInfo.Gender = *visit.User.Gender
|
|
||||||
// loc, _ := time.LoadLocation("America/Chicago")
|
|
||||||
// eligibility.ServiceInfo.DateOfService = time.Now().In(loc)
|
|
||||||
// eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
|
|
||||||
|
|
||||||
// resp, err := c.bcbsi.BXE.Get271(eligibility)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("Error to get eligibility: ", err.Error())
|
|
||||||
// return routeutils.ResponseAPIValidationError(ctx, err.Error())
|
|
||||||
// }
|
|
||||||
|
|
||||||
user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error to get user by memberID: ", err.Error())
|
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
if len(validationError.Errors) > 0 {
|
||||||
}
|
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||||
|
} else {
|
||||||
if user.ID == "" {
|
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||||
if len(user.Pass) == 0 {
|
}
|
||||||
user.Pass = c.generatePassword(8)
|
|
||||||
} else {
|
} else {
|
||||||
pass, err := b64.StdEncoding.DecodeString(user.Pass)
|
|
||||||
if err != nil {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "Invalid password", false)
|
|
||||||
}
|
|
||||||
user.Pass = string(pass)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.BirthDate == nil || user.BirthDate.IsZero() {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "birthdate is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Member == nil || len(*user.Member) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "member is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Gender == nil || len(*user.Gender) == 0 || (*user.Gender != "M" && *user.Gender != "F" && *user.Gender != "U") {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "gender is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.Name) == 0 && len(user.First) == 0 && len(user.Last) == 0 {
|
|
||||||
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
|
||||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.PhoneNumber != nil && len(*user.PhoneNumber) == 10 && !strings.Contains(*user.PhoneNumber, "+1") {
|
|
||||||
phoneNumber := fmt.Sprintf("+1%s", *user.PhoneNumber)
|
|
||||||
user.PhoneNumber = &phoneNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
profile, err := c.svc.Profile.GetByKey("US")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to get Profile: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
user.Profiles = append(user.Profiles, profile)
|
|
||||||
|
|
||||||
user, err = c.svc.Users.Create(user, authUser)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to create the user: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if visit.User.Email != nil && len(*visit.User.Email) > 0 {
|
|
||||||
user.Email = visit.User.Email
|
|
||||||
}
|
|
||||||
|
|
||||||
if visit.User.PhoneNumber != nil {
|
|
||||||
if len(*visit.User.PhoneNumber) == 10 && !strings.Contains(*visit.User.PhoneNumber, "+1") {
|
|
||||||
phoneNumber := fmt.Sprintf("+1%s", *visit.User.PhoneNumber)
|
|
||||||
visit.User.PhoneNumber = &phoneNumber
|
|
||||||
}
|
|
||||||
user.PhoneNumber = visit.User.PhoneNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.svc.Users.UpdateLogin(user)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error to update login: ", err.Error())
|
|
||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
visit.User = user
|
||||||
// address := viewmodel.Address{}
|
|
||||||
// header := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
||||||
// body := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
||||||
// zipCode := strings.TrimSpace(body.N403)
|
|
||||||
|
|
||||||
// address.AddressTypeName = "Home"
|
|
||||||
// address.AddressType = "home"
|
|
||||||
// address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
||||||
// address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
|
|
||||||
// address.CreatedUserUUID = authUser.ID
|
|
||||||
// address.User = user
|
|
||||||
// address.Type = "provider"
|
|
||||||
|
|
||||||
// googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
// return routeutils.HandleAPIError(ctx, err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// r := &maps.GeocodingRequest{
|
|
||||||
// Address: address.Address + " " + body.N402 + ", " + zipCode,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// result, err := googleMapsAPI.Geocode(context.Background(), r)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
||||||
// return routeutils.HandleAPIError(ctx, err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if len(result) > 0 {
|
|
||||||
// address.Latitude = result[0].Geometry.Location.Lat
|
|
||||||
// address.Longitude = result[0].Geometry.Location.Lng
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if address.Latitude != 0 && address.Longitude != 0 {
|
|
||||||
// if len(user.Addresses) > 0 {
|
|
||||||
// for _, a := range user.Addresses {
|
|
||||||
// if a.AddressType == "home" {
|
|
||||||
// err := c.svc.Users.RemoveAddress(a.UUID)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("Error to remove old address: ", err.Error())
|
|
||||||
// return routeutils.HandleAPIError(ctx, err)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// address, err = c.svc.Users.SaveAddress(address)
|
|
||||||
// if err != nil {
|
|
||||||
// fmt.Println("Error saving address: ", err.Error())
|
|
||||||
// return routeutils.HandleAPIError(ctx, err)
|
|
||||||
// }
|
|
||||||
// user.Addresses = append(user.Addresses, address)
|
|
||||||
// }
|
|
||||||
|
|
||||||
visit.TripType = viewmodel.TripType{
|
visit.TripType = viewmodel.TripType{
|
||||||
Key: "no_trip",
|
Key: "no_trip",
|
||||||
@@ -620,7 +431,11 @@ func (c *controller) handle(ctx echo.Context) error {
|
|||||||
return routeutils.HandleAPIError(ctx, err)
|
return routeutils.HandleAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return routeutils.ResponseAPIOK(ctx, visit)
|
if authUser.Profiles[0].Key == "VIRPT" {
|
||||||
|
return routeutils.ResponseNoContent(ctx, nil)
|
||||||
|
} else {
|
||||||
|
return routeutils.ResponseAPIOK(ctx, visit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) handleGetByID(ctx echo.Context) error {
|
func (c *controller) handleGetByID(ctx echo.Context) error {
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ func authSkipper(ctx echo.Context) bool {
|
|||||||
strings.Contains(path, "/v1/notification/ws") ||
|
strings.Contains(path, "/v1/notification/ws") ||
|
||||||
strings.HasPrefix(path, "/v1/lyfthook") ||
|
strings.HasPrefix(path, "/v1/lyfthook") ||
|
||||||
strings.HasPrefix(path, "/v1/docs") ||
|
strings.HasPrefix(path, "/v1/docs") ||
|
||||||
strings.HasPrefix(path, "/v1/selfregister"))
|
strings.HasPrefix(path, "/v1/selfregister") ||
|
||||||
|
strings.HasPrefix(path, "/v1/passwordreset"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// appSkipper is the default skipper for the application routes
|
// appSkipper is the default skipper for the application routes
|
||||||
|
|||||||
@@ -9,21 +9,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
firstNameMaxLength = 50
|
firstNameMaxLength = 50
|
||||||
lastNameMaxLength = 50
|
lastNameMaxLength = 50
|
||||||
emailMaxLength = 150
|
emailMaxLength = 150
|
||||||
|
|
||||||
memberNumberValidNumberOfLetters = 3
|
memberNumberValidNumberOfLetters = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
formModeVisit = 1
|
formModeVisit = 1
|
||||||
formModeRide = 2
|
formModeRide = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func isAlphabetic(input string) bool {
|
func isAlphabetic(input string) bool {
|
||||||
for _, character := range input {
|
for _, character := range input {
|
||||||
if !(characterIsUpperCase(character) || characterIsLowerCase(character)){
|
if !(characterIsUpperCase(character) || characterIsLowerCase(character)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ func isAlphabetic(input string) bool {
|
|||||||
|
|
||||||
func isNumeric(input string) bool {
|
func isNumeric(input string) bool {
|
||||||
for _, character := range input {
|
for _, character := range input {
|
||||||
if !characterIsNumber(character){
|
if !characterIsNumber(character) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ func isNumeric(input string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func isEmailValid (email string) bool {
|
func isEmailValid(email string) bool {
|
||||||
validEmailRegex := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
validEmailRegex := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
||||||
|
|
||||||
return validEmailRegex.MatchString(email)
|
return validEmailRegex.MatchString(email)
|
||||||
@@ -55,7 +55,7 @@ func isMemberNumberValid(input string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isNumeric(input[memberNumberValidNumberOfLetters:]){
|
if !isNumeric(input[memberNumberValidNumberOfLetters:]) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,14 +65,14 @@ func isMemberNumberValid(input string) bool {
|
|||||||
func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
||||||
var result []errors.ValidationError
|
var result []errors.ValidationError
|
||||||
|
|
||||||
formMode:= formModeVisit // This should be red from request, not hardcoded
|
formMode := formModeVisit // This should be red from request, not hardcoded
|
||||||
|
|
||||||
//First name validation
|
//First name validation
|
||||||
if len(user.First) < 1 {
|
if len(user.First) < 1 {
|
||||||
result = append(result, errors.ValidationError{Field: "first", Message: "First Name is required"})
|
result = append(result, errors.ValidationError{Field: "first", Message: "First Name is required"})
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAlphabetic(user.First){
|
if !isAlphabetic(user.First) {
|
||||||
result = append(result, errors.ValidationError{Field: "first", Message: "First Name contains non-alphabetic characters"})
|
result = append(result, errors.ValidationError{Field: "first", Message: "First Name contains non-alphabetic characters"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
|||||||
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name is required"})
|
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name is required"})
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAlphabetic(user.Last){
|
if !isAlphabetic(user.Last) {
|
||||||
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name contains non-alphabetic characters"})
|
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name contains non-alphabetic characters"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +94,8 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Email validation
|
//Email validation
|
||||||
if user.Email != nil {
|
if user.Email != nil && len(*user.Email) > 0 {
|
||||||
if (formMode==formModeRide) && len(*user.Email) < 1 {
|
if (formMode == formModeRide) && len(*user.Email) < 1 {
|
||||||
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +106,8 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
|||||||
if len(*user.Email) > emailMaxLength {
|
if len(*user.Email) > emailMaxLength {
|
||||||
result = append(result, errors.ValidationError{Field: "email", Message: "Email is too long"})
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is too long"})
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
if (formMode==formModeRide){
|
if formMode == formModeRide {
|
||||||
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,14 +123,14 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Member# validation
|
//Member# validation
|
||||||
if !isMemberNumberValid(*user.Member){
|
if !isMemberNumberValid(*user.Member) {
|
||||||
result = append(result, errors.ValidationError{Field: "member", Message: "Member# is invalid"})
|
result = append(result, errors.ValidationError{Field: "member", Message: "Member# is invalid"})
|
||||||
}
|
}
|
||||||
//Birthdate validation
|
//Birthdate validation
|
||||||
if user.BirthDate == nil {
|
if user.BirthDate == nil {
|
||||||
result = append(result, errors.ValidationError{Field: "birthdate", Message: "Choose a Birth Date"})
|
result = append(result, errors.ValidationError{Field: "birthdate", Message: "Choose a Birth Date"})
|
||||||
}else{
|
} else {
|
||||||
yesterday := time.Now().Add(-1*time.Hour*hoursInDay)
|
yesterday := time.Now().Add(-1 * time.Hour * hoursInDay)
|
||||||
if user.BirthDate.After(yesterday) {
|
if user.BirthDate.After(yesterday) {
|
||||||
result = append(result, errors.ValidationError{Field: "birthdate", Message: "Choose a valid Birth Date"})
|
result = append(result, errors.ValidationError{Field: "birthdate", Message: "Choose a valid Birth Date"})
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//User consent validation
|
//User consent validation
|
||||||
if !user.Consent{
|
if !user.Consent {
|
||||||
result = append(result, errors.ValidationError{Field: "consent", Message: "Must be 'Checked'"})
|
result = append(result, errors.ValidationError{Field: "consent", Message: "Must be 'Checked'"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
111
server/validation/selfregister.go
Normal file
111
server/validation/selfregister.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minimumPasswordLength = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
func validateSelfregistrationPassword(user *viewmodel.User, result *[]errors.ValidationError) {
|
||||||
|
if len(user.Pass) < minimumPasswordLength {
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password", Message: fmt.Sprint("Password must be at least ", minimumPasswordLength, " characters.")})
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(user.Pass, user.First) {
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password", Message: "Password cannot include your First Name."})
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(user.Pass, user.Last) {
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password", Message: "Password cannot include your Last Name."})
|
||||||
|
}
|
||||||
|
|
||||||
|
containsUpperCaseLetter := false
|
||||||
|
containsLowerCaseLetter := false
|
||||||
|
containsNumber := false
|
||||||
|
|
||||||
|
for _, character := range user.Pass {
|
||||||
|
containsUpperCaseLetter = containsUpperCaseLetter || characterIsUpperCase(character)
|
||||||
|
containsLowerCaseLetter = containsLowerCaseLetter || characterIsLowerCase(character)
|
||||||
|
containsNumber = containsNumber || characterIsNumber(character)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !containsUpperCaseLetter || !containsLowerCaseLetter || !containsNumber {
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password", Message: "Password must contain one of EACH :"})
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password-tab", Message: "an uppercase letter"})
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password-tab", Message: "a lowercase letter"})
|
||||||
|
*result = append(*result, errors.ValidationError{Field: "password-tab", Message: "a number"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateSelfregistration(user *viewmodel.User) []errors.ValidationError {
|
||||||
|
var result []errors.ValidationError
|
||||||
|
|
||||||
|
//Provider Organization Name validation
|
||||||
|
if len(user.Provider.OrganizatioName) < 1 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "provider.org_name", Message: "Provider Organization Name is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Provider NPI validation
|
||||||
|
if len(user.Provider.InternalID) != 10 || !isNumeric(user.Provider.InternalID) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "provider.internal_id", Message: "Provider NPI must be a 10 digit number"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//First name validation
|
||||||
|
if len(user.First) < 1 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "first", Message: "First Name is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isAlphabetic(user.First) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "first", Message: "First Name contains non-alphabetic characters"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user.First) > firstNameMaxLength {
|
||||||
|
result = append(result, errors.ValidationError{Field: "first", Message: "First Name is too long"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Last name validation
|
||||||
|
if len(user.Last) < 1 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isAlphabetic(user.Last) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name contains non-alphabetic characters"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user.Last) > lastNameMaxLength {
|
||||||
|
result = append(result, errors.ValidationError{Field: "last", Message: "Last Name is too long"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Email validation
|
||||||
|
if user.Email != nil {
|
||||||
|
if len(*user.Email) < 1 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isEmailValid(*user.Email) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is invalid"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*user.Email) > emailMaxLength {
|
||||||
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is too long"})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = append(result, errors.ValidationError{Field: "email", Message: "Email is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Mobile validation
|
||||||
|
if (user.PhoneNumber == nil) || len(*user.PhoneNumber) < 1 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "phonenumber", Message: "Phone number is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Password validation
|
||||||
|
validateSelfregistrationPassword(user, &result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -1,36 +1,34 @@
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"time"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tripTypeFromVisit = "from_visit"
|
tripTypeFromVisit = "from_visit"
|
||||||
tripTypeToVisit = "to_visit"
|
tripTypeToVisit = "to_visit"
|
||||||
tripTypeFromVisitWillCall = "from_visit_call"
|
tripTypeFromVisitWillCall = "from_visit_call"
|
||||||
tripTypeRoundTrip = "roundtrip"
|
tripTypeRoundTrip = "roundtrip"
|
||||||
tripTypeRountTripWillCall = "roundtrip_call"
|
tripTypeRountTripWillCall = "roundtrip_call"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
loadingTime = 30 //in minutes
|
loadingTime = 30 //in minutes
|
||||||
minimumLoadTime = 30 //in minutes
|
minimumLoadTime = 30 //in minutes
|
||||||
minimumPickupTime = 10 //in minutes
|
minimumPickupTime = 10 //in minutes
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
hoursInDay = 24
|
hoursInDay = 24
|
||||||
hoursIn180Days = 24*180
|
hoursIn180Days = 24 * 180
|
||||||
time8Hours = 8
|
time8Hours = 8
|
||||||
time10Minutes = 10
|
time10Minutes = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
func isMixedIDValid(id string) bool {
|
func isMixedIDValid(id string) bool {
|
||||||
@@ -38,7 +36,7 @@ func isMixedIDValid(id string) bool {
|
|||||||
hasLowerCase := false
|
hasLowerCase := false
|
||||||
hasNumber := false
|
hasNumber := false
|
||||||
|
|
||||||
for _, character := range (id) {
|
for _, character := range id {
|
||||||
hasUpperCase = hasUpperCase || ((character >= 65) && (character <= 90))
|
hasUpperCase = hasUpperCase || ((character >= 65) && (character <= 90))
|
||||||
hasLowerCase = hasLowerCase || ((character >= 97) && (character <= 122))
|
hasLowerCase = hasLowerCase || ((character >= 97) && (character <= 122))
|
||||||
hasNumber = hasNumber || ((character >= 48) && (character <= 57))
|
hasNumber = hasNumber || ((character >= 48) && (character <= 57))
|
||||||
@@ -47,27 +45,44 @@ func isMixedIDValid(id string) bool {
|
|||||||
return (hasUpperCase || hasLowerCase) && hasNumber
|
return (hasUpperCase || hasLowerCase) && hasNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateVisitRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []errors.ValidationError {
|
||||||
|
var result []errors.ValidationError
|
||||||
|
|
||||||
|
if user.Email != nil && len(*user.Email) == 0 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "email", Message: "Step #1 - Email is mandatory"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.PhoneNumber != nil && len(*user.PhoneNumber) == 0 {
|
||||||
|
result = append(result, errors.ValidationError{Field: "phonenumber", Message: "Step #1 - Phonenumber is mandatory"})
|
||||||
|
}
|
||||||
|
|
||||||
|
rideValidation := ValidateRide(requestRide, user)
|
||||||
|
result = append(result, rideValidation...)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func ValidateRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []errors.ValidationError {
|
func ValidateRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []errors.ValidationError {
|
||||||
var result []errors.ValidationError
|
var result []errors.ValidationError
|
||||||
var validUUIDregex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
|
var validUUIDregex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`)
|
||||||
|
|
||||||
//Step #1 validation
|
//Step #1 validation
|
||||||
|
|
||||||
if !validUUIDregex.MatchString(user.ID){
|
if !validUUIDregex.MatchString(user.ID) {
|
||||||
result = append(result, errors.ValidationError{Field : "user_uuid", Message : "Step #1 - Choose a Member" })
|
result = append(result, errors.ValidationError{Field: "user_uuid", Message: "Step #1 - Choose a Member"})
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("\n\n", requestRide.Origin.ID, "\n\n")
|
fmt.Println("\n\n", requestRide.Origin.ID, "\n\n")
|
||||||
if !isMixedIDValid(requestRide.Origin.ID) {
|
if !isMixedIDValid(requestRide.Origin.ID) {
|
||||||
//it is not UUID or similar to UUID, let's try with just a number
|
//it is not UUID or similar to UUID, let's try with just a number
|
||||||
if originID, err := strconv.Atoi(requestRide.Origin.ID) ; err!= nil || originID <= 0 {
|
if originID, err := strconv.Atoi(requestRide.Origin.ID); err != nil || originID <= 0 {
|
||||||
//it is not a number
|
//it is not a number
|
||||||
result = append (result, errors.ValidationError{Field : "origin.id", Message : "Step #1 - Choose a Pickup Address"})
|
result = append(result, errors.ValidationError{Field: "origin.id", Message: "Step #1 - Choose a Pickup Address"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !requestRide.UserConsent {
|
if !requestRide.UserConsent {
|
||||||
result = append (result, errors.ValidationError{Field : "user_consent", Message : "Step #1 - Member must consent to Terms of Use"})
|
result = append(result, errors.ValidationError{Field: "user_consent", Message: "Step #1 - Member must consent to Terms of Use"})
|
||||||
}
|
}
|
||||||
|
|
||||||
//Step #2 validation
|
//Step #2 validation
|
||||||
@@ -75,141 +90,140 @@ func ValidateRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []er
|
|||||||
fmt.Println("\n\n", requestRide.Destination.ID, "\n\n")
|
fmt.Println("\n\n", requestRide.Destination.ID, "\n\n")
|
||||||
if !isMixedIDValid(requestRide.Destination.ID) {
|
if !isMixedIDValid(requestRide.Destination.ID) {
|
||||||
//it is not UUID or similar to UUID, let's try with just a number
|
//it is not UUID or similar to UUID, let's try with just a number
|
||||||
if destinationID, err := strconv.Atoi(requestRide.Destination.ID) ; err!= nil || destinationID <= 0 {
|
if destinationID, err := strconv.Atoi(requestRide.Destination.ID); err != nil || destinationID <= 0 {
|
||||||
result = append (result, errors.ValidationError{Field : "destination.id", Message : "Step #2 - Choose a Provider"})
|
result = append(result, errors.ValidationError{Field: "destination.id", Message: "Step #2 - Choose a Provider"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Step #3 validation
|
//Step #3 validation
|
||||||
|
|
||||||
isVisitDayToday := requestRide.VisitDate.Day() == time.Now().Day() && requestRide.VisitDate.Month() == time.Now().Month() && requestRide.VisitDate.Year() == time.Now().Year()
|
isVisitDayToday := requestRide.VisitDate.Day() == time.Now().Day() && requestRide.VisitDate.Month() == time.Now().Month() && requestRide.VisitDate.Year() == time.Now().Year()
|
||||||
before8Hours := time.Now().Add(-time.Hour*time8Hours)
|
before8Hours := time.Now().Add(-time.Hour * time8Hours)
|
||||||
|
|
||||||
if requestRide.VisitDate == nil {
|
if requestRide.VisitDate == nil {
|
||||||
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Choose a Date for the Visit"})
|
result = append(result, errors.ValidationError{Field: "visit_date", Message: "Step #3 - Choose a Date for the Visit"})
|
||||||
}else{
|
} else {
|
||||||
dayBeforeToday := time.Now().Add(-time.Hour*hoursInDay)
|
dayBeforeToday := time.Now().Add(-time.Hour * hoursInDay)
|
||||||
if requestRide.VisitDate.Before(dayBeforeToday) {
|
if requestRide.VisitDate.Before(dayBeforeToday) {
|
||||||
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Visit cannot occur more than one day before today"})
|
result = append(result, errors.ValidationError{Field: "visit_date", Message: "Step #3 - Visit cannot occur more than one day before today"})
|
||||||
}
|
}
|
||||||
|
|
||||||
dayAfter180Days := time.Now().Add(time.Hour*hoursIn180Days)
|
dayAfter180Days := time.Now().Add(time.Hour * hoursIn180Days)
|
||||||
if requestRide.VisitDate.After(dayAfter180Days) {
|
if requestRide.VisitDate.After(dayAfter180Days) {
|
||||||
result = append (result, errors.ValidationError{Field : "visit_date", Message : "Step #3 - Visit cannot occur more than 180 days after today"})
|
result = append(result, errors.ValidationError{Field: "visit_date", Message: "Step #3 - Visit cannot occur more than 180 days after today"})
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestRide.VisitTime == nil {
|
if requestRide.VisitTime == nil {
|
||||||
result = append (result, errors.ValidationError{Field : "visit_time", Message : "Step #3 - Choose a Time for the Visit"})
|
result = append(result, errors.ValidationError{Field: "visit_time", Message: "Step #3 - Choose a Time for the Visit"})
|
||||||
}else{
|
} else {
|
||||||
if isVisitDayToday && requestRide.VisitTime.Before(before8Hours) {
|
if isVisitDayToday && requestRide.VisitTime.Before(before8Hours) {
|
||||||
result = append (result, errors.ValidationError{Field : "visit_time", Message : "Step #3 - Visit is more than 8 hours in the past"})
|
result = append(result, errors.ValidationError{Field: "visit_time", Message: "Step #3 - Visit is more than 8 hours in the past"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Step #4 validation
|
//Step #4 validation
|
||||||
|
|
||||||
timeWithDurationAndLoadingTime := requestRide.VisitTime.Add(-time.Duration(requestRide.Duration)*time.Second).Add(-loadingTime*time.Minute)
|
timeWithDurationAndLoadingTime := requestRide.VisitTime.Add(-time.Duration(requestRide.Duration) * time.Second).Add(-loadingTime * time.Minute)
|
||||||
after10Minutes := time.Now().Add(time.Minute*time10Minutes)
|
after10Minutes := time.Now().Add(time.Minute * time10Minutes)
|
||||||
|
|
||||||
isTripTypeValid := true
|
isTripTypeValid := true
|
||||||
|
|
||||||
switch requestRide.TripType.Key {
|
switch requestRide.TripType.Key {
|
||||||
case tripTypeToVisit:
|
case tripTypeToVisit:
|
||||||
if requestRide.PickupTime == nil {
|
if requestRide.PickupTime == nil {
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Choose a Pickup Time"})
|
||||||
}else{
|
} else {
|
||||||
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time must occur before Visit Time"})
|
||||||
}
|
|
||||||
|
|
||||||
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time before Visit Time"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Visit cannot occour in the past"})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case tripTypeFromVisit :
|
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
||||||
if requestRide.PickupTime == nil {
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time less than required time before Visit Time"})
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
|
|
||||||
}else{
|
|
||||||
timeWithMinimumPickupTime := time.Now().Add(minimumPickupTime*time.Minute)
|
|
||||||
if isVisitDayToday && requestRide.PickupTime.Before(timeWithMinimumPickupTime) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : fmt.Sprint("Step #4 - Time must be more than %d minutes from now",minimumPickupTime)})
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestRide.PickupTime.Before(*requestRide.VisitTime) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time after Visit Time"})
|
|
||||||
}
|
|
||||||
|
|
||||||
timeWithMinimumLoadTime := time.Now().Add(minimumLoadTime*time.Minute)
|
|
||||||
if requestRide.PickupTime.Before(timeWithMinimumLoadTime) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than Minimum Load Time before Visit Time"})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case tripTypeFromVisitWillCall:
|
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
|
||||||
//no special validation for this case
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Visit cannot occour in the past"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case tripTypeRoundTrip:
|
case tripTypeFromVisit:
|
||||||
if requestRide.PickupTime == nil {
|
if requestRide.PickupTime == nil {
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Choose a Pickup Time"})
|
||||||
}else{
|
} else {
|
||||||
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
timeWithMinimumPickupTime := time.Now().Add(minimumPickupTime * time.Minute)
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
|
if isVisitDayToday && requestRide.PickupTime.Before(timeWithMinimumPickupTime) {
|
||||||
}
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: fmt.Sprint("Step #4 - Time must be more than %d minutes from now", minimumPickupTime)})
|
||||||
|
|
||||||
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time before Visit Time"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if isVisitDayToday && requestRide.PickupTime.Before(after10Minutes) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must be at least 10 minutes from now"})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestRide.ReturnTime == nil {
|
if requestRide.PickupTime.Before(*requestRide.VisitTime) {
|
||||||
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Choose a Pickup Time"})
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time less than required time after Visit Time"})
|
||||||
}else{
|
|
||||||
if isVisitDayToday {
|
|
||||||
if requestRide.ReturnTime.Before(before8Hours) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Return Time is more than 8 hours after Visit Time"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestRide.ReturnTime.Before(after10Minutes) {
|
|
||||||
result = append (result, errors.ValidationError{Field : "return_time", Message : "Step #4 - Return Time must be at least 10 minutes from now"})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case tripTypeRountTripWillCall:
|
timeWithMinimumLoadTime := time.Now().Add(minimumLoadTime * time.Minute)
|
||||||
if requestRide.PickupTime == nil {
|
if requestRide.PickupTime.Before(timeWithMinimumLoadTime) {
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Choose a Pickup Time"})
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time less than Minimum Load Time before Visit Time"})
|
||||||
}else{
|
}
|
||||||
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
}
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time must occur before Visit Time"})
|
|
||||||
}
|
|
||||||
|
|
||||||
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
case tripTypeFromVisitWillCall:
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Pickup Time less than required time after Visit Time"})
|
//no special validation for this case
|
||||||
}
|
|
||||||
|
|
||||||
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
|
case tripTypeRoundTrip:
|
||||||
result = append (result, errors.ValidationError{Field : "pickup_time", Message : "Step #4 - Visit cannot occur in the past "})
|
if requestRide.PickupTime == nil {
|
||||||
}
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Choose a Pickup Time"})
|
||||||
|
} else {
|
||||||
|
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time must occur before Visit Time"})
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
||||||
isTripTypeValid = false
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time less than required time before Visit Time"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if isVisitDayToday && requestRide.PickupTime.Before(after10Minutes) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time must be at least 10 minutes from now"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestRide.ReturnTime == nil {
|
||||||
|
result = append(result, errors.ValidationError{Field: "return_time", Message: "Step #4 - Choose a Pickup Time"})
|
||||||
|
} else {
|
||||||
|
if isVisitDayToday {
|
||||||
|
if requestRide.ReturnTime.Before(before8Hours) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "return_time", Message: "Step #4 - Return Time is more than 8 hours after Visit Time"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestRide.ReturnTime.Before(after10Minutes) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "return_time", Message: "Step #4 - Return Time must be at least 10 minutes from now"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case tripTypeRountTripWillCall:
|
||||||
|
if requestRide.PickupTime == nil {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Choose a Pickup Time"})
|
||||||
|
} else {
|
||||||
|
if requestRide.PickupTime.After(*requestRide.VisitTime) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time must occur before Visit Time"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestRide.PickupTime.After(timeWithDurationAndLoadingTime) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Pickup Time less than required time after Visit Time"})
|
||||||
|
}
|
||||||
|
|
||||||
|
if isVisitDayToday && requestRide.PickupTime.Before(before8Hours) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "pickup_time", Message: "Step #4 - Visit cannot occur in the past "})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
isTripTypeValid = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isTripTypeValid {
|
if !isTripTypeValid {
|
||||||
result = append (result, errors.ValidationError{Field : "trip_type.key", Message : "Step #4 - Choose a Trip Type"})
|
result = append(result, errors.ValidationError{Field: "trip_type.key", Message: "Step #4 - Choose a Trip Type"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,44 @@
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ValidateVisit(visit *viewmodel.Visit, user *viewmodel.User) []errors.ValidationError {
|
func ValidateVisit(visit *viewmodel.Visit, user *viewmodel.User) []errors.ValidationError {
|
||||||
var result []errors.ValidationError
|
var result []errors.ValidationError
|
||||||
|
// Step #1
|
||||||
if len(visit.User.First) == 0 {
|
if len(visit.Provider.ProviderUUID) == 0 {
|
||||||
result = append(result, errors.ValidationError{Field: "first", Message: "Step #1 - First Name is mandatory"})
|
result = append(result, errors.ValidationError{Field: "provider.id", Message: "Step #1 - Provider is required"})
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(visit.User.Last) == 0 {
|
// Step #2
|
||||||
result = append(result, errors.ValidationError{Field: "last", Message: "Step #1 - Last Name is mandatory"})
|
eligibilityResult := ValidateEligibility(&visit.User)
|
||||||
|
if len(eligibilityResult) > 0 {
|
||||||
|
result = append(result, eligibilityResult...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if visit.User.Gender == nil || (*visit.User.Gender != "M" && *visit.User.Gender != "F" && *visit.User.Gender != "U") {
|
//Step #3
|
||||||
result = append(result, errors.ValidationError{Field: "gender", Message: "Step #1 - Gender is mandatory"})
|
if visit.VisitDatetime.IsZero() {
|
||||||
}
|
result = append(result, errors.ValidationError{Field: "visit_datetime", Message: "Step #3 - Choose a Date for the Visit"})
|
||||||
|
} else {
|
||||||
|
isVisitDayToday := visit.VisitDatetime.Day() == time.Now().Day() && visit.VisitDatetime.Month() == time.Now().Month() && visit.VisitDatetime.Year() == time.Now().Year()
|
||||||
|
before8Hours := time.Now().Add(-time.Hour * time8Hours)
|
||||||
|
dayBeforeToday := time.Now().Add(-time.Hour * hoursInDay)
|
||||||
|
if visit.VisitDatetime.Before(dayBeforeToday) {
|
||||||
|
result = append(result, errors.ValidationError{Field: "visit_datetime", Message: "Step #3 - Visit cannot occur more than one day before today"})
|
||||||
|
}
|
||||||
|
|
||||||
if visit.User.Type == nil || (*visit.User.Type != "S" && *visit.User.Gender != "D" && *visit.User.Gender != "U") {
|
dayAfter180Days := time.Now().Add(time.Hour * hoursIn180Days)
|
||||||
result = append(result, errors.ValidationError{Field: "type", Message: "Step #1 - Member Type is mandatory"})
|
if visit.VisitDatetime.After(dayAfter180Days) {
|
||||||
}
|
result = append(result, errors.ValidationError{Field: "visit_datetime", Message: "Step #3 - Visit cannot occur more than 180 days after today"})
|
||||||
|
}
|
||||||
|
|
||||||
if visit.User.Member == nil || len(*visit.User.Member) == 0 {
|
if isVisitDayToday && visit.VisitDatetime.Before(before8Hours) {
|
||||||
result = append(result, errors.ValidationError{Field: "member", Message: "Step #1 - Member # is mandatory"})
|
result = append(result, errors.ValidationError{Field: "visit_datetime", Message: "Step #3 - Visit is more than 8 hours in the past"})
|
||||||
}
|
}
|
||||||
|
|
||||||
if visit.User.BirthDate == nil || visit.User.BirthDate.IsZero() {
|
|
||||||
result = append(result, errors.ValidationError{Field: "birthdate", Message: "Step #1 - Birth Date is mandatory"})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
BIN
svijetlastrana
Executable file
BIN
svijetlastrana
Executable file
Binary file not shown.
Reference in New Issue
Block a user