initial commit 2

This commit is contained in:
Senad Uka
2018-04-25 13:16:36 +02:00
parent c1520d169c
commit 99c10b75fb
167 changed files with 25057 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
package bcbsi
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
BXE *bxeService
}
// New returns a new domain Service instance
func New(cfg *config.Config) *Service {
once.Do(func() {
instance = &Service{
BXE: newBXEService(cfg),
}
})
return instance
}

View File

@@ -0,0 +1,150 @@
package bcbsimodel
import (
"encoding/xml"
"time"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)
func GetEnvelope(eligibility viewmodel.Eligibility) Envelope {
soapEnvelope := Envelope{}
soapEnvelope.Namespace = "http://schemas.xmlsoap.org/soap/envelope/"
soapEnvelope.Body.MemberEligibilityRequest = GetEligibilityRequest(eligibility)
soapEnvelope.Body.MemberEligibilityRequest.Namespace = "http://v30.bx.services.bcbsa.com/eligibility-ext"
return soapEnvelope
}
func GetEligibilityRequest(eligibility viewmodel.Eligibility) MemberEligibilityRequest {
retVal := MemberEligibilityRequest{}
retVal.Version.MajorVersion = 3
retVal.Version.MinorVersion = 0
retVal.QueryHeader.TimeSent = time.Now().Format("2006-01-02T15:04:05")
retVal.QueryHeader.TrackingID = eligibility.TrackingID
retVal.Query.PayerInfo.PayerID = eligibility.Payer.PayerID
retVal.Query.PayerInfo.PayerName = eligibility.Payer.PayerName
retVal.Query.ProviderInfo.ProviderID = eligibility.Provider.ProviderID
retVal.Query.ProviderInfo.ProviderNPI = eligibility.Provider.ProviderNPI
retVal.Query.ProviderInfo.Provider.Organization = eligibility.Provider.ProviderName
retVal.Query.ProviderInfo.Provider.Name.First = eligibility.Provider.Name.First
retVal.Query.ProviderInfo.Provider.Name.Last = eligibility.Provider.Name.Last
retVal.Query.ProviderInfo.Provider.Name.Middle = eligibility.Provider.Name.Middle
retVal.Query.SubscriberInfo.SubscriberID = eligibility.Subscriber.SubscriberID
retVal.Query.SubscriberInfo.PatientType = eligibility.Subscriber.PatientType
retVal.Query.SubscriberInfo.Name.First = eligibility.Subscriber.Name.First
retVal.Query.SubscriberInfo.Name.Last = eligibility.Subscriber.Name.Last
retVal.Query.SubscriberInfo.Name.Middle = eligibility.Subscriber.Name.Middle
retVal.Query.SubscriberInfo.DemographicInfo.DateOfBirth = eligibility.Subscriber.DemographicInfo.DateOfBirth.Format("20060102")
retVal.Query.SubscriberInfo.DemographicInfo.GenderCode = eligibility.Subscriber.DemographicInfo.Gender
var dependents []Dependent
for _, d := range eligibility.Subscriber.Dependents {
dependent := Dependent{}
dependent.PatientAccountNumber = d.PatientAccountNumber
dependent.DemographicInfo.DateOfBirth = d.DemographicInfo.DateOfBirth.Format("20060102")
dependent.DemographicInfo.GenderCode = d.DemographicInfo.Gender
dependent.Name.First = d.Name.First
dependent.Name.Last = d.Name.Last
dependent.Name.Middle = d.Name.Middle
dependents = append(dependents, dependent)
}
if len(dependents) == 0 {
dependents = append(dependents, Dependent{})
}
retVal.Query.SubscriberInfo.DependentInfo.Dependents = dependents
retVal.Query.ServiceInfo.DateOfService = eligibility.ServiceInfo.DateOfService.Format("20060102")
retVal.Query.ServiceInfo.ServiceTypeCodes.ServiceTypeCode = eligibility.ServiceInfo.ServiceTypeCodes
return retVal
}
type Envelope struct {
XMLName xml.Name `xml:"soap:Envelope"`
Body EnvelopeBody `xml:"soap:Body"`
Namespace string `xml:"xmlns:soap,attr"`
}
type EnvelopeBody struct {
MemberEligibilityRequest MemberEligibilityRequest `xml:"elig:MemberEligibilityRequest"`
}
type MemberEligibilityRequest struct {
Version Version `xml:"version"`
QueryHeader QueryHeader `xml:"elig:eligibility-benefits-query-header"`
Query Query `xml:"elig:eligibility-benefits-query"`
Namespace string `xml:"xmlns:elig,attr"`
}
type Version struct {
MajorVersion int64 `xml:"majorVersion"`
MinorVersion int64 `xml:"minorVersion"`
}
type QueryHeader struct {
TrackingID string `xml:"tracking-id"`
TimeSent string `xml:"time-sent"`
}
type Query struct {
PayerInfo PayerInfo `xml:"elig:payer-info"`
ProviderInfo ProviderInfo `xml:"elig:provider-info"`
SubscriberInfo SubscriberInfo `xml:"elig:subscriber-info"`
ServiceInfo ServiceInfo `xml:"elig:service-info"`
}
type ServiceInfo struct {
DateOfService string `xml:"elig:date-of-service"`
ServiceTypeCodes ServiceTypeCodes `xml:"elig:service-type-codes"`
}
type ServiceTypeCodes struct {
ServiceTypeCode []string `xml:"elig:service-type-code"`
}
type SubscriberInfo struct {
PatientType string `xml:"elig:patient-type"`
SubscriberID string `xml:"elig:subscriber-id"`
Name Name `xml:"elig:name"`
DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
DependentInfo DependentInfo `xml:"elig:dependent-info"`
}
type DependentInfo struct {
Dependents []Dependent `xml:"elig:dependent"`
}
type Dependent struct {
PatientAccountNumber string `xml:"elig:patient-account-number"`
Name Name `xml:"elig:name"`
DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
}
type DemographicInfo struct {
DateOfBirth string `xml:"elig:date-of-birth"`
GenderCode string `xml:"elig:gender-code"`
}
type ProviderInfo struct {
ProviderID string `xml:"elig:provider-id"`
ProviderNPI string `xml:"elig:provider-npi"`
Provider Provider `xml:"elig:provider-name"`
}
type Provider struct {
Organization string `xml:"organization"`
Name Name `xml:"elig:name"`
}
type Name struct {
First string `xml:"elig:first"`
Last string `xml:"elig:last"`
Middle string `xml:"elig:middle"`
}
type PayerInfo struct {
PayerName string `xml:"elig:payer-name"`
PayerID string `xml:"elig:payer-id"`
}

