258 lines
7.8 KiB
Go
258 lines
7.8 KiB
Go
package eligibilityroute
|
|
|
|
import (
|
|
"context"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"html"
|
|
"math/rand"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"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/viewmodel"
|
|
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
|
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
|
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
|
|
"github.com/labstack/echo"
|
|
"googlemaps.github.io/maps"
|
|
)
|
|
|
|
var (
|
|
instance *controller
|
|
once sync.Once
|
|
)
|
|
|
|
type controller struct {
|
|
cfg *config.Config
|
|
svc *applicationservice.Service
|
|
bcbsi *bcbsi.Service
|
|
}
|
|
|
|
func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
|
|
once.Do(func() {
|
|
instance = &controller{
|
|
cfg: cfg,
|
|
svc: svc,
|
|
bcbsi: bcbsi.New(cfg),
|
|
}
|
|
})
|
|
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 {
|
|
var eligibility viewmodel.Eligibility
|
|
|
|
if err := ctx.Bind(&eligibility); err != nil {
|
|
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)
|
|
if err != nil {
|
|
fmt.Println("Error Here: ", err.Error())
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
|
|
if ret.QueryResult.QueryResultSummary.BenefitsFound {
|
|
xmlString := html.UnescapeString(ret.QueryResult.HIPPA271.T271)
|
|
xmlReader := strings.NewReader(xmlString)
|
|
|
|
var f viewmodel.Interchange271
|
|
err = xml.NewDecoder(xmlReader).Decode(&f)
|
|
if err != nil {
|
|
fmt.Println("Error to unmarshal: ", err.Error())
|
|
}
|
|
|
|
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
|
|
} else {
|
|
return routeutils.ResponseAPIFieldValidationError(ctx, "phonenumber", "Phone number is required")
|
|
}
|
|
|
|
user, err = c.svc.Users.Create(user, authUser)
|
|
if err != nil {
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
} else {
|
|
if eligibility.User.Email != nil && len(*eligibility.User.Email) > 0 {
|
|
user.Email = eligibility.User.Email
|
|
}
|
|
|
|
if eligibility.User.PhoneNumber != nil {
|
|
if len(*eligibility.User.PhoneNumber) == 10 && !strings.Contains(*eligibility.User.PhoneNumber, "+1") {
|
|
phoneNumber := fmt.Sprintf("+1%s", *eligibility.User.PhoneNumber)
|
|
eligibility.User.PhoneNumber = &phoneNumber
|
|
}
|
|
|
|
if len(*eligibility.User.PhoneNumber) > 0 {
|
|
user.PhoneNumber = eligibility.User.PhoneNumber
|
|
}
|
|
}
|
|
|
|
err = c.svc.Users.UpdateLogin(user)
|
|
if err != nil {
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
}
|
|
|
|
address := viewmodel.Address{}
|
|
header := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N3_0950
|
|
body := f.Division.HealthCareEligibilityResponse.LoopHL0030[0].HL_0460[0].HL_0890[0].NM1_0920[0].N4_0960
|
|
zipCode := strings.TrimSpace(body.N403)
|
|
|
|
address.AddressTypeName = "Home"
|
|
address.AddressType = "home"
|
|
address.Name = fmt.Sprintf("%s, %s", header.N301, body.N401)
|
|
address.Address = fmt.Sprintf("%s, %s (%s)", header.N301, body.N401, zipCode)
|
|
address.CreatedUserUUID = authUser.ID
|
|
address.User = user
|
|
address.Type = "provider"
|
|
|
|
googleMapsAPI, err := maps.NewClient(maps.WithClientIDAndSignature("gme-bluecrossandblue1", "msqgD-jdqCyR0M_1u5C1HION5iI="))
|
|
if err != nil {
|
|
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
|
|
r := &maps.GeocodingRequest{
|
|
Address: address.Address + " " + body.N402 + ", " + zipCode,
|
|
}
|
|
|
|
result, err := googleMapsAPI.Geocode(context.Background(), r)
|
|
if err != nil {
|
|
fmt.Println("Error to instantiate googles api: ", err.Error())
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
|
|
if len(result) > 0 {
|
|
address.Latitude = result[0].Geometry.Location.Lat
|
|
address.Longitude = result[0].Geometry.Location.Lng
|
|
}
|
|
|
|
if len(user.Addresses) > 0 {
|
|
for _, a := range user.Addresses {
|
|
if a.AddressType == "home" {
|
|
err := c.svc.Users.RemoveAddress(a.UUID)
|
|
if err != nil {
|
|
fmt.Println("Error to remove old address: ", err.Error())
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
address, err = c.svc.Users.SaveAddress(address)
|
|
if err != nil {
|
|
fmt.Println("Error to save address: ", err.Error())
|
|
return routeutils.HandleAPIError(ctx, err)
|
|
}
|
|
user.Addresses = append(user.Addresses, address)
|
|
|
|
return ctx.JSON(200, user)
|
|
} else {
|
|
return routeutils.ResponseAPINotEligibleWithMessageError(ctx, "No benefits found for member")
|
|
}
|
|
}
|