Compare commits

...

4 Commits

Author SHA1 Message Date
GotPPay
0e91373b55 edit self registration error message 2018-06-01 05:08:13 +02:00
Senad Uka
f1ac874276 Upstream sync 2018-05-30 08:45:32 +02:00
Senad Uka
756d84359d Upstream sync 2018-05-29 18:25:44 +02:00
Senad Uka
806e2b1f3b Upstream sync 2018-05-29 17:22:48 +02:00
22 changed files with 658 additions and 373 deletions

View File

@@ -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 {

View File

@@ -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)
} }

View File

@@ -50,6 +50,7 @@ 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,
} }
} }
@@ -79,6 +80,12 @@ func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types), Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
} }
if item.Type == nil {
user.Type = "S"
} else {
user.Type = *item.Type
}
if user.Name == "" { if user.Name == "" {
user.Name = fmt.Sprintf("%s %s", item.First, item.Last) user.Name = fmt.Sprintf("%s %s", item.First, item.Last)
} }

View File

@@ -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)

View File

@@ -58,6 +58,9 @@ type RideRequest struct {
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

View File

@@ -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 p AD * * * * * * *
113 p BDCAD * techsupport * * * /v1/nemt/eligibility POST
114 p PLANAD * plan * * * /v1/nemt/eligibility POST
115 p AD * * * * * /v1/nemt/eligibility POST
116 p VIRPT * * * * * /v1/nemt/users/member POST
117 p VIRPT * * * * * /v1/nemt/users/member GET
118 p VIRPT * * * * * /v1/nemt/eligibility POST
119 p VIRPT * * * * * /v1/nemt/visits POST
120 p VIRPT * * * * * /v1/nemt/rides/eta GET
121 p VIRPT * * * * * /v1/nemt/provider GET
122 p VIRPT * * * * * /v1/selfregister POST

View File

@@ -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

View File

@@ -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 {
@@ -192,7 +192,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)
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 +230,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,
@@ -277,7 +277,8 @@ func (c *userRepo) getQuery() string {
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
FROM FROM
tab_user a tab_user a
INNER JOIN INNER JOIN
@@ -521,7 +522,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 +587,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) VALUES(?, ?, ?, ?, ?, ?, SHA2(CONCAT_WS('-',?,?,?,?,?), 512)) ON DUPLICATE KEY UPDATE user_uuid = ?, `name` = ?, subscriber_id = ?, birth_date = ?, gender = ?;"
) )
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, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender))
if err != nil { if err != nil {
return 0, "", err return 0, "", err
} }

View File

@@ -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,

View File

@@ -30,6 +30,7 @@ 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"`
} }
type ContactInfo struct { type ContactInfo struct {

View File

@@ -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
} }

View File

@@ -16,6 +16,7 @@ import (
"bitbucket.org/nemt/nemt-portal-api/infra/auth" "bitbucket.org/nemt/nemt-portal-api/infra/auth"
"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"
"bitbucket.org/nemt/nemt-portal-api/server/validation"
"github.com/labstack/echo" "github.com/labstack/echo"
"googlemaps.github.io/maps" "googlemaps.github.io/maps"
) )
@@ -77,6 +78,10 @@ func (c *controller) handleEligibility(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
if validationErrors := validation.ValidateEligibility(&eligibility.User); len(validationErrors) > 0 {
return routeutils.ResponseAPICustomValidationError(ctx, "eligibility validation failed", validationErrors)
}
if eligibility.Provider.ProviderNPI == "" { if eligibility.Provider.ProviderNPI == "" {
provider, err := c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, authUser) provider, err := c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, authUser)
if err != nil { if err != nil {

View File

@@ -92,11 +92,12 @@ 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)
} }

View File

@@ -16,6 +16,12 @@ 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"
)
var ( var (
instance *controller instance *controller
once sync.Once once sync.Once
@@ -49,44 +55,20 @@ func (c *controller) handle(ctx echo.Context) error {
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 +121,31 @@ 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 {
return routeutils.HandleAPIError(ctx, err)
}
//Send sms notification to Authorized user
notification = viewmodel.Notification{
Type: applicationservice.NOtificationTypeSMS,
To: *user.PhoneNumber,
Message: notificationSmsBody,
}
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
return routeutils.ResponseAPIOK(ctx, user) return routeutils.ResponseAPIOK(ctx, user)
} }

View File

@@ -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]
@@ -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)
} }

View File