View File

@@ -0,0 +1,44 @@
package bcbsimodel
import (
"encoding/xml"
)
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Body EnvelopeBodyResponse `xml:"Body"`
}
type EnvelopeBodyResponse struct {
MemberEligibilityResponse MemberEligibilityResponse `xml:"MemberEligibilityResponse"`
}
type MemberEligibilityResponse struct {
Version Version `xml:"version" json:"-"`
QueryResult QueryResult `xml:"eligibility-benefits-query-results" json:"results"`
}
type QueryResult struct {
HIPPA271 HIPAA271 `xml:"vcml-271" json:"raw"`
QueryResultSummary QueryResultSummary `xml:"query-result-summary" json:"summary"`
}
type HIPAA271 struct {
T271 string `xml:"t271" json:"t271"`
}
type QueryResultSummary struct {
BenefitsFound bool `xml:"benefits-found" json:"benefits_found"`
ProcessingInfo ProcessingInfo `xml:"processing-info" json:"-"`
}
type ProcessingInfo struct {
Message string `xml:"message" json:"-"`
}
type EntityResponse struct {
EntityID int64 `json:"entity_id"`
ID string `json:"id"`
Name string `json:"name"`
Status bool `json:"status"`
}

View File

@@ -0,0 +1,126 @@
package bcbsi
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/pquerna/ffjson/ffjson"
"bitbucket.org/nemt/nemt-portal-api/application/third/eligibility/bcbsi/bcbsimodel"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
type bxeService struct {
cfg *config.Config
}
func newBXEService(cfg *config.Config) *bxeService {
return &bxeService{
cfg: cfg,
}
}
func (s bxeService) getSignature(APIKey string, secretKey string) string {
rawKey := fmt.Sprintf("%s%s%v", APIKey, secretKey, time.Now().Unix())
hasher := md5.New()
hasher.Write([]byte(rawKey))
key := hex.EncodeToString(hasher.Sum(nil))
return strings.ToLower(key)
}
func (s bxeService) GetPayerDetails(subscriberID string) ([]bcbsimodel.EntityResponse, error) {
apiKey := s.cfg.Blue365.APIKey
secretKey := s.cfg.Blue365.Secret
URL := s.cfg.Blue365.URL
prefix := subscriberID[:3]
client := &http.Client{}
req, _ := http.NewRequest("GET", URL+"/"+prefix, bytes.NewBuffer([]byte{}))
req.Header.Add("X-Api-Key", apiKey)
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
defer resp.Body.Close()
bReturn, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
var response []bcbsimodel.EntityResponse
err = ffjson.Unmarshal(bReturn, &response)
if err != nil {
fmt.Println("Error Blue365: ", err)
return nil, err
}
return response, nil
}
func (s bxeService) CheckEligibility(eligibility viewmodel.Eligibility) (bcbsimodel.MemberEligibilityResponse, error) {
payer, err := s.GetPayerDetails(eligibility.Subscriber.SubscriberID)
if err != nil {
return bcbsimodel.MemberEligibilityResponse{}, err
}
eligibility.Payer.PayerID = payer[0].ID
eligibility.Payer.PayerName = payer[0].Name
envelope := bcbsimodel.GetEnvelope(eligibility)
apiKey := s.cfg.BXE.APIKey
secretKey := s.cfg.BXE.Secret
bObj, err := xml.Marshal(envelope)
if err != nil {
return bcbsimodel.MemberEligibilityResponse{}, err
}
client := &http.Client{}
req, _ := http.NewRequest("POST", s.cfg.BXE.URL, bytes.NewBuffer(bObj))
req.Header.Add("Soapaction", "CheckEligibility")
req.Header.Add("Content-Type", "text/xml")
req.Header.Add("X-Api-Key", apiKey)
req.Header.Add("X-Signature", s.getSignature(apiKey, secretKey))
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
defer resp.Body.Close()
bReturn, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
sResponse := string(bReturn)
sResponse = strings.Replace(sResponse, "soapenv:Envelope", "Envelope", -1)
sResponse = strings.Replace(sResponse, "soapenv:Body", "Body", -1)
sResponse = strings.Replace(sResponse, "ns2:", "", -1)
var result bcbsimodel.EnvelopeResponse
err = xml.Unmarshal([]byte(sResponse), &result)
if err != nil {
fmt.Println("Error WebService: ", err)
return bcbsimodel.MemberEligibilityResponse{}, err
}
return result.Body.MemberEligibilityResponse, nil
}

