Upstream sync

This commit is contained in:
Senad Uka
2018-05-25 09:12:42 +02:00
parent 6e903b4d57
commit 94229831e0
38 changed files with 1281 additions and 156 deletions

View File

@@ -1,6 +1,7 @@
FROM nginx:latest FROM nginx:latest
RUN apt-get update; apt-get install -y openssl RUN apt-get update; apt-get install -y openssl
RUN apt-get install -y ca-certificates
RUN rm -rf /etc/nginx/conf.d/*; RUN rm -rf /etc/nginx/conf.d/*;
COPY ./dist/default.conf /etc/nginx/conf.d/ COPY ./dist/default.conf /etc/nginx/conf.d/

View File

@@ -23,7 +23,8 @@ type Service struct {
Notification *notificationService Notification *notificationService
Profile *profileService Profile *profileService
Organization *organizationService Organization *organizationService
Zipcodes *zipcodeService Zipcodes *zipcodeService
Plan *planService
} }
// New returns a new domain Service instance // New returns a new domain Service instance
@@ -37,7 +38,8 @@ func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notif
Notification: newNotificationService(svc, mapper, notification, cfg), Notification: newNotificationService(svc, mapper, notification, cfg),
Profile: newProfileService(svc, mapper), Profile: newProfileService(svc, mapper),
Organization: newOrganizationService(svc, mapper), Organization: newOrganizationService(svc, mapper),
Zipcodes: newZipcodeService(svc, mapper), Zipcodes: newZipcodeService(svc, mapper),
Plan: newPlanService(svc, mapper),
} }
}) })

View File

@@ -0,0 +1,57 @@
package applicationservice
import (
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/service"
)
// providerService holds methods to provider application service
type planService struct {
svc *service.Service
mapEntity *entitymapping.Mapper
}
// newProviderService returns a providerService instance
func newPlanService(svc *service.Service, mapper *entitymapping.Mapper) *planService {
return &planService{
svc: svc,
mapEntity: mapper,
}
}
func (s *planService) GetByAlphaPrefix(alphaPrefix string) (viewmodel.Plan, error) {
plan, err := s.svc.Plans.GetByAlphaPrefix(alphaPrefix)
if err != nil {
return viewmodel.Plan{}, err
}
return s.mapEntity.Plan.ToPlanModel(plan), nil
}
func (s *planService) GetByUUID(planUUID string) ([]viewmodel.Plan, error) {
plans, err := s.svc.Plans.GetByUUID(planUUID)
if err != nil {
return nil, err
}
return s.mapEntity.Plan.ToPlanModelSlice(plans), nil
}
func (s *planService) GetByID(planID int64) ([]viewmodel.Plan, error) {
plans, err := s.svc.Plans.GetByID(planID)
if err != nil {
return nil, err
}
return s.mapEntity.Plan.ToPlanModelSlice(plans), nil
}
func (s *planService) GetByPrefixUUID(prefixUUID string) (viewmodel.Plan, error) {
plan, err := s.svc.Plans.GetByPrefixUUID(prefixUUID)
if err != nil {
return viewmodel.Plan{}, err
}
return s.mapEntity.Plan.ToPlanModel(plan), nil
}

View File

@@ -68,3 +68,13 @@ func (s *providerService) GetByNPI(NPI string, user viewmodel.User) (viewmodel.P
return s.mapEntity.Provider.ToProviderRespModel(provider), nil return s.mapEntity.Provider.ToProviderRespModel(provider), nil
} }
func (s *providerService) GetByOrganization(organizationUUID string, user viewmodel.User) (viewmodel.ProviderResp, error) {
eUser := s.mapEntity.User.ToUserEntity(user)
provider, err := s.svc.Provider.GetByOrganization(organizationUUID, eUser)
if err != nil {
return viewmodel.ProviderResp{}, err
}
return s.mapEntity.Provider.ToProviderRespModel(provider), nil
}

View File

@@ -51,6 +51,16 @@ func (s *userService) GetByUUID(uuid string, profile string) (retVal viewmodel.U
return s.mapEntity.User.ToUserModel(user), nil return s.mapEntity.User.ToUserModel(user), nil
} }
// GetByID returns a specific user by its ID
func (s *userService) GetByMemberID(memberID string) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.GetByMemberID(memberID)
if err != nil {
return retVal, errors.Wrap(err)
}
return s.mapEntity.User.ToUserModel(user), nil
}
// Login returns a specific user by email and pass // Login returns a specific user by email and pass
func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (retVal viewmodel.User, err error) { func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (retVal viewmodel.User, err error) {
user, err := s.svc.Users.FullLogin(loginType, key, pass, profile) user, err := s.svc.Users.FullLogin(loginType, key, pass, profile)
@@ -131,6 +141,11 @@ func (s *userService) RemoveAddress(addressUUID string) error {
return s.svc.Users.RemoveAddress(addressUUID) return s.svc.Users.RemoveAddress(addressUUID)
} }
func (s *userService) UpdateLogin(user viewmodel.User) error {
eUser := s.mapEntity.User.ToUserEntity(user)
return s.svc.Users.UpdateLogin(eUser)
}
func (s *userService) SaveAddress(address viewmodel.Address) (retVal viewmodel.Address, err error) { func (s *userService) SaveAddress(address viewmodel.Address) (retVal viewmodel.Address, err error) {
entity := s.mapEntity.Address.ToAddressEntity(address) entity := s.mapEntity.Address.ToAddressEntity(address)
entity, err = s.svc.Users.SaveAddress(entity) entity, err = s.svc.Users.SaveAddress(entity)

View File

@@ -21,6 +21,38 @@ func newVisitService(svc *service.Service, mapper *entitymapping.Mapper) *visitS
} }
} }
func (s *visitService) Save(visit viewmodel.Visit) (viewmodel.Visit, error) {
entity := s.mapEntity.Visit.ToVisitEntity(visit)
for _, a := range visit.User.Addresses {
if a.AddressType == "home" {
address, err := s.svc.Users.GetAddressByUUID(a.UUID)
if err != nil {
return viewmodel.Visit{}, err
}
entity.PickupAddressID = address.ID
entity.Pickup.Address = address.Address
entity.Pickup.ID = address.UUID
entity.Pickup.Latitude = address.Latitude
entity.Pickup.Longitude = address.Longitude
entity.Pickup.Name = address.Name
}
}
provider, err := s.svc.Provider.GetByUUID(entity.Provider.ProviderUUID, entity.CreatedUser)
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
entity.Provider = provider
retVal, err := s.svc.Visits.Create(entity)
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
return s.mapEntity.Visit.ToVisitModel(retVal), err
}
// Save a new ride // Save a new ride
func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) { func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) {
entity := s.mapEntity.Visit.ToVisitEntity(visit) entity := s.mapEntity.Visit.ToVisitEntity(visit)
@@ -51,5 +83,17 @@ func (s *visitService) GetByUUID(visitUUID string, user viewmodel.User) (viewmod
return viewmodel.Visit{}, errors.Wrap(err) return viewmodel.Visit{}, errors.Wrap(err)
} }
visitUser, err := s.svc.Users.GetByUUID(retVal.User.UUID, "US")
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
retVal.User = visitUser
provider, err := s.svc.Provider.GetByUUID(retVal.Provider.ProviderUUID, eUser)
if err != nil {
return viewmodel.Visit{}, errors.Wrap(err)
}
retVal.Provider = provider
return s.mapEntity.Visit.ToVisitModel(retVal), err return s.mapEntity.Visit.ToVisitModel(retVal), err
} }

View File

@@ -21,7 +21,8 @@ type Mapper struct {
Notification *notificationMapping Notification *notificationMapping
Profile *profileMapping Profile *profileMapping
Organization *organizationMapping Organization *organizationMapping
Zipcode *zipcodeMapping Zipcode *zipcodeMapping
Plan *planMapping
} }
// New returns an EntityMapper for fluent mapping // New returns an EntityMapper for fluent mapping
@@ -38,6 +39,7 @@ func New() *Mapper {
instance.Profile = &profileMapping{instance} instance.Profile = &profileMapping{instance}
instance.Organization = &organizationMapping{instance} instance.Organization = &organizationMapping{instance}
instance.Zipcode = &zipcodeMapping{instance} instance.Zipcode = &zipcodeMapping{instance}
instance.Plan = &planMapping{instance}
}) })
return instance return instance

View File

@@ -0,0 +1,65 @@
package entitymapping
import (
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
// providerMapping has method to map provider entities to view models
type planMapping struct {
mapper *Mapper
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *planMapping) ToPlanEntitySlice(list []viewmodel.Plan) (retVal []entity.Plan) {
retVal = make([]entity.Plan, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToPlanEntity(item))
}
return retVal
}
func (mapping *planMapping) ToPlanEntity(model viewmodel.Plan) entity.Plan {
return entity.Plan{
UUID: model.ID,
Name: model.Name,
InternalID: model.InternalID,
Status: model.Status,
PlanEntityID: model.PlanEntityID,
EntityID: model.EntityID,
PayerID: model.PayerID,
PayerName: model.PayerName,
PrefixUUID: model.PrefixID,
AlphaPrefix: model.AlphaPrefix,
Active: model.Active,
}
}
// ToUserEntitySlice maps a User entity slice to User view model slice
func (mapping *planMapping) ToPlanModelSlice(list []entity.Plan) (retVal []viewmodel.Plan) {
retVal = make([]viewmodel.Plan, 0)
for _, item := range list {
retVal = append(retVal, mapping.ToPlanModel(item))
}
return retVal
}
func (mapping *planMapping) ToPlanModel(model entity.Plan) viewmodel.Plan {
return viewmodel.Plan{
ID: model.UUID,
Name: model.Name,
InternalID: model.InternalID,
Status: model.Status,
PlanEntityID: model.PlanEntityID,
EntityID: model.EntityID,
PayerID: model.PayerID,
PayerName: model.PayerName,
PrefixID: model.PrefixUUID,
AlphaPrefix: model.AlphaPrefix,
Active: model.Active,
}
}

View File

@@ -80,6 +80,8 @@ func (s bxeService) Get271(eligibility viewmodel.Eligibility) (bcbsimodel.Interc
return bcbsimodel.Interchange271{}, err return bcbsimodel.Interchange271{}, err
} }
fmt.Println(resp)
if resp.QueryResult.HIPPA271.T271 != "" { if resp.QueryResult.HIPPA271.T271 != "" {
xmlString := html.UnescapeString(resp.QueryResult.HIPPA271.T271) xmlString := html.UnescapeString(resp.QueryResult.HIPPA271.T271)
xmlReader := strings.NewReader(xmlString) xmlReader := strings.NewReader(xmlString)
@@ -98,13 +100,10 @@ func (s bxeService) Get271(eligibility viewmodel.Eligibility) (bcbsimodel.Interc
} }
func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimodel.MemberEligibilityResponse, error) { func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimodel.MemberEligibilityResponse, error) {
// payer, err := s.GetPayerDetails(eligibility.Subscriber.SubscriberID) if eligibility.Payer.PayerID == "" || eligibility.Payer.PayerName == "" {
// if err != nil { eligibility.Payer.PayerID = "621"
// return bcbsimodel.MemberEligibilityResponse{}, err eligibility.Payer.PayerName = "blue_cross_blue_shield_il"
// } }
eligibility.Payer.PayerID = "621"
eligibility.Payer.PayerName = "blue_cross_blue_shield_il"
envelope := bcbsimodel.GetEnvelope(eligibility) envelope := bcbsimodel.GetEnvelope(eligibility)
apiKey := s.cfg.BXE.APIKey apiKey := s.cfg.BXE.APIKey
@@ -146,7 +145,6 @@ func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimo
fmt.Println("Error WebService getting object: ", err) fmt.Println("Error WebService getting object: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err return bcbsimodel.MemberEligibilityResponse{}, err
} }
fmt.Println("Result: ", result.Body.MemberEligibilityResponse)
return result.Body.MemberEligibilityResponse, nil return result.Body.MemberEligibilityResponse, nil
} }

View File

@@ -11,6 +11,7 @@ type Eligibility struct {
Provider Provider `json:"provider,omitempty"` Provider Provider `json:"provider,omitempty"`
Subscriber Subscriber `json:"subscriber,omitempty"` Subscriber Subscriber `json:"subscriber,omitempty"`
ServiceInfo ServiceInfo `json:"service_info,omitempty"` ServiceInfo ServiceInfo `json:"service_info,omitempty"`
User User `json:"user,omitempty"`
} }
type Payer struct { type Payer struct {

View File

@@ -0,0 +1,15 @@
package viewmodel
type Plan struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
InternalID string `json:"key,omitempty"`
Status bool `json:"desc,omitempty"`
PlanEntityID int64 `json:"plan_entity_id,omitempty"`
EntityID int64 `json:"entity_id,omitempty"`
PayerID int64 `json:"payer_id,omitempty"`
PayerName string `json:"payer_name,omitempty"`
PrefixID string `json:"prefix_uuid,omitempty"`
AlphaPrefix string `json:"alpha_prefix,omitempty"`
Active bool `json:"active,omitempty"`
}

View File

@@ -18,6 +18,7 @@ pipelines:
- cp nemt-portal-api ./dist/ - cp nemt-portal-api ./dist/
- cp -R static/* ./dist/static/ - cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/ - cp -R docs/swagger/ ./dist/docs/
- cp -R certs/prd/* ./dist/certs/
- cp config.prd.toml ./dist/config.toml - cp config.prd.toml ./dist/config.toml
- cp default.prd.conf ./dist/default.conf - cp default.prd.conf ./dist/default.conf
- cp nginx.conf ./dist/nginx.conf - cp nginx.conf ./dist/nginx.conf
@@ -49,6 +50,7 @@ pipelines:
- cp nemt-portal-api ./dist/ - cp nemt-portal-api ./dist/
- cp -R static/* ./dist/static/ - cp -R static/* ./dist/static/
- cp -R docs/swagger/ ./dist/docs/ - cp -R docs/swagger/ ./dist/docs/
- cp -R certs/stg/* ./dist/certs/
- cp config.stg.toml ./dist/config.toml - cp config.stg.toml ./dist/config.toml
- cp default.stg.conf ./dist/default.conf - cp default.stg.conf ./dist/default.conf
- cp nginx.conf ./dist/nginx.conf - cp nginx.conf ./dist/nginx.conf

View File

@@ -1,41 +1,41 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIGvjCCBaagAwIBAgIQC3nVkJVbuOa1WFfJQc+IMDANBgkqhkiG9w0BAQsFADBN MIIGxzCCBa+gAwIBAgIQDARDXxHDhGyEB0wVou2tYTANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwNTIxMDAwMDAwWhcN aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwNTIxMDAwMDAwWhcN
MjAwNTIwMTIwMDAwWjCBhTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lz MjAwNTIwMTIwMDAwWjCBgTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lz
MRAwDgYDVQQHEwdDaGljYWdvMS8wLQYDVQQKEyZCbHVlIENyb3NzIGFuZCBCbHVl MRAwDgYDVQQHEwdDaGljYWdvMS8wLQYDVQQKEyZCbHVlIENyb3NzIGFuZCBCbHVl
IFNoaWVsZCBBc3NvY2lhdGlvbjEgMB4GA1UEAwwXKi5kZXYuYmNic2luc3RpdHV0 IFNoaWVsZCBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTKi5iY2JzaW5zdGl0dXRlLmNv
ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0VyKNSM/a/CzE bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKzhKJlWTkQjsFBzjdIC
16vidZzip1p4B7+EhJVyENoofRDk7D7afDddWV33yHUvI5opsyKIEMuGFRNIROH/ Z4CuIQqjEtvR3fZ8JeW0X+FsWi4wNUDeHlNpxNNUIf0msojKRXaFsld3wMxRQ47S
ZX47vV3H2ST/5UmkXhghEVjA/xQFUqx2hUxAjI+EkHyf+D3cofcoqFBGA7DVQ9MK AAnoM6O+Yd4OtSq5Pf55epfvVAsZUpJWBwMHL4iN1KU2PVEN3FPWAEp1ZiM4cUew
qgbRmwV09IgfQmdlFlF/D3/ZROYNYhY7NC5W+9d+JdmkV45Kp2zIDEa990roDF2p VmAZlzU7KxeLDD2ZSHH4mEVKrkQ6juNUzr+458Dt1drOTqwLGJP5K4Q30eG49l2U
oN6Nk0WsDMNn5nhyFtGyeuFmYcWwKeCI/XlMu5roko7tJtY0oC0boKSZ8S7xiEPK dSd/5L8E8MjU8r3QAbpaPxT6euhZlnxkwbKHXQUEueZ1nfSI7suXveV6pHjusX07
uBUxw9cWcHVbkLyeJXIr7lfIzg5xejX3A5/KA7UuKtPAc3HQh09TEOD40Rof5Mts HjDgMPBZhpqI1ZfcK+d5hR2ZMJQ8kLkbzYBiUxVn11WWgg5g8zPVfAf2CzW/PAIA
l5njh/MhAgMBAAGjggNfMIIDWzAfBgNVHSMEGDAWgBQPgGEcgjFh1S8o541GOLQs faUCAwEAAaOCA2wwggNoMB8GA1UdIwQYMBaAFA+AYRyCMWHVLyjnjUY4tCzhxtni
4cbZ4jAdBgNVHQ4EFgQUOlOHeILArFmCfRgy4zob9YD7ZdMwIgYDVR0RBBswGYIX MB0GA1UdDgQWBBQLp7ndHlG3iCGf7P7Np16aWJn+fzAxBgNVHREEKjAoghMqLmJj
Ki5kZXYuYmNic2luc3RpdHV0ZS5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW YnNpbnN0aXR1dGUuY29tghFiY2JzaW5zdGl0dXRlLmNvbTAOBgNVHQ8BAf8EBAMC
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjBrBgNVHR8EZDBiMC+gLaArhilodHRwOi8v BaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMGsGA1UdHwRkMGIwL6At
Y3JsMy5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDAvoC2gK4YpaHR0cDov oCuGKWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMC+g
L2NybDQuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5jcmwwTAYDVR0gBEUwQzA3 LaArhilodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc3NjYS1zaGEyLWc2LmNybDBM
BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu BgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3
Y29tL0NQUzAIBgZngQwBAgIwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhho dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjB8BggrBgEFBQcBAQRwMG4wJAYI
dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBGBggrBgEFBQcwAoY6
cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQw aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMlNlY3VyZVNl
CQYDVR0TBAIwADCCAYAGCisGAQQB1nkCBAIEggFwBIIBbAFqAHYApLkJkLQYWBSH cnZlckNBLmNydDAJBgNVHRMEAjAAMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgA
uxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFjhC1vrQAABAMARzBFAiEAjDaMTkKz dgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWOELVu6AAAEAwBH
JL1M7AloHKciZwIm9PhTpRJhtDedIoV2l5oCIEyT5kke4/OXoBE9guw1TPCKwuS5 MEUCIAZMGHS0chj0XWT4ikeIjqg0dglEBDIavlnouMrAEiCnAiEAzFN2rUdA0N/l
klDOeG+rlHiTHZvbAHcAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RMA +cJqOaEJHIop81RoAcrQ8ltrNkXdZD8AdgBvU3asMfAxGdiZAKRRFf93FRwR2QLB
AAFjhC1xQwAABAMASDBGAiEAzo+0zJUoqV0X0IqzaZ+9boXzWvIzZCR/OqT1qcAe ACkGjbIImjfZEwAAAWOELV3xAAAEAwBHMEUCIFojBHhsdHar7n0eJ35etIlqUtHR
a3QCIQCdMYaIEYnhnsaOXPMsyShv+ry41lQ9UvUZ3EAvhjgCeQB3ALvZ37wfinG1 WV9EQxu752OWrnmsAiEAod+vqZXLOUYR4DRzlA3h9BBkkm0hc4QAU2v2h9h46rQA
k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABY4QtcKQAAAQDAEgwRgIhAJ4XGViz dgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAWOELVwOAAAEAwBH
vfkGsR3/UWlVZhX9t5rLAlyhW/t1K17vkNjJAiEAhzQycmcTPIVb1Ul1Ug5UgWQ4 MEUCIEBiLv2mAcIhhIHNmCKFFxQM6UtbO4XmlNNm9PTQLtxEAiEAichicElMgsp9
eD2rp/4raewQVACs26QwDQYJKoZIhvcNAQELBQADggEBADjGzhdcyCYxemKuWoP9 wAXBuHQ5stQiDicsJ/04Ws2QzuxbpTQwDQYJKoZIhvcNAQELBQADggEBAB3kQbAX
Umd0jnS6gHPivwgpy2Ra4SSsFCkucHX8dRMi63MRghiKi4FPj9LsFoLpdHacfi+6 /RaGmnyIduvFE66Nzd/goThIr4bpBnrW0YKvZj2oHq34KjaVkmWX4VXHmyHTd9TI
Q1lX3fZ6Mv2ZpNjMtBe/g6SATLsFxUQl+UP5bMShEXHsQduinAvSW3m8UpQZ2UxG YJyHifiMrfZ/BCkS5FDg32J1Vocp89k5YDS+pHxlLLxqqMsrz80v5mtblhDhqenx
7L/XmNfeW8x213Mi4G2DNUJKDMjO28bO/GbCNB85HGfhnaDxj7OsQYllbE5oEDXN 2dsdwYErlbrAvNp95BKdwqcVbqvg2IHBhJ8myB5kgGLgU6Sn96SfsF5wytW+qnQx
Wkx1QZFrvqE3/2zoOa1ga36xymRXt0Sn3OSFr/ukZh3MCWAL5fuT4zjnSjybHDqT gIn3qfPkwXVou/mq8PbZSqsrNvggjOTKbkNj8k4u+/OAHd9nP4p/CBGN7hb5RxXs
2qdmV08ECgXwVNUMtbTFq9kenBN0xTrfPFR0Y0IPzqXQP5kTPktgrrYiAf+S875J e24Ql2MFqKXx2EIrsMs+ow2xnz6hNRAD39vsYp7HSFj7Ph32Wi8X1O+J68PiNbaW
IVo= ZblXGGMRXKXUfFA=
-----END CERTIFICATE----- -----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0BAQsFADBh

View File

@@ -28,7 +28,8 @@ type Conn struct {
notification *notificationRepo notification *notificationRepo
profile *profileRepo profile *profileRepo
organization *organizationRepo organization *organizationRepo
zipcodes *zipcodeRepo zipcodes *zipcodeRepo
plan *planRepo
} }
// Begin starts a transaction // Begin starts a transaction
@@ -81,10 +82,14 @@ func (c *Conn) Organization() contract.OrganizationRepo {
return c.organization return c.organization
} }
func (c *Conn) Zipcodes() contract.ZipcodeRepo{ func (c *Conn) Zipcodes() contract.ZipcodeRepo {
return c.zipcodes return c.zipcodes
} }
func (c *Conn) Plans() contract.PlanRepo {
return c.plan
}
// Instance returns an instance of a DataManager // Instance returns an instance of a DataManager
func Instance(cfg *config.Config) (contract.DataManager, error) { func Instance(cfg *config.Config) (contract.DataManager, error) {
once.Do(func() { once.Do(func() {
@@ -117,6 +122,7 @@ func Instance(cfg *config.Config) (contract.DataManager, error) {
instance.profile = newProfileRepo(db) instance.profile = newProfileRepo(db)
instance.organization = newOrganizationRepo(db) instance.organization = newOrganizationRepo(db)
instance.zipcodes = newZipcodeRepo(db) instance.zipcodes = newZipcodeRepo(db)
instance.plan = newPlanRepo(db)
}) })
return instance, connErr return instance, connErr

View File

@@ -44,7 +44,7 @@ func (c *organizationRepo) getProfileQuery(user entity.User) (query string, wher
where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID) where = fmt.Sprintf(` AND (a.organization_uuid = '%s' OR f.organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
return return
} }
case "SP", "SPT": case "SP", "SPT", "VIRPT":
switch p.Organization.Type.Key { switch p.Organization.Type.Key {
case "techsupport", "bcbsi", "bcbsa": case "techsupport", "bcbsi", "bcbsa":
return return

82
data/datamysql/plan.go Normal file
View File

@@ -0,0 +1,82 @@
package datamysql
import (
"database/sql"
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
type planRepo struct {
conn executor
}
func newPlanRepo(conn executor) *planRepo {
return &planRepo{
conn: conn,
}
}
func (c *planRepo) getQuery() string {
const query = `SELECT
a.plan_id,
a.plan_uuid,
a.plan_name,
a.plan_internal_id,
a.plan_internal_status,
a.plan_entity_id,
a.entity_id,
a.payer_id,
a.payer_name,
a.active,
a.created,
a.updated,
b.plan_prefix_id,
b.plan_prefix_uuid,
b.alpha_prefix
FROM
tab_plan a
INNER JOIN
tab_plan_alpha_prefix b ON a.plan_id = b.plan_id `
return query
}
func (c *planRepo) parseSet(rows *sql.Rows, err error) ([]entity.Plan, error) {
if err != nil {
return nil, errors.Wrap(err)
}
result := make([]entity.Plan, 0)
for rows.Next() {
entity, err := c.parseEntity(rows)
if err != nil {
return nil, errors.Wrap(err)
}
result = append(result, entity)
}
return result, nil
}
func (c *planRepo) parseEntity(row scanner) (retVal entity.Plan, err error) {
err = row.Scan(
&retVal.ID, &retVal.UUID, &retVal.Name, &retVal.InternalID, &retVal.Status, &retVal.PlanEntityID, &retVal.EntityID, &retVal.PayerID, &retVal.PayerName,
&retVal.Active, &retVal.Created, &retVal.Updated, &retVal.PrefixID, &retVal.PrefixUUID, &retVal.AlphaPrefix)
return retVal, errors.Wrap(err)
}
func (c *planRepo) GetByAlphaPrefix(alphaPrefix string) (entity.Plan, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE b.alpha_prefix = ? ", alphaPrefix))
}
func (c *planRepo) GetByUUID(planUUID string) ([]entity.Plan, error) {
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.plan_uuid = ? ", planUUID))
}
func (c *planRepo) GetByID(planID int64) ([]entity.Plan, error) {
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.plan_id = ? ", planID))
}
func (c *planRepo) GetByPrefixUUID(prefixUUID string) (entity.Plan, error) {
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE b.plan_prefix_uuid = ? ", prefixUUID))
}

View File

@@ -27,7 +27,7 @@ func (c *providerRepo) getProfileQuery(user entity.User) (query string, where st
if len(user.Profiles) > 0 { if len(user.Profiles) > 0 {
for _, p := range user.Profiles { for _, p := range user.Profiles {
switch p.Key { switch p.Key {
case "AD", "BCBSIAD", "BDCAD", "PLANAD": case "AD", "BCBSIAD", "BDCAD", "PLANAD", "VIRPT":
return return
case "SP", "SPT": case "SP", "SPT":
switch p.Organization.Type.Key { switch p.Organization.Type.Key {
@@ -145,6 +145,20 @@ func (c *providerRepo) GetByUUID(providerUUID string, user entity.User) (entity.
return c.parseEntity(c.conn.QueryRow(query, lat, long, lat, providerUUID)) return c.parseEntity(c.conn.QueryRow(query, lat, long, lat, providerUUID))
} }
func (c *providerRepo) GetByID(providerID int64, user entity.User) (entity.Provider, error) {
lat := 41.886406
long := -87.624225
query, where, err := c.getProfileQuery(user)
if err != nil {
return entity.Provider{}, err
}
query = c.getSelectQueryBase() + query + " WHERE a.provider_id = ? " + where
return c.parseEntity(c.conn.QueryRow(query, lat, long, lat, providerID))
}
func (c *providerRepo) GetByMukID(mukID string, user entity.User) (entity.Provider, error) { func (c *providerRepo) GetByMukID(mukID string, user entity.User) (entity.Provider, error) {
lat := 41.886406 lat := 41.886406
long := -87.624225 long := -87.624225

View File

@@ -144,13 +144,13 @@ func (c *rideRepo) getProfileQuery(user entity.User) (query string, where string
switch p.Key { switch p.Key {
case "AD", "BCBSIAD", "BDCAD", "PLANAD": case "AD", "BCBSIAD", "BDCAD", "PLANAD":
return return
case "SP", "SPT": case "SP", "SPT", "VIRPT":
switch p.Organization.Type.Key { switch p.Organization.Type.Key {
case "techsupport", "bcbsi", "bcbsa", "plan": case "techsupport", "bcbsi", "bcbsa", "plan":
return return
case "provider": case "provider":
query = `INNER JOIN viw_visit_provider o ON a.ride_id = o.ride_id` query = `INNER JOIN viw_visit_provider z ON a.ride_id = z.ride_id`
where = fmt.Sprintf(` AND (o.organization_uuid = '%s' OR o.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID) where = fmt.Sprintf(` AND (z.organization_uuid = '%s' OR z.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
return return
} }
} }
@@ -676,6 +676,7 @@ func (c *rideRepo) GetByUUID(uuid string, user entity.User) (entity.Ride, error)
} }
query = c.getQuery() + query + " WHERE a.ride_uuid = ? " + where query = c.getQuery() + query + " WHERE a.ride_uuid = ? " + where
return c.parseEntity(c.conn.QueryRow(query, uuid)) return c.parseEntity(c.conn.QueryRow(query, uuid))
} }

View File

@@ -16,7 +16,8 @@ type transaction struct {
notification *notificationRepo notification *notificationRepo
profile *profileRepo profile *profileRepo
organization *organizationRepo organization *organizationRepo
zipcodes *zipcodeRepo zipcodes *zipcodeRepo
plan *planRepo
} }
func newTransaction(tx *sql.Tx) *transaction { func newTransaction(tx *sql.Tx) *transaction {
@@ -28,6 +29,11 @@ func newTransaction(tx *sql.Tx) *transaction {
t.rides = newRideRepo(tx) t.rides = newRideRepo(tx)
t.visits = newVisitRepo(tx) t.visits = newVisitRepo(tx)
t.provider = newProviderRepo(tx) t.provider = newProviderRepo(tx)
t.notification = newNotificationRepo(tx)
t.profile = newProfileRepo(tx)
t.organization = newOrganizationRepo(tx)
t.zipcodes = newZipcodeRepo(tx)
t.plan = newPlanRepo(tx)
return t return t
} }
@@ -67,10 +73,14 @@ func (t transaction) Organization() contract.OrganizationRepo {
return t.organization return t.organization
} }
func (t transaction) Zipcodes() contract.ZipcodeRepo{ func (t transaction) Zipcodes() contract.ZipcodeRepo {
return t.zipcodes return t.zipcodes
} }
func (t transaction) Plans() contract.PlanRepo {
return t.plan
}
func (t *transaction) Commit() error { func (t *transaction) Commit() error {
err := t.tx.Commit() err := t.tx.Commit()

View File

@@ -22,6 +22,32 @@ func newUserRepo(conn executor) *userRepo {
} }
} }
func (c *userRepo) GetByMemberID(memberID string) (entity.User, error) {
finalQuery := c.getQuery() + " AND a.member = ? AND e.key = 'US'"
user, err := c.parseSet(c.conn.Query(finalQuery, memberID))
if err != nil {
return entity.User{}, err
}
if len(user) > 0 {
retVal := user[0]
retVal.Contacts, err = c.GetContacts(retVal.ID)
if err != nil {
return entity.User{}, err
}
retVal.Addresses = nil
retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
if err != nil {
return entity.User{}, err
}
return retVal, nil
} else {
return entity.User{}, nil
}
}
func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) { func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) {
params := make([]interface{}, 0) params := make([]interface{}, 0)
params = append(params, uuid) params = append(params, uuid)
@@ -390,6 +416,24 @@ func (c *userRepo) SaveContact(contact entity.ContactInfo) (entity.ContactInfo,
return c.addContactInfo(contact) return c.addContactInfo(contact)
} }
func (c *userRepo) UpdateLogin(user entity.User) error {
const (
query = `UPDATE tab_login a
INNER JOIN tab_user b
ON a.user_id = b.user_id
SET a.email = ?,
a.phone_number = ?
WHERE
b.user_uuid = ?`
)
if _, err := c.conn.Exec(query, user.Email, user.PhoneNumber, user.UUID); err != nil {
return err
}
return nil
}
func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) { func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
const ( const (
query = `DELETE FROM tab_contact WHERE contact_uuid = ?;` query = `DELETE FROM tab_contact WHERE contact_uuid = ?;`
@@ -561,7 +605,7 @@ func (c *userRepo) createUser(user entity.User) (int64, string, error) {
func (c *userRepo) RemoveAddress(addressUUID string) error { func (c *userRepo) RemoveAddress(addressUUID string) error {
const ( const (
query = "UPDATE tab_address SET active = 0 WHERE address_uuid = ?" query = "DELETE FROM tab_address WHERE address_uuid = ?;"
) )
_, err := c.conn.Exec(query, addressUUID) _, err := c.conn.Exec(query, addressUUID)

View File

@@ -27,14 +27,13 @@ func (c *visitRepo) getProfileQuery(user entity.User) (query string, where strin
switch p.Key { switch p.Key {
case "AD", "BCBSIAD", "BDCAD", "PLANAD": case "AD", "BCBSIAD", "BDCAD", "PLANAD":
return return
case "SP", "SPT": case "SP", "SPT", "VIRPT":
switch p.Organization.Type.Key { switch p.Organization.Type.Key {
case "techsupport", "bcbsi", "bcbsa", "plan": case "techsupport", "bcbsi", "bcbsa", "plan":
return return
case "provider": case "provider":
query = ` INNER JOIN viw_visit_provider f query = ` INNER JOIN viw_visit_provider AS o ON o.visit_id = a.visit_id `
ON f.visit_id = a.visit_id ` where = fmt.Sprintf(` AND ( o.organization_uuid = '%s' OR o.parent_organization_uuid = '%s' ) `, p.Organization.UUID, p.Organization.UUID)
where = fmt.Sprintf(` AND (f.organization_uuid = '%s' OR f.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
return return
} }
} }
@@ -85,17 +84,17 @@ func (c *visitRepo) getQuery() string {
IFNULL(f.provider_muk_id, '') provider_muk_id, IFNULL(f.provider_muk_id, '') provider_muk_id,
IFNULL(f.provider_name, '') provider_name IFNULL(f.provider_name, '') provider_name
FROM FROM
tab_visit a tab_visit AS a
INNER JOIN tab_visit_status b INNER JOIN tab_visit_status AS b
ON a.visit_status_id = b.visit_status_id ON a.visit_status_id = b.visit_status_id
INNER JOIN tab_user c INNER JOIN tab_user AS c
ON c.user_id = a.user_id ON c.user_id = a.user_id
INNER JOIN tab_user d INNER JOIN tab_user AS d
ON d.user_id = a.created_user_id ON d.user_id = a.created_user_id
INNER JOIN tab_trip_type e INNER JOIN tab_trip_type AS e
ON e.trip_type_id = a.trip_type_id ON e.trip_type_id = a.trip_type_id
INNER JOIN tab_provider f INNER JOIN tab_provider AS f
ON f.provider_id = a.provider_id ` ON f.provider_id = a.provider_id `
} }
func (c *visitRepo) GetAll(user entity.User) ([]entity.Visit, error) { func (c *visitRepo) GetAll(user entity.User) ([]entity.Visit, error) {
@@ -205,6 +204,5 @@ func (c *visitRepo) Create(visit entity.Visit) (entity.Visit, error) {
return retVal, err return retVal, err
} }
fmt.Println("Visit ID: ", retVal.ID)
return retVal, nil return retVal, nil
} }

View File

@@ -3,20 +3,6 @@ map $http_upgrade $connection_upgrade {
'' close; '' close;
} }
server {
listen 80;
server_name portal-api.dev.bcbinstitute.com;
location / {
proxy_pass http://127.0.0.1:5100;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server { server {
listen 443; listen 443;
ssl on; ssl on;

View File

@@ -3,20 +3,6 @@ map $http_upgrade $connection_upgrade {
'' close; '' close;
} }
server {
listen 80;
server_name portal-api.bcbinstitute.com;
location / {
proxy_pass http://127.0.0.1:5100;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server { server {
listen 443; listen 443;
ssl on; ssl on;

View File

@@ -3,20 +3,6 @@ map $http_upgrade $connection_upgrade {
'' close; '' close;
} }
server {
listen 80;
server_name portal-api.dev.bcbinstitute.com;
location / {
proxy_pass http://127.0.0.1:5100;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server { server {
listen 443; listen 443;
ssl on; ssl on;

View File

@@ -13,6 +13,7 @@ type repoManager interface {
Profile() ProfileRepo Profile() ProfileRepo
Organization() OrganizationRepo Organization() OrganizationRepo
Zipcodes() ZipcodeRepo Zipcodes() ZipcodeRepo
Plans() PlanRepo
} }
// UserRepo defines the data set for users // UserRepo defines the data set for users
@@ -20,6 +21,7 @@ type UserRepo interface {
GetAll() (list []entity.User, err error) GetAll() (list []entity.User, err error)
GetByID(userID int64) (retVal entity.User, err error) GetByID(userID int64) (retVal entity.User, err error)
GetByUUID(uuid string, profile string) (entity.User, error) GetByUUID(uuid string, profile string) (entity.User, error)
GetByMemberID(memberID string) (entity.User, error)
Login(email string, pass string) (entity.User, error) Login(email string, pass string) (entity.User, error)
FullLogin(loginType string, key string, pass string, profile string) (entity.User, error) FullLogin(loginType string, key string, pass string, profile string) (entity.User, error)
Create(user entity.User) (entity.User, error) Create(user entity.User) (entity.User, error)
@@ -30,6 +32,7 @@ type UserRepo interface {
RemoveAddress(addressUUID string) error RemoveAddress(addressUUID string) error
SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error) SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error)
RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error)
UpdateLogin(user entity.User) error
} }
// RideRepo defines the data set for Rides // RideRepo defines the data set for Rides
@@ -59,6 +62,7 @@ type ProviderRepo interface {
GetByMukID(mukID string, user entity.User) (entity.Provider, error) GetByMukID(mukID string, user entity.User) (entity.Provider, error)
GetByUUID(providerUUID string, user entity.User) (entity.Provider, error) GetByUUID(providerUUID string, user entity.User) (entity.Provider, error)
GetByNPI(NPI string, user entity.User) (entity.Provider, error) GetByNPI(NPI string, user entity.User) (entity.Provider, error)
GetByID(providerID int64, user entity.User) (entity.Provider, error)
} }
// NotificationRepo defines the data set for Notification // NotificationRepo defines the data set for Notification
@@ -94,6 +98,13 @@ type OrganizationRepo interface {
GetTypeByKey(key string) (entity.OrganizationType, error) GetTypeByKey(key string) (entity.OrganizationType, error)
} }
type PlanRepo interface {
GetByAlphaPrefix(alphaPrefix string) (entity.Plan, error)
GetByUUID(planUUID string) ([]entity.Plan, error)
GetByID(planID int64) ([]entity.Plan, error)
GetByPrefixUUID(prefixUUID string) (entity.Plan, error)
}
// VisitRepo defines the data set for Rides // VisitRepo defines the data set for Rides
type VisitRepo interface { type VisitRepo interface {
Create(visit entity.Visit) (entity.Visit, error) Create(visit entity.Visit) (entity.Visit, error)

21
domain/entity/plan.go Normal file
View File

@@ -0,0 +1,21 @@
package entity
import "time"
type Plan struct {
ID int64 `json:"-"`
UUID string `json:"id"`
Name string `json:"name"`
InternalID string `json:"key"`
Status bool `json:"desc"`
PlanEntityID int64 `json:"plan_entity_id"`
EntityID int64 `json:"entity_id"`
PayerID int64 `json:"payer_id"`
PayerName string `json:"payer_name"`
PrefixID int64 `json:"prefix_id"`
PrefixUUID string `json:"prefix_uuid"`
AlphaPrefix string `json:"alpha_prefix"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Active bool `json:"active"`
}

31
domain/service/plan.go Normal file
View File

@@ -0,0 +1,31 @@
package service
import (
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)
type planService struct {
svc *Service
}
func newPlanService(svc *Service) *planService {
return &planService{
svc: svc,
}
}
func (s *planService) GetByAlphaPrefix(alphaPrefix string) (entity.Plan, error) {
return s.svc.db.Plans().GetByAlphaPrefix(alphaPrefix)
}
func (s *planService) GetByUUID(planUUID string) ([]entity.Plan, error) {
return s.svc.db.Plans().GetByUUID(planUUID)
}
func (s *planService) GetByID(planID int64) ([]entity.Plan, error) {
return s.svc.db.Plans().GetByID(planID)
}
func (s *planService) GetByPrefixUUID(prefixUUID string) (entity.Plan, error) {
return s.svc.db.Plans().GetByPrefixUUID(prefixUUID)
}

View File

@@ -1,6 +1,8 @@
package service package service
import ( import (
"errors"
"bitbucket.org/nemt/nemt-portal-api/domain/entity" "bitbucket.org/nemt/nemt-portal-api/domain/entity"
) )
@@ -85,3 +87,21 @@ func (s *providerService) GetByNPI(NPI string, user entity.User) (entity.Provide
provider.Organization = organization provider.Organization = organization
return provider, nil return provider, nil
} }
func (s *providerService) GetByOrganization(organizationUUID string, user entity.User) (entity.Provider, error) {
organization, err := s.svc.db.Organization().GetByUUID(organizationUUID, user)
if err != nil {
return entity.Provider{}, err
}
if organization.Type.Key != "provider" {
return entity.Provider{}, errors.New("invalid organization")
}
provider, err := s.svc.db.Provider().GetByID(organization.ReferenceID, user)
if err != nil {
return entity.Provider{}, err
}
return provider, nil
}

View File

@@ -56,7 +56,12 @@ func (s *rideService) GetByID(id int64, user entity.User) (entity.Ride, error) {
// GetByUUID return a specific ride // GetByUUID return a specific ride
func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) { func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
return s.svc.db.Rides().GetByUUID(uuid, user) ride, err := s.svc.db.Rides().GetByUUID(uuid, user)
if err != nil {
return entity.Ride{}, err
}
return ride, nil
} }
// GetByUUID return a specific ride // GetByUUID return a specific ride

View File

@@ -25,7 +25,8 @@ type Service struct {
Notification *notificationService Notification *notificationService
Profile *profileService Profile *profileService
Organization *organizationService Organization *organizationService
Zipcodes *zipcodeService Zipcodes *zipcodeService
Plans *planService
} }
// New returns a new domain Service instance // New returns a new domain Service instance
@@ -41,6 +42,7 @@ func New(db contract.DataManager, cache contract.CacheManager, cfg *config.Confi
instance.Profile = newProfileService(instance) instance.Profile = newProfileService(instance)
instance.Organization = newOrganizationService(instance) instance.Organization = newOrganizationService(instance)
instance.Zipcodes = newZipcodeService(instance) instance.Zipcodes = newZipcodeService(instance)
instance.Plans = newPlanService(instance)
}) })
return instance, nil return instance, nil

View File

@@ -33,6 +33,10 @@ func (s *userService) GetByUUID(uuid string, profile string) (entity.User, error
return s.svc.db.Users().GetByUUID(uuid, profile) return s.svc.db.Users().GetByUUID(uuid, profile)
} }
func (s *userService) GetByMemberID(memberID string) (entity.User, error) {
return s.svc.db.Users().GetByMemberID(memberID)
}
// Login returns a specific user by email and pass // Login returns a specific user by email and pass
func (s *userService) Login(email string, pass string) (entity.User, error) { func (s *userService) Login(email string, pass string) (entity.User, error) {
return s.svc.db.Users().Login(email, pass) return s.svc.db.Users().Login(email, pass)
@@ -68,6 +72,10 @@ func (s *userService) CreateBulk(users []entity.User) ([]entity.User, error) {
return users, nil return users, nil
} }
func (s *userService) UpdateLogin(user entity.User) error {
return s.svc.db.Users().UpdateLogin(user)
}
// GetUsersByProfile returns a list of users by profile // GetUsersByProfile returns a list of users by profile
func (s *userService) GetUsersByProfile(profile string) ([]entity.User, error) { func (s *userService) GetUsersByProfile(profile string) ([]entity.User, error) {
return s.svc.db.Users().GetUsersByProfile(profile) return s.svc.db.Users().GetUsersByProfile(profile)

View File

@@ -29,10 +29,10 @@ func (s *visitService) GetAll(user entity.User) ([]entity.Visit, error) {
return nil, err return nil, err
} }
rides, err := s.svc.db.Rides().GetAll(user) rides, _ := s.svc.db.Rides().GetAll(user)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
ridesByVisit := make(map[int64][]entity.Ride) ridesByVisit := make(map[int64][]entity.Ride)
for _, r := range rides { for _, r := range rides {
@@ -55,10 +55,10 @@ func (s *visitService) GetByUUID(visitUUID string, user entity.User) (entity.Vis
return entity.Visit{}, errors.Wrap(err) return entity.Visit{}, errors.Wrap(err)
} }
rides, err := s.svc.db.Rides().GetByVisitUUID(visitUUID, user) rides, _ := s.svc.db.Rides().GetByVisitUUID(visitUUID, user)
if err != nil { // if err != nil {
return entity.Visit{}, errors.Wrap(err) // return entity.Visit{}, errors.Wrap(err)
} // }
visit.Rides = rides visit.Rides = rides
return visit, nil return visit, nil
@@ -71,10 +71,10 @@ func (s *visitService) GetByID(visitID int64, user entity.User) (entity.Visit, e
return entity.Visit{}, errors.Wrap(err) return entity.Visit{}, errors.Wrap(err)
} }
rides, err := s.svc.db.Rides().GetByVisitUUID(visit.UUID, user) rides, _ := s.svc.db.Rides().GetByVisitUUID(visit.UUID, user)
if err != nil { // if err != nil {
return entity.Visit{}, errors.Wrap(err) // return entity.Visit{}, errors.Wrap(err)
} // }
visit.Rides = rides visit.Rides = rides
return visit, nil return visit, nil

View File

@@ -1,18 +1,23 @@
package eligibilityroute package eligibilityroute
import ( import (
"context"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"html" "html"
"math/rand"
"strings" "strings"
"sync" "sync"
"time"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi" "bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel" "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"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"
"github.com/labstack/echo" "github.com/labstack/echo"
"googlemaps.github.io/maps"
) )
var ( var (
@@ -37,6 +42,29 @@ func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *co
return instance return instance
} }
func (c *controller) rangeIn(low, hi int) string {
result := low + rand.Intn(hi-low)
return fmt.Sprintf("%v", result)
}
func (c *controller) generatePassword(n int) string {
const (
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
)
return c.stringWithCharset(n, charset)
}
func (c *controller) 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 (c *controller) handleEligibility(ctx echo.Context) error { func (c *controller) handleEligibility(ctx echo.Context) error {
var eligibility viewmodel.Eligibility var eligibility viewmodel.Eligibility
@@ -44,13 +72,45 @@ func (c *controller) handleEligibility(ctx echo.Context) error {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
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) ret, err := c.bcbsi.BXE.CheckEligibility(eligibility)
if err != nil { if err != nil {
fmt.Println("Error Here: ", err.Error()) fmt.Println("Error Here: ", err.Error())
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
if ret.QueryResult.HIPPA271.T271 != "" { if ret.QueryResult.QueryResultSummary.BenefitsFound {
xmlString := html.UnescapeString(ret.QueryResult.HIPPA271.T271) xmlString := html.UnescapeString(ret.QueryResult.HIPPA271.T271)
xmlReader := strings.NewReader(xmlString) xmlReader := strings.NewReader(xmlString)
@@ -60,8 +120,133 @@ func (c *controller) handleEligibility(ctx echo.Context) error {
fmt.Println("Error to unmarshal: ", err.Error()) fmt.Println("Error to unmarshal: ", err.Error())
} }
return ctx.JSON(200, f) user, err := c.svc.Users.GetByMemberID(eligibility.Subscriber.SubscriberID)
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
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.Create(user, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
} 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
}
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)
} else { } else {
return routeutils.ResponseAPIOK(ctx, ret) return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "No benefits found for member")
} }
} }

View File

@@ -124,27 +124,27 @@ func (c *controller) handleList(ctx echo.Context) error {
name := ctx.QueryParam("name") name := ctx.QueryParam("name")
searchBy := ctx.QueryParam("searchBy") searchBy := ctx.QueryParam("searchBy")
// lat, err := routeutils.GetAndValidateFloatQueryParam(ctx, "lat", "latitude is mandatory") lat, err := routeutils.GetAndValidateFloatQueryParam(ctx, "lat", "latitude is required")
// if err != nil { if err != nil {
// return err return err
// } }
// long, err := routeutils.GetAndValidateFloatQueryParam(ctx, "long", "longitude is mandatory") long, err := routeutils.GetAndValidateFloatQueryParam(ctx, "long", "longitude is required")
// if err != nil { if err != nil {
// return err return err
// } }
distance, err := routeutils.GetAndValidateIntQueryParam(ctx, "distance", "distance is mandatory") distance, err := routeutils.GetAndValidateIntQueryParam(ctx, "distance", "distance is required")
if err != nil { if err != nil {
distance = 10 distance = 10
} }
limit, err := routeutils.GetAndValidateIntQueryParam(ctx, "limit", "limit is mandatory") limit, err := routeutils.GetAndValidateIntQueryParam(ctx, "limit", "limit is required")
if err != nil { if err != nil {
limit = 50 limit = 50
} }
sortBy, err := routeutils.GetAndValidateStringQueryParam(ctx, "sortby", "limit is mandatory") sortBy, err := routeutils.GetAndValidateStringQueryParam(ctx, "sortby", "limit is required")
if err != nil || (sortBy != "distance" && sortBy != "name") { if err != nil || (sortBy != "distance" && sortBy != "name") {
sortBy = "distance" sortBy = "distance"
} }
@@ -152,8 +152,8 @@ func (c *controller) handleList(ctx echo.Context) error {
providerParams := npdmodel.ProviderSearchParams{ providerParams := npdmodel.ProviderSearchParams{
Name: name, Name: name,
SearchBy: searchBy, SearchBy: searchBy,
Latitude: 41.819078, Latitude: lat,
Longitude: -87.623129, Longitude: long,
Distance: distance, Distance: distance,
Limit: limit, Limit: limit,
Offset: 0, Offset: 0,

View File

@@ -44,7 +44,7 @@ func Register(e *echo.Echo, cfg *config.Config, svc *applicationservice.Service,
usersroute.Register(appGroup.Group("/users"), cfg, svc) usersroute.Register(appGroup.Group("/users"), cfg, svc)
eligibilityroute.Register(appGroup.Group("/eligibility"), cfg, svc) eligibilityroute.Register(appGroup.Group("/eligibility"), cfg, svc)
tncroute.Register(appGroup.Group("/rides"), cfg, svc, tnc, notification) tncroute.Register(appGroup.Group("/rides"), cfg, svc, tnc, notification)
visitroute.Register(appGroup.Group("/visits"), cfg, svc) visitroute.Register(appGroup.Group("/visits"), cfg, svc, tnc)
providerroute.Register(appGroup.Group("/provider"), cfg, svc) providerroute.Register(appGroup.Group("/provider"), cfg, svc)
placesroute.Register(appGroup.Group("/places"), cfg, svc) placesroute.Register(appGroup.Group("/places"), cfg, svc)
profileroute.Register(appGroup.Group("/profile"), cfg, svc) profileroute.Register(appGroup.Group("/profile"), cfg, svc)

View File

@@ -230,7 +230,7 @@ func (c *controller) handle(ctx echo.Context) error {
} }
//Validate ride request //Validate ride request
if validationErrors := validation.ValidateRide(&requestRide, &user) ; len(validationErrors) > 0 { if validationErrors := validation.ValidateRide(&requestRide, &user); len(validationErrors) > 0 {
return routeutils.ResponseAPICustomValidationError(ctx, "ride validation failed", validationErrors) return routeutils.ResponseAPICustomValidationError(ctx, "ride validation failed", validationErrors)
} }
@@ -436,7 +436,7 @@ func (c *controller) handle(ctx echo.Context) error {
go func() { go func() {
err = c.svc.Notification.SendNotification(newRide.Status, roudtripRide, newRide) err = c.svc.Notification.SendNotification(newRide.Status, roudtripRide, newRide)
if err != nil { if err != nil {
fmt.Println("Error to notify user: ", err.Error()) fmt.Println("Error notifying user: ", err.Error())
} }
}() }()
} }

View File

@@ -1,18 +1,26 @@
package visitroute package visitroute
import ( import (
"context"
"fmt" "fmt"
"math/rand"
"strings"
"sync" "sync"
"time" "time"
b64 "encoding/base64"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi" "bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi"
"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel" "bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"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" "bitbucket.org/nemt/nemt-portal-api/server/validation"
"github.com/labstack/echo" "github.com/labstack/echo"
uuid "github.com/satori/go.uuid"
"googlemaps.github.io/maps"
) )
var ( var (
@@ -24,19 +32,383 @@ type controller struct {
svc *applicationservice.Service svc *applicationservice.Service
cfg *config.Config cfg *config.Config
bcbsi *bcbsi.Service bcbsi *bcbsi.Service
tnc *tncservice.Service
} }
func controllerInstance(svc *applicationservice.Service, cfg *config.Config) *controller { func controllerInstance(svc *applicationservice.Service, cfg *config.Config, tnc *tncservice.Service) *controller {
once.Do(func() { once.Do(func() {
instance = &controller{ instance = &controller{
svc: svc, svc: svc,
cfg: cfg, cfg: cfg,
bcbsi: bcbsi.New(cfg), bcbsi: bcbsi.New(cfg),
tnc: tnc,
} }
}) })
return instance return instance
} }
func (c *controller) generatePassword(n int) string {
const (
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
)
return c.stringWithCharset(n, charset)
}
func (c *controller) 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 (c *controller) handleRide(ctx echo.Context) error {
var ride viewmodel.RideRequest
if err := ctx.Bind(&ride); err != nil {
fmt.Println(err)
return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
}
authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
visit, err := c.svc.Visits.GetByUUID(ride.Visit.UUID, authUser)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
ride.Visit = visit
user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
if err != nil {
fmt.Println(err)
return routeutils.HandleAPIError(ctx, err)
}
ride.Visit.User = user
subscriber := "S"
ride.Visit.User.Type = &subscriber
var provider viewmodel.ProviderResp
if authUser.Profiles[0].Key == "VIRPT" {
provider, err = c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, authUser)
} else {
provider, err = c.svc.Provider.GetByUUID(ride.Visit.Provider.ProviderUUID, authUser)
}
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
eligibility := viewmodel.Eligibility{}
eligibility.Provider.ProviderNPI = provider.InternalID
eligibility.Provider.ProviderName = provider.OrganizatioName
eligibility.TrackingID = "1234567"
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
eligibility.ServiceInfo.DateOfService = time.Now()
eligibility.ServiceInfo.ServiceTypeCodes = []string{"30"}
resp271, err := c.bcbsi.BXE.Get271(eligibility)
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 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)
homeAddress := viewmodel.Address{}
for _, a := range visit.User.Addresses {
if a.AddressType == "home" {
homeAddress = a
}
}
ride.CreateUserUUID = authUser.ID
ride.Destination = viewmodel.Location{
ID: visit.Provider.ProviderUUID,
Name: visit.Provider.OrganizatioName,
Latitude: visit.Provider.Address.Latitude,
Longitude: visit.Provider.Address.Longitude,
Address: visit.Provider.Address.StreetAddress1,
}
ride.Origin = viewmodel.Location{
ID: homeAddress.UUID,
Name: homeAddress.AddressTypeName,
Latitude: homeAddress.Latitude,
Longitude: homeAddress.Longitude,
Address: homeAddress.Address,
}
ride.Notes = ride.Notes
ride.Passenger.FirstName = visit.User.First
ride.Passenger.LastName = " "
ride.Passenger.PhoneNumber = *visit.User.PhoneNumber
ride.RideType = "lyft"
ride.VisitDate = &visit.VisitDatetime
ride.VisitTime = &visit.VisitDatetime
var resp viewmodel.RideRequest
if ride.TripType.Key != "from_visit_call" {
if ride.TripType.Key == "from_visit" {
newOrigin := ride.Origin
ride.Origin = ride.Destination
ride.Destination = newOrigin
}
if c.cfg.LyftProd.UserUUID != authUser.ID {
resp, err = c.tnc.Lyft.RequestRide(ride)
} else {
fmt.Println("In Production")
resp, err = c.tnc.LyftProd.RequestRide(ride)
}
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
if ride.TripType.Key == "from_visit" {
newOrigin := resp.Origin
resp.Origin = resp.Destination
resp.Destination = newOrigin
}
resp.RideID = strings.Replace(resp.RideID, "s_", "", -1)
} else {
resp = ride
UUID, _ := uuid.NewV4()
resp.RideID = UUID.String()
}
if resp.Status == "scheduled" || ride.TripType.Key == "from_visit_call" {
if ride.PickupTime == nil {
currentDate := time.Now()
ride.PickupTime = &currentDate
}
requestMS := (ride.PickupTime.UnixNano() / int64(time.Millisecond))
generateDate := time.Now()
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
resp.RequestAt = ride.PickupTime
resp.RequestAtMS = &requestMS
resp.GeneratedAt = &generateDate
resp.GeneratedAtMS = &generateMS
}
resp.Passenger.FirstName = visit.User.First
resp.Passenger.LastName = visit.User.Last
resp.Passenger.PhoneNumber = *visit.User.PhoneNumber
if resp.Passenger.ImageURL == nil {
imageURL := " "
resp.Passenger.ImageURL = &imageURL
}
resp.UserUUID = visit.User.ID
if ride.TripType.Key == "from_visit" {
resp.Origin.Name = ride.Destination.Name
resp.Origin.ID = ride.Destination.ID
resp.Destination.Name = ride.Origin.Name
resp.Destination.ID = ride.Origin.ID
} else {
resp.Origin.Name = ride.Origin.Name
resp.Origin.ID = ride.Origin.ID
resp.Destination.Name = ride.Destination.Name
resp.Destination.ID = ride.Destination.ID
}
resp.Distance = ride.Distance
resp.Duration = ride.Duration
resp.ETA = ride.ETA
resp.PickupTime = ride.PickupTime
resp.VisitDate = &ride.Visit.VisitDatetime
resp.VisitTime = &ride.Visit.VisitDatetime
resp.VisitExternalID = ride.Visit.ExternalID
resp.CreateUserUUID = authUser.ID
resp.Visit.TripType = ride.Visit.TripType
resp.Visit = visit
if resp.TripType.Key == "from_visit_call" {
resp.Status = "willCall"
resp.Passenger.UserID = &resp.UserUUID
}
resp.TripType.Key = ride.TripType.Key
if ride.TripType.Key == "roundtrip" || ride.TripType.Key == "roundtrip_call" {
resp.TripType.Key = "to_visit"
} else if ride.TripType.Key == "from_visit_call" {
resp.TripType.Key = "from_visit_call"
}
entity, err := c.svc.Rides.Save(resp)
if err != nil {
fmt.Println("Error to save first ride: ", err.Error())
return routeutils.HandleAPIError(ctx, err)
}
go func() {
err = c.svc.Notification.SendNotification(resp.Status, entity, resp)
if err != nil {
fmt.Println("Error to notify user: ", err.Error())
}
}()
if ride.TripType.Key == "roundtrip" || ride.TripType.Key == "roundtrip_call" {
newRide := ride
if ride.TripType.Key == "roundtrip" {
destination := newRide.Origin
newRide.Origin = newRide.Destination
newRide.Destination = destination
if ride.ReturnTime != nil {
newRide.PickupTime = ride.ReturnTime
}
scheduledRide := make(map[string]interface{})
scheduledRide["timestamp_ms"] = ride.PickupTime.Unix()
newRide.ScheduledPickupRange = scheduledRide
newRide.Passenger.FirstName = visit.User.First
newRide.Passenger.LastName = " "
newRide.Passenger.PhoneNumber = *visit.User.PhoneNumber
if c.cfg.LyftProd.UserUUID != authUser.ID {
newRide, err = c.tnc.Lyft.RequestRide(newRide)
} else {
fmt.Println("In Production")
newRide, err = c.tnc.LyftProd.RequestRide(newRide)
}
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
destination = newRide.Origin
newRide.Origin = newRide.Destination
newRide.Destination = destination
if newRide.Error != "" {
fmt.Println("Error to schedule a ride on lyft: ", newRide.Error, newRide.ErrorDescription)
} else {
fmt.Println("Ride Scheduled: ", newRide.Status)
}
newRide.TripType.Key = "from_visit"
} else {
newRide.TripType.Key = "from_visit_call"
newRide.Status = "willCall"
newRide.RideID = entity.UUID
}
newRide.Visit = visit
newRide.PickupTime = ride.ReturnTime
requestMS := (newRide.PickupTime.UnixNano() / int64(time.Millisecond))
generateDate := time.Now()
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
newRide.RequestAt = newRide.PickupTime
newRide.RequestAtMS = &requestMS
newRide.GeneratedAt = &generateDate
newRide.GeneratedAtMS = &generateMS
newRide.Passenger.FirstName = visit.User.First
newRide.Passenger.LastName = visit.User.Last
newRide.Passenger.PhoneNumber = *visit.User.PhoneNumber
newRide.Passenger.UserID = &ride.UserUUID
if newRide.Passenger.ImageURL == nil {
imageURL := " "
newRide.Passenger.ImageURL = &imageURL
}
newRide.UserUUID = ride.UserUUID
newRide.Origin.Name = ride.Destination.Name
newRide.Origin.ID = ride.Destination.ID
newRide.Destination.Name = ride.Origin.Name
newRide.Destination.ID = ride.Origin.ID
newRide.Distance = ride.Distance
newRide.Duration = ride.Duration
newRide.ETA = ride.ETA
newRide.VisitDate = ride.VisitDate
newRide.VisitTime = ride.VisitTime
newRide.VisitExternalID = ride.VisitExternalID
newRide.CreateUserUUID = authUser.ID
roudtripRide, err := c.svc.Rides.Save(newRide)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
go func() {
err = c.svc.Notification.SendNotification(newRide.Status, roudtripRide, newRide)
if err != nil {
fmt.Println("Error to notify user: ", err.Error())
}
}()
}
ctx.Response().Header().Set("Content-Type", "application/json")
return routeutils.ResponseAPIOK(ctx, entity)
}
func (c *controller) rangeIn(low, hi int) string {
result := low + rand.Intn(hi-low)
return fmt.Sprintf("%v", result)
}
func (c *controller) handle(ctx echo.Context) error { func (c *controller) handle(ctx echo.Context) error {
var visit viewmodel.Visit var visit viewmodel.Visit
if err := ctx.Bind(&visit); err != nil { if err := ctx.Bind(&visit); err != nil {
@@ -44,25 +416,29 @@ func (c *controller) handle(ctx echo.Context) error {
return routeutils.ResponseAPIValidationError(ctx, "invalid parameters") return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
} }
user, err := auth.GetUserDetail(ctx, c.cfg) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
provider, err := c.svc.Provider.GetByUUID(visit.Provider.ProviderUUID, user) var provider viewmodel.ProviderResp
if authUser.Profiles[0].Key == "VIRPT" {
provider, err = c.svc.Provider.GetByOrganization(authUser.Profiles[0].Organization.UUID, authUser)
} else {
provider, err = c.svc.Provider.GetByUUID(visit.Provider.ProviderUUID, authUser)
}
if err != nil { if err != nil {
fmt.Println(err) return routeutils.HandleAPIError(ctx, err)
return routeutils.ResponseAPIValidationError(ctx, "invalid provider")
} }
if validationErrors := validation.ValidateVisit(&visit, &user); len(validationErrors) > 0 { if validationErrors := validation.ValidateVisit(&visit, &authUser); len(validationErrors) > 0 {
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.Name eligibility.Provider.ProviderName = provider.OrganizatioName
eligibility.TrackingID = *visit.User.Member 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
@@ -78,7 +454,144 @@ func (c *controller) handle(ctx echo.Context) error {
return routeutils.ResponseAPIValidationError(ctx, err.Error()) return routeutils.ResponseAPIValidationError(ctx, err.Error())
} }
return routeutils.ResponseAPIOK(ctx, resp) user, err := c.svc.Users.GetByMemberID(*visit.User.Member)
if err != nil {
fmt.Println(err)
return routeutils.HandleAPIError(ctx, err)
}
if user.ID == "" {
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)
}
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 {
return routeutils.HandleAPIError(ctx, err)
}
user.Profiles = append(user.Profiles, profile)
user, err = c.svc.Users.Create(user, authUser)
if err != nil {
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 {
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 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)
visit.TripType = viewmodel.TripType{
Key: "no_trip",
Value: "No Trip",
}
visit.User = user
visit.CreatedUser = authUser
visit, err = c.svc.Visits.Save(visit)
if err != nil {
return routeutils.HandleAPIError(ctx, err)
}
return routeutils.ResponseAPIOK(ctx, visit)
} }
func (c *controller) handleGetByID(ctx echo.Context) error { func (c *controller) handleGetByID(ctx echo.Context) error {
@@ -87,13 +600,14 @@ func (c *controller) handleGetByID(ctx echo.Context) error {
return routeutils.ResponseAPIValidationError(ctx, "visit_uuid param is mandatory") return routeutils.ResponseAPIValidationError(ctx, "visit_uuid param is mandatory")
} }
user, err := auth.GetUserDetail(ctx, c.cfg) authUser, err := auth.GetUserDetail(ctx, c.cfg)
if err != nil { if err != nil {
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }
resp, err := c.svc.Visits.GetByUUID(visit_uuid, user) resp, err := c.svc.Visits.GetByUUID(visit_uuid, authUser)
if err != nil { if err != nil {
fmt.Println("Error to get Visit: ", err.Error())
return routeutils.HandleAPIError(ctx, err) return routeutils.HandleAPIError(ctx, err)
} }

View File

@@ -2,6 +2,7 @@ package visitroute
import ( import (
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
"bitbucket.org/nemt/nemt-portal-api/infra/config" "bitbucket.org/nemt/nemt-portal-api/infra/config"
"github.com/labstack/echo" "github.com/labstack/echo"
) )
@@ -9,13 +10,15 @@ import (
const ( const (
rootRoute = "/" rootRoute = "/"
idRoute = "/:visit_uuid" idRoute = "/:visit_uuid"
rideRoute = "/:visit_uuid/ride"
) )
// Register registers the routes in the echo group // Register registers the routes in the echo group
func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service) { func Register(r *echo.Group, cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service) {
ctrl := controllerInstance(svc, cfg) ctrl := controllerInstance(svc, cfg, tnc)
r.POST(rootRoute, ctrl.handle) r.POST(rootRoute, ctrl.handle)
r.POST(rideRoute, ctrl.handleRide)
r.GET(rootRoute, ctrl.handleGetAll) r.GET(rootRoute, ctrl.handleGetAll)
r.GET(idRoute, ctrl.handleGetByID) r.GET(idRoute, ctrl.handleGetByID)