Upstream sync
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||
"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/infra/config"
|
||||
)
|
||||
@@ -30,8 +31,10 @@ type Service struct {
|
||||
// New returns a new domain Service instance
|
||||
func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
|
||||
once.Do(func() {
|
||||
bcbsi := bcbsi.New(cfg)
|
||||
|
||||
instance = &Service{
|
||||
Users: newUserService(svc, mapper),
|
||||
Users: newUserService(svc, mapper, bcbsi, cfg),
|
||||
Rides: newRideService(svc, mapper),
|
||||
Visits: newVisitService(svc, mapper),
|
||||
Provider: newProviderService(svc, mapper),
|
||||
|
||||
@@ -1,24 +1,40 @@
|
||||
package applicationservice
|
||||
|
||||
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/third/eligibility/bcbsi"
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"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
|
||||
type userService struct {
|
||||
svc *service.Service
|
||||
mapEntity *entitymapping.Mapper
|
||||
bcbsi *bcbsi.Service
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
// 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{
|
||||
svc: svc,
|
||||
mapEntity: mapper,
|
||||
bcbsi: bcbsi,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,3 +200,215 @@ func (s *userService) RemoveContact(contact viewmodel.Contact) (retVal viewmodel
|
||||
|
||||
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())}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 == "" {
|
||||
return viewmodel.User{}, &viewmodel.ValidationError{Message: "Provider not found"}
|
||||
} 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
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ func (mapping *userMapping) ToUserModel(item entity.User) viewmodel.User {
|
||||
Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
|
||||
Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
|
||||
Type: &item.Type,
|
||||
Test: item.Test,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
|
||||
Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
|
||||
Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
|
||||
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
|
||||
Test: item.Test,
|
||||
}
|
||||
|
||||
if item.Type == nil {
|
||||
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type Eligibility struct {
|
||||
TrackingID string `json:"tracking_id,omitempty"`
|
||||
Payer Payer `json:"payer,omitempty"`
|
||||
Provider Provider `json:"provider,omitempty"`
|
||||
Subscriber Subscriber `json:"subscriber,omitempty"`
|
||||
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
|
||||
User User `json:"user,omitempty"`
|
||||
TrackingID string `json:"tracking_id,omitempty"`
|
||||
Payer Payer `json:"payer,omitempty"`
|
||||
Provider Provider `json:"provider,omitempty"`
|
||||
Subscriber Subscriber `json:"subscriber,omitempty"`
|
||||
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
|
||||
User User `json:"user,omitempty"`
|
||||
RawProvider ProviderResponse `json:"raw_provider,omitempty"`
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -26,6 +26,7 @@ type User struct {
|
||||
Organizations []Organization `json:"organizations,omitempty"`
|
||||
Provider *ProviderResp `json:"provider,omitempty"`
|
||||
Consent bool `json:"consent,omitempty"`
|
||||
Test bool `json:"test,omitempty"`
|
||||
}
|
||||
|
||||
type Contact struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[app]
|
||||
name = "nemt"
|
||||
debug = true
|
||||
disable-zip-validation = true
|
||||
|
||||
[app.docs]
|
||||
swagger-path = "./static/swagger-ui"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[app]
|
||||
name = "nemt"
|
||||
debug = true
|
||||
disable-zip-validation = true
|
||||
|
||||
[app.docs]
|
||||
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||
@@ -9,7 +10,7 @@ debug = true
|
||||
[db]
|
||||
host = "db01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
||||
port = 3306
|
||||
name = "nemt_clean"
|
||||
name = "nemt"
|
||||
user = "nemt-user"
|
||||
pass = "OL&!n#p6J8Lu"
|
||||
max-life-minutes = 5
|
||||
@@ -74,8 +75,8 @@ user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
|
||||
|
||||
[bxe]
|
||||
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
||||
key = "dacg7jtsmb6ajr3z553jbczg"
|
||||
secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
|
||||
key = "c63z7gv9a5qz2zgx7zcm3253"
|
||||
secret = "hK4Yc9jtBrxaZTr4UU2VsfX9"
|
||||
|
||||
[blue365]
|
||||
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[app]
|
||||
name = "nemt"
|
||||
debug = true
|
||||
disable-zip-validation = true
|
||||
|
||||
[app.docs]
|
||||
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||
|
||||
@@ -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,
|
||||
&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, &retVal.Type)
|
||||
&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 != sql.ErrNoRows {
|
||||
return retVal, errors.Wrap(err)
|
||||
@@ -278,7 +278,8 @@ func (c *userRepo) getQuery() string {
|
||||
IFNULL(i.address, '') work_address,
|
||||
IFNULL(i.lat, 0) work_lat,
|
||||
IFNULL(i.long, 0) work_long,
|
||||
IFNULL(a.member_type, 'S') member_type
|
||||
IFNULL(a.member_type, 'S') member_type,
|
||||
user_test
|
||||
FROM
|
||||
tab_user a
|
||||
INNER JOIN
|
||||
@@ -587,11 +588,11 @@ func (c *userRepo) createLogin(user entity.User) (int64, string, error) {
|
||||
|
||||
func (c *userRepo) createUser(user entity.User) (int64, string, error) {
|
||||
const (
|
||||
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 = ?;"
|
||||
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()
|
||||
|
||||
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))
|
||||
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 {
|
||||
return 0, "", err
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ type User struct {
|
||||
Types []OrganizationType `json:"types,omitempty"`
|
||||
Organizations []Organization `json:"organizations,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Test bool `json:"test,omitempty"`
|
||||
}
|
||||
|
||||
type ContactInfo struct {
|
||||
|
||||
@@ -25,14 +25,15 @@ type Config struct {
|
||||
Blue365 Blue365Config
|
||||
Email EmailConfig
|
||||
GoogleShortener GoogleShortenerConfig
|
||||
Eligibility EligibilityConfig
|
||||
Eligibility EligibilityConfig
|
||||
}
|
||||
|
||||
// AppConfig represents the configuration values about the application.
|
||||
type AppConfig struct {
|
||||
Name string
|
||||
Debug bool
|
||||
Docs DocsConfig
|
||||
Name string
|
||||
Debug bool
|
||||
Docs DocsConfig
|
||||
DisableZipValidation bool
|
||||
}
|
||||
|
||||
// TwilioConfig represents the configuration values about the twilio.
|
||||
@@ -139,7 +140,7 @@ type GoogleShortenerConfig struct {
|
||||
}
|
||||
|
||||
type EligibilityConfig struct {
|
||||
Url string
|
||||
Url string
|
||||
}
|
||||
|
||||
// Read returns the configuration values,
|
||||
@@ -160,8 +161,9 @@ func Read() (*Config, error) {
|
||||
|
||||
return &Config{
|
||||
App: AppConfig{
|
||||
Name: viper.GetString("app.name"),
|
||||
Debug: viper.GetBool("app.debug"),
|
||||
Name: viper.GetString("app.name"),
|
||||
Debug: viper.GetBool("app.debug"),
|
||||
DisableZipValidation: viper.GetBool("app.disable-zip-validation"),
|
||||
Docs: DocsConfig{
|
||||
YAMLPath: viper.GetString("app.docs.yaml-path"),
|
||||
SwaggerPath: viper.GetString("app.docs.swagger-path"),
|
||||
@@ -243,8 +245,8 @@ func Read() (*Config, error) {
|
||||
ClientID: viper.GetString("google-shortener.client-id"),
|
||||
SecretKey: viper.GetString("google-shortener.secret-key"),
|
||||
},
|
||||
Eligibility : EligibilityConfig{
|
||||
Url : viper.GetString("eligibility.url"),
|
||||
Eligibility: EligibilityConfig{
|
||||
Url: viper.GetString("eligibility.url"),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package eligibilityroute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"html"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -16,9 +12,7 @@ import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||
"github.com/labstack/echo"
|
||||
"googlemaps.github.io/maps"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -78,185 +72,53 @@ func (c *controller) handleEligibility(ctx echo.Context) error {
|
||||
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 == "" {
|
||||
provider, err := c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, 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)
|
||||
var provider viewmodel.ProviderResp
|
||||
provider, err = c.svc.Provider.GetByNPI(eligibility.RawProvider.FivePartKeyGroups[0].ProviderNum, authUser)
|
||||
if err != nil {
|
||||
fmt.Println("Error Here: ", err.Error())
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
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 {
|
||||
fmt.Println("Error to unmarshal: ", err.Error())
|
||||
if provider.ProviderUUID == "" {
|
||||
org := viewmodel.Organization{
|
||||
Type: viewmodel.OrganizationType{
|
||||
Key: "provider",
|
||||
Name: "Provider",
|
||||
},
|
||||
Name: eligibility.RawProvider.OrgName,
|
||||
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 {
|
||||
fmt.Println(err)
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
if user.ID == "" {
|
||||
user.Pass = c.generatePassword(8)
|
||||
user.BirthDate = &eligibility.Subscriber.DemographicInfo.DateOfBirth
|
||||
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
|
||||
provider, err = c.svc.Provider.GetByOrganization(org.UUID, authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
profile, err := c.svc.Profile.GetByKey("US")
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
user.Profiles = append(user.Profiles, profile)
|
||||
|
||||
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
|
||||
user, err := c.svc.Users.CheckAndCreateMember(eligibility.User, provider, authUser)
|
||||
if err != nil {
|
||||
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||
if len(validationError.Errors) > 0 {
|
||||
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||
} else {
|
||||
return routeutils.ResponseAPIFieldValidationError(ctx, "phonenumber", "Phone number is required")
|
||||
}
|
||||
|
||||
user, err = c.svc.Users.Create(user, authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
|
||||
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 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)
|
||||
if authUser.Profiles[0].Key == "VIRPT" {
|
||||
return ctx.JSON(204, nil)
|
||||
} 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)
|
||||
}
|
||||
|
||||
authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
lyftRide := viewmodel.RideRequest{RideID: ride.InternalID}
|
||||
if ride.Status.Key == "scheduled" && !strings.Contains(ride.InternalID, "s_") {
|
||||
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.Error() != "ride_not_found" {
|
||||
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)
|
||||
}
|
||||
|
||||
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" {
|
||||
var lyftRide viewmodel.RideRequest
|
||||
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})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
lyftRide, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||
}
|
||||
if err != nil {
|
||||
@@ -236,7 +246,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
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})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -258,7 +268,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
||||
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
||||
lyftRide.RideType = "lyft"
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
|
||||
if authUser.Test {
|
||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
|
||||
@@ -57,8 +57,14 @@ func (c *controller) handleStateChange(ctx echo.Context) error {
|
||||
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
|
||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
||||
if authUser.Test {
|
||||
_, err = c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
|
||||
go func() {
|
||||
secondCall := func() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package selfregisterroute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
b64 "encoding/base64"
|
||||
@@ -22,6 +23,10 @@ const (
|
||||
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 (
|
||||
instance *controller
|
||||
once sync.Once
|
||||
@@ -44,12 +49,34 @@ func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *co
|
||||
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 {
|
||||
var user viewmodel.User
|
||||
if err := ctx.Bind(&user); err != nil {
|
||||
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", "")
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
@@ -132,10 +159,14 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
|
||||
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
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,
|
||||
@@ -144,7 +175,8 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
|
||||
notification, err = c.svc.Notification.SendNotificationWithoutWritingToDatabase(notification)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
logger := ctx.Logger()
|
||||
logger.Warnf("Application Error: Could not send sms notification to user mobile : %s", *user.PhoneNumber)
|
||||
}
|
||||
|
||||
return routeutils.ResponseAPIOK(ctx, user)
|
||||
|
||||
@@ -289,7 +289,7 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
requestRide.Destination = newOrigin
|
||||
}
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != createdUser.ID {
|
||||
if createdUser.Test {
|
||||
resp, err = c.tnc.Lyft.RequestRide(requestRide)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -404,7 +404,7 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
newRide.Passenger.LastName = " "
|
||||
newRide.Passenger.PhoneNumber = *user.PhoneNumber
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != createdUser.ID {
|
||||
if createdUser.Test {
|
||||
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -514,7 +514,7 @@ func (c *controller) handleRawLyft(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
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})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -546,7 +546,7 @@ func (c *controller) handleRideETA(ctx echo.Context) error {
|
||||
|
||||
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
||||
var lyftRide viewmodel.RideRequest
|
||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
||||
if user.Test {
|
||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -614,7 +614,7 @@ func (c *controller) handleCancel(ctx echo.Context) error {
|
||||
requestRide.RideID = "s_" + ride.InternalID
|
||||
}
|
||||
|
||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
||||
if user.Test {
|
||||
err = c.tnc.Lyft.CancelRide(requestRide)
|
||||
if err != nil && err.Error() == "ride_not_found" {
|
||||
err = nil
|
||||
@@ -719,7 +719,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
||||
|
||||
if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
|
||||
var lyftRide viewmodel.RideRequest
|
||||
if ride.CreatedUser.ID != c.cfg.LyftProd.UserUUID {
|
||||
if user.Test {
|
||||
lyftRide, err = c.tnc.Lyft.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -858,7 +858,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
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})
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -880,7 +880,7 @@ func (c *controller) handleReady(ctx echo.Context) error {
|
||||
lyftRide.Passenger.PhoneNumber = *nextRide.User.PhoneNumber
|
||||
lyftRide.RideType = "lyft"
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != nextRide.CreatedUser.ID {
|
||||
if user.Test {
|
||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||
} else {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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 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" {
|
||||
@@ -161,7 +168,7 @@ func (c *controller) handleTwilio(ctx echo.Context) error {
|
||||
lyftRide.Passenger.PhoneNumber = *readyRide.User.PhoneNumber
|
||||
lyftRide.RideType = "lyft"
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != readyRide.CreatedUser.ID {
|
||||
if authUser.Test {
|
||||
lyftRide, err = c.tnc.Lyft.RequestRide(lyftRide)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -209,7 +216,7 @@ func (c *controller) handleTwilio(ctx echo.Context) error {
|
||||
|
||||
if requestMessage == "YES" && lastRide.UUID != "" {
|
||||
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})
|
||||
if err != nil {
|
||||
fmt.Println("Error: ", err.Error())
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package usersroute
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -22,8 +18,6 @@ import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||
"github.com/labstack/echo"
|
||||
"golang.org/x/net/context"
|
||||
"googlemaps.github.io/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -345,11 +339,6 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
||||
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)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
@@ -359,153 +348,24 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
||||
return routeutils.ResponseAPIAuthError(ctx, "phonenumber or email is required", false)
|
||||
}
|
||||
|
||||
if len(user.Pass) == 0 {
|
||||
user.Pass = c.generatePassword(8)
|
||||
} 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)
|
||||
}
|
||||
|
||||
profile, err := c.svc.Profile.GetByKey("US")
|
||||
provider, err := c.svc.Provider.GetByNPI("1699849786", authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
return routeutils.ResponseAPIAuthError(ctx, "Provider not found", false)
|
||||
}
|
||||
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)
|
||||
user, err = c.svc.Users.CheckAndCreateMember(user, provider, authUser)
|
||||
if err != nil {
|
||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
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.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode > 300 {
|
||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
|
||||
eligibilityResponse := viewmodel.Interchange271{}
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
err = decoder.Decode(&eligibilityResponse)
|
||||
if err != nil {
|
||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
//================================================================
|
||||
|
||||
if len(eligibilityResponse.Division.HealthCareEligibilityResponse.LoopHL0030) < 1 {
|
||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
|
||||
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())
|
||||
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||
if len(validationError.Errors) > 0 {
|
||||
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||
} else {
|
||||
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -547,6 +407,7 @@ func (c *controller) handleBulkPortal(ctx echo.Context) error {
|
||||
return routeutils.ResponseAPIAuthError(ctx, "name is required", false)
|
||||
}
|
||||
|
||||
users[i].Test = true
|
||||
if len(users[i].First) != 0 && len(users[i].Last) != 0 {
|
||||
users[i].Name = fmt.Sprintf("%s %s", users[i].First, users[i].Last)
|
||||
}
|
||||
@@ -608,6 +469,7 @@ func (c *controller) handlePortal(ctx echo.Context) error {
|
||||
if len(user.First) != 0 && len(user.Last) != 0 {
|
||||
user.Name = fmt.Sprintf("%s %s", user.First, user.Last)
|
||||
}
|
||||
user.Test = true
|
||||
|
||||
user, err = c.svc.Users.Create(user, authUser)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package visitroute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
b64 "encoding/base64"
|
||||
|
||||
"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/tncservice"
|
||||
@@ -20,7 +17,6 @@ import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/server/validation"
|
||||
"github.com/labstack/echo"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"googlemaps.github.io/maps"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -81,103 +77,34 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
visit.User.PhoneNumber = ride.User.PhoneNumber
|
||||
visit.User.Email = ride.User.Email
|
||||
visit.User.Consent = true
|
||||
|
||||
ride.Visit = visit
|
||||
|
||||
user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
user.PhoneNumber = ride.User.PhoneNumber
|
||||
user.Email = ride.User.Email
|
||||
|
||||
ride.Visit.User = user
|
||||
if ride.Visit.User.Type == nil {
|
||||
subscriber := "S"
|
||||
ride.Visit.User.Type = &subscriber
|
||||
}
|
||||
|
||||
var provider viewmodel.ProviderResp
|
||||
provider, err = c.svc.Provider.GetByUUID(ride.Visit.Provider.ProviderUUID, authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
visit.Provider = provider
|
||||
ride.Visit.Provider = provider
|
||||
|
||||
eligibility := viewmodel.Eligibility{}
|
||||
eligibility.Provider.ProviderNPI = provider.InternalID
|
||||
eligibility.Provider.ProviderName = provider.OrganizatioName
|
||||
eligibility.TrackingID = c.rangeIn(1000000, 9999999)
|
||||
eligibility.Subscriber.SubscriberID = *ride.Visit.User.Member
|
||||
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)
|
||||
user, err := c.svc.Users.CheckAndCreateMember(ride.Visit.User, provider, authUser)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return routeutils.ResponseAPIValidationError(ctx, err.Error())
|
||||
}
|
||||
|
||||
address := viewmodel.Address{}
|
||||
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)
|
||||
}
|
||||
}
|
||||
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||
if len(validationError.Errors) > 0 {
|
||||
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||
} else {
|
||||
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||
}
|
||||
}
|
||||
|
||||
address, err = c.svc.Users.SaveAddress(address)
|
||||
if err != nil {
|
||||
fmt.Println("Error to save address: ", err.Error())
|
||||
} else {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
user.Addresses = append(user.Addresses, address)
|
||||
}
|
||||
ride.Visit.User = user
|
||||
ride.User = user
|
||||
|
||||
homeAddress := viewmodel.Address{}
|
||||
for _, a := range visit.User.Addresses {
|
||||
@@ -226,7 +153,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
||||
ride.Destination = newOrigin
|
||||
}
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != authUser.ID {
|
||||
if authUser.Test {
|
||||
resp, err = c.tnc.Lyft.RequestRide(ride)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -340,7 +267,7 @@ func (c *controller) handleRide(ctx echo.Context) error {
|
||||
newRide.Passenger.LastName = " "
|
||||
newRide.Passenger.PhoneNumber = *visit.User.PhoneNumber
|
||||
|
||||
if c.cfg.LyftProd.UserUUID != authUser.ID {
|
||||
if authUser.Test {
|
||||
newRide, err = c.tnc.Lyft.RequestRide(newRide)
|
||||
} else {
|
||||
fmt.Println("In Production")
|
||||
@@ -471,154 +398,19 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
return routeutils.ResponseAPICustomValidationError(ctx, "visit validation failed", validationErrors)
|
||||
}
|
||||
|
||||
eligibility := viewmodel.Eligibility{}
|
||||
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)
|
||||
user, err := c.svc.Users.CheckAndCreateMember(visit.User, provider, authUser)
|
||||
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 {
|
||||
fmt.Println("Error to get user by memberID: ", err.Error())
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
if user.ID == "" {
|
||||
if len(user.Pass) == 0 {
|
||||
user.Pass = c.generatePassword(8)
|
||||
if validationError, ok := err.(*viewmodel.ValidationError); ok {
|
||||
if len(validationError.Errors) > 0 {
|
||||
return routeutils.ResponseAPICustomValidationError(ctx, validationError.Message, validationError.Errors)
|
||||
} else {
|
||||
return routeutils.ResponseAPIServiceError(ctx, validationError.Message)
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
|
||||
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.User = user
|
||||
|
||||
visit.TripType = viewmodel.TripType{
|
||||
Key: "no_trip",
|
||||
@@ -634,7 +426,11 @@ func (c *controller) handle(ctx echo.Context) error {
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user