View File

@@ -0,0 +1,28 @@
package npd
import (
"sync"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
var (
instance *Service
once sync.Once
)
// Service holds the domain service repositories
type Service struct {
Provider *providerService
}
// New returns a new domain Service instance
func New(cfg *config.Config) *Service {
once.Do(func() {
instance = &Service{
Provider: newProviderService(cfg),
}
})
return instance
}

View File

@@ -0,0 +1,124 @@
package npdmodel
type ProviderHeaderResponse struct {
ResultStatus string `json:"resultStatus"`
Count CountResponse `json:"counts"`
Providers []ProviderResponse `json:"providers"`
FacetFields []FacetField `json:"facetEntries"`
}
type CountResponse struct {
Total string `json:"total"`
Groups string `json:"groups"`
}
type FacetField struct {
Name string `json:"name"`
FacetEntries []map[string]string `json:"facetEntries"`
}
type ProviderResponse struct {
MukID string `json:"mukId"`
FivePartKeyGroups []PartKeyGroup `json:"fivePartKeyGroups"`
OrgName string `json:"orgName"`
Gender string `json:"gender"`
AcceptNewPatients string `json:"acceptNewPatients"`
ProviderName string `json:"providerName"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
MiddleName string `json:"middleName"`
ProviderTitle string `json:"providerTitle"`
StreetName1 string `json:"streetName_1"`
StreetName2 string `json:"streetName_2"`
CityName string `json:"cityName"`
State string `json:"state"`
ZipCode string `json:"zipCode"`
Country string `json:"country"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
PhoneNumber string `json:"phoneNumber"`
ProviderEntityName string `json:"providerEntityName"`
ProviderEntityCode string `json:"providerEntityCode"`
ProviderTypeCode []ProviderTypeCode `json:"providerTypeCode"`
Distance string `json:"distance"`
AvailabilityOfCost string `json:"availabilityOfCost"`
TDDPhoneNumber string `json:"tddPhoneNumber"`
ExtendedOfficeHours string `json:"extendedOfficeHours"`
ProviderCountyCode string `json:"providerCountyCode"`
ProviderCountyName string `json:"providerCountyName"`
HospitalAffiliationNames []HospitalAffiliationNames `json:"hospitalAffiliationNames"`
ProviderAffiliationNumber string `json:"providerAffiliationNumber"`
ProviderAffiliationName string `json:"providerAffiliationName"`
LanguagesSpoken []Languages `json:"languagesSpoken"`
OfficeLanguagesSpoken []Languages `json:"officeLanguagesSpoken"`
MedSchool string `json:"medSchool"`
MedSchoolYear string `json:"medSchoolYear"`
Internship string `json:"internship"`
Residence string `json:"residency"`
Specialty1 string `json:"specialty1"`
Specialty2 string `json:"specialty2"`
Specialty3 string `json:"specialty3"`
Specialty4 string `json:"specialty4"`
Certification1 string `json:"certification1"`
Certification2 string `json:"certification2"`
Certification3 string `json:"certification3"`
Certification4 string `json:"certification4"`
}
type HospitalAffiliationNames struct {
HospAffProvOrgName string `json:"hospAffProvOrgName"`
}
type Languages struct {
Code string `json:"code"`
}
type ProviderTypeCode struct {
Code string `json:"code"`
}
type PartKeyGroup struct {
ProviderNum string `json:"providerNum"`
ProviderNumSuffix string `json:"providerNumSuffix"`
LocationSeqNum string `json:"locationSeqNum"`
PlanCode string `json:"planCode"`
ProductID string `json:"productId"`
TreatmentCategoryCode string `json:"treatmentCategoryCode"`
}
// ProviderSearchParams entity data
type ProviderSearchParams struct {
Name string
AlphaPrefix string
SearchBy string
Specialty string
Languages string
OfficeLanguages string
Gender string
AcceptNewPatients string
TreatmentCategoryCode string
SummaryScore string
AvailabilityOfCost string
AvailabilityOfQuality string
ExtendedOfficeHours string
HospitalAffiliation string
ProviderAffiliation string
ProviderEntityName string
NameRange string
BluPhyRcgIndicator string
Latitude float64
Longitude float64
Distance int64
Offset int64
Limit int64
SortBy string
FacetAcceptNewPatients string
FacetGender string
FacetExtendedOfficeHours string
FacetProviderEntityName string
FacetSummaryScore string
FacetLanguage string
FacetOfficeLanguages string
FacetHospitalAffiliations string
FacetProviderAffiliations string
}

View File

@@ -0,0 +1,56 @@
package npd
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"github.com/pquerna/ffjson/ffjson"
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
)
type providerService struct {
cfg *config.Config
}
func newProviderService(cfg *config.Config) *providerService {
return &providerService{
cfg: cfg,
}
}
func (c *providerService) GetProviders(searchParams npdmodel.ProviderSearchParams) (npdmodel.ProviderHeaderResponse, error) {
providerURL := "https://api-pve.bcbs.com/Providers/V30%s"
params := "?name=%s&alphaPrefix=BCB&lat=%v&long=%v&distance=%v&offset=%v&limit=%v&sortBy=%s&facetAcceptNewPatients=%s&facetGender=%s&facetExtendedOfficeHours=%s&facetProviderEntityName=%s&facetSummaryScore=%s&facetlanguage=%s&facetOfficelanguages=%s&facetHospitalAffiliations=%s&facetProviderAffiliations=%s"
params = fmt.Sprintf(params, url.QueryEscape(searchParams.Name), searchParams.Latitude, searchParams.Longitude, searchParams.Distance, searchParams.Offset, searchParams.Limit, url.QueryEscape(searchParams.SortBy), url.QueryEscape(searchParams.FacetAcceptNewPatients), url.QueryEscape(searchParams.FacetGender), url.QueryEscape(searchParams.FacetExtendedOfficeHours), url.QueryEscape(searchParams.FacetProviderEntityName), url.QueryEscape(searchParams.FacetSummaryScore), url.QueryEscape(searchParams.FacetLanguage), url.QueryEscape(searchParams.FacetOfficeLanguages), url.QueryEscape(searchParams.FacetHospitalAffiliations), url.QueryEscape(searchParams.FacetProviderAffiliations))
providerURL = fmt.Sprintf(providerURL, params)
req, err := http.NewRequest("GET", providerURL, nil)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
req.Header.Add("X-Api-Key", "sv6fs4dyh8macvuyyzgqs45w")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
defer resp.Body.Close()
bObject, err := ioutil.ReadAll(resp.Body)
if err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
var providers npdmodel.ProviderHeaderResponse
if err := ffjson.Unmarshal(bObject, &providers); err != nil {
return npdmodel.ProviderHeaderResponse{}, err
}
return providers, nil
}