@@ -1,15 +1,15 @@
package usersroute package usersroute
import ( import (
"bytes"
b64 "encoding/base64" b64 "encoding/base64"
"encoding/json"
"fmt" "fmt"
"math/rand" "math/rand"
"net/http"
"strings"
"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,8 +19,8 @@ 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" "golang.org/x/net/context"
"googlemaps.github.io/maps" "googlemaps.github.io/maps"
@@ -420,7 +420,7 @@ func (c *controller) handleMember(ctx echo.Context) error {
client := &http.Client{} client := &http.Client{}
eligibilityJson, err := json.Marshal(eligibility) eligibilityJson, err := json.Marshal(eligibility)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.ResponseAPINotEligibleError(ctx)
} }
req, _ := http.NewRequest("POST", c.cfg.Eligibility.Url, bytes.NewBuffer(eligibilityJson)) req, _ := http.NewRequest("POST", c.cfg.Eligibility.Url, bytes.NewBuffer(eligibilityJson))
req.Header.Add("App", c.cfg.HTTP.Auth.AppKey) req.Header.Add("App", c.cfg.HTTP.Auth.AppKey)
@@ -429,24 +429,24 @@ func (c *controller) handleMember(ctx echo.Context) error {
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.ResponseAPINotEligibleError(ctx)
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 300 { if resp.StatusCode < 200 || resp.StatusCode > 300 {
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility") return routeutils.ResponseAPINotEligibleError(ctx)
} }
eligibilityResponse := viewmodel.Interchange271{} eligibilityResponse := viewmodel.Interchange271{}
decoder := json.NewDecoder(resp.Body) decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&eligibilityResponse) err = decoder.Decode(&eligibilityResponse)
if err != nil { if err != nil {
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility") return routeutils.ResponseAPINotEligibleError(ctx)
} }
//================================================================ //================================================================
if len(eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030) < 1 { if len(eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030) < 1 {
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Cannot check eligibility") return routeutils.ResponseAPINotEligibleError(ctx)
} }
address := viewmodel.Address{} address := viewmodel.Address{}

View File

@@ -88,9 +88,14 @@ func (c *controller) handleRide(ctx echo.Context) error {
fmt.Println(err) fmt.Println(err)
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
user.PhoneNumber = ride.User.PhoneNumber
user.Email = ride.User.Email
ride.Visit.User = user ride.Visit.User = user
if ride.Visit.User.Type == nil {
subscriber := "S" subscriber := "S"
ride.Visit.User.Type = &subscriber 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)
@@ -189,6 +194,8 @@ 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,
} }
if len(ride.Origin.ID) == 0 {
ride.Origin = viewmodel.Location{ ride.Origin = viewmodel.Location{
ID: homeAddress.UUID, ID: homeAddress.UUID,
Name: homeAddress.AddressTypeName, Name: homeAddress.AddressTypeName,
@@ -196,6 +203,8 @@ func (c *controller) handleRide(ctx echo.Context) error {
Longitude: homeAddress.Longitude, Longitude: homeAddress.Longitude,
Address: homeAddress.Address, Address: homeAddress.Address,
} }
}
ride.Notes = ride.Notes ride.Notes = ride.Notes
ride.Passenger.FirstName = visit.User.First ride.Passenger.FirstName = visit.User.First
ride.Passenger.LastName = " " ride.Passenger.LastName = " "
@@ -203,6 +212,11 @@ func (c *controller) handleRide(ctx echo.Context) error {
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" {
@@ -457,25 +471,25 @@ 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{} eligibility := viewmodel.Eligibility{}
// eligibility.Provider.ProviderNPI = provider.InternalID eligibility.Provider.ProviderNPI = provider.InternalID
// eligibility.Provider.ProviderName = provider.OrganizatioName eligibility.Provider.ProviderName = provider.OrganizatioName
// eligibility.TrackingID = c.rangeIn(1000000, 9999999) eligibility.TrackingID = c.rangeIn(1000000, 9999999)
// eligibility.Subscriber.SubscriberID = *visit.User.Member eligibility.Subscriber.SubscriberID = *visit.User.Member
// eligibility.Subscriber.PatientType = *visit.User.Type eligibility.Subscriber.PatientType = *visit.User.Type
// eligibility.Subscriber.Name.First = visit.User.First eligibility.Subscriber.Name.First = visit.User.First
// eligibility.Subscriber.Name.Last = visit.User.Last eligibility.Subscriber.Name.Last = visit.User.Last
// eligibility.Subscriber.DemographicInfo.DateOfBirth = *visit.User.BirthDate eligibility.Subscriber.DemographicInfo.DateOfBirth = *visit.User.BirthDate
// eligibility.Subscriber.DemographicInfo.Gender = *visit.User.Gender eligibility.Subscriber.DemographicInfo.Gender = *visit.User.Gender
// loc, _ := time.LoadLocation("America/Chicago") loc, _ := time.LoadLocation("America/Chicago")
// eligibility.ServiceInfo.DateOfService = time.Now().In(loc) eligibility.ServiceInfo.DateOfService = time.Now().In(loc)
// eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"} eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
// resp, err := c.bcbsi.BXE.Get271(eligibility) resp, err := c.bcbsi.BXE.Get271(eligibility)
// if err != nil { if err != nil {
// fmt.Println("Error to get eligibility: ", err.Error()) fmt.Println("Error to get eligibility: ", err.Error())
// return routeutils.ResponseAPIValidationError(ctx, err.Error()) return routeutils.ResponseAPIValidationError(ctx, err.Error())
// } }
user, err := c.svc.Users.GetByMemberID(*visit.User.Member) user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
if err != nil { if err != nil {
@@ -551,60 +565,60 @@ func (c *controller) handle(ctx echo.Context) error {
} }
} }
// address := viewmodel.Address{} address := viewmodel.Address{}
// header := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950 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 body := resp.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
// zipCode := strings.TrimSpace(body.N403) zipCode := strings.TrimSpace(body.N403)
// address.AddressTypeName = "Home" address.AddressTypeName = "Home"
// address.AddressType = "home" address.AddressType = "home"
// address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401) address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
// address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode) address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
// address.CreatedUserUUID = authUser.ID address.CreatedUserUUID = authUser.ID
// address.User = user address.User = user
// address.Type = "provider" address.Type = "provider"
// googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI=")) googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
// if err != nil { if err != nil {
// fmt.Println("Error to instantiate googles api: ", err.Error()) fmt.Println("Error to instantiate googles api: ", err.Error())
// return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
// } }
// r := &maps.GeocodingRequest{ r := &maps.GeocodingRequest{
// Address: address.Address + " " + body.N402 + ", " + zipCode, Address: address.Address + " " + body.N402 + ", " + zipCode,
// } }
// result, err := googleMapsAPI.Geocode(context.Background(), r) result, err := googleMapsAPI.Geocode(context.Background(), r)
// if err != nil { if err != nil {
// fmt.Println("Error to instantiate googles api: ", err.Error()) fmt.Println("Error to instantiate googles api: ", err.Error())
// return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
// } }
// if len(result) > 0 { if len(result) > 0 {
// address.Latitude = result[0].Geometry.Location.Lat address.Latitude = result[0].Geometry.Location.Lat
// address.Longitude = result[0].Geometry.Location.Lng address.Longitude = result[0].Geometry.Location.Lng
// } }
// if address.Latitude != 0 && address.Longitude != 0 { if address.Latitude != 0 && address.Longitude != 0 {
// if len(user.Addresses) > 0 { if len(user.Addresses) > 0 {
// for _, a := range user.Addresses { for _, a := range user.Addresses {
// if a.AddressType == "home" { if a.AddressType == "home" {
// err := c.svc.Users.RemoveAddress(a.UUID) err := c.svc.Users.RemoveAddress(a.UUID)
// if err != nil { if err != nil {
// fmt.Println("Error to remove old address: ", err.Error()) fmt.Println("Error to remove old address: ", err.Error())
// return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
// } }
// } }
// } }
// } }
// address, err = c.svc.Users.SaveAddress(address) address, err = c.svc.Users.SaveAddress(address)
// if err != nil { if err != nil {
// fmt.Println("Error saving address: ", err.Error()) fmt.Println("Error saving address: ", err.Error())
// return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
// } }
// user.Addresses = append(user.Addresses, address) user.Addresses = append(user.Addresses, address)
// } }
visit.TripType = viewmodel.TripType{ visit.TripType = viewmodel.TripType{
Key: "no_trip", Key: "no_trip",

View File

@@ -94,7 +94,7 @@ 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"})
} }
@@ -107,7 +107,7 @@ func ValidateEligibility(user *viewmodel.User) []errors.ValidationError {
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"})
} }
} }

View 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
}

View File

@@ -1,15 +1,13 @@
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 (
@@ -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,6 +45,23 @@ 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}$`)
@@ -210,6 +225,5 @@ func ValidateRide(requestRide *viewmodel.RideRequest, user *viewmodel.User) []er
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
} }

View File

@@ -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