Upstream sync
This commit is contained in:
@@ -23,6 +23,7 @@ type Service struct {
|
||||
Notification *notificationService
|
||||
Profile *profileService
|
||||
Organization *organizationService
|
||||
Zipcodes *zipcodeService
|
||||
}
|
||||
|
||||
// New returns a new domain Service instance
|
||||
@@ -36,6 +37,7 @@ func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notif
|
||||
Notification: newNotificationService(svc, mapper, notification, cfg),
|
||||
Profile: newProfileService(svc, mapper),
|
||||
Organization: newOrganizationService(svc, mapper),
|
||||
Zipcodes: newZipcodeService(svc, mapper),
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
37
application/applicationservice/zipcode.go
Normal file
37
application/applicationservice/zipcode.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package applicationservice
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||
)
|
||||
|
||||
// zipcodeService holds methods to participating zipcode application service
|
||||
type zipcodeService struct {
|
||||
svc *service.Service
|
||||
mapEntity *entitymapping.Mapper
|
||||
}
|
||||
|
||||
// newZipcodeService returns a zipcodeService instance
|
||||
func newZipcodeService(svc *service.Service, mapper *entitymapping.Mapper) *zipcodeService {
|
||||
return &zipcodeService{
|
||||
svc: svc,
|
||||
mapEntity: mapper,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *zipcodeService) GetAll() ([]viewmodel.Zipcode, error) {
|
||||
result, err := s.svc.Zipcodes.GetAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.mapEntity.Zipcode.ToZipcodeModelSlice(result), nil
|
||||
}
|
||||
|
||||
func (s *zipcodeService) GetByParticipatingZipcode(zipcode string) (viewmodel.Zipcode, error) {
|
||||
result, err := s.svc.Zipcodes.GetByParticipatingZipcode(zipcode)
|
||||
if err != nil {
|
||||
return viewmodel.Zipcode{}, err
|
||||
}
|
||||
return s.mapEntity.Zipcode.ToZipcodeModel(result), nil
|
||||
}
|
||||
@@ -21,6 +21,7 @@ type Mapper struct {
|
||||
Notification *notificationMapping
|
||||
Profile *profileMapping
|
||||
Organization *organizationMapping
|
||||
Zipcode *zipcodeMapping
|
||||
}
|
||||
|
||||
// New returns an EntityMapper for fluent mapping
|
||||
@@ -36,6 +37,7 @@ func New() *Mapper {
|
||||
instance.Notification = ¬ificationMapping{instance}
|
||||
instance.Profile = &profileMapping{instance}
|
||||
instance.Organization = &organizationMapping{instance}
|
||||
instance.Zipcode = &zipcodeMapping{instance}
|
||||
})
|
||||
|
||||
return instance
|
||||
|
||||
51
application/entitymapping/zipcode.go
Normal file
51
application/entitymapping/zipcode.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package entitymapping
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||
)
|
||||
|
||||
// zipcodeMapping has method to map zipcode entities to view models
|
||||
type zipcodeMapping struct {
|
||||
mapper *Mapper
|
||||
}
|
||||
|
||||
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||
func (mapping *zipcodeMapping) ToZipcodeEntitySlice(list []viewmodel.Zipcode) (retVal []entity.Zipcode) {
|
||||
retVal = make([]entity.Zipcode, 0)
|
||||
|
||||
for _, item := range list {
|
||||
retVal = append(retVal, mapping.ToZipcodeEntity(item))
|
||||
}
|
||||
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (mapping *zipcodeMapping) ToZipcodeEntity(model viewmodel.Zipcode) entity.Zipcode {
|
||||
return entity.Zipcode{
|
||||
ID: model.ID,
|
||||
UUID: model.UUID,
|
||||
Zipcode: model.Zipcode,
|
||||
Participating: model.Participating,
|
||||
}
|
||||
}
|
||||
|
||||
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||
func (mapping *zipcodeMapping) ToZipcodeModelSlice(list []entity.Zipcode) (retVal []viewmodel.Zipcode) {
|
||||
retVal = make([]viewmodel.Zipcode, 0)
|
||||
|
||||
for _, item := range list {
|
||||
retVal = append(retVal, mapping.ToZipcodeModel(item))
|
||||
}
|
||||
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (mapping *zipcodeMapping) ToZipcodeModel(model entity.Zipcode) viewmodel.Zipcode {
|
||||
return viewmodel.Zipcode{
|
||||
ID: model.ID,
|
||||
UUID: model.UUID,
|
||||
Zipcode: model.Zipcode,
|
||||
Participating: model.Participating,
|
||||
}
|
||||
}
|
||||
8
application/viewmodel/zipcode.go
Normal file
8
application/viewmodel/zipcode.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package viewmodel
|
||||
|
||||
type Zipcode struct {
|
||||
ID int64 `json:"-"`
|
||||
UUID string `json:"uuid"`
|
||||
Zipcode string `json:"zipcode"`
|
||||
Participating bool `json:"participating"`
|
||||
}
|
||||
@@ -28,6 +28,7 @@ type Conn struct {
|
||||
notification *notificationRepo
|
||||
profile *profileRepo
|
||||
organization *organizationRepo
|
||||
zipcodes *zipcodeRepo
|
||||
}
|
||||
|
||||
// Begin starts a transaction
|
||||
@@ -80,6 +81,10 @@ func (c *Conn) Organization() contract.OrganizationRepo {
|
||||
return c.organization
|
||||
}
|
||||
|
||||
func (c *Conn) Zipcodes() contract.ZipcodeRepo{
|
||||
return c.zipcodes
|
||||
}
|
||||
|
||||
// Instance returns an instance of a DataManager
|
||||
func Instance(cfg *config.Config) (contract.DataManager, error) {
|
||||
once.Do(func() {
|
||||
@@ -111,6 +116,7 @@ func Instance(cfg *config.Config) (contract.DataManager, error) {
|
||||
instance.notification = newNotificationRepo(db)
|
||||
instance.profile = newProfileRepo(db)
|
||||
instance.organization = newOrganizationRepo(db)
|
||||
instance.zipcodes = newZipcodeRepo(db)
|
||||
})
|
||||
|
||||
return instance, connErr
|
||||
|
||||
@@ -16,6 +16,7 @@ type transaction struct {
|
||||
notification *notificationRepo
|
||||
profile *profileRepo
|
||||
organization *organizationRepo
|
||||
zipcodes *zipcodeRepo
|
||||
}
|
||||
|
||||
func newTransaction(tx *sql.Tx) *transaction {
|
||||
@@ -66,6 +67,10 @@ func (t transaction) Organization() contract.OrganizationRepo {
|
||||
return t.organization
|
||||
}
|
||||
|
||||
func (t transaction) Zipcodes() contract.ZipcodeRepo{
|
||||
return t.zipcodes
|
||||
}
|
||||
|
||||
func (t *transaction) Commit() error {
|
||||
|
||||
err := t.tx.Commit()
|
||||
|
||||
65
data/datamysql/zipcode.go
Normal file
65
data/datamysql/zipcode.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package datamysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
)
|
||||
|
||||
// rideRepo maps methods to database
|
||||
type zipcodeRepo struct {
|
||||
conn executor
|
||||
}
|
||||
|
||||
func newZipcodeRepo(conn executor) *zipcodeRepo {
|
||||
return &zipcodeRepo{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *zipcodeRepo) getQuery() string {
|
||||
const (
|
||||
query = `SELECT
|
||||
a.participating_zip_code_id,
|
||||
a.participating_zip_code_uuid,
|
||||
a.zipcode,
|
||||
a.participating
|
||||
FROM
|
||||
tab_participating_zip_code a `
|
||||
)
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
// parseSet parses a result set result to an entity array
|
||||
func (c *zipcodeRepo) parseSet(rows *sql.Rows, err error) ([]entity.Zipcode, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
result := make([]entity.Zipcode, 0)
|
||||
for rows.Next() {
|
||||
entity, err := c.parseEntity(rows)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
result = append(result, entity)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// parseEntity parses a result to an entity
|
||||
func (c *zipcodeRepo) parseEntity(row scanner) (retVal entity.Zipcode, err error) {
|
||||
err = row.Scan(
|
||||
&retVal.ID, &retVal.UUID, &retVal.Zipcode, &retVal.Participating)
|
||||
|
||||
return retVal, errors.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *zipcodeRepo) GetAll() ([]entity.Zipcode, error) {
|
||||
return c.parseSet(c.conn.Query(c.getQuery()))
|
||||
}
|
||||
|
||||
func (c *zipcodeRepo) GetByParticipatingZipcode(zipcode string) (entity.Zipcode, error) {
|
||||
return c.parseEntity(c.conn.QueryRow(c.getQuery()+"WHERE a.participating = 1 AND a.zipcode = ?", zipcode))
|
||||
}
|
||||
@@ -12,6 +12,7 @@ type repoManager interface {
|
||||
Notification() NotificationRepo
|
||||
Profile() ProfileRepo
|
||||
Organization() OrganizationRepo
|
||||
Zipcodes() ZipcodeRepo
|
||||
}
|
||||
|
||||
// UserRepo defines the data set for users
|
||||
@@ -105,3 +106,8 @@ type ProfileRepo interface {
|
||||
GetVisibles(visible bool) ([]entity.Profile, error)
|
||||
GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error)
|
||||
}
|
||||
|
||||
type ZipcodeRepo interface {
|
||||
GetAll() ([]entity.Zipcode, error)
|
||||
GetByParticipatingZipcode(zipcode string) (entity.Zipcode, error)
|
||||
}
|
||||
|
||||
8
domain/entity/zipcode.go
Normal file
8
domain/entity/zipcode.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package entity
|
||||
|
||||
type Zipcode struct {
|
||||
ID int64 `db:"participating_zip_code_id" json:"-"`
|
||||
UUID string `db:"participating_zip_code_uuid" json:"uuid"`
|
||||
Zipcode string `db:"zipcode" json:"zipcode"`
|
||||
Participating bool `db:"participating" json:"participating"`
|
||||
}
|
||||
@@ -25,6 +25,7 @@ type Service struct {
|
||||
Notification *notificationService
|
||||
Profile *profileService
|
||||
Organization *organizationService
|
||||
Zipcodes *zipcodeService
|
||||
}
|
||||
|
||||
// New returns a new domain Service instance
|
||||
@@ -39,6 +40,7 @@ func New(db contract.DataManager, cache contract.CacheManager, cfg *config.Confi
|
||||
instance.Notification = newNotificationService(instance)
|
||||
instance.Profile = newProfileService(instance)
|
||||
instance.Organization = newOrganizationService(instance)
|
||||
instance.Zipcodes = newZipcodeService(instance)
|
||||
})
|
||||
|
||||
return instance, nil
|
||||
|
||||
25
domain/service/zipcode.go
Normal file
25
domain/service/zipcode.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||
)
|
||||
|
||||
// userService is the domain service for user operations
|
||||
type zipcodeService struct {
|
||||
svc *Service
|
||||
}
|
||||
|
||||
// newUserService returns an instance of userService
|
||||
func newZipcodeService(svc *Service) *zipcodeService {
|
||||
return &zipcodeService{
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *zipcodeService) GetAll() ([]entity.Zipcode, error) {
|
||||
return s.svc.db.Zipcodes().GetAll()
|
||||
}
|
||||
|
||||
func (s *zipcodeService) GetByParticipatingZipcode(zipcode string) (entity.Zipcode, error) {
|
||||
return s.svc.db.Zipcodes().GetByParticipatingZipcode(zipcode)
|
||||
}
|
||||
@@ -92,6 +92,15 @@ func ResponseAPINotFoundError(c echo.Context) error {
|
||||
return ResponseAPIError(c, http.StatusNotFound, "Not Found", false)
|
||||
}
|
||||
|
||||
//ResponseAPINotEligible returns a standard API not eligible to the response
|
||||
func ResponseAPINotEligibleError(c echo.Context) error {
|
||||
return ResponseAPIError(c, http.StatusForbidden, "Eligibility Not Found or Error", false)
|
||||
}
|
||||
|
||||
func ResponseAPINotEligibleWithMessageError(c echo.Context, message string) error {
|
||||
return ResponseAPIError(c, http.StatusForbidden, message, false)
|
||||
}
|
||||
|
||||
func ignoreDefaultWrappedErrors(c echo.Context, errorToHandle *errors.WrappedError, handler func(echo.Context, error) error) error {
|
||||
err := errorToHandle.GetOriginalError()
|
||||
|
||||
|
||||
@@ -382,11 +382,6 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
||||
}
|
||||
user.Profiles = append(user.Profiles, profile)
|
||||
|
||||
user, err = c.svc.Users.Create(user, authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
eligibility := viewmodel.Eligibility{}
|
||||
eligibility.Provider.ProviderNPI = "1699849786"
|
||||
eligibility.Provider.ProviderName = "LITHOLINK CORPORATION"
|
||||
@@ -403,41 +398,61 @@ func (c *controller) handleMember(ctx echo.Context) error {
|
||||
resp, err := c.bcbsi.BXE.Get271(eligibility)
|
||||
if err != nil {
|
||||
fmt.Println("Eligibility Not Found or Error: ", err.Error())
|
||||
} else {
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
||||
zipCodeFromAddress := body.N403
|
||||
zipCodeObj, err := c.svc.Zipcodes.GetByParticipatingZipcode(zipCodeFromAddress)
|
||||
|
||||
if err != nil{
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
if !zipCodeObj.Participating {
|
||||
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "Member's Home zipcode, " + zipCodeFromAddress + ", 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.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
|
||||
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.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
|
||||
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 instantiate googles api: ", err.Error())
|
||||
fmt.Println("Error to save address: ", err.Error())
|
||||
return routeutils.ResponseAPINotEligibleError(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
user, err = c.svc.Users.Create(user, authUser)
|
||||
if err != nil {
|
||||
return routeutils.HandleAPIError(ctx, err)
|
||||
}
|
||||
|
||||
return routeutils.ResponseAPIOK(ctx, user)
|
||||
|
||||
Reference in New Issue
Block a user