initial commit 2
This commit is contained in:
421
data/datamysql/provider.go
Normal file
421
data/datamysql/provider.go
Normal file
@@ -0,0 +1,421 @@
|
||||
package datamysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
// rideRepo maps methods to database
|
||||
type providerRepo struct {
|
||||
conn executor
|
||||
}
|
||||
|
||||
func newProviderRepo(conn executor) *providerRepo {
|
||||
return &providerRepo{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *providerRepo) getProfileQuery(user entity.User) (query string, where string, err error) {
|
||||
if len(user.Profiles) > 0 {
|
||||
for _, p := range user.Profiles {
|
||||
switch p.Key {
|
||||
case "AD", "BCBSIAD", "BDCAD", "PLANAD":
|
||||
return
|
||||
case "SP", "SPT":
|
||||
switch p.Organization.Type.Key {
|
||||
case "techsupport", "bcbsi", "bcbsa", "plan":
|
||||
return
|
||||
case "provider":
|
||||
query = ` INNER JOIN viw_organization_provider c
|
||||
ON a.provider_id = c.provider_id `
|
||||
where = fmt.Sprintf(` AND (c.organization_uuid = '%s' OR c.parent_organization_uuid = '%s') `, p.Organization.UUID, p.Organization.UUID)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if query == "" && where == "" {
|
||||
return "", "", fmt.Errorf("Invalid Query")
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return "", "", fmt.Errorf("User has no profile to search")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *providerRepo) getSelectQueryBaseKey() string {
|
||||
return `SELECT
|
||||
a.provider_key_id,
|
||||
a.provider_id,
|
||||
a.internal_id,
|
||||
a.internal_id_suffix,
|
||||
a.location_seq_num,
|
||||
a.plan_code,
|
||||
a.product_id,
|
||||
a.treatment_category_code,
|
||||
a.active,
|
||||
a.enabled,
|
||||
a.create_at,
|
||||
a.update_at,
|
||||
a.created_user
|
||||
FROM tab_provider_key a `
|
||||
}
|
||||
|
||||
func (c *providerRepo) getSelectQueryBase() string {
|
||||
return `SELECT DISTINCT
|
||||
a.provider_id,
|
||||
a.provider_uuid,
|
||||
a.provider_internal_id,
|
||||
a.provider_internal_id_suffix,
|
||||
a.provider_muk_id,
|
||||
a.organization_name,
|
||||
a.gender,
|
||||
a.accept_new_patients,
|
||||
a.provider_name,
|
||||
a.first_name,
|
||||
a.last_name,
|
||||
a.middle_name,
|
||||
a.provider_title,
|
||||
a.street_name1,
|
||||
a.street_name2,
|
||||
a.city_name,
|
||||
a.state,
|
||||
a.zipcode,
|
||||
a.country,
|
||||
a.latitude,
|
||||
a.longitude,
|
||||
a.phone_number,
|
||||
a.create_at,
|
||||
a.update_at,
|
||||
a.active,
|
||||
a.enabled,
|
||||
a.created_user,
|
||||
(3959 * acos (
|
||||
cos ( radians(?) )
|
||||
* cos( radians( a.latitude ) )
|
||||
* cos( radians( a.longitude ) - radians(?) )
|
||||
+ sin ( radians(?) )
|
||||
* sin( radians( a.latitude ) )
|
||||
)) AS distance_in_miles
|
||||
FROM
|
||||
tab_provider a
|
||||
INNER JOIN tab_provider_key b
|
||||
ON a.provider_id = b.provider_id `
|
||||
}
|
||||
|
||||
func (c *providerRepo) GetAll(user entity.User) ([]entity.Provider, error) {
|
||||
lat := 41.886406
|
||||
long := -87.624225
|
||||
|
||||
query, where, err := c.getProfileQuery(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = c.getSelectQueryBase() + query + " WHERE 1 = 1 " + where
|
||||
|
||||
providers, err := c.parseSet(c.conn.Query(query, lat, long, lat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.getKeys("", "", providers)
|
||||
}
|
||||
|
||||
func (c *providerRepo) GetByMukID(mukID string, 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_muk_id = ? " + where
|
||||
|
||||
return c.parseEntity(c.conn.QueryRow(query, lat, long, lat, mukID))
|
||||
}
|
||||
|
||||
func (c *providerRepo) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user entity.User) ([]entity.Provider, error) {
|
||||
filter := " WHERE 1 = 1 "
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
if lat == 0 && long == 0 {
|
||||
lat = 41.886406
|
||||
long = -87.624225
|
||||
}
|
||||
params = append(params, lat, long, lat)
|
||||
|
||||
if query != "" && (mukID == "" && internalID == "") {
|
||||
filter += " AND (a.provider_name LIKE ? OR a.street_name1 LIKE ? OR a.street_name2 LIKE ? OR a.zipcode LIKE ?) "
|
||||
// MATCH(a.provider_internal_id, a.provider_internal_id_suffix, a.provider_muk_id, a.provider_name, a.street_name1, a.street_name2, a.city_name, a.state, a.zipcode, a.country, a.phone_number) AGAINST (?)
|
||||
|
||||
query = "%" + query + "%"
|
||||
params = append(params, query, query, query, query)
|
||||
}
|
||||
|
||||
if planCode != "" {
|
||||
filter += " AND b.plan_code = ? "
|
||||
params = append(params, planCode)
|
||||
}
|
||||
|
||||
if productID != "" {
|
||||
filter += " AND b.product_id = ? "
|
||||
params = append(params, productID)
|
||||
}
|
||||
|
||||
if mukID != "" {
|
||||
filter += " AND a.provider_muk_id = ? "
|
||||
params = append(params, mukID)
|
||||
}
|
||||
|
||||
if internalID != "" {
|
||||
filter += " AND a.provider_internal_id = ? "
|
||||
params = append(params, internalID)
|
||||
}
|
||||
|
||||
final := " HAVING distance_in_miles < ? "
|
||||
params = append(params, distance)
|
||||
|
||||
if sort == "name" {
|
||||
final += " ORDER BY a.provider_name ASC "
|
||||
} else if sort == "distance" {
|
||||
final += " ORDER BY distance_in_miles ASC "
|
||||
}
|
||||
|
||||
query, where, err := c.getProfileQuery(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = c.getSelectQueryBase() + query + filter + where + final
|
||||
|
||||
providers, err := c.parseSet(c.conn.Query(query, params...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(providers) > 0 {
|
||||
return c.getKeys(planCode, productID, providers)
|
||||
} else {
|
||||
return providers, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *providerRepo) getKeys(planCode string, productID string, providers []entity.Provider) ([]entity.Provider, error) {
|
||||
var params []interface{}
|
||||
var queryParams = " WHERE a.provider_id IN ("
|
||||
for _, p := range providers {
|
||||
queryParams += "?,"
|
||||
params = append(params, p.ProviderID)
|
||||
}
|
||||
queryParams = queryParams[0 : len(queryParams)-1]
|
||||
queryParams += ") "
|
||||
|
||||
if planCode != "" {
|
||||
queryParams += " AND a.plan_code = ? "
|
||||
params = append(params, planCode)
|
||||
}
|
||||
|
||||
if productID != "" {
|
||||
queryParams += " AND a.product_id = ? "
|
||||
params = append(params, productID)
|
||||
}
|
||||
|
||||
keys, err := c.parseKeySet(c.conn.Query(c.getSelectQueryBaseKey()+queryParams, params...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sortedResults := make(map[string][]entity.ProviderKey)
|
||||
for _, k := range keys {
|
||||
sortedKey := fmt.Sprintf("provider%v", k.Provider.ProviderID)
|
||||
sortedResults[sortedKey] = append(sortedResults[sortedKey], k)
|
||||
}
|
||||
|
||||
for i := range providers {
|
||||
sortedKey := fmt.Sprintf("provider%v", providers[i].ProviderID)
|
||||
providers[i].Keys = sortedResults[sortedKey]
|
||||
}
|
||||
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
// parseSet parses a result set result to an entity array
|
||||
func (c *providerRepo) parseKeySet(rows *sql.Rows, err error) ([]entity.ProviderKey, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
result := make([]entity.ProviderKey, 0)
|
||||
for rows.Next() {
|
||||
entity, err := c.parseKeyEntity(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 *providerRepo) parseKeyEntity(row scanner) (retVal entity.ProviderKey, err error) {
|
||||
err = row.Scan(
|
||||
&retVal.ProviderKeyID, &retVal.Provider.ProviderID, &retVal.InternalID, &retVal.InternalSuffixID, &retVal.LocationSeqNumber, &retVal.PlanCode, &retVal.ProductID, &retVal.TreatmentCategoryCode, &retVal.Active, &retVal.Enabled, &retVal.CreateDate, &retVal.UpdateDate, &retVal.CreatedUser.ID)
|
||||
|
||||
return retVal, errors.Wrap(err)
|
||||
}
|
||||
|
||||
// parseSet parses a result set result to an entity array
|
||||
func (c *providerRepo) parseSet(rows *sql.Rows, err error) ([]entity.Provider, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
result := make([]entity.Provider, 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 *providerRepo) parseEntity(row scanner) (retVal entity.Provider, err error) {
|
||||
err = row.Scan(
|
||||
&retVal.ProviderID, &retVal.ProviderUUID, &retVal.InternalID, &retVal.InternalSuffixID, &retVal.MukID, &retVal.OrganizatioName, &retVal.Gender, &retVal.AcceptNewPatients, &retVal.Name, &retVal.FirstName, &retVal.LastName, &retVal.MiddleName, &retVal.Title, &retVal.Address.StreetAddress1, &retVal.Address.StreetAddress2, &retVal.Address.CityName, &retVal.Address.State, &retVal.Address.ZipCode, &retVal.Address.Country, &retVal.Address.Latitude, &retVal.Address.Longitude, &retVal.Address.PhoneNumber, &retVal.CreateDate, &retVal.UpdateDate, &retVal.Active, &retVal.Enabled, &retVal.CreatedUser.ID, &retVal.Distance)
|
||||
|
||||
return retVal, errors.Wrap(err)
|
||||
}
|
||||
|
||||
func (c *providerRepo) Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error) {
|
||||
var savedProviders = make([]entity.Provider, 0)
|
||||
for _, p := range providers {
|
||||
provider, err := c.saveProvider(p, user)
|
||||
if err != nil {
|
||||
if driverErr, ok := err.(*mysql.MySQLError); ok {
|
||||
if driverErr.Number != 1062 {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
savedProviders = append(savedProviders, provider)
|
||||
}
|
||||
}
|
||||
|
||||
return savedProviders, nil
|
||||
}
|
||||
|
||||
func (c *providerRepo) saveProvider(provider entity.ProviderResponse, user entity.User) (entity.Provider, error) {
|
||||
const (
|
||||
query = `INSERT INTO tab_provider(provider_uuid,provider_internal_id,provider_internal_id_suffix,provider_muk_id,organization_name,gender,accept_new_patients,provider_name,first_name,last_name,middle_name,provider_title,street_name1,street_name2,city_name,state,zipcode,country,latitude,longitude,phone_number,created_user)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);`
|
||||
)
|
||||
|
||||
UUID, _ := uuid.NewV4()
|
||||
lat, _ := strconv.ParseFloat(provider.Latitude, 64)
|
||||
long, _ := strconv.ParseFloat(provider.Longitude, 64)
|
||||
|
||||
p := entity.Provider{
|
||||
ProviderUUID: UUID.String(),
|
||||
InternalID: provider.FivePartKeyGroups[0].ProviderNum,
|
||||
InternalSuffixID: provider.FivePartKeyGroups[0].ProviderNumSuffix,
|
||||
MukID: provider.MukID,
|
||||
OrganizatioName: provider.OrgName,
|
||||
Gender: provider.Gender,
|
||||
AcceptNewPatients: provider.AcceptNewPatients,
|
||||
Name: provider.ProviderName,
|
||||
FirstName: provider.FirstName,
|
||||
MiddleName: provider.MiddleName,
|
||||
LastName: provider.LastName,
|
||||
Title: provider.ProviderTitle,
|
||||
Address: entity.ProviderAddress{
|
||||
StreetAddress1: provider.StreetName1,
|
||||
StreetAddress2: provider.StreetName2,
|
||||
CityName: provider.CityName,
|
||||
State: provider.State,
|
||||
ZipCode: provider.ZipCode,
|
||||
Country: provider.Country,
|
||||
Latitude: lat,
|
||||
Longitude: long,
|
||||
PhoneNumber: provider.PhoneNumber,
|
||||
},
|
||||
CreateDate: time.Now(),
|
||||
UpdateDate: time.Now(),
|
||||
Active: true,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
result, err := c.conn.Exec(query, p.ProviderUUID, p.InternalID, p.InternalSuffixID, p.MukID, p.OrganizatioName, p.Gender, p.AcceptNewPatients, p.Name, p.FirstName, p.LastName, p.MiddleName, p.Title, p.Address.StreetAddress1, p.Address.StreetAddress2, p.Address.CityName, p.Address.State, p.Address.ZipCode, p.Address.Country, p.Address.Latitude, p.Address.Longitude, p.Address.PhoneNumber, 1)
|
||||
if err != nil {
|
||||
if driverErr, ok := err.(*mysql.MySQLError); ok {
|
||||
if driverErr.Number != 1062 {
|
||||
return entity.Provider{}, err
|
||||
} else {
|
||||
tempProvider, err := c.GetByMukID(p.MukID, user)
|
||||
if err != nil {
|
||||
return entity.Provider{}, err
|
||||
}
|
||||
p.ProviderID = tempProvider.ProviderID
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.ProviderID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return entity.Provider{}, err
|
||||
}
|
||||
}
|
||||
|
||||
var providerKeys []entity.ProviderKey
|
||||
for _, fk := range provider.FivePartKeyGroups {
|
||||
key, err := c.saveKeys(p.ProviderID, fk)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
providerKeys = append(providerKeys, key)
|
||||
}
|
||||
p.Keys = providerKeys
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (c *providerRepo) saveKeys(ProviderID int64, fk entity.PartKeyGroup) (entity.ProviderKey, error) {
|
||||
const (
|
||||
query = `INSERT INTO tab_provider_key (provider_id, internal_id, internal_id_suffix, location_seq_num, plan_code, product_id, treatment_category_code, created_user)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE provider_id = ?, internal_id = ?, internal_id_suffix = ?, location_seq_num = ?, plan_code = ?, product_id = ?, treatment_category_code = ?, created_user = ?;`
|
||||
)
|
||||
|
||||
key := entity.ProviderKey{
|
||||
InternalID: fk.ProviderNum,
|
||||
InternalSuffixID: fk.ProviderNumSuffix,
|
||||
TreatmentCategoryCode: fk.TreatmentCategoryCode,
|
||||
ProductID: fk.ProductID,
|
||||
PlanCode: fk.PlanCode,
|
||||
LocationSeqNumber: fk.LocationSeqNum,
|
||||
Provider: entity.Provider{
|
||||
ProviderID: ProviderID,
|
||||
},
|
||||
}
|
||||
|
||||
result, err := c.conn.Exec(query, key.Provider.ProviderID, key.InternalID, key.InternalSuffixID, key.LocationSeqNumber, key.PlanCode, key.ProductID, key.TreatmentCategoryCode, 1, key.Provider.ProviderID, key.InternalID, key.InternalSuffixID, key.LocationSeqNumber, key.PlanCode, key.ProductID, key.TreatmentCategoryCode, 1)
|
||||
if err != nil {
|
||||
return key, err
|
||||
}
|
||||
|
||||
key.ProviderKeyID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return key, err
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
Reference in New Issue
Block a user