Upstream sync

This commit is contained in:
Senad Uka
2018-05-19 10:15:27 +02:00
parent cf5b94edcc
commit 157b23da3c
14 changed files with 276 additions and 35 deletions

View File

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

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

View File

@@ -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 = &notificationMapping{instance}
instance.Profile = &profileMapping{instance}
instance.Organization = &organizationMapping{instance}
instance.Zipcode = &zipcodeMapping{instance}
})
return instance

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

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

View File

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

View File

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

View File

@@ -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
View 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"`
}

View File

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

View File

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

View File

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