initial commit 2
This commit is contained in:
23
Dockerfile.build
Normal file
23
Dockerfile.build
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
FROM golang:1.9.2
|
||||||
|
|
||||||
|
# Install glide
|
||||||
|
RUN curl https://glide.sh/get | sh
|
||||||
|
|
||||||
|
# Sets the arguments.
|
||||||
|
ARG BIN_NAME
|
||||||
|
ARG APP_NAME
|
||||||
|
ARG WORKDIR=/go/src/bitbucket.org/nemt/${APP_NAME}
|
||||||
|
|
||||||
|
# Prepares the work directory.
|
||||||
|
RUN mkdir -p ${WORKDIR}
|
||||||
|
ADD . ${WORKDIR}
|
||||||
|
WORKDIR ${WORKDIR}
|
||||||
|
RUN rm -rf glide.lock
|
||||||
|
RUN rm -rf vendor/
|
||||||
|
|
||||||
|
# Installs dependencies and builds app.
|
||||||
|
RUN glide install -force
|
||||||
|
RUN go build -o ${BIN_NAME} .
|
||||||
|
|
||||||
|
# Pauses the container.
|
||||||
|
CMD read
|
||||||
22
Dockerfile.run
Normal file
22
Dockerfile.run
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
FROM amazonlinux
|
||||||
|
|
||||||
|
# Sets the arguments.
|
||||||
|
ARG BIN_NAME=nemt-portal-api
|
||||||
|
ARG APP_NAME=nemt-portal-api
|
||||||
|
ARG WORKDIR=/opt/app/
|
||||||
|
|
||||||
|
# Creates the necessary directories.
|
||||||
|
RUN mkdir -p /opt/app/docs
|
||||||
|
RUN mkdir -p /opt/app/static
|
||||||
|
RUN mkdir -p /var/log/bsbsi
|
||||||
|
|
||||||
|
# Copies the files to the container.
|
||||||
|
COPY ./dist/${BIN_NAME} /opt/app/${BIN_NAME}
|
||||||
|
ADD ./dist/docs/ /opt/app/docs/
|
||||||
|
ADD ./dist/static/ /opt/app/static/
|
||||||
|
ADD ./dist/config.toml /opt/app/config.toml
|
||||||
|
|
||||||
|
# Sets and executes the app.
|
||||||
|
WORKDIR /opt/app
|
||||||
|
EXPOSE 5000
|
||||||
|
CMD ./nemt-portal-api
|
||||||
12
Dockerrun.aws.json
Normal file
12
Dockerrun.aws.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"AWSEBDockerrunVersion": "1",
|
||||||
|
"Image": {
|
||||||
|
"Update": "true"
|
||||||
|
},
|
||||||
|
"Ports": [
|
||||||
|
{
|
||||||
|
"ContainerPort": "5000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Logging": "/var/log/eb-docker/containers/eb-current-app/stdouterr.log"
|
||||||
|
}
|
||||||
102
Jenkinsfile
vendored
Normal file
102
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
node {
|
||||||
|
stage("Setting variables") {
|
||||||
|
echo "Setting variables"
|
||||||
|
|
||||||
|
BRANCH_PRD = 'master'
|
||||||
|
BRANCH_STG = 'staging'
|
||||||
|
BRANCH_DEV = 'development'
|
||||||
|
|
||||||
|
// Gets the environment based on the current Git branch.
|
||||||
|
if (env.BRANCH_NAME == BRANCH_PRD) {
|
||||||
|
env.DEPLOY_ENV = 'prd'
|
||||||
|
} else if (env.BRANCH_NAME == BRANCH_STG) {
|
||||||
|
env.DEPLOY_ENV = 'stg'
|
||||||
|
} else if (env.BRANCH_NAME == BRANCH_DEV) {
|
||||||
|
env.DEPLOY_ENV = 'dev'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define environment variables for other files to use it.
|
||||||
|
env.APP_NAME = "nemt-portal-api"
|
||||||
|
env.ENV_NAME = "${env.APP_NAME}-${env.DEPLOY_ENV}"
|
||||||
|
|
||||||
|
echo "Branch: ${env.BRANCH_NAME}"
|
||||||
|
echo "Environment: ${env.DEPLOY_ENV}"
|
||||||
|
|
||||||
|
echo "Setting variables complete"
|
||||||
|
}
|
||||||
|
stage("Cleaning") {
|
||||||
|
echo "Cleaning"
|
||||||
|
|
||||||
|
sh "rm -rf ${pwd()}/*"
|
||||||
|
deleteDir()
|
||||||
|
|
||||||
|
echo "Cleaning complete"
|
||||||
|
}
|
||||||
|
stage("Build") {
|
||||||
|
echo "Building"
|
||||||
|
|
||||||
|
// Sets package name based on the AWS job name, the current Git tag version and the build ID.
|
||||||
|
GIT_TAG = "\$(git describe --tags --always --dirty)"
|
||||||
|
PKG_NAME = "${GIT_TAG}-${env.JOB_BASE_NAME}-${env.BUILD_ID}"
|
||||||
|
ZIP_FILE_NAME = "${PKG_NAME}.zip"
|
||||||
|
|
||||||
|
// Sets the variables used for Docker login.
|
||||||
|
AWS_DOCKER_ROLE_NAME = "rvbrazil-bsbsi-deploy"
|
||||||
|
AWS_DOCKER_ROLE_ARN = "arn:aws:iam::xxxxxxxxxxx:role/bsbsi-deploy"
|
||||||
|
|
||||||
|
// Downloads repository.
|
||||||
|
echo "Downloading repository"
|
||||||
|
checkout scm
|
||||||
|
|
||||||
|
// Assumes role into our AWS account (for Docker login).
|
||||||
|
sh "aws-assume-role ${AWS_DOCKER_ROLE_ARN} ${AWS_DOCKER_ROLE_NAME}"
|
||||||
|
|
||||||
|
// Uses the AWS CLI to get our Docker login commmand and executes it.
|
||||||
|
sh "\$(aws --region us-east-1 --profile ${AWS_DOCKER_ROLE_NAME} ecr get-login)"
|
||||||
|
|
||||||
|
// Builds the application.
|
||||||
|
sh "make build-${env.DEPLOY_ENV}"
|
||||||
|
|
||||||
|
// Zips the files that will go to S3.
|
||||||
|
sh "cp Dockerfile.run Dockerfile"
|
||||||
|
sh "rm -rf ./*.zip"
|
||||||
|
sh "zip -r ${ZIP_FILE_NAME} dist Dockerfile Dockerrun.aws.json"
|
||||||
|
|
||||||
|
echo "Building complete"
|
||||||
|
}
|
||||||
|
stage("Deploy") {
|
||||||
|
echo "Deploying"
|
||||||
|
|
||||||
|
echo "Environment: ${env.DEPLOY_ENV}"
|
||||||
|
|
||||||
|
// Sets the variables used for deploying.
|
||||||
|
S3_BUCKET = "boilerplate-builds"
|
||||||
|
S3_KEY = "${env.APP_NAME}/${env.DEPLOY_ENV}/${ZIP_FILE_NAME}"
|
||||||
|
S3_PATH = "${S3_BUCKET}/${S3_KEY}"
|
||||||
|
AWS_ROLE_NAME = "qrides-bsbsi-deploy"
|
||||||
|
AWS_ROLE_ARN = "arn:aws:iam::xxxxxxxxxx:role/bsbsi-deploy"
|
||||||
|
|
||||||
|
// Assumes role into our AWS account (for S3 deploy).
|
||||||
|
sh "aws-assume-role ${AWS_ROLE_ARN} ${AWS_ROLE_NAME}"
|
||||||
|
|
||||||
|
// Deploys container to S3.
|
||||||
|
sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} s3 mv ${ZIP_FILE_NAME} s3://${S3_PATH}"
|
||||||
|
|
||||||
|
// Deploys to EBS.
|
||||||
|
sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} elasticbeanstalk \
|
||||||
|
create-application-version \
|
||||||
|
--application-name \"${env.APP_NAME}\" \
|
||||||
|
--version-label \"${PKG_NAME}\" \
|
||||||
|
--description \"${ZIP_FILE_NAME}\" \
|
||||||
|
--source-bundle S3Bucket=\"${S3_BUCKET}\",S3Key=\"${S3_KEY}\""
|
||||||
|
|
||||||
|
// Updates EBS environment.
|
||||||
|
sh "aws --region sa-east-1 --profile ${AWS_ROLE_NAME} elasticbeanstalk \
|
||||||
|
update-environment \
|
||||||
|
--application-name \"${env.APP_NAME}\" \
|
||||||
|
--environment-name \"${env.ENV_NAME}\" \
|
||||||
|
--version-label \"${PKG_NAME}\""
|
||||||
|
|
||||||
|
echo "Deploying complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
147
Makefile
Normal file
147
Makefile
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
PORT ?= 5000
|
||||||
|
DEPLOY_ENV ?= loc
|
||||||
|
|
||||||
|
BIN_NAME ?= nemt-portal-api
|
||||||
|
APP_NAME ?= nemt-portal-api
|
||||||
|
|
||||||
|
BUILD_CONTAINER_NAME = ${APP_NAME}-build
|
||||||
|
RUN_CONTAINER_NAME = ${APP_NAME}-run
|
||||||
|
|
||||||
|
#############################
|
||||||
|
## Environment definition. ##
|
||||||
|
#############################
|
||||||
|
|
||||||
|
set-loc:
|
||||||
|
$(eval DEPLOY_ENV := loc)
|
||||||
|
|
||||||
|
set-dev:
|
||||||
|
$(eval DEPLOY_ENV := dev)
|
||||||
|
|
||||||
|
set-stg:
|
||||||
|
$(eval DEPLOY_ENV := stg)
|
||||||
|
|
||||||
|
set-prd:
|
||||||
|
$(eval DEPLOY_ENV := prd)
|
||||||
|
|
||||||
|
######################
|
||||||
|
## Building process ##
|
||||||
|
######################
|
||||||
|
|
||||||
|
# Creates the container for the building process.
|
||||||
|
create-build-container:
|
||||||
|
|
||||||
|
# Verifies if the container already exists.
|
||||||
|
$(eval CONTAINER_ID:=$(shell docker ps -q --filter ancestor=$(BUILD_CONTAINER_NAME)))
|
||||||
|
|
||||||
|
# If it does, removes it.
|
||||||
|
if [ $(CONTAINER_ID) ]; then \
|
||||||
|
docker stop $(CONTAINER_ID) && \
|
||||||
|
docker rm $(CONTAINER_ID) && \
|
||||||
|
docker rmi -f $(BUILD_CONTAINER_NAME); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Creates "build" container.
|
||||||
|
docker build -f Dockerfile.build -t ${BUILD_CONTAINER_NAME}:latest --build-arg BIN_NAME=${BIN_NAME} --build-arg APP_NAME=${APP_NAME} --force-rm .
|
||||||
|
|
||||||
|
# Runs the `build` container and gets its binary.
|
||||||
|
build: clean create-build-container
|
||||||
|
|
||||||
|
# Creates the necessary folders.
|
||||||
|
mkdir -p dist/static
|
||||||
|
mkdir -p dist/docs
|
||||||
|
|
||||||
|
# Builds inside the container.
|
||||||
|
docker run \
|
||||||
|
--name ${BUILD_CONTAINER_NAME} -d ${BUILD_CONTAINER_NAME}
|
||||||
|
|
||||||
|
# Gets the binary.
|
||||||
|
docker cp \
|
||||||
|
${BUILD_CONTAINER_NAME}:/go/src/bitbucket.org/nemt/${APP_NAME}/${BIN_NAME} \
|
||||||
|
./dist/${BIN_NAME}
|
||||||
|
|
||||||
|
# Kills the container.
|
||||||
|
docker stop ${BUILD_CONTAINER_NAME}
|
||||||
|
docker rm ${BUILD_CONTAINER_NAME}
|
||||||
|
|
||||||
|
# Copies the docs and the static files to the correct folder.
|
||||||
|
cp -R static/* ./dist/static/
|
||||||
|
cp -R docs/swagger/ ./dist/docs/
|
||||||
|
cp config.${DEPLOY_ENV}.toml ./dist/config.toml
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
## Building, based on the current environment. ##
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
build-loc: set-loc build
|
||||||
|
|
||||||
|
build-dev: set-dev build
|
||||||
|
|
||||||
|
build-stg: set-stg build
|
||||||
|
|
||||||
|
build-prd: set-prd build
|
||||||
|
|
||||||
|
#####################
|
||||||
|
## Running process ##
|
||||||
|
#####################
|
||||||
|
|
||||||
|
create-run-container:
|
||||||
|
|
||||||
|
# Verifies if the container already exists.
|
||||||
|
$(eval CONTAINER_ID:=$(shell docker ps -q --filter ancestor=$(RUN_CONTAINER_NAME)))
|
||||||
|
|
||||||
|
# If it does, removes it.
|
||||||
|
if [ $(CONTAINER_ID) ]; then \
|
||||||
|
docker stop $(CONTAINER_ID) && \
|
||||||
|
docker rm $(CONTAINER_ID) && \
|
||||||
|
docker rmi -f $(RUN_CONTAINER_NAME); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Creates "run" container.
|
||||||
|
docker build -f Dockerfile.run -t ${RUN_CONTAINER_NAME}:latest --force-rm \
|
||||||
|
--build-arg BIN_NAME=${BIN_NAME} \
|
||||||
|
--build-arg APP_NAME=${APP_NAME} \
|
||||||
|
.
|
||||||
|
|
||||||
|
run: create-run-container
|
||||||
|
docker run -p ${PORT}:${PORT} -d --rm --name ${RUN_CONTAINER_NAME} ${RUN_CONTAINER_NAME}
|
||||||
|
echo 'Container exposing port ${PORT}.'
|
||||||
|
|
||||||
|
################################################
|
||||||
|
## Running, based on the current environment. ##
|
||||||
|
################################################
|
||||||
|
|
||||||
|
build-run-loc: build-loc create-run-container
|
||||||
|
|
||||||
|
build-run-dev: build-dev create-run-container
|
||||||
|
|
||||||
|
build-run-stg: build-stg create-run-container
|
||||||
|
|
||||||
|
build-run-prd: build-prd create-run-container
|
||||||
|
|
||||||
|
run-loc: build-run-loc run
|
||||||
|
|
||||||
|
run-dev: build-run-dev run
|
||||||
|
|
||||||
|
run-stg: build-run-stg run
|
||||||
|
|
||||||
|
run-prd: build-run-prd run
|
||||||
|
|
||||||
|
############
|
||||||
|
## Others ##
|
||||||
|
############
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${BIN_NAME}
|
||||||
|
rm -rf dist
|
||||||
|
|
||||||
|
run-host:
|
||||||
|
glide install
|
||||||
|
go build -o ${BIN_NAME} .
|
||||||
|
cp config.loc.toml ./config.toml
|
||||||
|
./${BIN_NAME}
|
||||||
|
|
||||||
|
migrate:
|
||||||
|
echo "Not implemented" && exit 500
|
||||||
|
|
||||||
|
test:
|
||||||
|
echo "Not implemented" && exit 500
|
||||||
43
application/applicationservice/applicationservice.go
Normal file
43
application/applicationservice/applicationservice.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Service
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service holds the domain service repositories
|
||||||
|
type Service struct {
|
||||||
|
Users *userService
|
||||||
|
Rides *rideService
|
||||||
|
Visits *visitService
|
||||||
|
Provider *providerService
|
||||||
|
Notification *notificationService
|
||||||
|
Profile *profileService
|
||||||
|
Organization *organizationService
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new domain Service instance
|
||||||
|
func New(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *Service {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Service{
|
||||||
|
Users: newUserService(svc, mapper),
|
||||||
|
Rides: newRideService(svc, mapper),
|
||||||
|
Visits: newVisitService(svc, mapper),
|
||||||
|
Provider: newProviderService(svc, mapper),
|
||||||
|
Notification: newNotificationService(svc, mapper, notification, cfg),
|
||||||
|
Profile: newProfileService(svc, mapper),
|
||||||
|
Organization: newOrganizationService(svc, mapper),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
640
application/applicationservice/notification.go
Normal file
640
application/applicationservice/notification.go
Normal file
@@ -0,0 +1,640 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pquerna/ffjson/ffjson"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"google.golang.org/api/googleapi/transport"
|
||||||
|
urlshortener "google.golang.org/api/urlshortener/v1"
|
||||||
|
gomail "gopkg.in/gomail.v2"
|
||||||
|
redis "gopkg.in/redis.v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NotificationTypeEmail = "email"
|
||||||
|
NOtificationTypeSMS = "sms"
|
||||||
|
NotificationTypeAPP = "app"
|
||||||
|
|
||||||
|
StatusPending = "pending"
|
||||||
|
StatusAccepted = "accepted"
|
||||||
|
StatusArrived = "arrived"
|
||||||
|
StatusPickedUp = "pickedUp"
|
||||||
|
StatusDroppedOff = "droppedOff"
|
||||||
|
StatusCanceled = "canceled"
|
||||||
|
StatusScheduled = "scheduled"
|
||||||
|
StatusWillCall = "willCall"
|
||||||
|
|
||||||
|
hourMinuteAMPM = "03:04 PM"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerService holds methods to provider application service
|
||||||
|
type notificationService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
notification *notificationservice.Service
|
||||||
|
cfg *config.Config
|
||||||
|
store *Store
|
||||||
|
pubSub *redis.PubSub
|
||||||
|
redisConn *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// newProviderService returns a providerService instance
|
||||||
|
func newNotificationService(svc *service.Service, mapper *entitymapping.Mapper, notification *notificationservice.Service, cfg *config.Config) *notificationService {
|
||||||
|
redisClient := redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
|
MasterName: "master01",
|
||||||
|
SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
|
||||||
|
Password: cfg.Cache.Pass,
|
||||||
|
DB: cfg.Cache.DB,
|
||||||
|
})
|
||||||
|
|
||||||
|
pubSub, err := redisClient.Subscribe()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ¬ificationService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
notification: notification,
|
||||||
|
cfg: cfg,
|
||||||
|
redisConn: redisClient,
|
||||||
|
store: &Store{
|
||||||
|
Users: make(map[string]*UserNotification),
|
||||||
|
redisClient: redisClient,
|
||||||
|
pubSub: pubSub,
|
||||||
|
},
|
||||||
|
pubSub: pubSub,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) secondsToMinutes(inSeconds int64) string {
|
||||||
|
minutes := inSeconds / 60
|
||||||
|
seconds := inSeconds % 60
|
||||||
|
str := fmt.Sprintf("%v minutes", minutes)
|
||||||
|
|
||||||
|
if seconds > 0 {
|
||||||
|
str += fmt.Sprintf(" %v seconds", seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) getReadyURLShortened(ride viewmodel.Ride) (string, error) {
|
||||||
|
const (
|
||||||
|
url = "https://portal.bcbsinstitute.com/#/ride/%s/%s/ready"
|
||||||
|
)
|
||||||
|
|
||||||
|
svc, err := urlshortener.New(&http.Client{
|
||||||
|
Transport: &transport.APIKey{Key: s.cfg.GoogleShortener.APIKey},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID)
|
||||||
|
shortURL, err := svc.Url.Insert(&urlshortener.Url{
|
||||||
|
Kind: "urlshortener#url", // Not really needed
|
||||||
|
LongUrl: userURL,
|
||||||
|
}).Do()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortURL.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) getURLShortened(ride viewmodel.Ride) (string, error) {
|
||||||
|
const (
|
||||||
|
url = "https://portal.bcbsinstitute.com/#/ride/%s/%s"
|
||||||
|
)
|
||||||
|
|
||||||
|
svc, err := urlshortener.New(&http.Client{
|
||||||
|
Transport: &transport.APIKey{Key: s.cfg.GoogleShortener.APIKey},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
userURL := fmt.Sprintf(url, ride.UUID, ride.User.ID)
|
||||||
|
shortURL, err := svc.Url.Insert(&urlshortener.Url{
|
||||||
|
Kind: "urlshortener#url", // Not really needed
|
||||||
|
LongUrl: userURL,
|
||||||
|
}).Do()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortURL.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) SendNotification(state string, ride viewmodel.Ride, lyftRide viewmodel.RideRequest) error {
|
||||||
|
notifications := make([]viewmodel.Notification, 0)
|
||||||
|
url, err := s.getURLShortened(ride)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to short url: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
loc, _ := time.LoadLocation("America/Chicago")
|
||||||
|
switch state {
|
||||||
|
case StatusWillCall:
|
||||||
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
||||||
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
||||||
|
|
||||||
|
messageMemberSMS := fmt.Sprintf(MessageSMSWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageMemberEmail := fmt.Sprintf(MessageEmailWillCallMember, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
urlReady, err := s.getReadyURLShortened(ride)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
|
||||||
|
messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, ride.Route.Destination.Name, urlReady)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailWillCallDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSWillCallMemberTitle, messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSWillCallDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailWillCallMemberTitle, messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailWillCallDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallMemberTitle, ride.Status.Value, ride.Route.Destination.Address), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", "Ride Scheduled "+strings.ToLower(ride.TripType.Value), fmt.Sprintf(MessageAppWillCallDispatcherTitle, ride.Status.Value, ride.Route.Destination.Address), true, "ride"))
|
||||||
|
case StatusScheduled:
|
||||||
|
dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
|
||||||
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
||||||
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
||||||
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
||||||
|
|
||||||
|
if ride.TripType.Key == "from_visit" && lyftRide.ReturnTime != nil {
|
||||||
|
dateFormat = lyftRide.ReturnTime.In(loc).Format("01/02/2006 03:04 PM")
|
||||||
|
pickupTime = lyftRide.ReturnTime.In(loc).Format(hourMinuteAMPM)
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMemberSMS := fmt.Sprintf(MessageSMSScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageMemberEmail := fmt.Sprintf(MessageEmailScheduledMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailScheduledDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledMemberTitle, dateFormat), messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledMemberTitle, dateFormat), messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailScheduledDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
|
||||||
|
|
||||||
|
// if ride.TripType.Key == "to_visit" {
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+strings.ToLower(ride.TripType.Value), ride.Status.Value), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
|
||||||
|
// } else if ride.TripType.Key == "from_visit" {
|
||||||
|
// notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledMemberTitle, pickupTime, ride.Route.Destination.Name), false, "ride"))
|
||||||
|
// notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("Ride %s "+strings.ToLower(ride.TripType.Value), StatusScheduled), fmt.Sprintf(MessageAppScheduledDispatcherTitle, pickupTime, ride.Route.Destination.Name), true, "ride"))
|
||||||
|
// }
|
||||||
|
case StatusPending:
|
||||||
|
dateFormat := ride.PickupTime.In(loc).Format("01/02/2006 03:04 PM")
|
||||||
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
||||||
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
||||||
|
visitDate := ride.VisitDate.In(loc).Format("01/02/2006")
|
||||||
|
|
||||||
|
messageMemberSMS := fmt.Sprintf(MessageSMSPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageMemberEmail := fmt.Sprintf(MessageEmailPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
//messageMemberApp := fmt.Sprintf(MessageAppPendingMember, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPendingDispatcher, ride.User.Name, visitTime, ride.Route.Destination.Name, visitDate, ride.Route.Origin.Address, pickupTime)
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingMemberTitle, dateFormat), messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingMemberTitle, dateFormat), messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPendingDispatcherTitle, ride.User.Name, dateFormat), messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingMemberTitle, pickupTime, ride.Route.Origin.Name), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPendingDispatcherTitle, pickupTime, ride.Route.Origin.Name), true, "ride"))
|
||||||
|
case StatusAccepted:
|
||||||
|
pickupTime := ride.PickupTime.In(loc).Format(hourMinuteAMPM)
|
||||||
|
|
||||||
|
messageMemberSMS := fmt.Sprintf(MessageSMSAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageMemberEmail := fmt.Sprintf(MessageEmailAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
//messageMemberApp := fmt.Sprintf(MessageAppAcceptedMember, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, pickupTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppAcceptedDispatcher, lyftRide.Driver.FirstName, ride.Route.Origin.Address, visitTime, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSAcceptedMemberTitle, messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSAcceptedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailAcceptedMemberTitle, messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailAcceptedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedMemberTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppAcceptedDispatcherTitle, s.secondsToMinutes(*lyftRide.Origin.ETASeconds), ride.Route.Origin.Name), true, "ride"))
|
||||||
|
case StatusArrived:
|
||||||
|
messageMemberSMS := fmt.Sprintf(MessageSMSArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
messageMemberSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageMemberEmail := fmt.Sprintf(MessageEmailArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
//messageMemberApp := fmt.Sprintf(MessageAppArrivedMember, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppArrivedDispatcher, ride.Route.Origin.Address, lyftRide.Driver.FirstName, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate, url)
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSArrivedMemberTitle, messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSArrivedDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailArrivedMemberTitle, messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailArrivedDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", "Your ride is HERE", fmt.Sprintf(MessageAppArrivedMemberTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", "Waiting for member", fmt.Sprintf(MessageAppArrivedDispatcherTitle, lyftRide.Vehicle.Color, lyftRide.Vehicle.Make, lyftRide.Vehicle.Model, lyftRide.Vehicle.LicensePlate), true, "ride"))
|
||||||
|
case StatusPickedUp:
|
||||||
|
dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
|
||||||
|
visitTime := ride.VisitDate.In(loc).Format(hourMinuteAMPM)
|
||||||
|
pickupTime := lyftRide.Pickup.Time.In(loc).Format(hourMinuteAMPM)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
||||||
|
messageDispatcherSMS += "\n\n" + MessageSMSReplyOrCancel
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppPickedUpDispatcher, ride.User.Name, ride.Route.Origin.Address, dateFormat, url, visitTime, s.secondsToMinutes(*lyftRide.Destination.ETASeconds))
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSPickedUpDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailPickedUpDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppPickedUpDispatcherTitle, pickupTime), true, "ride"))
|
||||||
|
case StatusDroppedOff:
|
||||||
|
dateFormat := time.Now().In(loc).Format("01/02/2006 03:04 PM")
|
||||||
|
dropOffTime := lyftRide.DropOff.Time.In(loc).Format(hourMinuteAMPM)
|
||||||
|
|
||||||
|
// messageMemberSMS := MessageSMSDroppedOffMember
|
||||||
|
// messageMemberEmail := MessageEmailDroppedOffMember
|
||||||
|
|
||||||
|
// if ride.Visit.TripType.Key == "roundtrip_call" && ride.TripType.Key == "to_visit" {
|
||||||
|
// entityRide, err := s.svc.Rides.GetByUUID(ride.UUID)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var nextRide entity.Ride
|
||||||
|
// for _, r := range entityRide.Visit.Rides {
|
||||||
|
// fmt.Println("Ride Tryp Type: ", r.TripType.Key)
|
||||||
|
// if r.TripType.Key == "from_visit_call" {
|
||||||
|
// nextRide = r
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Println("NextRide Found: ", nextRide.UUID)
|
||||||
|
// if nextRide.UUID != "" {
|
||||||
|
// urlReady, err := s.getReadyURLShortened(nextRide)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// messageMemberSMS += "\n" + fmt.Sprintf(MessageSMSIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
|
||||||
|
// messageMemberEmail += "\n" + fmt.Sprintf(MessageEmailIAmReadyOrClick, nextRide.Route.Destination.Name, urlReady)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Println("SMS Message: ", messageMemberSMS)
|
||||||
|
|
||||||
|
messageDispatcherSMS := fmt.Sprintf(MessageSMSDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherEmail := fmt.Sprintf(MessageEmailDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
||||||
|
//messageDispatcherApp := fmt.Sprintf(MessageAppDroppedOffDispatcher, ride.User.Name, ride.Route.Destination.Name, dateFormat, url, ride.Visit.ExternalID)
|
||||||
|
|
||||||
|
//notifications = append(notifications, s.GetNotification(ride, "sms", MessageSMSDroppedOffMemberTitle, messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", fmt.Sprintf(MessageSMSDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherSMS, true, ""))
|
||||||
|
//notifications = append(notifications, s.GetNotification(ride, "email", MessageEmailDroppedOffMemberTitle, messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", fmt.Sprintf(MessageEmailDroppedOffDispatcherTitle, ride.User.Name), messageDispatcherEmail, true, ""))
|
||||||
|
//notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), fmt.Sprintf(MessageAppDroppedOffMemberTitle, ride.Route.Destination.Name), false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), fmt.Sprintf(MessageAppDroppedOffDispatcherTitle, dropOffTime), true, "ride"))
|
||||||
|
case StatusCanceled:
|
||||||
|
visitTime := ride.VisitDate.Format(hourMinuteAMPM)
|
||||||
|
visitDate := ride.VisitDate.Format("01/02/2006")
|
||||||
|
|
||||||
|
var messageMemberSMS string
|
||||||
|
var messageMemberSMSTitle string
|
||||||
|
var messageMemberEmail string
|
||||||
|
var messageMemberEmailTitle string
|
||||||
|
//var messageMemberApp string
|
||||||
|
var messageMemberAppTitle string
|
||||||
|
|
||||||
|
var messageDispatcherSMS string
|
||||||
|
var messageDispatcherSMSTitle string
|
||||||
|
var messageDispatcherEmail string
|
||||||
|
var messageDispatcherEmailTitle string
|
||||||
|
//var messageDispatcherApp string
|
||||||
|
var messageDispatcherAppTitle string
|
||||||
|
|
||||||
|
if lyftRide.CanceledBy == "driver" {
|
||||||
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberSMSTitle = MessageSMSCanceledByDriverMemberTitle
|
||||||
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberEmailTitle = MessageEmailCanceledByDriverMemberTitle
|
||||||
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledByDriverMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberAppTitle = MessageAppCanceledByDriverMemberTitle
|
||||||
|
|
||||||
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledByDriverDispatcherTitle, ride.User.Name)
|
||||||
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledByDriverDispatcherTitle, ride.User.Name)
|
||||||
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledByDriverDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherAppTitle = MessageAppCanceledByDriverDispatcherTitle
|
||||||
|
} else if lyftRide.CanceledBy == "no_drivers_available" {
|
||||||
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
messageMemberSMSTitle = MessageSMSCanceledNoDriverMemberTitle
|
||||||
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
messageMemberEmailTitle = MessageEmailCanceledNoDriverMemberTitle
|
||||||
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledNoDriverMember, visitTime, ride.Route.Destination.Name, visitDate)
|
||||||
|
messageMemberAppTitle = MessageAppCanceledNoDriverMemberTitle
|
||||||
|
|
||||||
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledNoDriverDispatcherTitle, ride.User.Name)
|
||||||
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledNoDriverDispatcherTitle, ride.User.Name)
|
||||||
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledNoDriverDispatcher, visitTime, ride.Route.Destination.Name, visitDate, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherAppTitle = MessageAppCanceledNoDriverDispatcherTitle
|
||||||
|
} else {
|
||||||
|
messageMemberSMS = fmt.Sprintf(MessageSMSCanceledMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberSMSTitle = MessageSMSCanceledMemberTitle
|
||||||
|
messageMemberEmail = fmt.Sprintf(MessageEmailCanceledMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberEmailTitle = MessageEmailCanceledMemberTitle
|
||||||
|
//messageMemberApp = fmt.Sprintf(MessageAppCanceledMember, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageMemberAppTitle = MessageAppCanceledMemberTitle
|
||||||
|
|
||||||
|
messageDispatcherSMS = fmt.Sprintf(MessageSMSCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherSMSTitle = fmt.Sprintf(MessageSMSCanceledDispatcherTitle, ride.User.Name)
|
||||||
|
messageDispatcherEmail = fmt.Sprintf(MessageEmailCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherEmailTitle = fmt.Sprintf(MessageEmailCanceledDispatcherTitle, ride.User.Name)
|
||||||
|
//messageDispatcherApp = fmt.Sprintf(MessageAppCanceledDispatcher, visitTime, ride.Visit.ExternalID)
|
||||||
|
messageDispatcherAppTitle = MessageAppCanceledDispatcherTitle //fmt.Sprintf(MessageAppCanceledDispatcherTitle, ride.User.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", messageMemberSMSTitle, messageMemberSMS, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "sms", messageDispatcherSMSTitle, messageDispatcherSMS, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", messageMemberEmailTitle, messageMemberEmail, false, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "email", messageDispatcherEmailTitle, messageDispatcherEmail, true, ""))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageMemberAppTitle, false, "ride"))
|
||||||
|
notifications = append(notifications, s.GetNotification(ride, "app", fmt.Sprintf("%s | "+ride.TripType.Value, ride.Status.Value), messageDispatcherAppTitle, true, "ride"))
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications, err = s.SendNotifications(notifications)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to notify")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) GetNotification(ride viewmodel.Ride, notificationType string, subject string, message string, isDispatcher bool, messageType string) viewmodel.Notification {
|
||||||
|
retVal := viewmodel.Notification{
|
||||||
|
Type: notificationType,
|
||||||
|
Message: message,
|
||||||
|
Subject: subject,
|
||||||
|
Ride: ride,
|
||||||
|
User: ride.User,
|
||||||
|
CreatedUser: ride.CreatedUser,
|
||||||
|
Read: false,
|
||||||
|
MessageType: messageType,
|
||||||
|
}
|
||||||
|
|
||||||
|
if isDispatcher {
|
||||||
|
retVal.User = ride.CreatedUser
|
||||||
|
retVal.CreatedUser = ride.User
|
||||||
|
}
|
||||||
|
|
||||||
|
switch notificationType {
|
||||||
|
case NotificationTypeEmail:
|
||||||
|
if isDispatcher {
|
||||||
|
retVal.To = *ride.CreatedUser.Email
|
||||||
|
} else {
|
||||||
|
retVal.To = *ride.User.Email
|
||||||
|
}
|
||||||
|
case NOtificationTypeSMS:
|
||||||
|
if isDispatcher {
|
||||||
|
retVal.To = *ride.CreatedUser.PhoneNumber
|
||||||
|
} else {
|
||||||
|
retVal.To = *ride.User.PhoneNumber
|
||||||
|
}
|
||||||
|
case NotificationTypeAPP:
|
||||||
|
if isDispatcher {
|
||||||
|
retVal.To = ride.CreatedUser.ID
|
||||||
|
} else {
|
||||||
|
retVal.To = ride.User.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) SendMessage(message viewmodel.Message) error {
|
||||||
|
bMessage, err := ffjson.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.store.redisClient.Publish(message.DeliveryID, string(bMessage)).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) GetByUserUUIDAndReadStatus(user viewmodel.User, contactType string, isRead bool) ([]viewmodel.Notification, error) {
|
||||||
|
n, err := s.svc.Notification.GetByUserUUIDAndReadStatus(user.ID, contactType, isRead)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
authUser, err := s.svc.Users.GetByUUID(user.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isRead {
|
||||||
|
for i, _ := range n {
|
||||||
|
r, err := s.svc.Rides.GetByID(n[i].Ride.ID, authUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n[i].Ride = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Notification.ToNotificationModelSlice(n), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
|
||||||
|
return s.store.Subscribe(user, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) DeliverMessage() {
|
||||||
|
for {
|
||||||
|
v, _ := s.pubSub.Receive()
|
||||||
|
switch t := v.(type) {
|
||||||
|
case *redis.Message:
|
||||||
|
var m viewmodel.Message
|
||||||
|
ffjson.Unmarshal([]byte(t.Payload), &m)
|
||||||
|
s.store.FindAndDeliver(m)
|
||||||
|
case error:
|
||||||
|
fmt.Println("Error to delivery messages: ", t.Error())
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
if t != nil {
|
||||||
|
fmt.Println("Unknown Event: ", t)
|
||||||
|
fmt.Println("Type: ", reflect.TypeOf(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FindAndDeliver will send a message to an open channel
|
||||||
|
func (s *Store) FindAndDeliver(m viewmodel.Message) {
|
||||||
|
if s.Users[m.DeliveryID] != nil {
|
||||||
|
if s.Users[m.DeliveryID].ID != "" {
|
||||||
|
if len(s.Users[m.DeliveryID].Conn) > 0 {
|
||||||
|
for i, _ := range s.Users[m.DeliveryID].Conn {
|
||||||
|
if s.Users[m.DeliveryID].Conn[i] != nil {
|
||||||
|
if err := s.Users[m.DeliveryID].Conn[i].WriteJSON(m); err != nil {
|
||||||
|
s.Users[m.DeliveryID].Conn[i] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Subscribe add the user to a subscription
|
||||||
|
func (s *Store) Subscribe(user viewmodel.User, conn *websocket.Conn) (*UserNotification, error) {
|
||||||
|
u := s.Users[user.ID]
|
||||||
|
if u == nil {
|
||||||
|
u := &UserNotification{
|
||||||
|
ID: user.ID,
|
||||||
|
Conn: []*websocket.Conn{conn},
|
||||||
|
User: user,
|
||||||
|
}
|
||||||
|
s.Users[u.ID] = u
|
||||||
|
} else {
|
||||||
|
u.Conn = append(u.Conn, conn)
|
||||||
|
s.Users[u.ID] = u
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.pubSub.Subscribe(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *notificationService) ReadStatus(notificationUUID string, isRead bool) error {
|
||||||
|
return s.svc.Notification.ReadStatus(notificationUUID, isRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNotifications will send all the notifications to email or SMS
|
||||||
|
func (s *notificationService) SendNotifications(notifications []viewmodel.Notification) ([]viewmodel.Notification, error) {
|
||||||
|
if len(notifications) > 0 {
|
||||||
|
retVal := make([]viewmodel.Notification, 0)
|
||||||
|
for _, n := range notifications {
|
||||||
|
if n.To != "" {
|
||||||
|
notification := s.mapEntity.Notification.ToNotificationEntity(n)
|
||||||
|
notification, err := s.svc.Notification.Create(notification)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch n.Type {
|
||||||
|
case NOtificationTypeSMS:
|
||||||
|
if n.From == "" {
|
||||||
|
if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, n.To, n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
}
|
||||||
|
if err := s.notification.Twilio.SendSMS(s.cfg.Twilio.Sender, "+17083038497", n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := s.notification.Twilio.SendSMS(n.From, n.To, n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
}
|
||||||
|
if err := s.notification.Twilio.SendSMS(n.From, "+17083038497", n.Message); err != nil {
|
||||||
|
fmt.Println("Error to send SMS: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case NotificationTypeEmail:
|
||||||
|
m := gomail.NewMessage()
|
||||||
|
m.SetHeader("From", s.cfg.Email.Sender)
|
||||||
|
m.SetHeader("To", n.To)
|
||||||
|
m.SetHeader("Subject", n.Subject)
|
||||||
|
m.SetBody("text/plain", n.Message)
|
||||||
|
d := gomail.NewDialer(s.cfg.Email.Server, s.cfg.Email.Port, s.cfg.Email.User, s.cfg.Email.Pass)
|
||||||
|
|
||||||
|
if err := d.DialAndSend(m); err != nil {
|
||||||
|
fmt.Println("Error to send Email: ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
m = gomail.NewMessage()
|
||||||
|
m.SetHeader("From", s.cfg.Email.Sender)
|
||||||
|
m.SetHeader("To", "nemt@brighterdevelopment.com")
|
||||||
|
m.SetHeader("Subject", n.Subject)
|
||||||
|
m.SetBody("text/plain", n.Message)
|
||||||
|
|
||||||
|
if err := d.DialAndSend(m); err != nil {
|
||||||
|
fmt.Println("Error to send Email: ", err.Error())
|
||||||
|
}
|
||||||
|
case NotificationTypeAPP:
|
||||||
|
m := viewmodel.Message{
|
||||||
|
DeliveryID: n.To,
|
||||||
|
NotificationID: notification.UUID,
|
||||||
|
CreateDate: notification.Created,
|
||||||
|
Read: notification.Read,
|
||||||
|
Content: viewmodel.MessageContent{
|
||||||
|
Type: n.MessageType,
|
||||||
|
Subject: n.Subject,
|
||||||
|
Content: n.Message,
|
||||||
|
Payload: n.Ride,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.SendMessage(m); err != nil {
|
||||||
|
fmt.Println("Error to send notification to the users: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retVal = append(retVal, s.mapEntity.Notification.ToNotificationModel(notification))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
return notifications, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserNotification struct {
|
||||||
|
ID string
|
||||||
|
Conn []*websocket.Conn
|
||||||
|
User viewmodel.User
|
||||||
|
}
|
||||||
|
|
||||||
|
type Store struct {
|
||||||
|
Users map[string]*UserNotification
|
||||||
|
redisClient *redis.Client
|
||||||
|
pubSub *redis.PubSub
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
131
application/applicationservice/notificationmessage.go
Normal file
131
application/applicationservice/notificationmessage.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
const (
|
||||||
|
MessageSMSIAmReadyOrClick = "When you ready to go back to %s, click on the following link:\n %s\n or reply this message with I AM READY"
|
||||||
|
MessageEmailIAmReadyOrClick = "When you are ready to go back to %s, click on the following link:\n %s"
|
||||||
|
|
||||||
|
MessageSMSReplyOrCancel = "Reply CANCEL RIDE to cancel or DRIVER to contact driver"
|
||||||
|
MessageSMSPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageSMSPendingMemberTitle = "Ride Pending for %s"
|
||||||
|
MessageSMSPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageSMSPendingDispatcherTitle = "Ride Pending for %s on %s"
|
||||||
|
MessageEmailPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageEmailPendingMemberTitle = "Ride Pending for %s"
|
||||||
|
MessageEmailPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageEmailPendingDispatcherTitle = "Ride Pending for %s on %s"
|
||||||
|
MessageAppPendingMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageAppPendingMemberTitle = "Pickup: %s | %s"
|
||||||
|
MessageAppPendingDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageAppPendingDispatcherTitle = "Pickup: %s | %s"
|
||||||
|
|
||||||
|
MessageSMSWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
|
||||||
|
MessageSMSWillCallMemberTitle = "Ride Pending for %s"
|
||||||
|
MessageSMSWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
|
||||||
|
MessageSMSWillCallDispatcherTitle = "Ride Pending for %s"
|
||||||
|
MessageEmailWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
|
||||||
|
MessageEmailWillCallMemberTitle = "Ride Pending for %s"
|
||||||
|
MessageEmailWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
|
||||||
|
MessageEmailWillCallDispatcherTitle = "Ride Pending for %s"
|
||||||
|
MessageAppWillCallMember = "A ride has been scheduled for your %s visit to %s on %s."
|
||||||
|
MessageAppWillCallMemberTitle = "Pickup: %s | %s"
|
||||||
|
MessageAppWillCallDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s."
|
||||||
|
MessageAppWillCallDispatcherTitle = "Pickup: %s | %s"
|
||||||
|
|
||||||
|
MessageSMSScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageSMSScheduledMemberTitle = "Ride Scheduled for %s"
|
||||||
|
MessageSMSScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageSMSScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
|
||||||
|
MessageEmailScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageEmailScheduledMemberTitle = "Ride Scheduled for %s"
|
||||||
|
MessageEmailScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageEmailScheduledDispatcherTitle = "Ride Scheduled for %s on %s"
|
||||||
|
MessageAppScheduledMember = "A ride has been scheduled for your %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageAppScheduledMemberTitle = "Pickup: %s | %s"
|
||||||
|
MessageAppScheduledDispatcher = "A ride has been scheduled for %s's %s visit to %s on %s.\n\nThe driver will arrive at %s by %s."
|
||||||
|
MessageAppScheduledDispatcherTitle = "Pickup: %s | %s"
|
||||||
|
|
||||||
|
MessageSMSAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageSMSAcceptedMemberTitle = "Your Ride is on the way !"
|
||||||
|
MessageSMSAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageSMSAcceptedDispatcherTitle = "Ride Accepted for %s"
|
||||||
|
MessageEmailAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageEmailAcceptedMemberTitle = "Your Ride is on the way !"
|
||||||
|
MessageEmailAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageEmailAcceptedDispatcherTitle = "Ride Accepted for %s"
|
||||||
|
MessageAppAcceptedMember = "Your driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageAppAcceptedMemberTitle = "ETA: %s at %s"
|
||||||
|
MessageAppAcceptedDispatcher = "A driver, %s, is on the way to %s and will arrive by %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageAppAcceptedDispatcherTitle = "ETA: %s at %s"
|
||||||
|
|
||||||
|
MessageSMSArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageSMSArrivedMemberTitle = "Your Ride is HERE !"
|
||||||
|
MessageSMSArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageSMSArrivedDispatcherTitle = "Ride Arrived for %s"
|
||||||
|
MessageEmailArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageEmailArrivedMemberTitle = "Your Ride is HERE !"
|
||||||
|
MessageEmailArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageEmailArrivedDispatcherTitle = "Ride Arrived for %s"
|
||||||
|
MessageAppArrivedMember = "Your ride has arrived at %s.\n\nPlease look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageAppArrivedMemberTitle = "Look for %s %s %s (%s)"
|
||||||
|
MessageAppArrivedDispatcher = "Vehicle has arrived at %s.\n\nPlease tell member to look for %s in a %s %s %s (%s).\n\nView Ride %s"
|
||||||
|
MessageAppArrivedDispatcherTitle = "Look for %s %s %s (%s)"
|
||||||
|
|
||||||
|
MessageSMSPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
|
||||||
|
MessageSMSPickedUpDispatcherTitle = "%s is in Transit"
|
||||||
|
MessageEmailPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
|
||||||
|
MessageEmailPickedUpDispatcherTitle = "%s is in Transit"
|
||||||
|
MessageAppPickedUpDispatcher = "Member %s was picked up at %s at %s.\n\nView Ride %s\n\nVISIT: %s\n\nESTIMATED ARRIVAL: %s"
|
||||||
|
MessageAppPickedUpDispatcherTitle = "Actual Pickup Time: %s"
|
||||||
|
|
||||||
|
MessageSMSDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
|
||||||
|
MessageSMSDroppedOffDispatcherTitle = "%s has arrived"
|
||||||
|
MessageEmailDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
|
||||||
|
MessageEmailDroppedOffDispatcherTitle = "%s has arrived"
|
||||||
|
MessageAppDroppedOffDispatcher = "Member %s was dropped off at %s at ACTUAL %s.\n\nView Ride %s\n\nVISIT: %s"
|
||||||
|
MessageAppDroppedOffDispatcherTitle = "Arrival Time: %s"
|
||||||
|
MessageSMSDroppedOffMember = "Your ride has been ended, Thank you."
|
||||||
|
MessageSMSDroppedOffMemberTitle = "Ride Ended"
|
||||||
|
MessageEmailDroppedOffMember = "Your ride has been ended, Thank you."
|
||||||
|
MessageEmailDroppedOffMemberTitle = "Ride Ended"
|
||||||
|
MessageAppDroppedOffMember = "Your ride has been ended, Thank you."
|
||||||
|
MessageAppDroppedOffMemberTitle = "Arrived to %s"
|
||||||
|
|
||||||
|
MessageSMSCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageSMSCanceledByDriverMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageSMSCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageSMSCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageEmailCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageEmailCanceledByDriverMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageEmailCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageEmailCanceledByDriverDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageAppCanceledByDriverMember = "Your scheduled ride has been CANCELLED by your assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageAppCanceledByDriverMemberTitle = "Canceled by Driver"
|
||||||
|
MessageAppCanceledByDriverDispatcher = "The member's scheduled ride has been CANCELLED by the assigned driver.\n\nWe will schedule a NEW ride for your %s visit and notify you when your NEW driver has been assigned.\n\nVISIT: %s"
|
||||||
|
MessageAppCanceledByDriverDispatcherTitle = "Canceled by Driver"
|
||||||
|
|
||||||
|
MessageSMSCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
|
||||||
|
MessageSMSCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageSMSCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
|
||||||
|
MessageSMSCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageEmailCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
|
||||||
|
MessageEmailCanceledNoDriverMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageEmailCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
|
||||||
|
MessageEmailCanceledNoDriverDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageAppCanceledNoDriverMember = "Your scheduled ride for your %s visit to %s on %s has been CANCELLED because no drivers are currently available in your area.\n\nYour medical provider will contact you shortly to arrange alternative transportation or reschedule your visit."
|
||||||
|
MessageAppCanceledNoDriverMemberTitle = "No drivers available"
|
||||||
|
MessageAppCanceledNoDriverDispatcher = "The member's ride to a %s visit to %s on %s has been CANCELLED because no drivers are currently available near the pickup area.\n\nPlease contact member to arrange alternative transportation or reschedule member visit.\n\nVISIT: %s"
|
||||||
|
MessageAppCanceledNoDriverDispatcherTitle = "No drivers available"
|
||||||
|
|
||||||
|
MessageSMSCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageSMSCanceledMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageSMSCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageSMSCanceledDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageEmailCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageEmailCanceledMemberTitle = "Your Ride has been Canceled"
|
||||||
|
MessageEmailCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageEmailCanceledDispatcherTitle = "Ride for %s Canceled"
|
||||||
|
MessageAppCanceledMember = "Your scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for your %s visit and notify you when your NEW ride has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageAppCanceledMemberTitle = "Canceled by Member"
|
||||||
|
MessageAppCanceledDispatcher = "The member's scheduled ride has been CANCELLED by our transportation partner, Lyft, because of a technical problem with their system.\n\nWe will attempt to schedule a NEW ride for member's %s visit and notify you when a NEW scheduled has been scheduled.\n\nVISIT: %s"
|
||||||
|
MessageAppCanceledDispatcherTitle = "Canceled by Member"
|
||||||
|
)
|
||||||
230
application/applicationservice/organization.go
Normal file
230
application/applicationservice/organization.go
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"github.com/pquerna/ffjson/ffjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerService holds methods to provider application service
|
||||||
|
type organizationService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newProviderService returns a providerService instance
|
||||||
|
func newOrganizationService(svc *service.Service, mapper *entitymapping.Mapper) *organizationService {
|
||||||
|
return &organizationService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetAllTypes() ([]viewmodel.OrganizationType, error) {
|
||||||
|
result, err := s.svc.Organization.GetAllTypes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Organization.ToOrganizationTypeModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByType(organizationTypeKey string) ([]viewmodel.Organization, error) {
|
||||||
|
result, err := s.svc.Organization.GetByType(organizationTypeKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByUUID(organizationUUID string) (viewmodel.Organization, error) {
|
||||||
|
result, err := s.svc.Organization.GetByUUID(organizationUUID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Organization{}, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Organization.ToOrganizationModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByName(name string, searchType string) ([]viewmodel.Organization, error) {
|
||||||
|
result, err := s.svc.Organization.GetByName(name, searchType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Organization.ToOrganizationModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetParentOrganization(organizationUUID string, parentOrganizationUUID string) (viewmodel.Organization, error) {
|
||||||
|
child, err := s.svc.Organization.GetByUUID(organizationUUID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
parent, err := s.svc.Organization.GetByUUID(parentOrganizationUUID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.svc.Organization.SetParentOrganization(child.ID, parent.ID); err != nil {
|
||||||
|
return viewmodel.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetByUUID(organizationUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) InactivateOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) error {
|
||||||
|
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
|
||||||
|
entityAddress.Organization = &entity.Organization{
|
||||||
|
UUID: organizationUUID,
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.Users.GetByUUID(address.UpdatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entityAddress.UpdatedUser = user
|
||||||
|
|
||||||
|
if err := s.svc.Organization.InactivateOrganizationAddress(entityAddress); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetOrganizationAddress(organizationUUID string, address viewmodel.OrganizationAddress) (viewmodel.OrganizationAddress, error) {
|
||||||
|
entityAddress := s.mapEntity.Organization.ToOrganizationAddressEntity(address)
|
||||||
|
entityAddress.Organization = &entity.Organization{
|
||||||
|
UUID: organizationUUID,
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.Users.GetByUUID(address.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.OrganizationAddress{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entityAddress.CreatedUser = user
|
||||||
|
entityAddress.UpdatedUser = user
|
||||||
|
|
||||||
|
entityAddress, err = s.svc.Organization.SetOrganizationAddress(entityAddress)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.OrganizationAddress{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Organization.ToOrganizationAddressModel(entityAddress), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) InactivateOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) error {
|
||||||
|
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
|
||||||
|
entityContact.Organization = &entity.Organization{
|
||||||
|
UUID: organizationUUID,
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entityContact.UpdatedUser = user
|
||||||
|
|
||||||
|
if err := s.svc.Organization.InactivateOrganizationContact(entityContact); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetOrganizationContact(organizationUUID string, contact viewmodel.OrganizationContact) (viewmodel.OrganizationContact, error) {
|
||||||
|
entityContact := s.mapEntity.Organization.ToOrganizationContactEntity(contact)
|
||||||
|
entityContact.Organization = &entity.Organization{
|
||||||
|
UUID: organizationUUID,
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.Users.GetByUUID(contact.CreatedUser.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.OrganizationContact{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entityContact.CreatedUser = user
|
||||||
|
entityContact.UpdatedUser = user
|
||||||
|
|
||||||
|
entityContact, err = s.svc.Organization.SetOrganizationContact(entityContact)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.OrganizationContact{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Organization.ToOrganizationContactModel(entityContact), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) AddOrganization(organization viewmodel.Organization, user viewmodel.User) (viewmodel.Organization, error) {
|
||||||
|
enOrg := s.mapEntity.Organization.ToOrganizationEntity(organization)
|
||||||
|
enUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
|
||||||
|
author, err := s.svc.Users.GetByUUID(organization.Author.ID, "")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Organization{}, nil
|
||||||
|
}
|
||||||
|
enOrg.Author = author
|
||||||
|
enOrg.LastEditor = enOrg.Author
|
||||||
|
|
||||||
|
if organization.Reference != nil {
|
||||||
|
switch organization.Type.Key {
|
||||||
|
case "provider":
|
||||||
|
var provider npdmodel.ProviderResponse
|
||||||
|
bProvider, err := ffjson.Marshal(organization.Reference)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to marshal provider")
|
||||||
|
return viewmodel.Organization{}, nil
|
||||||
|
}
|
||||||
|
if err := ffjson.Unmarshal(bProvider, &provider); err != nil {
|
||||||
|
fmt.Println("Error to convert provider")
|
||||||
|
return viewmodel.Organization{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
eProviders, err := s.svc.Provider.Save(s.mapEntity.Provider.ToProviderEntitySlice([]npdmodel.ProviderResponse{provider}), enUser)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save provider")
|
||||||
|
return viewmodel.Organization{}, nil
|
||||||
|
}
|
||||||
|
respProvider := eProviders[0]
|
||||||
|
enOrg.ReferenceID = respProvider.ProviderID
|
||||||
|
|
||||||
|
lat, _ := strconv.ParseFloat(provider.Latitude, 64)
|
||||||
|
long, _ := strconv.ParseFloat(provider.Longitude, 64)
|
||||||
|
address := entity.OrganizationAddress{
|
||||||
|
InternalID: provider.MukID,
|
||||||
|
Name: "Main Address",
|
||||||
|
Address: fmt.Sprintf("%s %s - %s, %s (%s)", provider.StreetName1, provider.StreetName2, provider.CityName, provider.State, provider.ZipCode),
|
||||||
|
Latitude: lat,
|
||||||
|
Longitude: long,
|
||||||
|
CreatedUser: enOrg.Author,
|
||||||
|
UpdatedUser: enOrg.LastEditor,
|
||||||
|
}
|
||||||
|
enOrg.Addresses = append(enOrg.Addresses, address)
|
||||||
|
fmt.Println("Phone Number: ", provider.PhoneNumber)
|
||||||
|
if provider.PhoneNumber != "" {
|
||||||
|
formattedPhone := "+1" + strings.Replace(provider.PhoneNumber, "-", "", -1)
|
||||||
|
contact := entity.OrganizationContact{
|
||||||
|
Type: entity.ContactType{
|
||||||
|
Key: "phone",
|
||||||
|
},
|
||||||
|
Contact: formattedPhone,
|
||||||
|
Name: "Main Phone",
|
||||||
|
CreatedUser: enOrg.Author,
|
||||||
|
UpdatedUser: enOrg.LastEditor,
|
||||||
|
}
|
||||||
|
enOrg.Contacts = append(enOrg.Contacts, contact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enOrg, err = s.svc.Organization.AddOrganization(enOrg)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Organization{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetByUUID(enOrg.UUID)
|
||||||
|
}
|
||||||
58
application/applicationservice/profile.go
Normal file
58
application/applicationservice/profile.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerService holds methods to provider application service
|
||||||
|
type profileService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newProviderService returns a providerService instance
|
||||||
|
func newProfileService(svc *service.Service, mapper *entitymapping.Mapper) *profileService {
|
||||||
|
return &profileService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetAll() ([]viewmodel.Profile, error) {
|
||||||
|
result, err := s.svc.Profile.GetAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetByKey(key string) (viewmodel.Profile, error) {
|
||||||
|
result, err := s.svc.Profile.GetByKey(key)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Profile{}, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Profile.ToProfileModel(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetVisibles(visible bool) ([]viewmodel.Profile, error) {
|
||||||
|
result, err := s.svc.Profile.GetVisibles(visible)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetByOrganizationType(organizationTypeKey string) ([]viewmodel.Profile, error) {
|
||||||
|
orgType, err := s.svc.Organization.GetTypeByKey(organizationTypeKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := s.svc.Profile.GetByOrganizationType(orgType.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Profile.ToProfileModelSlice(result), nil
|
||||||
|
}
|
||||||
50
application/applicationservice/provider.go
Normal file
50
application/applicationservice/provider.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerService holds methods to provider application service
|
||||||
|
type providerService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newProviderService returns a providerService instance
|
||||||
|
func newProviderService(svc *service.Service, mapper *entitymapping.Mapper) *providerService {
|
||||||
|
return &providerService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) Save(providers []npdmodel.ProviderResponse, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
entities := s.mapEntity.Provider.ToProviderEntitySlice(providers)
|
||||||
|
result, err := s.svc.Provider.Save(entities, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Provider.ToProviderRespModelSlice(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) GetAll(user viewmodel.User) ([]viewmodel.ProviderResp, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
providers, err := s.svc.Provider.GetAll(eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user viewmodel.User) ([]viewmodel.ProviderResp, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
providers, err := s.svc.Provider.Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.mapEntity.Provider.ToProviderRespModelSlice(providers), nil
|
||||||
|
}
|
||||||
420
application/applicationservice/ride.go
Normal file
420
application/applicationservice/ride.go
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideService holds methods to user application service
|
||||||
|
type rideService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns a userService instance
|
||||||
|
func newRideService(svc *service.Service, mapper *entitymapping.Mapper) *rideService {
|
||||||
|
return &rideService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) UpdateNewRide(ride viewmodel.Ride, lyftRide viewmodel.RideRequest, user viewmodel.User) (viewmodel.Ride, error) {
|
||||||
|
webhookModel := viewmodel.WebhookResponse{
|
||||||
|
Ride: ride,
|
||||||
|
Event: lyftRide,
|
||||||
|
}
|
||||||
|
webhook := s.mapEntity.Ride.ToWebhookEntity(webhookModel)
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
oldRide, err := s.svc.Rides.GetByUUID(ride.UUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
|
||||||
|
generateDate := time.Now()
|
||||||
|
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
|
||||||
|
if webhook.Ride.RequestDate == nil {
|
||||||
|
webhook.Ride.RequestDate = oldRide.PickupTime
|
||||||
|
}
|
||||||
|
if webhook.Ride.RequestMiliseconds == nil {
|
||||||
|
webhook.Ride.RequestMiliseconds = &requestMS
|
||||||
|
}
|
||||||
|
if webhook.Ride.GenerateDate == nil {
|
||||||
|
webhook.Ride.GenerateDate = &generateDate
|
||||||
|
}
|
||||||
|
if webhook.Ride.GenerateMiliseconds == nil {
|
||||||
|
webhook.Ride.GenerateMiliseconds = &generateMS
|
||||||
|
}
|
||||||
|
|
||||||
|
switch webhook.Ride.Status.Key {
|
||||||
|
case "scheduled":
|
||||||
|
webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
|
||||||
|
case "accepted":
|
||||||
|
if lyftRide.Origin.ETASeconds != nil {
|
||||||
|
webhook.Ride.Route.ETA = *lyftRide.Origin.ETASeconds
|
||||||
|
} else {
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
case "arrived", "pickedUp":
|
||||||
|
if lyftRide.Destination.ETASeconds != nil {
|
||||||
|
webhook.Ride.Route.ETA = *lyftRide.Destination.ETASeconds
|
||||||
|
} else {
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
case "droppedOff":
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
|
||||||
|
|
||||||
|
webhook.Ride.InternalID = lyftRide.RideID
|
||||||
|
webhook.Ride.ID = oldRide.ID
|
||||||
|
webhook.Ride.UUID = oldRide.UUID
|
||||||
|
webhook.Ride.Driver.ID = oldRide.Driver.ID
|
||||||
|
webhook.Ride.Passenger.ID = oldRide.Passenger.ID
|
||||||
|
webhook.Ride.Route.ID = oldRide.Route.ID
|
||||||
|
webhook.Ride.Type.ID = oldRide.Type.ID
|
||||||
|
webhook.Ride.User = oldRide.User
|
||||||
|
webhook.Ride.CreatedUser = oldRide.CreatedUser
|
||||||
|
webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
|
||||||
|
webhook.Ride.Visit = oldRide.Visit
|
||||||
|
webhook.Ride.VisitDate = oldRide.VisitDate
|
||||||
|
webhook.Ride.VisitTime = oldRide.VisitTime
|
||||||
|
//webhook.Ride.PickupTime = oldRide.PickupTime
|
||||||
|
|
||||||
|
entityRide, err := s.svc.Rides.Update(webhook)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModel(entityRide), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) Update(ride viewmodel.WebhookResponse) (viewmodel.Ride, error) {
|
||||||
|
webhook := s.mapEntity.Ride.ToWebhookEntity(ride)
|
||||||
|
oldRide, err := s.svc.Rides.GetByInternalID(ride.Event.RideID)
|
||||||
|
if err != nil {
|
||||||
|
oldRide, err = s.svc.Rides.GetByInternalPassengerID(*ride.Event.Passenger.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestMS := (oldRide.PickupTime.UnixNano() / int64(time.Millisecond))
|
||||||
|
generateDate := time.Now()
|
||||||
|
generateMS := (generateDate.UnixNano() / int64(time.Millisecond))
|
||||||
|
if webhook.Ride.RequestDate == nil {
|
||||||
|
webhook.Ride.RequestDate = oldRide.PickupTime
|
||||||
|
}
|
||||||
|
if webhook.Ride.RequestMiliseconds == nil {
|
||||||
|
webhook.Ride.RequestMiliseconds = &requestMS
|
||||||
|
}
|
||||||
|
if webhook.Ride.GenerateDate == nil {
|
||||||
|
webhook.Ride.GenerateDate = &generateDate
|
||||||
|
}
|
||||||
|
if webhook.Ride.GenerateMiliseconds == nil {
|
||||||
|
webhook.Ride.GenerateMiliseconds = &generateMS
|
||||||
|
}
|
||||||
|
|
||||||
|
switch webhook.Ride.Status.Key {
|
||||||
|
case "scheduled":
|
||||||
|
webhook.Ride.Route.ETA = oldRide.PickupTime.UnixNano() / int64(time.Second)
|
||||||
|
case "accepted":
|
||||||
|
if ride.Event.Origin.ETASeconds != nil {
|
||||||
|
webhook.Ride.Route.ETA = *ride.Event.Origin.ETASeconds
|
||||||
|
} else {
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
case "arrived", "pickedUp":
|
||||||
|
if ride.Event.Destination.ETASeconds != nil {
|
||||||
|
webhook.Ride.Route.ETA = *ride.Event.Destination.ETASeconds
|
||||||
|
} else {
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
case "droppedOff":
|
||||||
|
webhook.Ride.Route.ETA = 0
|
||||||
|
}
|
||||||
|
webhook.Ride.Route.Duration = int64(time.Now().Sub(*oldRide.PickupTime).Seconds())
|
||||||
|
|
||||||
|
webhook.Ride.InternalID = ride.Event.RideID
|
||||||
|
webhook.Ride.ID = oldRide.ID
|
||||||
|
webhook.Ride.UUID = oldRide.UUID
|
||||||
|
webhook.Ride.Driver.ID = oldRide.Driver.ID
|
||||||
|
webhook.Ride.Passenger.ID = oldRide.Passenger.ID
|
||||||
|
webhook.Ride.Route.ID = oldRide.Route.ID
|
||||||
|
webhook.Ride.Type.ID = oldRide.Type.ID
|
||||||
|
webhook.Ride.User = oldRide.User
|
||||||
|
webhook.Ride.CreatedUser = oldRide.CreatedUser
|
||||||
|
webhook.Ride.Vehicle.ID = oldRide.Vehicle.ID
|
||||||
|
webhook.Ride.Visit = oldRide.Visit
|
||||||
|
webhook.Ride.VisitDate = oldRide.VisitDate
|
||||||
|
webhook.Ride.VisitTime = oldRide.VisitTime
|
||||||
|
webhook.Ride.PickupTime = oldRide.PickupTime
|
||||||
|
|
||||||
|
entityRide, err := s.svc.Rides.Update(webhook)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModel(entityRide), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a new ride
|
||||||
|
func (s *rideService) Save(ride viewmodel.RideRequest) (viewmodel.Ride, error) {
|
||||||
|
rideEntity := s.mapEntity.Ride.ToRideEntity(ride)
|
||||||
|
|
||||||
|
if ride.Visit.UUID == "" {
|
||||||
|
visit := entity.Visit{}
|
||||||
|
visit.User = rideEntity.User
|
||||||
|
visit.Pickup = rideEntity.Route.Origin
|
||||||
|
visit.Notes = &rideEntity.Note
|
||||||
|
visit.PickupDatetime = *rideEntity.PickupTime
|
||||||
|
visit.VisitDatetime = *rideEntity.VisitTime
|
||||||
|
visit.CreatedUser.UUID = ride.CreateUserUUID
|
||||||
|
visit.ExternalID = ride.VisitExternalID
|
||||||
|
visit.TripType = rideEntity.Visit.TripType
|
||||||
|
visit.ReturnDate = ride.ReturnTime
|
||||||
|
|
||||||
|
address, _ := s.svc.Users.GetAddressByUUID(rideEntity.Route.Destination.ID)
|
||||||
|
createdUser, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if address.ID > 0 {
|
||||||
|
visit.DestinationAddressID = address.ID
|
||||||
|
provider, err := s.svc.Provider.GetByMukID(address.InternalID, createdUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
visit.Provider = provider
|
||||||
|
} else {
|
||||||
|
provider, err := s.svc.Provider.GetByMukID(rideEntity.Route.Destination.ID, createdUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
visit.Provider = provider
|
||||||
|
}
|
||||||
|
|
||||||
|
visit, err = s.svc.Visits.Create(visit)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
rideEntity.Visit = visit
|
||||||
|
} else {
|
||||||
|
user, err := s.svc.Users.GetByUUID(ride.CreateUserUUID, "")
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
visit, err := s.svc.Visits.GetByUUID(ride.Visit.UUID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
rideEntity.Visit = visit
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err := s.svc.Rides.Save(rideEntity)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll returns a list of users
|
||||||
|
func (s *rideService) GetAll(user viewmodel.User) ([]viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetAll(eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUUID returns a specific Ride
|
||||||
|
func (s *rideService) GetByUUID(uuid string, user viewmodel.User) (viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetByUUID(uuid, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Visit.ID > 0 {
|
||||||
|
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByVisitUUID(visitUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetByVisitUUID(visitUUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, _ := range retVal {
|
||||||
|
retVal[i].Visit = visit
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user viewmodel.User) (viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetByVisitUUIDAndTripType(visitUUID, tripTypeKey, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
visit, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Visit = visit
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUUID returns a specific Ride
|
||||||
|
func (s *rideService) GetByUUIDAndUserUUID(uuid string, user_uuid string) (viewmodel.Ride, error) {
|
||||||
|
retVal, err := s.svc.Rides.GetByUUIDAndUserUUID(uuid, user_uuid)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Visit.ID > 0 {
|
||||||
|
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByInternalID returns a specific Ride
|
||||||
|
func (s *rideService) GetByInternalID(internalID string) (viewmodel.Ride, error) {
|
||||||
|
retVal, err := s.svc.Rides.GetByInternalID(internalID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Visit.ID > 0 {
|
||||||
|
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUserID returns a list of rides for an user
|
||||||
|
func (s *rideService) GetByUserID(userID int64, user viewmodel.User) ([]viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetByUserID(userID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return []viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStatus change the status of the ride
|
||||||
|
func (s *rideService) UpdateStatus(rideUUID string, status string) error {
|
||||||
|
err := s.svc.Rides.UpdateStatus(rideUUID, status)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUserID returns a list of rides for an user
|
||||||
|
func (s *rideService) GetByUserUUID(userUUID string, user viewmodel.User) ([]viewmodel.Ride, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Rides.GetByUserUUID(userUUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return []viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Ride.ToRideModelSlice(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetLastRideByPhoneNumber(phoneNumber string, notificationType string, status string) (viewmodel.Ride, error) {
|
||||||
|
// if notificationType == ""{
|
||||||
|
// notificationType = "message"
|
||||||
|
// }
|
||||||
|
|
||||||
|
if status == "" {
|
||||||
|
status = "sms"
|
||||||
|
}
|
||||||
|
|
||||||
|
notification, err := s.svc.Notification.GetLastNotificationFromPhoneNumber(notificationType, phoneNumber, status)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.Users.GetByID(notification.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err := s.svc.Rides.GetByID(notification.Ride.ID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Visit.ID > 0 {
|
||||||
|
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetLastRideByDriversNumber(phoneNumber string) (viewmodel.Ride, error) {
|
||||||
|
retVal, err := s.svc.Rides.GetLastRideByDriversNumber(phoneNumber)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Visit.ID > 0 {
|
||||||
|
user, err := s.svc.Users.GetByID(retVal.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Visit, err = s.svc.Visits.GetByID(retVal.Visit.ID, user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Ride{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.mapEntity.Ride.ToRideModel(retVal), err
|
||||||
|
}
|
||||||
149
application/applicationservice/user.go
Normal file
149
application/applicationservice/user.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
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/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService holds methods to user application service
|
||||||
|
type userService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns a userService instance
|
||||||
|
func newUserService(svc *service.Service, mapper *entitymapping.Mapper) *userService {
|
||||||
|
return &userService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll returns a list of users
|
||||||
|
func (s *userService) GetAll(quantity int64, page int64) (retVal []viewmodel.User, err error) {
|
||||||
|
users, err := s.svc.Users.GetAll()
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
return s.mapEntity.User.ToUserModelSlice(users), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID returns a specific user by its ID
|
||||||
|
func (s *userService) GetByID(id int64) (retVal viewmodel.User, err error) {
|
||||||
|
user, err := s.svc.Users.GetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID returns a specific user by its ID
|
||||||
|
func (s *userService) GetByUUID(uuid string, profile string) (retVal viewmodel.User, err error) {
|
||||||
|
user, err := s.svc.Users.GetByUUID(uuid, profile)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login returns a specific user by email and pass
|
||||||
|
func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (retVal viewmodel.User, err error) {
|
||||||
|
user, err := s.svc.Users.FullLogin(loginType, key, pass, profile)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login returns a specific user by email and pass
|
||||||
|
func (s *userService) Login(email string, pass string) (retVal viewmodel.User, err error) {
|
||||||
|
user, err := s.svc.Users.Login(email, pass)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(user), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) Create(user viewmodel.User) (retVal viewmodel.User, err error) {
|
||||||
|
entity := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
|
||||||
|
for i, _ := range entity.Organizations {
|
||||||
|
entity.Organizations[i], err = s.svc.Organization.GetByUUID(entity.Organizations[i].UUID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity, err = s.svc.Users.Create(entity)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModel(entity), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) CreateBulk(users []viewmodel.User) (retVal []viewmodel.User, err error) {
|
||||||
|
entities := s.mapEntity.User.ToUserEntitySlice(users)
|
||||||
|
organizations := make([]entity.Organization, 0)
|
||||||
|
for i, _ := range entities {
|
||||||
|
if i == 0 {
|
||||||
|
for o, _ := range entities[i].Organizations {
|
||||||
|
org, err := s.svc.Organization.GetByUUID(entities[i].Organizations[o].UUID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
organizations = append(organizations, org)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entities[i].Organizations = organizations
|
||||||
|
}
|
||||||
|
|
||||||
|
entities, err = s.svc.Users.CreateBulk(entities)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToUserModelSlice(entities), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsersByProfile returns a list of users by profile
|
||||||
|
func (s *userService) GetUsersByProfile(profile string) (retVal []viewmodel.User, err error) {
|
||||||
|
users, err := s.svc.Users.GetUsersByProfile(profile)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
list := s.mapEntity.User.ToUserModelSlice(users)
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) RemoveAddress(addressUUID string) error {
|
||||||
|
return s.svc.Users.RemoveAddress(addressUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) SaveAddress(address viewmodel.Address) (retVal viewmodel.Address, err error) {
|
||||||
|
entity := s.mapEntity.Address.ToAddressEntity(address)
|
||||||
|
entity, err = s.svc.Users.SaveAddress(entity)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Address.ToAddressModel(entity), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) GetContactType() (retVal []viewmodel.ContactType, err error) {
|
||||||
|
entity, err := s.svc.Users.GetContactType()
|
||||||
|
if err != nil {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.User.ToContactTypeModelSlice(entity), nil
|
||||||
|
}
|
||||||
38
application/applicationservice/util.go
Normal file
38
application/applicationservice/util.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package applicationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getTakeSkipPaging return the take and skip from page number and item quantity
|
||||||
|
func getTakeSkipPaging(quantity int64, page int64) (take int64, skip int64) {
|
||||||
|
if page < 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if quantity < 1 {
|
||||||
|
quantity = 10
|
||||||
|
} else if quantity > 1000 {
|
||||||
|
quantity = 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
take = quantity // itens per page
|
||||||
|
skip = (page - 1) * quantity
|
||||||
|
|
||||||
|
return take, skip
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildPaginatedResult returns a paginatedResult instance
|
||||||
|
func buildPaginatedResult(list interface{}, skip int64, take int64, totalRecords int64) viewmodel.PaginatedResult {
|
||||||
|
return viewmodel.PaginatedResult{
|
||||||
|
List: list,
|
||||||
|
Pagination: viewmodel.ReturnPagination{
|
||||||
|
CurrentPage: (skip / take) + 1,
|
||||||
|
RecordsPerPage: take,
|
||||||
|
TotalRecords: totalRecords,
|
||||||
|
TotalPages: int64(math.Ceil(float64(totalRecords) / float64(take))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
55
application/applicationservice/visit.go
Normal file
55
application/applicationservice/visit.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
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"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideService holds methods to user application service
|
||||||
|
type visitService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns a userService instance
|
||||||
|
func newVisitService(svc *service.Service, mapper *entitymapping.Mapper) *visitService {
|
||||||
|
return &visitService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a new ride
|
||||||
|
func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) {
|
||||||
|
entity := s.mapEntity.Visit.ToVisitEntity(visit)
|
||||||
|
retVal, err := s.svc.Visits.Create(entity)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Visit.ToVisitModel(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a new ride
|
||||||
|
func (s *visitService) GetAll(user viewmodel.User) ([]viewmodel.Visit, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Visits.GetAll(eUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Visit.ToVisitModelSlice(retVal), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a new ride
|
||||||
|
func (s *visitService) GetByUUID(visitUUID string, user viewmodel.User) (viewmodel.Visit, error) {
|
||||||
|
eUser := s.mapEntity.User.ToUserEntity(user)
|
||||||
|
retVal, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.mapEntity.Visit.ToVisitModel(retVal), err
|
||||||
|
}
|
||||||
74
application/entitymapping/address.go
Normal file
74
application/entitymapping/address.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideMapping has method to map ride entities to view models
|
||||||
|
type addressMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVisitEntity maps a User entity to User view model
|
||||||
|
func (mapping *addressMapping) ToAddressEntity(item viewmodel.Address) entity.Address {
|
||||||
|
return entity.Address{
|
||||||
|
UUID: item.UUID,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
Name: item.Name,
|
||||||
|
Address: item.Address,
|
||||||
|
AddressType: mapping.ToParamEntity(item.AddressType),
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
Origin: mapping.ToParamEntity(item.Type),
|
||||||
|
User: mapping.mapper.User.ToUserEntity(item.User),
|
||||||
|
CreatedUser: entity.User{
|
||||||
|
UUID: item.CreatedUserUUID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *addressMapping) ToParamEntity(item string) entity.Params {
|
||||||
|
return entity.Params{
|
||||||
|
Key: item,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVisitEntity maps a User entity to User view model
|
||||||
|
func (mapping *addressMapping) ToAddressModel(item entity.Address) viewmodel.Address {
|
||||||
|
return viewmodel.Address{
|
||||||
|
UUID: item.UUID,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
Name: item.Name,
|
||||||
|
Address: item.Address,
|
||||||
|
AddressType: item.AddressType.Key,
|
||||||
|
AddressTypeName: item.AddressType.Name,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
Type: item.Origin.Key,
|
||||||
|
User: mapping.mapper.User.ToUserModel(item.User),
|
||||||
|
CreatedUserUUID: item.CreatedUser.UUID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *addressMapping) ToAddressEntitySlice(list []viewmodel.Address) (retVal []entity.Address) {
|
||||||
|
retVal = make([]entity.Address, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToAddressEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
|
||||||
|
func (mapping *addressMapping) ToAddressModelSlice(list []entity.Address) (retVal []viewmodel.Address) {
|
||||||
|
retVal = make([]viewmodel.Address, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToAddressModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
51
application/entitymapping/entitymapping.go
Normal file
51
application/entitymapping/entitymapping.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Mapper
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mapper has mapping methods to map entities to view models
|
||||||
|
type Mapper struct {
|
||||||
|
User *userMapping
|
||||||
|
Ride *rideMapping
|
||||||
|
Visit *visitMapping
|
||||||
|
Address *addressMapping
|
||||||
|
Provider *providerMapping
|
||||||
|
Notification *notificationMapping
|
||||||
|
Profile *profileMapping
|
||||||
|
Organization *organizationMapping
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns an EntityMapper for fluent mapping
|
||||||
|
func New() *Mapper {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Mapper{}
|
||||||
|
|
||||||
|
instance.User = &userMapping{instance}
|
||||||
|
instance.Ride = &rideMapping{instance}
|
||||||
|
instance.Visit = &visitMapping{instance}
|
||||||
|
instance.Address = &addressMapping{instance}
|
||||||
|
instance.Provider = &providerMapping{instance}
|
||||||
|
instance.Notification = ¬ificationMapping{instance}
|
||||||
|
instance.Profile = &profileMapping{instance}
|
||||||
|
instance.Organization = &organizationMapping{instance}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
// isEmpty returns the alternative option in case the first is empty
|
||||||
|
func ifEmpty(firstOption string, alternativeOption string) string {
|
||||||
|
if strings.TrimSpace(firstOption) == "" {
|
||||||
|
return alternativeOption
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstOption
|
||||||
|
}
|
||||||
69
application/entitymapping/notification.go
Normal file
69
application/entitymapping/notification.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerMapping has method to map provider entities to view models
|
||||||
|
type notificationMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *notificationMapping) ToNotificationEntitySlice(list []viewmodel.Notification) (retVal []entity.Notification) {
|
||||||
|
retVal = make([]entity.Notification, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToNotificationEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *notificationMapping) ToNotificationEntity(model viewmodel.Notification) entity.Notification {
|
||||||
|
return entity.Notification{
|
||||||
|
UUID: model.UUID,
|
||||||
|
To: model.To,
|
||||||
|
From: model.From,
|
||||||
|
Type: model.Type,
|
||||||
|
Subject: model.Subject,
|
||||||
|
Message: model.Message,
|
||||||
|
Created: model.Created,
|
||||||
|
Ride: entity.Ride{
|
||||||
|
UUID: model.Ride.UUID,
|
||||||
|
},
|
||||||
|
User: mapping.mapper.User.ToUserEntity(model.User),
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
|
||||||
|
Read: model.Read,
|
||||||
|
MessageType: model.MessageType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *notificationMapping) ToNotificationModelSlice(list []entity.Notification) (retVal []viewmodel.Notification) {
|
||||||
|
retVal = make([]viewmodel.Notification, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToNotificationModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *notificationMapping) ToNotificationModel(model entity.Notification) viewmodel.Notification {
|
||||||
|
return viewmodel.Notification{
|
||||||
|
UUID: model.UUID,
|
||||||
|
To: model.To,
|
||||||
|
From: model.From,
|
||||||
|
Type: model.Type,
|
||||||
|
Subject: model.Subject,
|
||||||
|
Message: model.Message,
|
||||||
|
Created: model.Created,
|
||||||
|
Ride: mapping.mapper.Ride.ToRideModel(model.Ride),
|
||||||
|
User: mapping.mapper.User.ToUserModel(model.User),
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
|
||||||
|
Read: model.Read,
|
||||||
|
MessageType: model.MessageType,
|
||||||
|
}
|
||||||
|
}
|
||||||
256
application/entitymapping/organization.go
Normal file
256
application/entitymapping/organization.go
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerMapping has method to map provider entities to view models
|
||||||
|
type organizationMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationTypeEntitySlice(list []viewmodel.OrganizationType) (retVal []entity.OrganizationType) {
|
||||||
|
retVal = make([]entity.OrganizationType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationTypeEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationEntitySlice(list []viewmodel.Organization) (retVal []entity.Organization) {
|
||||||
|
retVal = make([]entity.Organization, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationEntity(model viewmodel.Organization) entity.Organization {
|
||||||
|
return entity.Organization{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
Type: mapping.ToOrganizationTypeEntity(model.Type),
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
ReferenceID: model.ReferenceID,
|
||||||
|
ParentID: model.ParentID,
|
||||||
|
Main: model.Main,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
Active: model.Active,
|
||||||
|
Blocked: model.Blocked,
|
||||||
|
Suspended: model.Suspended,
|
||||||
|
Author: mapping.mapper.User.ToUserEntity(model.Author),
|
||||||
|
LastEditor: mapping.mapper.User.ToUserEntity(model.LastEditor),
|
||||||
|
Contacts: mapping.ToOrganizationContactEntitySlice(model.Contacts),
|
||||||
|
Addresses: mapping.ToOrganizationAddressEntitySlice(model.Addresses),
|
||||||
|
ChildOrgs: mapping.ToOrganizationEntitySlice(model.ChildOrgs),
|
||||||
|
Parent: mapping.ToOrganizationEntityPointer(model.Parent),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationEntityPointer(model *viewmodel.Organization) *entity.Organization {
|
||||||
|
if model != nil {
|
||||||
|
convertibleModel := *model
|
||||||
|
convertibleEntity := mapping.ToOrganizationEntity(convertibleModel)
|
||||||
|
return &convertibleEntity
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationModelPointer(model *entity.Organization) *viewmodel.Organization {
|
||||||
|
if model != nil {
|
||||||
|
convertibleModel := *model
|
||||||
|
convertibleEntity := mapping.ToOrganizationModel(convertibleModel)
|
||||||
|
return &convertibleEntity
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationTypeEntity(model viewmodel.OrganizationType) entity.OrganizationType {
|
||||||
|
return entity.OrganizationType{
|
||||||
|
ID: model.ID,
|
||||||
|
Name: model.Name,
|
||||||
|
Key: model.Key,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationTypeModelSlice(list []entity.OrganizationType) (retVal []viewmodel.OrganizationType) {
|
||||||
|
retVal = make([]viewmodel.OrganizationType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationTypeModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationModelSlice(list []entity.Organization) (retVal []viewmodel.Organization) {
|
||||||
|
retVal = make([]viewmodel.Organization, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationModel(model entity.Organization) viewmodel.Organization {
|
||||||
|
return viewmodel.Organization{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
Type: mapping.ToOrganizationTypeModel(model.Type),
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
ReferenceID: model.ReferenceID,
|
||||||
|
ParentID: model.ParentID,
|
||||||
|
Main: model.Main,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
Active: model.Active,
|
||||||
|
Blocked: model.Blocked,
|
||||||
|
Suspended: model.Suspended,
|
||||||
|
Author: mapping.mapper.User.ToUserModel(model.Author),
|
||||||
|
LastEditor: mapping.mapper.User.ToUserModel(model.LastEditor),
|
||||||
|
Contacts: mapping.ToOrganizationContactModelSlice(model.Contacts),
|
||||||
|
Addresses: mapping.ToOrganizationAddressModelSlice(model.Addresses),
|
||||||
|
ChildOrgs: mapping.ToOrganizationModelSlice(model.ChildOrgs),
|
||||||
|
Parent: mapping.ToOrganizationModelPointer(model.Parent),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationTypeModel(model entity.OrganizationType) viewmodel.OrganizationType {
|
||||||
|
return viewmodel.OrganizationType{
|
||||||
|
ID: model.ID,
|
||||||
|
Name: model.Name,
|
||||||
|
Key: model.Key,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationContactModel(model entity.OrganizationContact) viewmodel.OrganizationContact {
|
||||||
|
return viewmodel.OrganizationContact{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
Type: mapping.mapper.User.ToContactTypeModel(model.Type),
|
||||||
|
Contact: model.Contact,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
|
||||||
|
Updated: model.Updated,
|
||||||
|
UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
|
||||||
|
Active: model.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationContactEntity(model viewmodel.OrganizationContact) entity.OrganizationContact {
|
||||||
|
return entity.OrganizationContact{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
Type: mapping.mapper.User.ToContactTypeEntity(model.Type),
|
||||||
|
Contact: model.Contact,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
|
||||||
|
Updated: model.Updated,
|
||||||
|
UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
|
||||||
|
Active: model.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationContactModelSlice(list []entity.OrganizationContact) (retVal []viewmodel.OrganizationContact) {
|
||||||
|
retVal = make([]viewmodel.OrganizationContact, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationContactModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationContactEntitySlice(list []viewmodel.OrganizationContact) (retVal []entity.OrganizationContact) {
|
||||||
|
retVal = make([]entity.OrganizationContact, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationContactEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationAddressModel(model entity.OrganizationAddress) viewmodel.OrganizationAddress {
|
||||||
|
return viewmodel.OrganizationAddress{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
InternalID: model.InternalID,
|
||||||
|
Address: model.Address,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Latitude: model.Latitude,
|
||||||
|
Longitude: model.Longitude,
|
||||||
|
Created: model.Created,
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserModel(model.CreatedUser),
|
||||||
|
Updated: model.Updated,
|
||||||
|
UpdatedUser: mapping.mapper.User.ToUserModel(model.UpdatedUser),
|
||||||
|
Active: model.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *organizationMapping) ToOrganizationAddressEntity(model viewmodel.OrganizationAddress) entity.OrganizationAddress {
|
||||||
|
return entity.OrganizationAddress{
|
||||||
|
ID: model.ID,
|
||||||
|
UUID: model.UUID,
|
||||||
|
InternalID: model.InternalID,
|
||||||
|
Address: model.Address,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Latitude: model.Latitude,
|
||||||
|
Longitude: model.Longitude,
|
||||||
|
Created: model.Created,
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserEntity(model.CreatedUser),
|
||||||
|
Updated: model.Updated,
|
||||||
|
UpdatedUser: mapping.mapper.User.ToUserEntity(model.UpdatedUser),
|
||||||
|
Active: model.Active,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationAddressModelSlice(list []entity.OrganizationAddress) (retVal []viewmodel.OrganizationAddress) {
|
||||||
|
retVal = make([]viewmodel.OrganizationAddress, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationAddressModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *organizationMapping) ToOrganizationAddressEntitySlice(list []viewmodel.OrganizationAddress) (retVal []entity.OrganizationAddress) {
|
||||||
|
retVal = make([]entity.OrganizationAddress, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToOrganizationAddressEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
65
application/entitymapping/profile.go
Normal file
65
application/entitymapping/profile.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerMapping has method to map provider entities to view models
|
||||||
|
type profileMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *profileMapping) ToProfileEntitySlice(list []viewmodel.Profile) (retVal []entity.Profile) {
|
||||||
|
retVal = make([]entity.Profile, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProfileEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *profileMapping) ToProfileEntity(model viewmodel.Profile) entity.Profile {
|
||||||
|
return entity.Profile{
|
||||||
|
ID: model.ID,
|
||||||
|
Key: model.Key,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
Active: model.Active,
|
||||||
|
Visible: model.Visible,
|
||||||
|
Blocked: model.Blocked,
|
||||||
|
Suspended: model.Suspended,
|
||||||
|
Organization: mapping.mapper.Organization.ToOrganizationEntity(model.Organization),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *profileMapping) ToProfileModelSlice(list []entity.Profile) (retVal []viewmodel.Profile) {
|
||||||
|
retVal = make([]viewmodel.Profile, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProfileModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *profileMapping) ToProfileModel(model entity.Profile) viewmodel.Profile {
|
||||||
|
return viewmodel.Profile{
|
||||||
|
ID: model.ID,
|
||||||
|
Key: model.Key,
|
||||||
|
Name: model.Name,
|
||||||
|
Description: model.Description,
|
||||||
|
Created: model.Created,
|
||||||
|
Updated: model.Updated,
|
||||||
|
Active: model.Active,
|
||||||
|
Visible: model.Visible,
|
||||||
|
Blocked: model.Blocked,
|
||||||
|
Suspended: model.Suspended,
|
||||||
|
Organization: mapping.mapper.Organization.ToOrganizationModel(model.Organization),
|
||||||
|
}
|
||||||
|
}
|
||||||
375
application/entitymapping/provider.go
Normal file
375
application/entitymapping/provider.go
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/third/npd/npdmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// providerMapping has method to map provider entities to view models
|
||||||
|
type providerMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderRespEntitySlice(list []viewmodel.ProviderResp) (retVal []entity.Provider) {
|
||||||
|
retVal = make([]entity.Provider, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderRespEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderRespEntity(item viewmodel.ProviderResp) entity.Provider {
|
||||||
|
return entity.Provider{
|
||||||
|
ProviderUUID: item.ProviderUUID,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
InternalSuffixID: item.InternalSuffixID,
|
||||||
|
MukID: item.MukID,
|
||||||
|
OrganizatioName: item.OrganizatioName,
|
||||||
|
Gender: item.Gender,
|
||||||
|
AcceptNewPatients: item.AcceptNewPatients,
|
||||||
|
Name: item.Name,
|
||||||
|
FirstName: item.FirstName,
|
||||||
|
MiddleName: item.MiddleName,
|
||||||
|
LastName: item.LastName,
|
||||||
|
Title: item.Title,
|
||||||
|
Distance: item.Distance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderRespModelSlice(list []entity.Provider) (retVal []viewmodel.ProviderResp) {
|
||||||
|
retVal = make([]viewmodel.ProviderResp, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderRespModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderRespModel(item entity.Provider) viewmodel.ProviderResp {
|
||||||
|
return viewmodel.ProviderResp{
|
||||||
|
ProviderUUID: item.ProviderUUID,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
InternalSuffixID: item.InternalSuffixID,
|
||||||
|
MukID: item.MukID,
|
||||||
|
OrganizatioName: item.OrganizatioName,
|
||||||
|
Gender: item.Gender,
|
||||||
|
AcceptNewPatients: item.AcceptNewPatients,
|
||||||
|
Name: item.Name,
|
||||||
|
FirstName: item.FirstName,
|
||||||
|
MiddleName: item.MiddleName,
|
||||||
|
LastName: item.LastName,
|
||||||
|
Title: item.Title,
|
||||||
|
Keys: mapping.ToProviderKeyModelSlice(item.Keys),
|
||||||
|
Address: mapping.ToProviderRespAddressModel(item.Address),
|
||||||
|
Distance: item.Distance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderKeyModelSlice(list []entity.ProviderKey) (retVal []viewmodel.ProviderKey) {
|
||||||
|
retVal = make([]viewmodel.ProviderKey, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderKeyModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderKeyModel(item entity.ProviderKey) viewmodel.ProviderKey {
|
||||||
|
return viewmodel.ProviderKey{
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
InternalSuffixID: item.InternalSuffixID,
|
||||||
|
LocationSeqNumber: item.LocationSeqNumber,
|
||||||
|
PlanCode: item.PlanCode,
|
||||||
|
ProductID: item.ProductID,
|
||||||
|
TreatmentCategoryCode: item.TreatmentCategoryCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderRespAddressModel(item entity.ProviderAddress) viewmodel.ProviderAddress {
|
||||||
|
return viewmodel.ProviderAddress{
|
||||||
|
StreetAddress1: item.StreetAddress1,
|
||||||
|
StreetAddress2: item.StreetAddress2,
|
||||||
|
CityName: item.CityName,
|
||||||
|
State: item.State,
|
||||||
|
ZipCode: item.ZipCode,
|
||||||
|
Country: item.Country,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
PhoneNumber: item.PhoneNumber,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderEntity(item npdmodel.ProviderResponse) entity.ProviderResponse {
|
||||||
|
return entity.ProviderResponse{
|
||||||
|
MukID: item.MukID,
|
||||||
|
FivePartKeyGroups: mapping.ToPartKeyGroupEntitySlice(item.FivePartKeyGroups),
|
||||||
|
OrgName: item.OrgName,
|
||||||
|
Gender: item.Gender,
|
||||||
|
AcceptNewPatients: item.AcceptNewPatients,
|
||||||
|
ProviderName: item.ProviderName,
|
||||||
|
FirstName: item.FirstName,
|
||||||
|
LastName: item.LastName,
|
||||||
|
MiddleName: item.MiddleName,
|
||||||
|
ProviderTitle: item.ProviderTitle,
|
||||||
|
StreetName1: item.StreetName1,
|
||||||
|
StreetName2: item.StreetName2,
|
||||||
|
CityName: item.CityName,
|
||||||
|
State: item.State,
|
||||||
|
ZipCode: item.ZipCode,
|
||||||
|
Country: item.Country,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
PhoneNumber: item.PhoneNumber,
|
||||||
|
ProviderEntityName: item.ProviderEntityName,
|
||||||
|
ProviderEntityCode: item.ProviderEntityCode,
|
||||||
|
ProviderTypeCode: mapping.ToProviderTypeCodeEntitySlice(item.ProviderTypeCode),
|
||||||
|
Distance: item.Distance,
|
||||||
|
AvailabilityOfCost: item.AvailabilityOfCost,
|
||||||
|
TDDPhoneNumber: item.TDDPhoneNumber,
|
||||||
|
ExtendedOfficeHours: item.ExtendedOfficeHours,
|
||||||
|
ProviderCountyCode: item.ProviderCountyCode,
|
||||||
|
ProviderCountyName: item.ProviderCountyName,
|
||||||
|
HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesEntitySlice(item.HospitalAffiliationNames),
|
||||||
|
ProviderAffiliationNumber: item.ProviderAffiliationNumber,
|
||||||
|
ProviderAffiliationName: item.ProviderAffiliationName,
|
||||||
|
LanguagesSpoken: mapping.ToLanguagesEntitySlice(item.LanguagesSpoken),
|
||||||
|
OfficeLanguagesSpoken: mapping.ToLanguagesEntitySlice(item.OfficeLanguagesSpoken),
|
||||||
|
MedSchool: item.MedSchool,
|
||||||
|
MedSchoolYear: item.MedSchoolYear,
|
||||||
|
Internship: item.Internship,
|
||||||
|
Residence: item.Residence,
|
||||||
|
Specialty1: item.Specialty1,
|
||||||
|
Specialty2: item.Specialty2,
|
||||||
|
Specialty3: item.Specialty3,
|
||||||
|
Specialty4: item.Specialty4,
|
||||||
|
Certification1: item.Certification1,
|
||||||
|
Certification2: item.Certification2,
|
||||||
|
Certification3: item.Certification3,
|
||||||
|
Certification4: item.Certification4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderModel(item entity.ProviderResponse) npdmodel.ProviderResponse {
|
||||||
|
return npdmodel.ProviderResponse{
|
||||||
|
MukID: item.MukID,
|
||||||
|
FivePartKeyGroups: mapping.ToPartKeyGroupModelSlice(item.FivePartKeyGroups),
|
||||||
|
OrgName: item.OrgName,
|
||||||
|
Gender: item.Gender,
|
||||||
|
AcceptNewPatients: item.AcceptNewPatients,
|
||||||
|
ProviderName: item.ProviderName,
|
||||||
|
FirstName: item.FirstName,
|
||||||
|
LastName: item.LastName,
|
||||||
|
MiddleName: item.MiddleName,
|
||||||
|
ProviderTitle: item.ProviderTitle,
|
||||||
|
StreetName1: item.StreetName1,
|
||||||
|
StreetName2: item.StreetName2,
|
||||||
|
CityName: item.CityName,
|
||||||
|
State: item.State,
|
||||||
|
ZipCode: item.ZipCode,
|
||||||
|
Country: item.Country,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
PhoneNumber: item.PhoneNumber,
|
||||||
|
ProviderEntityName: item.ProviderEntityName,
|
||||||
|
ProviderEntityCode: item.ProviderEntityCode,
|
||||||
|
ProviderTypeCode: mapping.ToProviderTypeCodeModelSlice(item.ProviderTypeCode),
|
||||||
|
Distance: item.Distance,
|
||||||
|
AvailabilityOfCost: item.AvailabilityOfCost,
|
||||||
|
TDDPhoneNumber: item.TDDPhoneNumber,
|
||||||
|
ExtendedOfficeHours: item.ExtendedOfficeHours,
|
||||||
|
ProviderCountyCode: item.ProviderCountyCode,
|
||||||
|
ProviderCountyName: item.ProviderCountyName,
|
||||||
|
HospitalAffiliationNames: mapping.ToHospitalAffiliationNamesModelSlice(item.HospitalAffiliationNames),
|
||||||
|
ProviderAffiliationNumber: item.ProviderAffiliationNumber,
|
||||||
|
ProviderAffiliationName: item.ProviderAffiliationName,
|
||||||
|
LanguagesSpoken: mapping.ToLanguagesModelSlice(item.LanguagesSpoken),
|
||||||
|
OfficeLanguagesSpoken: mapping.ToLanguagesModelSlice(item.OfficeLanguagesSpoken),
|
||||||
|
MedSchool: item.MedSchool,
|
||||||
|
MedSchoolYear: item.MedSchoolYear,
|
||||||
|
Internship: item.Internship,
|
||||||
|
Residence: item.Residence,
|
||||||
|
Specialty1: item.Specialty1,
|
||||||
|
Specialty2: item.Specialty2,
|
||||||
|
Specialty3: item.Specialty3,
|
||||||
|
Specialty4: item.Specialty4,
|
||||||
|
Certification1: item.Certification1,
|
||||||
|
Certification2: item.Certification2,
|
||||||
|
Certification3: item.Certification3,
|
||||||
|
Certification4: item.Certification4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToHospitalAffiliationNamesEntity(item npdmodel.HospitalAffiliationNames) entity.HospitalAffiliationNames {
|
||||||
|
return entity.HospitalAffiliationNames{
|
||||||
|
HospAffProvOrgName: item.HospAffProvOrgName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToHospitalAffiliationNamesModel(item entity.HospitalAffiliationNames) npdmodel.HospitalAffiliationNames {
|
||||||
|
return npdmodel.HospitalAffiliationNames{
|
||||||
|
HospAffProvOrgName: item.HospAffProvOrgName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToHospitalAffiliationNamesEntitySlice(list []npdmodel.HospitalAffiliationNames) (retVal []entity.HospitalAffiliationNames) {
|
||||||
|
retVal = make([]entity.HospitalAffiliationNames, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToHospitalAffiliationNamesEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToHospitalAffiliationNamesModelSlice(list []entity.HospitalAffiliationNames) (retVal []npdmodel.HospitalAffiliationNames) {
|
||||||
|
retVal = make([]npdmodel.HospitalAffiliationNames, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToHospitalAffiliationNamesModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToLanguagesEntity(item npdmodel.Languages) entity.Languages {
|
||||||
|
return entity.Languages{
|
||||||
|
Code: item.Code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToLanguagesModel(item entity.Languages) npdmodel.Languages {
|
||||||
|
return npdmodel.Languages{
|
||||||
|
Code: item.Code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToLanguagesEntitySlice(list []npdmodel.Languages) (retVal []entity.Languages) {
|
||||||
|
retVal = make([]entity.Languages, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToLanguagesEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToLanguagesModelSlice(list []entity.Languages) (retVal []npdmodel.Languages) {
|
||||||
|
retVal = make([]npdmodel.Languages, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToLanguagesModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderTypeCodeEntity(item npdmodel.ProviderTypeCode) entity.ProviderTypeCode {
|
||||||
|
return entity.ProviderTypeCode{
|
||||||
|
Code: item.Code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToProviderTypeCodeModel(item entity.ProviderTypeCode) npdmodel.ProviderTypeCode {
|
||||||
|
return npdmodel.ProviderTypeCode{
|
||||||
|
Code: item.Code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderTypeCodeEntitySlice(list []npdmodel.ProviderTypeCode) (retVal []entity.ProviderTypeCode) {
|
||||||
|
retVal = make([]entity.ProviderTypeCode, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderTypeCodeEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderTypeCodeModelSlice(list []entity.ProviderTypeCode) (retVal []npdmodel.ProviderTypeCode) {
|
||||||
|
retVal = make([]npdmodel.ProviderTypeCode, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderTypeCodeModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToPartKeyGroupEntity(item npdmodel.PartKeyGroup) entity.PartKeyGroup {
|
||||||
|
return entity.PartKeyGroup{
|
||||||
|
ProviderNum: item.ProviderNum,
|
||||||
|
ProviderNumSuffix: item.ProviderNumSuffix,
|
||||||
|
LocationSeqNum: item.LocationSeqNum,
|
||||||
|
PlanCode: item.PlanCode,
|
||||||
|
ProductID: item.ProductID,
|
||||||
|
TreatmentCategoryCode: item.TreatmentCategoryCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *providerMapping) ToPartKeyGroupModel(item entity.PartKeyGroup) npdmodel.PartKeyGroup {
|
||||||
|
return npdmodel.PartKeyGroup{
|
||||||
|
ProviderNum: item.ProviderNum,
|
||||||
|
ProviderNumSuffix: item.ProviderNumSuffix,
|
||||||
|
LocationSeqNum: item.LocationSeqNum,
|
||||||
|
PlanCode: item.PlanCode,
|
||||||
|
ProductID: item.ProductID,
|
||||||
|
TreatmentCategoryCode: item.TreatmentCategoryCode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToPartKeyGroupEntitySlice(list []npdmodel.PartKeyGroup) (retVal []entity.PartKeyGroup) {
|
||||||
|
retVal = make([]entity.PartKeyGroup, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToPartKeyGroupEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToPartKeyGroupModelSlice(list []entity.PartKeyGroup) (retVal []npdmodel.PartKeyGroup) {
|
||||||
|
retVal = make([]npdmodel.PartKeyGroup, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToPartKeyGroupModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderEntitySlice(list []npdmodel.ProviderResponse) (retVal []entity.ProviderResponse) {
|
||||||
|
retVal = make([]entity.ProviderResponse, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *providerMapping) ToProviderModelSlice(list []entity.ProviderResponse) (retVal []npdmodel.ProviderResponse) {
|
||||||
|
retVal = make([]npdmodel.ProviderResponse, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToProviderModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
254
application/entitymapping/ride.go
Normal file
254
application/entitymapping/ride.go
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideMapping has method to map ride entities to view models
|
||||||
|
type rideMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideModel(item entity.Ride) viewmodel.Ride {
|
||||||
|
return viewmodel.Ride{
|
||||||
|
User: mapping.mapper.User.ToUserModel(item.User),
|
||||||
|
Status: mapping.ToRideStatusModel(item.Status),
|
||||||
|
Type: mapping.ToRideTypeModel(item.Type),
|
||||||
|
UUID: item.UUID,
|
||||||
|
Note: item.Note,
|
||||||
|
Driver: mapping.ToDriverUserModel(item.Driver),
|
||||||
|
Passenger: mapping.ToPassengerUserModel(item.Passenger),
|
||||||
|
Vehicle: mapping.ToVehicleModel(item.Vehicle),
|
||||||
|
Route: mapping.ToRouteModel(item.Route),
|
||||||
|
PickupTime: item.PickupTime,
|
||||||
|
VisitDate: item.VisitDate,
|
||||||
|
VisitTime: item.VisitTime,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
Visit: mapping.mapper.Visit.ToVisitModel(item.Visit),
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
|
||||||
|
CreateAt: item.Created,
|
||||||
|
UpdateAt: item.Updated,
|
||||||
|
TripType: mapping.mapper.Visit.ToTripTypeModel(item.TripType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideInternalEntity(item viewmodel.Ride) entity.Ride {
|
||||||
|
return entity.Ride{
|
||||||
|
User: mapping.mapper.User.ToUserEntity(item.User),
|
||||||
|
UUID: item.UUID,
|
||||||
|
Note: item.Note,
|
||||||
|
PickupTime: item.PickupTime,
|
||||||
|
VisitDate: item.VisitDate,
|
||||||
|
VisitTime: item.VisitTime,
|
||||||
|
InternalID: item.InternalID,
|
||||||
|
TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRouteModel(item entity.RideRoute) viewmodel.RideRoute {
|
||||||
|
return viewmodel.RideRoute{
|
||||||
|
Origin: mapping.ToLocationModel(item.Origin),
|
||||||
|
Destination: mapping.ToLocationModel(item.Destination),
|
||||||
|
RouteKML: item.RouteKML,
|
||||||
|
ETA: item.ETA,
|
||||||
|
Distance: item.Distance,
|
||||||
|
Duration: item.Duration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToLocationModel(item entity.Location) viewmodel.Location {
|
||||||
|
return viewmodel.Location{
|
||||||
|
ID: item.ID,
|
||||||
|
Name: item.Name,
|
||||||
|
Address: item.Address,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToVehicleModel(item entity.RideVehicle) viewmodel.Vehicle {
|
||||||
|
return viewmodel.Vehicle{
|
||||||
|
Color: item.Color,
|
||||||
|
Make: item.Make,
|
||||||
|
LicensePlate: item.LicensePlate,
|
||||||
|
ImageURL: item.ImageURL,
|
||||||
|
Year: item.Year,
|
||||||
|
LicensePlateState: item.LicensePlateState,
|
||||||
|
Model: item.Model,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToDriverUserModel(item entity.RideDriver) viewmodel.UserLyft {
|
||||||
|
return viewmodel.UserLyft{
|
||||||
|
FirstName: item.Name,
|
||||||
|
ImageURL: item.ImageURL,
|
||||||
|
PhoneNumber: item.PhoneNumber,
|
||||||
|
Rating: item.Rating,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToPassengerUserModel(item entity.RidePassenger) viewmodel.UserLyft {
|
||||||
|
return viewmodel.UserLyft{
|
||||||
|
FirstName: item.FirstName,
|
||||||
|
LastName: item.LastName,
|
||||||
|
ImageURL: item.ImageURL,
|
||||||
|
PhoneNumber: item.PhoneNumber,
|
||||||
|
UserID: item.InternalID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideStatusModel(item entity.RideStatus) viewmodel.RideStatus {
|
||||||
|
return viewmodel.RideStatus{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideTypeModel(item entity.RideType) viewmodel.RideType {
|
||||||
|
return viewmodel.RideType{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToWebhookEntity(item viewmodel.WebhookResponse) entity.WebhookResponse {
|
||||||
|
occurredAt, _ := time.Parse(time.RFC3339Nano, item.OccurredAt)
|
||||||
|
|
||||||
|
return entity.WebhookResponse{
|
||||||
|
EventID: item.EventID,
|
||||||
|
HREF: item.HREF,
|
||||||
|
OccurredAt: occurredAt,
|
||||||
|
EventType: item.EventType,
|
||||||
|
Ride: mapping.ToRideEntity(item.Event),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserModel maps a User entity to User view model
|
||||||
|
func (mapping *rideMapping) ToRideEntity(item viewmodel.RideRequest) entity.Ride {
|
||||||
|
return entity.Ride{
|
||||||
|
User: entity.User{
|
||||||
|
UUID: item.UserUUID,
|
||||||
|
},
|
||||||
|
Status: mapping.ToRideStatusEntity(item),
|
||||||
|
Type: mapping.ToRideTypeEntity(item),
|
||||||
|
InternalID: item.RideID,
|
||||||
|
RequestDate: item.RequestAt,
|
||||||
|
RequestMiliseconds: item.RequestAtMS,
|
||||||
|
GenerateDate: item.GeneratedAt,
|
||||||
|
GenerateMiliseconds: item.GeneratedAtMS,
|
||||||
|
Note: item.Notes,
|
||||||
|
PrimetimePercentage: item.PrimetimePercentage,
|
||||||
|
Passenger: mapping.ToRidePassengerEntity(item),
|
||||||
|
Driver: mapping.ToRideDriverEntity(item),
|
||||||
|
Vehicle: mapping.ToRideVehicleEntity(item),
|
||||||
|
Route: mapping.ToRideRouteEntity(item),
|
||||||
|
PickupTime: item.PickupTime,
|
||||||
|
VisitDate: item.VisitDate,
|
||||||
|
VisitTime: item.VisitTime,
|
||||||
|
Visit: mapping.mapper.Visit.ToVisitEntity(item.Visit),
|
||||||
|
TripType: mapping.mapper.Visit.ToTripTypeEntity(item.TripType),
|
||||||
|
CreatedUser: entity.User{
|
||||||
|
UUID: item.CreateUserUUID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideRouteEntity(item viewmodel.RideRequest) entity.RideRoute {
|
||||||
|
return entity.RideRoute{
|
||||||
|
Origin: mapping.ToLocationEntity(item.Origin),
|
||||||
|
Destination: mapping.ToLocationEntity(item.Destination),
|
||||||
|
RouteKML: &item.RouteURL,
|
||||||
|
ETA: item.ETA,
|
||||||
|
Distance: item.Distance,
|
||||||
|
Duration: item.Duration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToLocationEntity(item viewmodel.Location) entity.Location {
|
||||||
|
return entity.Location{
|
||||||
|
ID: item.ID,
|
||||||
|
Name: item.Name,
|
||||||
|
Address: item.Address,
|
||||||
|
Latitude: item.Latitude,
|
||||||
|
Longitude: item.Longitude,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideVehicleEntity(item viewmodel.RideRequest) entity.RideVehicle {
|
||||||
|
return entity.RideVehicle{
|
||||||
|
Color: item.Vehicle.Color,
|
||||||
|
Make: item.Vehicle.Make,
|
||||||
|
LicensePlate: item.Vehicle.LicensePlate,
|
||||||
|
LicensePlateState: item.Vehicle.LicensePlateState,
|
||||||
|
ImageURL: item.Vehicle.ImageURL,
|
||||||
|
Model: item.Vehicle.Model,
|
||||||
|
Year: item.Vehicle.Year,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideDriverEntity(item viewmodel.RideRequest) entity.RideDriver {
|
||||||
|
return entity.RideDriver{
|
||||||
|
Name: item.Driver.FirstName,
|
||||||
|
ImageURL: item.Driver.ImageURL,
|
||||||
|
PhoneNumber: item.Driver.PhoneNumber,
|
||||||
|
Rating: item.Driver.Rating,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRidePassengerEntity(item viewmodel.RideRequest) entity.RidePassenger {
|
||||||
|
return entity.RidePassenger{
|
||||||
|
FirstName: item.Passenger.FirstName,
|
||||||
|
LastName: item.Passenger.LastName,
|
||||||
|
ImageURL: item.Passenger.ImageURL,
|
||||||
|
PhoneNumber: item.Passenger.PhoneNumber,
|
||||||
|
InternalID: item.Passenger.UserID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideStatusEntity(item viewmodel.RideRequest) entity.RideStatus {
|
||||||
|
return entity.RideStatus{
|
||||||
|
Key: item.Status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *rideMapping) ToRideTypeEntity(item viewmodel.RideRequest) entity.RideType {
|
||||||
|
return entity.RideType{
|
||||||
|
Key: item.RideType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *rideMapping) ToRideEntitySlice(list []viewmodel.RideRequest) (retVal []entity.Ride) {
|
||||||
|
retVal = make([]entity.Ride, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToRideEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *rideMapping) ToRideInternalEntitySlice(list []viewmodel.Ride) (retVal []entity.Ride) {
|
||||||
|
retVal = make([]entity.Ride, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToRideInternalEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
|
||||||
|
func (mapping *rideMapping) ToRideModelSlice(list []entity.Ride) (retVal []viewmodel.Ride) {
|
||||||
|
retVal = make([]viewmodel.Ride, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToRideModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
194
application/entitymapping/user.go
Normal file
194
application/entitymapping/user.go
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userMapping has method to map User entities to view models
|
||||||
|
type userMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserModel maps a User entity to User view model
|
||||||
|
func (mapping *userMapping) ToUserModel(item entity.User) viewmodel.User {
|
||||||
|
var birthDate *time.Time
|
||||||
|
if !item.BirthDate.IsZero() {
|
||||||
|
birthDate = &item.BirthDate
|
||||||
|
}
|
||||||
|
|
||||||
|
first := ""
|
||||||
|
last := ""
|
||||||
|
fullName := strings.Split(item.Name, " ")
|
||||||
|
if len(fullName) > 0 {
|
||||||
|
first = fullName[0]
|
||||||
|
if len(fullName) > 1 {
|
||||||
|
last = fullName[len(fullName)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewmodel.User{
|
||||||
|
ID: item.UUID,
|
||||||
|
Name: item.Name,
|
||||||
|
First: first,
|
||||||
|
Last: last,
|
||||||
|
Email: &item.Email,
|
||||||
|
PhoneNumber: &item.PhoneNumber,
|
||||||
|
Gender: &item.Gender,
|
||||||
|
Member: &item.Member,
|
||||||
|
BirthDate: birthDate,
|
||||||
|
Active: item.Active,
|
||||||
|
Created: item.Created,
|
||||||
|
Updated: item.Updated,
|
||||||
|
Contacts: mapping.ToContactModelSlice(item.Contacts),
|
||||||
|
Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
|
||||||
|
Addresses: mapping.mapper.Address.ToAddressModelSlice(item.Addresses),
|
||||||
|
Profiles: mapping.mapper.Profile.ToProfileModelSlice(item.Profiles),
|
||||||
|
Organizations: mapping.mapper.Organization.ToOrganizationModelSlice(item.Organizations),
|
||||||
|
Types: mapping.mapper.Organization.ToOrganizationTypeModelSlice(item.Types),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserModelSlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *userMapping) ToUserModelSlice(list []entity.User) (retVal []viewmodel.User) {
|
||||||
|
retVal = make([]viewmodel.User, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToUserModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserModel maps a User entity to User view model
|
||||||
|
func (mapping *userMapping) ToUserEntity(item viewmodel.User) entity.User {
|
||||||
|
user := entity.User{
|
||||||
|
UUID: item.ID,
|
||||||
|
Name: item.Name,
|
||||||
|
Pass: item.Pass,
|
||||||
|
Active: item.Active,
|
||||||
|
Created: item.Created,
|
||||||
|
Updated: item.Updated,
|
||||||
|
Contacts: mapping.ToContactEntitySlice(item.Contacts),
|
||||||
|
Profiles: mapping.mapper.Profile.ToProfileEntitySlice(item.Profiles),
|
||||||
|
Organizations: mapping.mapper.Organization.ToOrganizationEntitySlice(item.Organizations),
|
||||||
|
Types: mapping.mapper.Organization.ToOrganizationTypeEntitySlice(item.Types),
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Name == "" {
|
||||||
|
user.Name = fmt.Sprintf("%s %s", item.First, item.Last)
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Email != nil {
|
||||||
|
user.Email = *item.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.PhoneNumber != nil {
|
||||||
|
user.PhoneNumber = *item.PhoneNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Gender != nil {
|
||||||
|
user.Gender = *item.Gender
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Member != nil {
|
||||||
|
user.Member = *item.Member
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.BirthDate != nil {
|
||||||
|
user.BirthDate = *item.BirthDate
|
||||||
|
}
|
||||||
|
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *userMapping) ToUserEntitySlice(list []viewmodel.User) (retVal []entity.User) {
|
||||||
|
retVal = make([]entity.User, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToUserEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactTypeEntity maps a Contact type entity to Contact Type view model
|
||||||
|
func (mapping *userMapping) ToContactTypeEntity(item viewmodel.ContactType) entity.ContactType {
|
||||||
|
return entity.ContactType{
|
||||||
|
Key: item.Key,
|
||||||
|
Value: item.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactTypeEntitySlice maps a User entity slice to Contact Type view model slice
|
||||||
|
func (mapping *userMapping) ToContactTypeEntitySlice(list []viewmodel.ContactType) (retVal []entity.ContactType) {
|
||||||
|
retVal = make([]entity.ContactType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToContactTypeEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactTypeModel maps a Contact type entity to Contact Type view model
|
||||||
|
func (mapping *userMapping) ToContactTypeModel(item entity.ContactType) viewmodel.ContactType {
|
||||||
|
return viewmodel.ContactType{
|
||||||
|
Key: item.Key,
|
||||||
|
Value: item.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactTypeModelSlice maps a User entity slice to Contact Type view model slice
|
||||||
|
func (mapping *userMapping) ToContactTypeModelSlice(list []entity.ContactType) (retVal []viewmodel.ContactType) {
|
||||||
|
retVal = make([]viewmodel.ContactType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToContactTypeModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactModel maps a Contact entity to Contact view model
|
||||||
|
func (mapping *userMapping) ToContactModel(item entity.ContactInfo) viewmodel.Contact {
|
||||||
|
return viewmodel.Contact{
|
||||||
|
Type: mapping.ToContactTypeModel(item.Type),
|
||||||
|
Value: item.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactModelSlice maps a Contact entity slice to Contact view model slice
|
||||||
|
func (mapping *userMapping) ToContactModelSlice(list []entity.ContactInfo) (retVal []viewmodel.Contact) {
|
||||||
|
retVal = make([]viewmodel.Contact, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToContactModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactEntity maps a Contact entity to Contact view model
|
||||||
|
func (mapping *userMapping) ToContactEntity(item viewmodel.Contact) entity.ContactInfo {
|
||||||
|
return entity.ContactInfo{
|
||||||
|
Type: mapping.ToContactTypeEntity(item.Type),
|
||||||
|
Value: item.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToContactEntitySlice maps a Contact entity slice to Contact view model slice
|
||||||
|
func (mapping *userMapping) ToContactEntitySlice(list []viewmodel.Contact) (retVal []entity.ContactInfo) {
|
||||||
|
retVal = make([]entity.ContactInfo, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToContactEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
131
application/entitymapping/visit.go
Normal file
131
application/entitymapping/visit.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package entitymapping
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideMapping has method to map ride entities to view models
|
||||||
|
type visitMapping struct {
|
||||||
|
mapper *Mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVisitEntity maps a User entity to User view model
|
||||||
|
func (mapping *visitMapping) ToVisitEntity(item viewmodel.Visit) entity.Visit {
|
||||||
|
return entity.Visit{
|
||||||
|
UUID: item.UUID,
|
||||||
|
Status: mapping.ToVisitStatusEntity(item.Status),
|
||||||
|
User: mapping.mapper.User.ToUserEntity(item.User),
|
||||||
|
VisitDuration: item.VisitDuration,
|
||||||
|
VisitDatetime: item.VisitDatetime,
|
||||||
|
PickupDatetime: item.PickupDatetime,
|
||||||
|
Notes: item.Notes,
|
||||||
|
PickupAddressID: item.PickupAddressID,
|
||||||
|
DestinationAddressID: item.DestinationAddressID,
|
||||||
|
Pickup: mapping.mapper.Ride.ToLocationEntity(item.Pickup),
|
||||||
|
Provider: mapping.mapper.Provider.ToProviderRespEntity(item.Provider),
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserEntity(item.CreatedUser),
|
||||||
|
Created: item.CreatedDate,
|
||||||
|
Updated: item.UpdatedDate,
|
||||||
|
ReturnDate: item.ReturnDate,
|
||||||
|
ExternalID: item.ExternalID,
|
||||||
|
TripType: mapping.ToTripTypeEntity(item.TripType),
|
||||||
|
Rides: mapping.mapper.Ride.ToRideInternalEntitySlice(item.Rides),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *visitMapping) ToVisitStatusEntity(item viewmodel.VisitStatus) entity.VisitStatus {
|
||||||
|
return entity.VisitStatus{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToVisitEntity maps a User entity to User view model
|
||||||
|
func (mapping *visitMapping) ToVisitModel(item entity.Visit) viewmodel.Visit {
|
||||||
|
return viewmodel.Visit{
|
||||||
|
UUID: item.UUID,
|
||||||
|
Status: mapping.ToVisitStatusModel(item.Status),
|
||||||
|
User: mapping.mapper.User.ToUserModel(item.User),
|
||||||
|
VisitDuration: item.VisitDuration,
|
||||||
|
VisitDatetime: item.VisitDatetime,
|
||||||
|
PickupDatetime: item.PickupDatetime,
|
||||||
|
Notes: item.Notes,
|
||||||
|
PickupAddressID: item.PickupAddressID,
|
||||||
|
DestinationAddressID: item.DestinationAddressID,
|
||||||
|
Pickup: mapping.mapper.Ride.ToLocationModel(item.Pickup),
|
||||||
|
Provider: mapping.mapper.Provider.ToProviderRespModel(item.Provider),
|
||||||
|
CreatedUser: mapping.mapper.User.ToUserModel(item.CreatedUser),
|
||||||
|
CreatedDate: item.Created,
|
||||||
|
UpdatedDate: item.Updated,
|
||||||
|
ReturnDate: item.ReturnDate,
|
||||||
|
ExternalID: item.ExternalID,
|
||||||
|
TripType: mapping.ToTripTypeModel(item.TripType),
|
||||||
|
Rides: mapping.mapper.Ride.ToRideModelSlice(item.Rides),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *visitMapping) ToVisitStatusModel(item entity.VisitStatus) viewmodel.VisitStatus {
|
||||||
|
return viewmodel.VisitStatus{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *visitMapping) ToVisitEntitySlice(list []viewmodel.Visit) (retVal []entity.Visit) {
|
||||||
|
retVal = make([]entity.Visit, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToVisitEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
|
||||||
|
func (mapping *visitMapping) ToVisitModelSlice(list []entity.Visit) (retVal []viewmodel.Visit) {
|
||||||
|
retVal = make([]viewmodel.Visit, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToVisitModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *visitMapping) ToTripTypeModel(item entity.TripType) viewmodel.TripType {
|
||||||
|
return viewmodel.TripType{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mapping *visitMapping) ToTripTypeEntity(item viewmodel.TripType) entity.TripType {
|
||||||
|
return entity.TripType{
|
||||||
|
Value: item.Value,
|
||||||
|
Key: item.Key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUserEntitySlice maps a User entity slice to User view model slice
|
||||||
|
func (mapping *visitMapping) ToTripTypeEntitySlice(list []viewmodel.TripType) (retVal []entity.TripType) {
|
||||||
|
retVal = make([]entity.TripType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToTripTypeEntity(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToRideModelSlice maps a Ride entity slice to Ride view model slice
|
||||||
|
func (mapping *visitMapping) ToTripTypeModelSlice(list []entity.TripType) (retVal []viewmodel.TripType) {
|
||||||
|
retVal = make([]viewmodel.TripType, 0)
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
retVal = append(retVal, mapping.ToTripTypeModel(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
}
|
||||||
31
application/notificationservice/notificationservice.go
Normal file
31
application/notificationservice/notificationservice.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package notificationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Service
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service holds the domain service repositories
|
||||||
|
type Service struct {
|
||||||
|
Twilio *twilioService
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new domain Service instance
|
||||||
|
func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *Service {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Service{
|
||||||
|
Twilio: newTwilioService(svc, mapper, cfg, cache),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
259
application/notificationservice/twilio.go
Normal file
259
application/notificationservice/twilio.go
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
package notificationservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
twilioMessageURL = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json"
|
||||||
|
twilioNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/AvailablePhoneNumbers/US/Local.json"
|
||||||
|
twiliActualNumbersURL = "https://api.twilio.com/2010-04-01/Accounts/%s/IncomingPhoneNumbers.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// twilioService holds methods to twillio application service
|
||||||
|
type twilioService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
cfg *config.Config
|
||||||
|
urlMessage string
|
||||||
|
urlNumber string
|
||||||
|
urlActualNumber string
|
||||||
|
cache contract.CacheManager
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTwilioService returns a twilioService instance
|
||||||
|
func newTwilioService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, cache contract.CacheManager) *twilioService {
|
||||||
|
return &twilioService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
cfg: cfg,
|
||||||
|
urlMessage: fmt.Sprintf(twilioMessageURL, cfg.Twilio.Account),
|
||||||
|
urlNumber: fmt.Sprintf(twilioNumbersURL, cfg.Twilio.Account),
|
||||||
|
urlActualNumber: fmt.Sprintf(twiliActualNumbersURL, cfg.Twilio.Account),
|
||||||
|
cache: cache,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) GetProxyNumber(to string) (viewmodel.ProxyNumber, error) {
|
||||||
|
key := "proxy" + to
|
||||||
|
var number viewmodel.ProxyNumber
|
||||||
|
err := s.cache.GetStruct(key, &number)
|
||||||
|
if err != nil || err == domain.ErrCacheMiss {
|
||||||
|
return number, err
|
||||||
|
} else {
|
||||||
|
return number, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) GetAvaliableNumbers(to string) (viewmodel.ListNumbers, error) {
|
||||||
|
if to != "" {
|
||||||
|
if strings.Contains(to, "+1") {
|
||||||
|
to = strings.Replace(to, "+1", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
area := to[0:3]
|
||||||
|
|
||||||
|
msgData := url.Values{}
|
||||||
|
msgData.Set("PhoneNumber", area)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("GET", s.urlActualNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
|
||||||
|
|
||||||
|
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Twilio: ", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||||
|
var data viewmodel.ListNumbers
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
err := decoder.Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.ListNumbers{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
} else {
|
||||||
|
return viewmodel.ListNumbers{}, errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return viewmodel.ListNumbers{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) GetAvaliableNewNumbers(to string) (viewmodel.ListNumbers, error) {
|
||||||
|
if to != "" {
|
||||||
|
if strings.Contains(to, "+1") {
|
||||||
|
to = strings.Replace(to, "+1", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
area := to[0:3]
|
||||||
|
|
||||||
|
msgData := url.Values{}
|
||||||
|
msgData.Set("AreaCode", area)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("GET", s.urlNumber+"?"+msgData.Encode(), bytes.NewBuffer([]byte{}))
|
||||||
|
|
||||||
|
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Twilio: ", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||||
|
var data viewmodel.ListNumbers
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
err := decoder.Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.ListNumbers{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
} else {
|
||||||
|
return viewmodel.ListNumbers{}, errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return viewmodel.ListNumbers{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) SaveNewNumber(number viewmodel.Number) (viewmodel.Number, error) {
|
||||||
|
phoneNumber := number.PhoneNumber
|
||||||
|
if strings.Contains(phoneNumber, "+1") {
|
||||||
|
phoneNumber = strings.Replace(phoneNumber, "+1", "", -1)
|
||||||
|
}
|
||||||
|
area := phoneNumber[0:3]
|
||||||
|
|
||||||
|
msgData := url.Values{}
|
||||||
|
msgData.Set("PhoneNumber", number.PhoneNumber)
|
||||||
|
msgData.Set("AreaCode", area)
|
||||||
|
msgData.Set("FriendlyName", number.FriendlyName)
|
||||||
|
msgData.Set("SmsApplicationSid", s.cfg.Twilio.TwiMLSID)
|
||||||
|
msgDataReader := *strings.NewReader(msgData.Encode())
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("POST", s.urlActualNumber, &msgDataReader)
|
||||||
|
req.Header.Add("Accept", "application/json")
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Twilio: ", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
err := decoder.Decode(&number)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Number{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return number, nil
|
||||||
|
} else {
|
||||||
|
return viewmodel.Number{}, errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) GetValidNumber(from string, to string) (viewmodel.Number, error) {
|
||||||
|
list, err := s.GetAvaliableNumbers(to)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Number{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list.IncomingPhones) > 0 {
|
||||||
|
return list.IncomingPhones[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err = s.GetAvaliableNewNumbers(to)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.Number{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list.AvailableNumbers) > 0 {
|
||||||
|
number, err := s.SaveNewNumber(list.AvailableNumbers[0])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error on GetValidNumber: ", err.Error())
|
||||||
|
return viewmodel.Number{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return number, nil
|
||||||
|
} else {
|
||||||
|
return viewmodel.Number{}, errors.New("No new number available")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) GetNumber(from string, to string) (string, error) {
|
||||||
|
number, err := s.GetValidNumber(from, to)
|
||||||
|
if err != nil {
|
||||||
|
return from, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return number.PhoneNumber, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s twilioService) SendSMS(from string, to string, message string) error {
|
||||||
|
if from == "" {
|
||||||
|
return errors.New("TwilioService.SendSMS: from parameter is mandatory")
|
||||||
|
}
|
||||||
|
if to == "" {
|
||||||
|
return errors.New("TwilioService.SendSMS: to parameter is mandatory")
|
||||||
|
}
|
||||||
|
if message == "" {
|
||||||
|
return errors.New("TwilioService.SendSMS: message parameter is mandatory")
|
||||||
|
}
|
||||||
|
|
||||||
|
senderNumber, err := s.GetNumber(from, to)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msgData := url.Values{}
|
||||||
|
msgData.Set("To", to)
|
||||||
|
msgData.Set("From", senderNumber)
|
||||||
|
msgData.Set("Body", message)
|
||||||
|
|
||||||
|
msgDataReader := *strings.NewReader(msgData.Encode())
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("POST", s.urlMessage, &msgDataReader)
|
||||||
|
|
||||||
|
req.SetBasicAuth(s.cfg.Twilio.Account, s.cfg.Twilio.Token)
|
||||||
|
req.Header.Add("Accept", "application/json")
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Twilio: ", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||||
|
var data map[string]interface{}
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
err := decoder.Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Error on Twilio Response: ", resp.Status)
|
||||||
|
return errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
28
application/third/eligibility/bcbsi/bcbsi.go
Normal file
28
application/third/eligibility/bcbsi/bcbsi.go
Normal 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
|
||||||
|
}
|
||||||
150
application/third/eligibility/bcbsi/bcbsimodel/eligibility.go
Normal file
150
application/third/eligibility/bcbsi/bcbsimodel/eligibility.go
Normal 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"`
|
||||||
|
}
|
||||||
44
application/third/eligibility/bcbsi/bcbsimodel/response.go
Normal file
44
application/third/eligibility/bcbsi/bcbsimodel/response.go
Normal 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"`
|
||||||
|
}
|
||||||
126
application/third/eligibility/bcbsi/bxe.go
Normal file
126
application/third/eligibility/bcbsi/bxe.go
Normal 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
|
||||||
|
}
|
||||||
28
application/third/npd/npd.go
Normal file
28
application/third/npd/npd.go
Normal 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
|
||||||
|
}
|
||||||
124
application/third/npd/npdmodel/provider.go
Normal file
124
application/third/npd/npdmodel/provider.go
Normal 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
|
||||||
|
}
|
||||||
56
application/third/npd/provider.go
Normal file
56
application/third/npd/provider.go
Normal 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
|
||||||
|
}
|
||||||
305
application/tncservice/lyft.go
Normal file
305
application/tncservice/lyft.go
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
package tncservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"github.com/lyft/lyft-go-sdk/lyft"
|
||||||
|
"github.com/pquerna/ffjson/ffjson"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"golang.org/x/oauth2/clientcredentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
lyftURL = "https://api.lyft.com/v1/"
|
||||||
|
)
|
||||||
|
|
||||||
|
// lyftService holds methods to lyft application service
|
||||||
|
type lyftService struct {
|
||||||
|
svc *service.Service
|
||||||
|
mapEntity *entitymapping.Mapper
|
||||||
|
client *lyft.APIClient
|
||||||
|
httpClient *http.Client
|
||||||
|
cfg *config.Config
|
||||||
|
notification *notificationservice.Service
|
||||||
|
lyftConfig clientcredentials.Config
|
||||||
|
refreshToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newLyftProdService returns a lyftService instance with production info
|
||||||
|
func newLyftProdService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
|
||||||
|
config := clientcredentials.Config{
|
||||||
|
ClientID: cfg.LyftProd.Lyft.Client,
|
||||||
|
ClientSecret: cfg.LyftProd.Lyft.Secret,
|
||||||
|
TokenURL: "https://api.lyft.com/oauth/token",
|
||||||
|
Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
|
||||||
|
}
|
||||||
|
httpClient := config.Client(context.Background())
|
||||||
|
|
||||||
|
return &lyftService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
client: lyft.NewAPIClient(httpClient, "nemt"),
|
||||||
|
httpClient: httpClient,
|
||||||
|
cfg: cfg,
|
||||||
|
notification: notificationService,
|
||||||
|
lyftConfig: config,
|
||||||
|
refreshToken: cfg.LyftProd.Lyft.RefreshToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newLyftService returns a lyftService instance
|
||||||
|
func newLyftService(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *lyftService {
|
||||||
|
config := clientcredentials.Config{
|
||||||
|
ClientID: cfg.Lyft.Client,
|
||||||
|
ClientSecret: cfg.Lyft.Secret,
|
||||||
|
TokenURL: "https://api.lyft.com/oauth/token",
|
||||||
|
Scopes: []string{"public", "privileged.rides.dispatch", "rides.read", "rides.request", "profile", "offline"},
|
||||||
|
}
|
||||||
|
httpClient := config.Client(context.Background())
|
||||||
|
|
||||||
|
return &lyftService{
|
||||||
|
svc: svc,
|
||||||
|
mapEntity: mapper,
|
||||||
|
client: lyft.NewAPIClient(httpClient, "nemt"),
|
||||||
|
httpClient: httpClient,
|
||||||
|
cfg: cfg,
|
||||||
|
notification: notificationService,
|
||||||
|
lyftConfig: config,
|
||||||
|
refreshToken: cfg.Lyft.RefreshToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) getToken() string {
|
||||||
|
token, err := s.lyftConfig.Token(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to get token: ", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Bearer " + token.AccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) setTokenHeader(req *http.Request) string {
|
||||||
|
type Token struct {
|
||||||
|
GrantType string `json:"grant_type"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
token := Token{
|
||||||
|
GrantType: "refresh_token",
|
||||||
|
RefreshToken: s.refreshToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
bObject, err := ffjson.Marshal(token)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenReq, err := http.NewRequest("POST", s.lyftConfig.TokenURL, bytes.NewBuffer(bObject))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
tokenReq.Header.Set("Content-Type", "application/json")
|
||||||
|
tokenReq.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", s.lyftConfig.ClientID, s.lyftConfig.ClientSecret))))
|
||||||
|
tokenReq.Header.Add("cache-control", "no-cache")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(tokenReq)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to refresh token: ", err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
var returnToken oauth2.Token
|
||||||
|
err = ffjson.Unmarshal(body, &returnToken)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to parse token: ", err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
returnToken.SetAuthHeader(req)
|
||||||
|
|
||||||
|
return "Bearer " + returnToken.AccessToken
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetRideDetails(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
|
||||||
|
url := lyftURL + "dispatches/" + rideRequest.RideID
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
s.setTokenHeader(req)
|
||||||
|
req.Header.Add("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
var raw viewmodel.RideRequest
|
||||||
|
err = ffjson.Unmarshal(body, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetRideStatus(rideRequest viewmodel.RideRequest, param string) (viewmodel.RideRequest, error) {
|
||||||
|
params := make(map[string]string)
|
||||||
|
params["status"] = param
|
||||||
|
|
||||||
|
bObject, err := ffjson.Marshal(params)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("STATUS CHANGE REQUEST ON LYFT")
|
||||||
|
fmt.Println("Ride ID: ", rideRequest.RideID)
|
||||||
|
fmt.Println("Status: ", param)
|
||||||
|
url := lyftURL + "sandbox/dispatches/" + rideRequest.RideID
|
||||||
|
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(bObject))
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
req.Header.Add("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := s.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
fmt.Println("STATUS CHANGE RESPONSE ON LYFT")
|
||||||
|
fmt.Println(string(body))
|
||||||
|
|
||||||
|
var raw viewmodel.RideRequest
|
||||||
|
err = ffjson.Unmarshal(body, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rideRequest.Status = raw.Status
|
||||||
|
return s.GetRideDetails(rideRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) CancelRide(rideRequest viewmodel.RideRequest) error {
|
||||||
|
finalURL := lyftURL + "dispatches/" + rideRequest.RideID + "/cancel"
|
||||||
|
req, err := http.NewRequest("POST", finalURL, bytes.NewBuffer([]byte{}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.setTokenHeader(req)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode == 204 || resp.StatusCode == 404 {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
fmt.Println("Response Body: ", string(body))
|
||||||
|
|
||||||
|
raw := map[string]interface{}{}
|
||||||
|
err = ffjson.Unmarshal(body, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return errors.New(raw["error_description"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) RequestRide(rideRequest viewmodel.RideRequest) (viewmodel.RideRequest, error) {
|
||||||
|
bObject, err := ffjson.Marshal(rideRequest)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", lyftURL+"dispatches", bytes.NewBuffer(bObject))
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
s.setTokenHeader(req)
|
||||||
|
req.Header.Add("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
var raw viewmodel.RideRequest
|
||||||
|
err = ffjson.Unmarshal(body, &raw)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.RideRequest{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw.Error != "" {
|
||||||
|
fmt.Println("Error to call Lyft: ", raw.Error+" - "+raw.ErrorDescription)
|
||||||
|
return viewmodel.RideRequest{}, errors.New("Lyft Error: " + raw.Error + " - " + raw.ErrorDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetRideDetails(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
|
||||||
|
resp, _, err := s.client.PublicApi.GetETA(lag, log, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetCost(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
|
||||||
|
resp, _, err := s.client.PublicApi.GetCost(lag, log, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetDrivers(lag float64, log float64) (interface{}, error) {
|
||||||
|
resp, _, err := s.client.PublicApi.GetDrivers(lag, log)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *lyftService) GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
|
||||||
|
resp, _, err := s.client.PublicApi.GetRideTypes(lag, log, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
33
application/tncservice/tncservice.go
Normal file
33
application/tncservice/tncservice.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package tncservice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/service"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Service
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service holds the domain service repositories
|
||||||
|
type Service struct {
|
||||||
|
Lyft *lyftService
|
||||||
|
LyftProd *lyftService
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new domain Service instance
|
||||||
|
func New(svc *service.Service, mapper *entitymapping.Mapper, cfg *config.Config, notificationService *notificationservice.Service) *Service {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Service{
|
||||||
|
Lyft: newLyftService(svc, mapper, cfg, notificationService),
|
||||||
|
LyftProd: newLyftProdService(svc, mapper, cfg, notificationService),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
15
application/viewmodel/address.go
Normal file
15
application/viewmodel/address.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
UUID string `json:"address_uuid,omitempty"`
|
||||||
|
InternalID string `json:"id,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Address string `json:"address,omitempty"`
|
||||||
|
AddressType string `json:"address_type,omitempty"`
|
||||||
|
AddressTypeName string `json:"address_type_name,omitempty"`
|
||||||
|
Latitude float64 `json:"lat,omitempty"`
|
||||||
|
Longitude float64 `json:"lng,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
User User `json:"user,omitempty"`
|
||||||
|
CreatedUserUUID string `json:"-"`
|
||||||
|
}
|
||||||
9
application/viewmodel/auth.go
Normal file
9
application/viewmodel/auth.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
// AuthResponse has data from authentication routes
|
||||||
|
type AuthResponse struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
ValidTime int64 `json:"valid_time"`
|
||||||
|
ServerTime int64 `json:"server_time"`
|
||||||
|
User User `json:"user"`
|
||||||
|
}
|
||||||
55
application/viewmodel/bxe.go
Normal file
55
application/viewmodel/bxe.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Eligibility struct {
|
||||||
|
TrackingID string `json:"tracking_id,omitempty"`
|
||||||
|
Payer Payer `json:"payer,omitempty"`
|
||||||
|
Provider Provider `json:"provider,omitempty"`
|
||||||
|
Subscriber Subscriber `json:"subscriber,omitempty"`
|
||||||
|
ServiceInfo ServiceInfo `json:"service_info,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Payer struct {
|
||||||
|
PayerID string `json:"payer_id,omitempty"`
|
||||||
|
PayerName string `json:"payer_name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Provider struct {
|
||||||
|
ProviderID string `json:"provider_id,omitempty"`
|
||||||
|
ProviderNPI string `json:"provider_npi,omitempty"`
|
||||||
|
ProviderName string `json:"provider_name,omitempty"`
|
||||||
|
Name Name `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Name struct {
|
||||||
|
First string `json:"first,omitempty"`
|
||||||
|
Last string `json:"last,omitempty"`
|
||||||
|
Middle string `json:"middle,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subscriber struct {
|
||||||
|
PatientType string `json:"patient_type,omitempty"`
|
||||||
|
SubscriberID string `json:"subscriber_id,omitempty"`
|
||||||
|
Name Name `json:"name,omitempty"`
|
||||||
|
DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
|
||||||
|
Dependents []Dependent `json:"dependents,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DemographicInfo struct {
|
||||||
|
DateOfBirth time.Time `json:"date_of_birth,omitempty"`
|
||||||
|
Gender string `json:"gender,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dependent struct {
|
||||||
|
PatientAccountNumber string `json:"patient_account_number,omitempty"`
|
||||||
|
Name Name `json:"name,omitempty"`
|
||||||
|
DemographicInfo DemographicInfo `json:"demographic_info,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceInfo struct {
|
||||||
|
DateOfService time.Time `json:"date_of_service,omitempty"`
|
||||||
|
ServiceTypeCodes []string `json:"service_type_codes,omitempty"`
|
||||||
|
}
|
||||||
34
application/viewmodel/notification.go
Normal file
34
application/viewmodel/notification.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Notification struct {
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
To string `json:"to"`
|
||||||
|
From string `json:"from"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Subject string `json:"subject"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Ride Ride `json:"ride"`
|
||||||
|
User User `json:"user"`
|
||||||
|
CreatedUser User `json:"created_user"`
|
||||||
|
Created time.Time `json:"create_at"`
|
||||||
|
MessageType string `json:"message_type"`
|
||||||
|
Read bool `json:"read"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
DeliveryID string `json:"id"`
|
||||||
|
NotificationID string `json:"nid"`
|
||||||
|
CreateDate time.Time `json:"date"`
|
||||||
|
Read bool `json:"readed"`
|
||||||
|
Content MessageContent `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageContent struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Subject string `json:"subject"`
|
||||||
|
Content string `json:"body,omitempty"`
|
||||||
|
Payload interface{} `json:"payload,omitempty"`
|
||||||
|
RedirectLink string `json:"redirect,omitempty"`
|
||||||
|
}
|
||||||
69
application/viewmodel/organization.go
Normal file
69
application/viewmodel/organization.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrganizationType struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Description string `json:"desc,omitempty"`
|
||||||
|
Created time.Time `json:"-"`
|
||||||
|
Updated time.Time `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Organization struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Type OrganizationType `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"desc,omitempty"`
|
||||||
|
ReferenceID int64 `json:"-"`
|
||||||
|
ParentID int64 `json:"-"`
|
||||||
|
Main bool `json:"main"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
Suspended bool `json:"suspended"`
|
||||||
|
Author User `json:"author"`
|
||||||
|
LastEditor User `json:"last_editor"`
|
||||||
|
Contacts []OrganizationContact `json:"contacts"`
|
||||||
|
Addresses []OrganizationAddress `json:"addresses"`
|
||||||
|
ChildOrgs []Organization `json:"childs,omitempty"`
|
||||||
|
Parent *Organization `json:"parent,omitempty"`
|
||||||
|
Reference interface{} `json:"reference,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrganizationContact struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Organization *Organization `json:"organization,omitempty"`
|
||||||
|
Type ContactType `json:"type"`
|
||||||
|
Contact string `json:"contact"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
CreatedUser User `json:"author"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
UpdatedUser User `json:"last_editor"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrganizationAddress struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Organization *Organization `json:"organization,omitempty"`
|
||||||
|
InternalID string `json:"internal_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Latitude float64 `json:"lat"`
|
||||||
|
Longitude float64 `json:"long"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
CreatedUser User `json:"author"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
UpdatedUser User `json:"last_editor"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
15
application/viewmodel/pagination.go
Normal file
15
application/viewmodel/pagination.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
// ReturnPagination holds the pagination data result
|
||||||
|
type ReturnPagination struct {
|
||||||
|
TotalRecords int64 `json:"total_records"`
|
||||||
|
RecordsPerPage int64 `json:"records_per_page"`
|
||||||
|
TotalPages int64 `json:"total_pages"`
|
||||||
|
CurrentPage int64 `json:"current_page"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaginatedResult is the standard paginated list result
|
||||||
|
type PaginatedResult struct {
|
||||||
|
Pagination ReturnPagination `json:"pagination,omitempty"`
|
||||||
|
List interface{} `json:"data,omitempty"`
|
||||||
|
}
|
||||||
17
application/viewmodel/profile.go
Normal file
17
application/viewmodel/profile.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Profile struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
Suspended bool `json:"suspended"`
|
||||||
|
Visible bool `json:"visible"`
|
||||||
|
Organization Organization `json:"organization"`
|
||||||
|
}
|
||||||
119
application/viewmodel/provider.go
Normal file
119
application/viewmodel/provider.go
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
type ProviderResp struct {
|
||||||
|
ProviderUUID string `json:"provider_uuid,omitempty"`
|
||||||
|
InternalID string `json:"internal_id,omitempty"`
|
||||||
|
InternalSuffixID string `json:"internal_suffix_id,omitempty"`
|
||||||
|
MukID string `json:"muk_id,omitempty"`
|
||||||
|
OrganizatioName string `json:"org_name,omitempty"`
|
||||||
|
Gender string `json:"gender,omitempty"`
|
||||||
|
AcceptNewPatients string `json:"accept_new_patients,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
FirstName string `json:"first,omitempty"`
|
||||||
|
MiddleName string `json:"middle,omitempty"`
|
||||||
|
LastName string `json:"last,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
Keys []ProviderKey `json:"keys,omitempty"`
|
||||||
|
Address ProviderAddress `json:"address,omitempty"`
|
||||||
|
Distance float64 `json:"distance,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderKey struct {
|
||||||
|
InternalID string `json:"internal_id"`
|
||||||
|
InternalSuffixID string `json:"internal_suffix_id"`
|
||||||
|
LocationSeqNumber string `json:"location_seq_number"`
|
||||||
|
PlanCode string `json:"plan_code"`
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
TreatmentCategoryCode string `json:"treatment_category_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderAddress struct {
|
||||||
|
StreetAddress1 string `json:"street_address_1,omitempty"`
|
||||||
|
StreetAddress2 string `json:"street_address_2,omitempty"`
|
||||||
|
CityName string `json:"city,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
ZipCode string `json:"zipcode,omitempty"`
|
||||||
|
Country string `json:"country,omitempty"`
|
||||||
|
Latitude float64 `json:"lat,omitempty"`
|
||||||
|
Longitude float64 `json:"long,omitempty"`
|
||||||
|
PhoneNumber string `json:"phone_number,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderSearchParams entity data
|
||||||
|
type ProviderSearchParams struct {
|
||||||
|
Name string
|
||||||
|
SearchBy string
|
||||||
|
Latitude float64
|
||||||
|
Longitude float64
|
||||||
|
Distance int64
|
||||||
|
Limit int64
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
161
application/viewmodel/tnc.go
Normal file
161
application/viewmodel/tnc.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
//WebhookResponse has the data and events from the webhook
|
||||||
|
type WebhookResponse struct {
|
||||||
|
EventID string `json:"event_id,omitempty"`
|
||||||
|
HREF string `json:"href,omitempty"`
|
||||||
|
OccurredAt string `json:"occurred_at,omitempty"`
|
||||||
|
EventType string `json:"event_type,omitempty"`
|
||||||
|
Event RideRequest `json:"event,omitempty"`
|
||||||
|
Ride Ride `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//RideRequest has the data to dispatch a ride
|
||||||
|
type RideRequest struct {
|
||||||
|
UserUUID string `json:"user_uuid,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
RideID string `json:"ride_id,omitempty"`
|
||||||
|
RideType string `json:"ride_type,omitempty"`
|
||||||
|
Origin Location `json:"origin,omitempty"`
|
||||||
|
Location Location `json:"location,omitempty"`
|
||||||
|
Destination Location `json:"destination,omitempty"`
|
||||||
|
Passenger UserLyft `json:"passenger,omitempty"`
|
||||||
|
Notes string `json:"external_note,omitempty"`
|
||||||
|
RouteURL string `json:"route_url,omitempty"`
|
||||||
|
ScheduledPickupRange interface{} `json:"scheduled_pickup_range,omitempty"`
|
||||||
|
PrimetimePercentage string `json:"primetime_percentage,omitempty"`
|
||||||
|
Pickup Location `json:"pickup,omitempty"`
|
||||||
|
DropOff Location `json:"dropoff,omitempty"`
|
||||||
|
Vehicle Vehicle `json:"vehicle,omitempty"`
|
||||||
|
Price Price `json:"price,omitempty"`
|
||||||
|
Driver UserLyft `json:"driver,omitempty"`
|
||||||
|
GeneratedAtMS *int64 `json:"generated_at_ms,omitempty"`
|
||||||
|
GeneratedAt *time.Time `json:"generated_at,omitempty"`
|
||||||
|
RequestAtMS *int64 `json:"requested_at_ms,omitempty"`
|
||||||
|
RequestAt *time.Time `json:"requested_at,omitempty"`
|
||||||
|
LineItems []Price `json:"line_items,omitempty"`
|
||||||
|
BeaconColor string `json:"beacon_color,omitempty"`
|
||||||
|
Charges []Charge `json:"charges,omitempty"`
|
||||||
|
VisitDate *time.Time `json:"visit_date,omitempty"`
|
||||||
|
VisitTime *time.Time `json:"visit_time,omitempty"`
|
||||||
|
PickupTime *time.Time `json:"pickup_time,omitempty"`
|
||||||
|
ReturnTime *time.Time `json:"return_time,omitempty"`
|
||||||
|
Distance float64 `json:"distance,omitempty"`
|
||||||
|
ETA int64 `json:"eta,omitempty"`
|
||||||
|
Duration int64 `json:"duration,omitempty"`
|
||||||
|
Visit Visit `json:"visit,omitempty"`
|
||||||
|
CreateUserUUID string `json:"created_user_uuid,omitempty"`
|
||||||
|
VisitExternalID string `json:"visit_external_id,omitempty"`
|
||||||
|
CanCancel []string `json:"can_cancel,omitempty"`
|
||||||
|
PricingDetailsURL string `json:"pricing_details_url,omitempty"`
|
||||||
|
RideProfile string `json:"ride_profile,omitempty"`
|
||||||
|
DistanceInMiles float64 `json:"distance_miles,omitempty"`
|
||||||
|
DurationInSeconds float64 `json:"duration_seconds,omitempty"`
|
||||||
|
CanceledBy string `json:"canceled_by,omitempty"`
|
||||||
|
TripType TripType `json:"trip_type,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
ErrorDescription string `json:"error_description,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Charge information
|
||||||
|
type Charge struct {
|
||||||
|
Currency string `json:"currency,omitempty"`
|
||||||
|
PaymentMethod string `json:"payment_method,omitempty"`
|
||||||
|
Amount int64 `json:"amount,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Price information
|
||||||
|
type Price struct {
|
||||||
|
Currency string `json:"currency,omitempty"`
|
||||||
|
Amount float64 `json:"amount,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Vehicle information
|
||||||
|
type Vehicle struct {
|
||||||
|
Color string `json:"color,omitempty"`
|
||||||
|
Make string `json:"make,omitempty"`
|
||||||
|
LicensePlate string `json:"license_plate,omitempty"`
|
||||||
|
ImageURL string `json:"image_url,omitempty"`
|
||||||
|
Year int64 `json:"year,omitempty"`
|
||||||
|
LicensePlateState string `json:"license_plate_state,omitempty"`
|
||||||
|
Model string `json:"model,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Location has the coordinates from the user
|
||||||
|
type Location struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Latitude float64 `json:"lat,omitempty"`
|
||||||
|
Longitude float64 `json:"lng,omitempty"`
|
||||||
|
Address string `json:"address,omitempty"`
|
||||||
|
ETASeconds *int64 `json:"eta_seconds,omitempty"`
|
||||||
|
TimeMS *int64 `json:"time_ms,omitempty"`
|
||||||
|
Time *time.Time `json:"time,omitempty"`
|
||||||
|
Bearing *float64 `json:"bearing,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//UserLyft has the personal information
|
||||||
|
type UserLyft struct {
|
||||||
|
UserID *string `json:"user_id,omitempty"`
|
||||||
|
Rating *string `json:"rating,omitempty"`
|
||||||
|
ImageURL *string `json:"image_url,omitempty"`
|
||||||
|
FirstName string `json:"first_name,omitempty"`
|
||||||
|
LastName string `json:"last_name,omitempty"`
|
||||||
|
PhoneNumber string `json:"phone_number,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ride entity data
|
||||||
|
type Ride struct {
|
||||||
|
UUID string `json:"ride_uuid,omitempty"`
|
||||||
|
InternalID string `json:"internal_id,omitempty"`
|
||||||
|
User User `json:"user,omitempty"`
|
||||||
|
Status RideStatus `json:"status,omitempty"`
|
||||||
|
Type RideType `json:"type,omitempty"`
|
||||||
|
Note string `json:"notes,omitempty"`
|
||||||
|
Passenger UserLyft `json:"passenger,omitempty"`
|
||||||
|
Driver UserLyft `json:"driver,omitempty"`
|
||||||
|
Vehicle Vehicle `json:"vehicle,omitempty"`
|
||||||
|
Route RideRoute `json:"route,omitempty"`
|
||||||
|
VisitDate *time.Time `json:"visit_date,omitempty"`
|
||||||
|
VisitTime *time.Time `json:"visit_time,omitempty"`
|
||||||
|
PickupTime *time.Time `json:"pickup_time,omitempty"`
|
||||||
|
Visit Visit `json:"visit,omitempty"`
|
||||||
|
CreatedUser User `json:"created_user,omitempty"`
|
||||||
|
CreateAt time.Time `json:"create_at,omitempty"`
|
||||||
|
UpdateAt time.Time `json:"update_at,omitempty"`
|
||||||
|
TripType TripType `json:"trip_type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideStatus entity data
|
||||||
|
type RideStatus struct {
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TripType entity data
|
||||||
|
type TripType struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideType entity data
|
||||||
|
type RideType struct {
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideRoute entity data
|
||||||
|
type RideRoute struct {
|
||||||
|
Origin Location `json:"origin,omitempty"`
|
||||||
|
Destination Location `json:"destination,omitempty"`
|
||||||
|
Location Location `json:"location,omitempty"`
|
||||||
|
RouteKML *string `json:"route_kml,omitempty"`
|
||||||
|
Distance float64 `json:"distance,omitempty"`
|
||||||
|
Duration int64 `json:"duration,omitempty"`
|
||||||
|
ETA int64 `json:"eta,omitempty"`
|
||||||
|
Bearing int64 `json:"bearing,omitempty"`
|
||||||
|
}
|
||||||
87
application/viewmodel/twillio.go
Normal file
87
application/viewmodel/twillio.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
type ListNumbers struct {
|
||||||
|
AvailableNumbers []Number `json:"available_phone_numbers,omitempty"`
|
||||||
|
Page int64 `json:"page,omitempty"`
|
||||||
|
PageSize int64 `json:"page_size,omitempty"`
|
||||||
|
URI string `json:"uri,omitempty"`
|
||||||
|
FirstPageURI string `json:"first_page_uri,omitempty"`
|
||||||
|
PreviousPageURI string `json:"previous_page_uri,omitempty"`
|
||||||
|
NextPageURI string `json:"next_page_uri,omitempty"`
|
||||||
|
IncomingPhones []Number `json:"incoming_phone_numbers,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Number struct {
|
||||||
|
SID *string `json:"sid,omitempty"`
|
||||||
|
AccountSID *string `json:"account_sid,omitempty"`
|
||||||
|
FriendlyName string `json:"friendly_name,omitempty"`
|
||||||
|
PhoneNumber string `json:"phone_number,omitempty"`
|
||||||
|
Lata string `json:"lata,omitempty"`
|
||||||
|
RateCenter string `json:"rate_center,omitempty"`
|
||||||
|
Latitude string `json:"latitude,omitempty"`
|
||||||
|
Longitude string `json:"longitude,omitempty"`
|
||||||
|
Region string `json:"region,omitempty"`
|
||||||
|
PostalCode string `json:"postal_code,omitempty"`
|
||||||
|
ISOCountry string `json:"iso_country,omitempty"`
|
||||||
|
Beta bool `json:"beta,omitempty"`
|
||||||
|
Capabilities Capabilities `json:"capabilities,omitempty"`
|
||||||
|
VoiceURL *string `json:"voice_url,omitempty"`
|
||||||
|
VoiceMethod *string `json:"voice_method,omitempty"`
|
||||||
|
VoiceFallbackURL *string `json:"voice_fallback_url,omitempty"`
|
||||||
|
VoiceFallbackMethod *string `json:"voice_fallback_method,omitempty"`
|
||||||
|
VoiceCallerIDLookup bool `json:"voice_caller_id_lookup,omitempty"`
|
||||||
|
VoiceApplicationSID *string `json:"voice_application_sid,omitempty"`
|
||||||
|
DateCreated *string `json:"date_created,omitempty"`
|
||||||
|
DateUpdated *string `json:"date_updated,omitempty"`
|
||||||
|
SmsURL *string `json:"sms_url,omitempty"`
|
||||||
|
SmsMethod *string `json:"sms_method,omitempty"`
|
||||||
|
SmsFallbackURL *string `json:"sms_fallback_url,omitempty"`
|
||||||
|
SmsFallbackMethod *string `json:"sms_fallback_method,omitempty"`
|
||||||
|
SmsApplicationID *string `json:"sms_application_sid,omitempty"`
|
||||||
|
StatusCallback *string `json:"status_callback,omitempty"`
|
||||||
|
StatusCallbackMethod *string `json:"status_callback_method,omitempty"`
|
||||||
|
APIVersion *string `json:"api_version,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Capabilities struct {
|
||||||
|
Voice bool `json:"voice,omitempty"`
|
||||||
|
SMS bool `json:"SMS,omitempty"`
|
||||||
|
MMS bool `json:"MMS,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProxyNumber struct {
|
||||||
|
From string `json:"from,omitempty"`
|
||||||
|
To string `json:"to,omitempty"`
|
||||||
|
Proxy string `json:"proxy,omitempty"`
|
||||||
|
Number Number `json:"details,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SocketMessage struct {
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Filled bool `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TwilioWebhook struct {
|
||||||
|
ToCountry string `json:"ToCountry,omitempty"`
|
||||||
|
ToState string `json:"ToState,omitempty"`
|
||||||
|
SMSMessageSID string `json:"SmsMessageSid,omitempty"`
|
||||||
|
NumMedia string `json:"NumMedia,omitempty"`
|
||||||
|
ToCity string `json:"ToCity,omitempty"`
|
||||||
|
FromZip string `json:"FromZip,omitempty"`
|
||||||
|
SMSSID string `json:"SmsSid,omitempty"`
|
||||||
|
FromState string `json:"FromState,omitempty"`
|
||||||
|
SMSStatus string `json:"SmsStatus,omitempty"`
|
||||||
|
FromCity string `json:"FromCity,omitempty"`
|
||||||
|
Body string `json:"Body,omitempty"`
|
||||||
|
FromCountry string `json:"FromCountry,omitempty"`
|
||||||
|
To string `json:"To,omitempty"`
|
||||||
|
ToZip string `json:"ToZip,omitempty"`
|
||||||
|
AddOns string `json:"AddOns,omitempty"`
|
||||||
|
NumSegments string `json:"NumSegments,omitempty"`
|
||||||
|
MessageSID string `json:"MessageSid,omitempty"`
|
||||||
|
AccountSID string `json:"AccountSid,omitempty"`
|
||||||
|
From string `json:"From,omitempty"`
|
||||||
|
APIVersion string `json:"ApiVersion,omitempty"`
|
||||||
|
}
|
||||||
36
application/viewmodel/user.go
Normal file
36
application/viewmodel/user.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// User model for API binding
|
||||||
|
type User struct {
|
||||||
|
ID string `json:"useruuid"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
First string `json:"first,omitempty"`
|
||||||
|
Last string `json:"last,omitempty"`
|
||||||
|
Gender *string `json:"gender,omitempty"`
|
||||||
|
Member *string `json:"member,omitempty"`
|
||||||
|
BirthDate *time.Time `json:"birthdate,omitempty"`
|
||||||
|
Email *string `json:"email,omitempty"`
|
||||||
|
PhoneNumber *string `json:"phonenumber,omitempty"`
|
||||||
|
Pass string `json:"pass,omitempty"`
|
||||||
|
Active bool `json:"active,omitempty"`
|
||||||
|
Created time.Time `json:"created,omitempty"`
|
||||||
|
Updated time.Time `json:"updated,omitempty"`
|
||||||
|
Contacts []Contact `json:"contacts,omitempty"`
|
||||||
|
Rides []Ride `json:"rides,omitempty"`
|
||||||
|
Addresses []Address `json:"addresses,omitempty"`
|
||||||
|
Profiles []Profile `json:"profiles,omitempty"`
|
||||||
|
Types []OrganizationType `json:"types,omitempty"`
|
||||||
|
Organizations []Organization `json:"organizations,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Contact struct {
|
||||||
|
Type ContactType `json:"type,omitempty"`
|
||||||
|
Value string `json:"contact,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContactType struct {
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
33
application/viewmodel/visit.go
Normal file
33
application/viewmodel/visit.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package viewmodel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VisitStatus entity data
|
||||||
|
type VisitStatus struct {
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit entity data
|
||||||
|
type Visit struct {
|
||||||
|
UUID string `json:"visit_uuid,omitempty"`
|
||||||
|
Status VisitStatus `json:"visit_status,omitempty"`
|
||||||
|
User User `json:"user,omitempty"`
|
||||||
|
VisitDatetime time.Time `json:"visit_datetime,omitempty"`
|
||||||
|
VisitDuration int64 `json:"visit_duration,omitempty"`
|
||||||
|
PickupDatetime time.Time `json:"pickup_datetime,omitempty"`
|
||||||
|
Notes *string `json:"notes,omitempty"`
|
||||||
|
PickupAddressID int64 `json:"pickup_address_id,omitempty"`
|
||||||
|
DestinationAddressID int64 `json:"destination_address_id,omitempty"`
|
||||||
|
Pickup Location `json:"pickup,omitempty"`
|
||||||
|
Provider ProviderResp `json:"provider,omitempty"`
|
||||||
|
CreatedUser User `json:"created_user,omitempty"`
|
||||||
|
CreatedDate time.Time `json:"created,omitempty"`
|
||||||
|
UpdatedDate time.Time `json:"updated,omitempty"`
|
||||||
|
ReturnDate *time.Time `json:"return_date,omitempty"`
|
||||||
|
TripType TripType `json:"trip_type,omitempty"`
|
||||||
|
ExternalID string `json:"visit_external_id,omitempty"`
|
||||||
|
Rides []Ride `json:"rides,omitempty"`
|
||||||
|
}
|
||||||
59
bitbucket-pipelines.yml
Normal file
59
bitbucket-pipelines.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
image: golang:1.9.2
|
||||||
|
pipelines:
|
||||||
|
branches:
|
||||||
|
master:
|
||||||
|
- step:
|
||||||
|
script:
|
||||||
|
- curl https://glide.sh/get | sh
|
||||||
|
- mkdir -p /go/src/bitbucket.org/nemt/nemt-portal-api
|
||||||
|
- pwd
|
||||||
|
- ls -al
|
||||||
|
- cp -R ./* /go/src/bitbucket.org/nemt/nemt-portal-api/
|
||||||
|
- cd /go/src/bitbucket.org/nemt/nemt-portal-api/
|
||||||
|
- rm -rf glide.lock
|
||||||
|
- rm -rf vendor/
|
||||||
|
- glide install -force
|
||||||
|
- go build -o nemt-portal-api
|
||||||
|
- mkdir -p dist/{static,docs}
|
||||||
|
- cp nemt-portal-api ./dist/
|
||||||
|
- cp -R static/* ./dist/static/
|
||||||
|
- cp -R docs/swagger/ ./dist/docs/
|
||||||
|
- cp config.prd.toml ./dist/config.toml
|
||||||
|
- docker build -f Dockerfile.run -t nemt-portal-api-run:prod --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
|
||||||
|
- apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
|
||||||
|
- apt-get install python3-pip -y
|
||||||
|
- pip3 install --upgrade awscli
|
||||||
|
- eval $(aws ecr get-login --no-include-email --region us-east-2)
|
||||||
|
- docker tag nemt-portal-api-run:prod 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod
|
||||||
|
- docker push 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod
|
||||||
|
- eval $(aws --region us-east-2 ecs register-task-definition --cli-input-json file://ecs.prd.json >/dev/null)
|
||||||
|
- eval $(aws --region us-east-2 ecs update-service --cluster App --service portal-api --task-definition portal-api-prod >/dev/null)
|
||||||
|
development:
|
||||||
|
- step:
|
||||||
|
script:
|
||||||
|
- curl https://glide.sh/get | sh
|
||||||
|
- mkdir -p /go/src/bitbucket.org/nemt/nemt-portal-api
|
||||||
|
- pwd
|
||||||
|
- ls -al
|
||||||
|
- cp -R ./* /go/src/bitbucket.org/nemt/nemt-portal-api/
|
||||||
|
- cd /go/src/bitbucket.org/nemt/nemt-portal-api/
|
||||||
|
- rm -rf glide.lock
|
||||||
|
- rm -rf vendor/
|
||||||
|
- glide install -force
|
||||||
|
- go build -o nemt-portal-api
|
||||||
|
- mkdir -p dist/{static,docs}
|
||||||
|
- cp nemt-portal-api ./dist/
|
||||||
|
- cp -R static/* ./dist/static/
|
||||||
|
- cp -R docs/swagger/ ./dist/docs/
|
||||||
|
- cp config.stg.toml ./dist/config.toml
|
||||||
|
- docker build -f Dockerfile.run -t nemt-portal-api-run:dev --force-rm --build-arg BIN_NAME=nemt-portal-api --build-arg APP_NAME=nemt-portal-api .
|
||||||
|
- apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get -y autoremove && apt-get clean
|
||||||
|
- apt-get install python3-pip -y
|
||||||
|
- pip3 install --upgrade awscli
|
||||||
|
- eval $(aws ecr get-login --no-include-email --region us-east-2)
|
||||||
|
- docker tag nemt-portal-api-run:dev 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev
|
||||||
|
- docker push 105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev
|
||||||
|
- eval $(aws --region us-east-2 ecs register-task-definition --cli-input-json file://ecs.stg.json >/dev/null)
|
||||||
|
- eval $(aws --region us-east-2 ecs update-service --cluster NemtCluster2 --service portal-api --task-definition portal-api-dev >/dev/null)
|
||||||
|
options:
|
||||||
|
docker: true
|
||||||
82
config.dev.toml
Normal file
82
config.dev.toml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
[app]
|
||||||
|
name = "nemt"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[app.docs]
|
||||||
|
swagger-path = "./static/swagger-ui"
|
||||||
|
yaml-path = "./docs/swagger"
|
||||||
|
|
||||||
|
[db]
|
||||||
|
host = "dbdev01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
||||||
|
port = 3306
|
||||||
|
name = "nemt"
|
||||||
|
user = "nemt-user"
|
||||||
|
pass = "4umQ3ENNzt"
|
||||||
|
max-life-minutes = 5
|
||||||
|
max-idle-conns = 5
|
||||||
|
max-open-conns = 100
|
||||||
|
|
||||||
|
[http]
|
||||||
|
port = 5100
|
||||||
|
prefix = "/v1"
|
||||||
|
|
||||||
|
[http.auth]
|
||||||
|
app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
|
||||||
|
certificate-path = "./static/cert/nemt-portal-api.key"
|
||||||
|
frontend-urls = [
|
||||||
|
"http://localhost:3100"
|
||||||
|
]
|
||||||
|
|
||||||
|
[aws]
|
||||||
|
s3-bucket = "static.nemt-portal-api.com.br/development"
|
||||||
|
|
||||||
|
[cache]
|
||||||
|
server = "internal-REDISDEV-INT-ELB01-905785815.us-east-2.elb.amazonaws.com"
|
||||||
|
port = 6379
|
||||||
|
db = 0
|
||||||
|
pass = "3rdaP3KL2x%V"
|
||||||
|
prefix = "nemt-portal-api-dev"
|
||||||
|
default-expiration = "5m"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
log-to-file = false
|
||||||
|
path = "nemt-portal-api.log"
|
||||||
|
|
||||||
|
[twilio]
|
||||||
|
account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
|
||||||
|
token = "36ba77236be5eb5848b3746e4400f4e2"
|
||||||
|
sender = "+17084261667"
|
||||||
|
twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
|
||||||
|
|
||||||
|
[email]
|
||||||
|
server = "email-smtp.us-east-1.amazonaws.com"
|
||||||
|
port = 587
|
||||||
|
user = "AKIAIP2QTIHICY5I5BBA"
|
||||||
|
pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
|
||||||
|
sender = "no-reply@chmhub.com"
|
||||||
|
|
||||||
|
[google-shortener]
|
||||||
|
client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
|
||||||
|
secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
|
||||||
|
api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
|
||||||
|
|
||||||
|
[lyft]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
|
||||||
|
|
||||||
|
[lyft-prod]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
|
||||||
|
user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
|
||||||
|
|
||||||
|
[bxe]
|
||||||
|
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
||||||
|
key = "dacg7jtsmb6ajr3z553jbczg"
|
||||||
|
secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
|
||||||
|
|
||||||
|
[blue365]
|
||||||
|
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
||||||
|
key = "jcn5xjxvarc96rtjxp25dctj"
|
||||||
|
secret = "6XdEusG2w2PWWXsfXVyweQnY"
|
||||||
82
config.prd.toml
Normal file
82
config.prd.toml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
[app]
|
||||||
|
name = "nemt"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[app.docs]
|
||||||
|
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||||
|
yaml-path = "/opt/app/nemt-portal-api/docs/swagger"
|
||||||
|
|
||||||
|
[db]
|
||||||
|
host = "db01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
||||||
|
port = 3306
|
||||||
|
name = "nemt_clean"
|
||||||
|
user = "nemt-user"
|
||||||
|
pass = "OL&!n#p6J8Lu"
|
||||||
|
max-life-minutes = 5
|
||||||
|
max-idle-conns = 5
|
||||||
|
max-open-conns = 100
|
||||||
|
|
||||||
|
[http]
|
||||||
|
port = 5100
|
||||||
|
prefix = "/v1"
|
||||||
|
|
||||||
|
[http.auth]
|
||||||
|
app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
|
||||||
|
certificate-path = "/opt/app/static/cert/nemt-portal-api.key"
|
||||||
|
frontend-urls = [
|
||||||
|
"http://localhost:3100"
|
||||||
|
]
|
||||||
|
|
||||||
|
[aws]
|
||||||
|
s3-bucket = "static.nemt-portal-api.com.br/prod"
|
||||||
|
|
||||||
|
[cache]
|
||||||
|
server = "internal-REDIS-INT-ELB01-661255167.us-east-2.elb.amazonaws.com"
|
||||||
|
port = 6379
|
||||||
|
db = 0
|
||||||
|
pass = "3rdaP3KL2x%V"
|
||||||
|
prefix = "portal-api-prod"
|
||||||
|
default-expiration = "5m"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
log-to-file = false
|
||||||
|
path = "nemt-portal-api.log"
|
||||||
|
|
||||||
|
[twilio]
|
||||||
|
account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
|
||||||
|
token = "36ba77236be5eb5848b3746e4400f4e2"
|
||||||
|
sender = "+17084261667"
|
||||||
|
twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
|
||||||
|
|
||||||
|
[email]
|
||||||
|
server = "email-smtp.us-east-1.amazonaws.com"
|
||||||
|
port = 587
|
||||||
|
user = "AKIAIP2QTIHICY5I5BBA"
|
||||||
|
pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
|
||||||
|
sender = "no-reply@chmhub.com"
|
||||||
|
|
||||||
|
[google-shortener]
|
||||||
|
client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
|
||||||
|
secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
|
||||||
|
api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
|
||||||
|
|
||||||
|
[lyft]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
|
||||||
|
|
||||||
|
[lyft-prod]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
|
||||||
|
user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
|
||||||
|
|
||||||
|
[bxe]
|
||||||
|
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
||||||
|
key = "dacg7jtsmb6ajr3z553jbczg"
|
||||||
|
secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
|
||||||
|
|
||||||
|
[blue365]
|
||||||
|
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
||||||
|
key = "jcn5xjxvarc96rtjxp25dctj"
|
||||||
|
secret = "6XdEusG2w2PWWXsfXVyweQnY"
|
||||||
82
config.stg.toml
Normal file
82
config.stg.toml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
[app]
|
||||||
|
name = "nemt"
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[app.docs]
|
||||||
|
swagger-path = "/opt/app/nemt-portal-api/static/swagger-ui"
|
||||||
|
yaml-path = "/opt/app/nemt-portal-api/docs/swagger"
|
||||||
|
|
||||||
|
[db]
|
||||||
|
host = "dbdev01.cj5318jcaupw.us-east-2.rds.amazonaws.com"
|
||||||
|
port = 3306
|
||||||
|
name = "nemt"
|
||||||
|
user = "nemt-user"
|
||||||
|
pass = "4umQ3ENNzt"
|
||||||
|
max-life-minutes = 5
|
||||||
|
max-idle-conns = 5
|
||||||
|
max-open-conns = 100
|
||||||
|
|
||||||
|
[http]
|
||||||
|
port = 5100
|
||||||
|
prefix = "/v1"
|
||||||
|
|
||||||
|
[http.auth]
|
||||||
|
app-key = "8a266a40-ed2e-4be2-bdfc-459a507bf02e"
|
||||||
|
certificate-path = "/opt/app/static/cert/nemt-portal-api.key"
|
||||||
|
frontend-urls = [
|
||||||
|
"http://localhost:3100"
|
||||||
|
]
|
||||||
|
|
||||||
|
[aws]
|
||||||
|
s3-bucket = "static.nemt-portal-api.com.br/staging"
|
||||||
|
|
||||||
|
[cache]
|
||||||
|
server = "internal-REDISDEV-INT-ELB01-905785815.us-east-2.elb.amazonaws.com"
|
||||||
|
port = 6379
|
||||||
|
db = 0
|
||||||
|
pass = "3rdaP3KL2x%V"
|
||||||
|
prefix = "portal-api-test"
|
||||||
|
default-expiration = "5m"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
log-to-file = false
|
||||||
|
path = "nemt-portal-api.log"
|
||||||
|
|
||||||
|
[twilio]
|
||||||
|
account = "AC3106c1aeb2c74b7e45adc1ba0ff8c6e2"
|
||||||
|
token = "36ba77236be5eb5848b3746e4400f4e2"
|
||||||
|
sender = "+17084261667"
|
||||||
|
twiml-sid = "APc33ccb8af94ecf3d61c6bfd9a7f69749"
|
||||||
|
|
||||||
|
[email]
|
||||||
|
server = "email-smtp.us-east-1.amazonaws.com"
|
||||||
|
port = 587
|
||||||
|
user = "AKIAIP2QTIHICY5I5BBA"
|
||||||
|
pass = "AkInsFK64iCbrAftVnVGFVVJOcMIG/pv8k1aFZwAQ5lF"
|
||||||
|
sender = "no-reply@chmhub.com"
|
||||||
|
|
||||||
|
[google-shortener]
|
||||||
|
client-id = "1059812138553-t7jents4d3a7uqpb9ms9nf2luqkqplrt.apps.googleusercontent.com"
|
||||||
|
secret-key = "r478-RtEmvAcDWlLQk1CZatQ"
|
||||||
|
api-key = "AIzaSyAQsoEaUmg96-TxxNCTJhyu5HEOLBzxcCw"
|
||||||
|
|
||||||
|
[lyft]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "SANDBOX-8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "UyjcHl7fC6LxRWgZ8I6-_LJ0_j6YcWNg9ct2xEXMdX2iRiGrMrjrbJmxtPlNPGvN"
|
||||||
|
|
||||||
|
[lyft-prod]
|
||||||
|
key = "KkS0DgSPuJ84"
|
||||||
|
secret = "8LxipL9BYDJrcAZSgqr8yODjQRDXQQ_T"
|
||||||
|
token = "Xa8n7M8TQ62iRpElan0gaPZwaPzUIa85G-epIesWJysJgOQU5zRDLdqD1ygZk8-Y"
|
||||||
|
user-uuid = "11a49fa4-fbc7-4fe9-87fe-52a5bc3b71f8"
|
||||||
|
|
||||||
|
[bxe]
|
||||||
|
url = "https://api-pve.bcbs.com/BXDirectConnect/V30"
|
||||||
|
key = "dacg7jtsmb6ajr3z553jbczg"
|
||||||
|
secret = "vFhNeWE8JdJpbDZQtcm6AHjX"
|
||||||
|
|
||||||
|
[blue365]
|
||||||
|
url = "https://api-cloud.bcbs.com/blue365deals-stg/v1/validatePrefix/"
|
||||||
|
key = "jcn5xjxvarc96rtjxp25dctj"
|
||||||
|
secret = "6XdEusG2w2PWWXsfXVyweQnY"
|
||||||
11
data/data.go
Normal file
11
data/data.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/data/datamysql"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Connect(cfg *config.Config) (contract.DataManager, error) {
|
||||||
|
return datamysql.Instance(cfg)
|
||||||
|
}
|
||||||
133
data/datamysql/datamysql.go
Normal file
133
data/datamysql/datamysql.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
"github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Conn
|
||||||
|
once sync.Once
|
||||||
|
connErr error
|
||||||
|
)
|
||||||
|
|
||||||
|
// Conn is the MySQL connection manager
|
||||||
|
type Conn struct {
|
||||||
|
db *sql.DB
|
||||||
|
users *userRepo
|
||||||
|
rides *rideRepo
|
||||||
|
visit *visitRepo
|
||||||
|
provider *providerRepo
|
||||||
|
notification *notificationRepo
|
||||||
|
profile *profileRepo
|
||||||
|
organization *organizationRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin starts a transaction
|
||||||
|
func (c *Conn) Begin() (contract.TransactionManager, error) {
|
||||||
|
tx, err := c.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTransaction(tx), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the db connection
|
||||||
|
func (c *Conn) Close() (err error) {
|
||||||
|
return c.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Users returns the users set
|
||||||
|
func (c *Conn) Users() contract.UserRepo {
|
||||||
|
return c.users
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rides returns the rides set
|
||||||
|
func (c *Conn) Rides() contract.RideRepo {
|
||||||
|
return c.rides
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visits returns the rides set
|
||||||
|
func (c *Conn) Visits() contract.VisitRepo {
|
||||||
|
return c.visit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (c *Conn) Provider() contract.ProviderRepo {
|
||||||
|
return c.provider
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (c *Conn) Profile() contract.ProfileRepo {
|
||||||
|
return c.profile
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (c *Conn) Notification() contract.NotificationRepo {
|
||||||
|
return c.notification
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (c *Conn) Organization() contract.OrganizationRepo {
|
||||||
|
return c.organization
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance returns an instance of a DataManager
|
||||||
|
func Instance(cfg *config.Config) (contract.DataManager, error) {
|
||||||
|
once.Do(func() {
|
||||||
|
|
||||||
|
db, err := sql.Open("mysql", getMySQLConfig(cfg).FormatDSN())
|
||||||
|
if err != nil {
|
||||||
|
connErr = errors.Wrap(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Ping()
|
||||||
|
if err != nil {
|
||||||
|
connErr = errors.Wrap(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connMaxLifetime := time.Duration(cfg.DB.MaxLifeInMinutes) * time.Minute
|
||||||
|
db.SetConnMaxLifetime(connMaxLifetime)
|
||||||
|
db.SetMaxIdleConns(cfg.DB.MaxIdleConns)
|
||||||
|
db.SetMaxOpenConns(cfg.DB.MaxOpenConns)
|
||||||
|
|
||||||
|
instance = new(Conn)
|
||||||
|
instance.db = db
|
||||||
|
|
||||||
|
instance.users = newUserRepo(db)
|
||||||
|
instance.rides = newRideRepo(db)
|
||||||
|
instance.visit = newVisitRepo(db)
|
||||||
|
instance.provider = newProviderRepo(db)
|
||||||
|
instance.notification = newNotificationRepo(db)
|
||||||
|
instance.profile = newProfileRepo(db)
|
||||||
|
instance.organization = newOrganizationRepo(db)
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance, connErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMySQLConfig returns the configuration for MySQL driver
|
||||||
|
func getMySQLConfig(cfg *config.Config) *mysql.Config {
|
||||||
|
loc, _ := time.LoadLocation("UTC")
|
||||||
|
|
||||||
|
return &mysql.Config{
|
||||||
|
Net: "tcp",
|
||||||
|
Addr: fmt.Sprintf("%s:%d", cfg.DB.Host, cfg.DB.Port),
|
||||||
|
DBName: cfg.DB.Name,
|
||||||
|
User: cfg.DB.User,
|
||||||
|
Passwd: cfg.DB.Pass,
|
||||||
|
ParseTime: true,
|
||||||
|
Strict: true,
|
||||||
|
Loc: loc,
|
||||||
|
}
|
||||||
|
}
|
||||||
140
data/datamysql/notification.go
Normal file
140
data/datamysql/notification.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// visitRepo maps methods to database
|
||||||
|
type notificationRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNotificationRepo(conn executor) *notificationRepo {
|
||||||
|
return ¬ificationRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) Create(notification entity.Notification) (entity.Notification, error) {
|
||||||
|
const (
|
||||||
|
statusQuery = `SELECT a.contact_type_id, b.ride_id, c.user_id, d.user_id created_user_id FROM tab_contact_type a, tab_ride b, tab_user c, tab_user d WHERE a.key = ? AND b.ride_uuid = ? AND c.user_uuid = ? AND d.user_uuid = ?;`
|
||||||
|
query = `INSERT INTO tab_notification(notification_uuid, ride_id, user_id, contact_type_id, contact, message, created_user_id, readed, notificaton_type) VALUES(?, ?, ?, ?, ?, ?, ?, 0, ?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal := notification
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
retVal.UUID = UUID.String()
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(statusQuery, retVal.Type, retVal.Ride.UUID, retVal.User.UUID, retVal.CreatedUser.UUID)
|
||||||
|
if err := row.Scan(&retVal.TypeID, &retVal.Ride.ID, &retVal.User.ID, &retVal.CreatedUser.ID); err != nil {
|
||||||
|
fmt.Println("Error to get base data: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := c.conn.Exec(query, retVal.UUID, retVal.Ride.ID, retVal.User.ID, retVal.TypeID, retVal.Subject, retVal.Message, retVal.CreatedUser.ID, retVal.MessageType)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.GetByID(retVal.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) getQuery() string {
|
||||||
|
return `SELECT
|
||||||
|
a.notification_id,
|
||||||
|
a.notification_uuid,
|
||||||
|
a.ride_id,
|
||||||
|
a.user_id,
|
||||||
|
c.user_uuid,
|
||||||
|
c.name user_name,
|
||||||
|
CASE WHEN b.key = 'sms' THEN e.phone_number WHEN b.key = 'email' THEN e.email WHEN b.key = 'app' THEN c.user_uuid END to_address,
|
||||||
|
CASE WHEN b.key = 'sms' THEN f.phone_number WHEN b.key = 'email' THEN f.email WHEN b.key = 'app' THEN d.user_uuid END from_address,
|
||||||
|
a.contact_type_id,
|
||||||
|
b.key contact_type_key,
|
||||||
|
a.contact,
|
||||||
|
a.message,
|
||||||
|
a.create_at,
|
||||||
|
a.readed,
|
||||||
|
d.user_id created_user_id,
|
||||||
|
d.user_uuid created_user_uuid,
|
||||||
|
d.name created_user_name,
|
||||||
|
a.notificaton_type
|
||||||
|
FROM
|
||||||
|
tab_notification a
|
||||||
|
INNER JOIN tab_contact_type b
|
||||||
|
ON a.contact_type_id = b.contact_type_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON a.user_id = c.user_id
|
||||||
|
INNER JOIN tab_user d
|
||||||
|
ON a.created_user_id = d.user_id
|
||||||
|
INNER JOIN tab_login e
|
||||||
|
ON c.user_id = e.user_id
|
||||||
|
INNER JOIN tab_login f
|
||||||
|
ON d.user_id = f.user_id`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error) {
|
||||||
|
const (
|
||||||
|
whereClause = ` WHERE
|
||||||
|
a.notificaton_type = ?
|
||||||
|
AND e.phone_number = ?
|
||||||
|
AND b.key = ?
|
||||||
|
ORDER BY a.notification_id DESC
|
||||||
|
LIMIT 1;`
|
||||||
|
)
|
||||||
|
finalQuery := c.getQuery() + whereClause
|
||||||
|
|
||||||
|
return c.parseEntity(c.conn.QueryRow(finalQuery, notificationType, phoneNumber, status))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.readed = ? AND b.key = ? AND c.user_uuid = ?; ", isRead, status, userUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) GetByUserUUID(userUUID string, status string) ([]entity.Notification, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE b.key = ? AND c.user_uuid = ?; ", status, userUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) ReadStatus(notificationUUID string, isRead bool) error {
|
||||||
|
const query = "UPDATE tab_notification SET readed = ? WHERE notification_uuid = ?"
|
||||||
|
_, err := c.conn.Exec(query, isRead, notificationUUID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationRepo) GetByID(ID int64) (entity.Notification, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.notification_id = ?; ", ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *notificationRepo) parseSet(rows *sql.Rows, err error) ([]entity.Notification, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.Notification, 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 *notificationRepo) parseEntity(row scanner) (retVal entity.Notification, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.Ride.ID, &retVal.User.ID, &retVal.User.UUID, &retVal.User.Name, &retVal.To, &retVal.From, &retVal.TypeID, &retVal.Type, &retVal.Subject, &retVal.Message, &retVal.Created, &retVal.Read, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.MessageType)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
482
data/datamysql/organization.go
Normal file
482
data/datamysql/organization.go
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rideRepo maps methods to database
|
||||||
|
type organizationRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOrganizationRepo(conn executor) *organizationRepo {
|
||||||
|
return &organizationRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) getQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.organization_id,
|
||||||
|
a.organization_uuid,
|
||||||
|
b.organization_type_id,
|
||||||
|
b.organization_type,
|
||||||
|
b.organization_type_key,
|
||||||
|
a.organization_name,
|
||||||
|
a.organization_description,
|
||||||
|
a.organization_reference_id,
|
||||||
|
a.organization_parent_id,
|
||||||
|
(a.main_organization = b'1') main_organization,
|
||||||
|
a.create_at,
|
||||||
|
a.update_at,
|
||||||
|
(a.active = b'1') active,
|
||||||
|
(a.suspended = b'1') suspended,
|
||||||
|
(a.blocked = b'1') blocked,
|
||||||
|
c.user_id created_user_id,
|
||||||
|
c.user_uuid created_user_uuid,
|
||||||
|
c.name created_user_name,
|
||||||
|
d.user_id updated_user_id,
|
||||||
|
d.user_uuid updated_user_uuid,
|
||||||
|
d.name updated_user_name
|
||||||
|
FROM
|
||||||
|
tab_organization a
|
||||||
|
INNER JOIN tab_organization_type b
|
||||||
|
ON a.organization_type_id = b.organization_type_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON c.user_id = a.created_user
|
||||||
|
INNER JOIN tab_user d
|
||||||
|
ON d.user_id = a.updated_user `
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
func (c *organizationRepo) getAddressQuery() string {
|
||||||
|
const query = `SELECT
|
||||||
|
a.organization_address_id,
|
||||||
|
a.organization_address_uuid,
|
||||||
|
a.internal_id,
|
||||||
|
a.name,
|
||||||
|
a.address,
|
||||||
|
a.desc,
|
||||||
|
a.lat,
|
||||||
|
a.long,
|
||||||
|
a.created,
|
||||||
|
a.created_user_id,
|
||||||
|
c.user_uuid created_user_uuid,
|
||||||
|
c.name created_user_name,
|
||||||
|
a.updated,
|
||||||
|
a.updated_user_id,
|
||||||
|
d.user_uuid updated_user_uuid,
|
||||||
|
d.name updated_user_name,
|
||||||
|
(a.active = b'1') active
|
||||||
|
FROM tab_organization_address a
|
||||||
|
INNER JOIN tab_organization b
|
||||||
|
ON b.organization_id = a.organization_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON c.user_id = a.created_user_id
|
||||||
|
INNER JOIN tab_user d
|
||||||
|
ON d.user_id = a.updated_user_id `
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) getContactQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.organization_contact_id,
|
||||||
|
a.organization_contact_uuid,
|
||||||
|
b.contact_type_id,
|
||||||
|
b.key contact_type_key,
|
||||||
|
b.name contact_type_name,
|
||||||
|
a.contact,
|
||||||
|
a.contact_name,
|
||||||
|
a.contact_desc,
|
||||||
|
a.created,
|
||||||
|
a.created_user_id,
|
||||||
|
d.user_uuid created_user_uuid,
|
||||||
|
d.name created_user_name,
|
||||||
|
a.updated,
|
||||||
|
a.updated_user_id,
|
||||||
|
e.user_uuid updated_user_uuid,
|
||||||
|
e.name updated_user_name,
|
||||||
|
(a.active = b'1') active
|
||||||
|
FROM tab_organization_contact a
|
||||||
|
INNER JOIN tab_contact_type b
|
||||||
|
ON a.contact_type_id = b.contact_type_id
|
||||||
|
INNER JOIN tab_organization c
|
||||||
|
ON c.organization_id = a.organization_id
|
||||||
|
INNER JOIN tab_user d
|
||||||
|
ON d.user_id = a.created_user_id
|
||||||
|
INNER JOIN tab_user e
|
||||||
|
ON e.user_id = a.updated_user_id `
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) getTypeQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
organization_type_id,
|
||||||
|
organization_type,
|
||||||
|
organization_type_key,
|
||||||
|
description,
|
||||||
|
create_at,
|
||||||
|
update_at
|
||||||
|
FROM
|
||||||
|
tab_organization_type `
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *organizationRepo) parseSet(rows *sql.Rows, err error) ([]entity.Organization, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.Organization, 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 *organizationRepo) parseEntity(row scanner) (retVal entity.Organization, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.Type.ID, &retVal.Type.Name, &retVal.Type.Key, &retVal.Name, &retVal.Description, &retVal.ReferenceID, &retVal.ParentID, &retVal.Main, &retVal.Created, &retVal.Updated, &retVal.Active, &retVal.Suspended, &retVal.Blocked, &retVal.Author.ID, &retVal.Author.UUID, &retVal.Author.Name, &retVal.LastEditor.ID, &retVal.LastEditor.UUID, &retVal.LastEditor.Name)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *organizationRepo) parseContactSet(rows *sql.Rows, err error) ([]entity.OrganizationContact, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.OrganizationContact, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseContactEntity(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 *organizationRepo) parseContactEntity(row scanner) (retVal entity.OrganizationContact, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.Type.ID, &retVal.Type.Key, &retVal.Type.Value, &retVal.Contact, &retVal.Name, &retVal.Description, &retVal.Created, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Updated, &retVal.UpdatedUser.ID, &retVal.UpdatedUser.UUID, &retVal.UpdatedUser.Name, &retVal.Active)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *organizationRepo) parseAddressSet(rows *sql.Rows, err error) ([]entity.OrganizationAddress, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.OrganizationAddress, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseAddressEntity(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 *organizationRepo) parseAddressEntity(row scanner) (retVal entity.OrganizationAddress, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.InternalID, &retVal.Name, &retVal.Address, &retVal.Description, &retVal.Latitude, &retVal.Longitude, &retVal.Created, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Updated, &retVal.UpdatedUser.ID, &retVal.UpdatedUser.UUID, &retVal.UpdatedUser.Name, &retVal.Active)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *organizationRepo) parseTypeSet(rows *sql.Rows, err error) ([]entity.OrganizationType, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.OrganizationType, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseTypeEntity(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 *organizationRepo) parseTypeEntity(row scanner) (retVal entity.OrganizationType, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.Name, &retVal.Key, &retVal.Description, &retVal.Created, &retVal.Updated)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetAllTypes() ([]entity.OrganizationType, error) {
|
||||||
|
return c.parseTypeSet(c.conn.Query(c.getTypeQuery()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetTypeByKey(key string) (entity.OrganizationType, error) {
|
||||||
|
return c.parseTypeEntity(c.conn.QueryRow(c.getTypeQuery()+" WHERE organization_type_key=?", key))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
|
||||||
|
if organizationTypeKey == "" {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()))
|
||||||
|
} else {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE b.organization_type_key = ? ", organizationTypeKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetByName(name string, searchType string) ([]entity.Organization, error) {
|
||||||
|
finalQuery := c.getQuery() + " WHERE a.organization_name LIKE ?"
|
||||||
|
switch searchType {
|
||||||
|
case "parent":
|
||||||
|
finalQuery += " AND a.organization_parent_id > 0; "
|
||||||
|
case "child":
|
||||||
|
finalQuery += " AND a.organization_parent_id = 0; "
|
||||||
|
}
|
||||||
|
name = "%" + name + "%"
|
||||||
|
|
||||||
|
fmt.Println(finalQuery)
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(finalQuery, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetByUUID(organizationUUID string) (entity.Organization, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_uuid = ? ", organizationUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetByID(organizationID int64) (entity.Organization, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.organization_id = ? ", organizationID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetChildsByID(organizationID int64) ([]entity.Organization, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+" WHERE a.organization_parent_id = ? ", organizationID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) {
|
||||||
|
return c.parseContactSet(c.conn.Query(c.getContactQuery()+" WHERE a.active = 1 AND c.organization_uuid = ? ", organizationUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error) {
|
||||||
|
return c.parseContactSet(c.conn.Query(c.getContactQuery()+" WHERE a.active = 1 AND c.organization_id = ? ", organizationID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error) {
|
||||||
|
return c.parseContactEntity(c.conn.QueryRow(c.getContactQuery()+" WHERE a.organization_contact_uuid = ? ", contactUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error) {
|
||||||
|
return c.parseAddressSet(c.conn.Query(c.getAddressQuery()+" WHERE a.active = 1 AND b.organization_uuid = ? ", organizationUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error) {
|
||||||
|
return c.parseAddressSet(c.conn.Query(c.getAddressQuery()+" WHERE a.active = 1 AND b.organization_id = ? ", organizationID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error) {
|
||||||
|
return c.parseAddressEntity(c.conn.QueryRow(c.getAddressQuery()+" WHERE a.organization_address_uuid = ? ", contactUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) SetParentOrganization(organizationID int64, parentOrganizationID int64) error {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_organization SET organization_parent_id = ? WHERE organization_id = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
_, err := c.conn.Exec(query, parentOrganizationID, organizationID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
|
||||||
|
const (
|
||||||
|
query = "UPDATE tab_organization_address SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_address_uuid = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
if address.Organization == nil {
|
||||||
|
return errors.NewNotFoundError()
|
||||||
|
}
|
||||||
|
|
||||||
|
organization, err := c.GetByUUID(address.Organization.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.conn.Exec(query, address.UpdatedUser.ID, organization.ID, address.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_organization_address(organization_address_uuid, organization_id, internal_id, `name`, address, `desc`, lat, `long`, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
if address.Organization == nil {
|
||||||
|
return entity.OrganizationAddress{}, errors.NewNotFoundError()
|
||||||
|
}
|
||||||
|
|
||||||
|
organization, err := c.GetByUUID(address.Organization.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.OrganizationAddress{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
result, err := c.conn.Exec(query, UUID.String(), organization.ID, address.InternalID, address.Name, address.Address, address.Description, address.Latitude, address.Longitude, address.CreatedUser.ID, address.UpdatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.OrganizationAddress{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address.ID, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) InactivateOrganizationContact(contact entity.OrganizationContact) error {
|
||||||
|
const (
|
||||||
|
query = "UPDATE tab_organization_contact SET active = 0, updated = CURRENT_TIMESTAMP, updated_user_id = ? WHERE organization_id = ? and organization_contact_uuid = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
if contact.Organization == nil {
|
||||||
|
return errors.NewNotFoundError()
|
||||||
|
}
|
||||||
|
|
||||||
|
organization, err := c.GetByUUID(contact.Organization.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.conn.Exec(query, contact.UpdatedUser.ID, organization.ID, contact.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
|
||||||
|
const (
|
||||||
|
selectQuery = "SELECT a.contact_type_id, a.name, a.key FROM tab_contact_type a WHERE a.key = ?"
|
||||||
|
query = "INSERT INTO tab_organization_contact(organization_contact_uuid, organization_id, contact_type_id, contact, contact_name, contact_desc, created_user_id, updated_user_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
if contact.Organization == nil {
|
||||||
|
return entity.OrganizationContact{}, errors.NewNotFoundError()
|
||||||
|
}
|
||||||
|
|
||||||
|
organization, err := c.GetByUUID(contact.Organization.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.OrganizationContact{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(selectQuery, contact.Type.Key)
|
||||||
|
err = row.Scan(&contact.Type.ID, &contact.Type.Value, &contact.Type.Key)
|
||||||
|
if err != nil {
|
||||||
|
return entity.OrganizationContact{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
result, err := c.conn.Exec(query, UUID.String(), organization.ID, contact.Type.ID, contact.Contact, contact.Name, contact.Description, contact.CreatedUser.ID, contact.UpdatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.OrganizationContact{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contact.ID, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return contact, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return contact, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *organizationRepo) AddOrganization(organization entity.Organization) (entity.Organization, error) {
|
||||||
|
const (
|
||||||
|
queryOrgType = "SELECT a.organization_type_id FROM tab_organization_type a WHERE a.organization_type_key = ?;"
|
||||||
|
queryParentOrg = "SELECT a.organization_id FROM tab_organization a WHERE a.organization_uuid = ?;"
|
||||||
|
query = "INSERT INTO tab_organization(organization_uuid, organization_type_id, organization_name, organization_description, organization_reference_id, organization_parent_id, main_organization, created_user, updated_user) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(queryOrgType, organization.Type.Key)
|
||||||
|
err := row.Scan(&organization.Type.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization.Parent != nil && organization.Parent.UUID != "" {
|
||||||
|
row := c.conn.QueryRow(queryParentOrg, organization.Parent.UUID)
|
||||||
|
err := row.Scan(&organization.Parent.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
organization.ParentID = organization.Parent.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
organization.UUID = UUID.String()
|
||||||
|
result, err := c.conn.Exec(query, organization.UUID, organization.Type.ID, organization.Name, organization.Description, organization.ReferenceID, organization.ParentID, false, organization.Author.ID, organization.LastEditor.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ID, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
organization.ID = ID
|
||||||
|
if len(organization.Addresses) > 0 {
|
||||||
|
for i, a := range organization.Addresses {
|
||||||
|
a.Organization = &organization
|
||||||
|
address, err := c.SetOrganizationAddress(a)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save addresses")
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
organization.Addresses[i] = address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(organization.Contacts) > 0 {
|
||||||
|
for i, ct := range organization.Contacts {
|
||||||
|
ct.Organization = &organization
|
||||||
|
contact, err := c.SetOrganizationContact(ct)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save contacts")
|
||||||
|
return entity.Organization{}, err
|
||||||
|
}
|
||||||
|
organization.Contacts[i] = contact
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return organization, nil
|
||||||
|
}
|
||||||
77
data/datamysql/profile.go
Normal file
77
data/datamysql/profile.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
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 profileRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProfileRepo(conn executor) *profileRepo {
|
||||||
|
return &profileRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *profileRepo) getQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.profile_id,
|
||||||
|
a.name,
|
||||||
|
a.key,
|
||||||
|
a.description,
|
||||||
|
a.create_time,
|
||||||
|
a.update_time,
|
||||||
|
(a.active = b'1') active,
|
||||||
|
(a.visible = b'1') visible
|
||||||
|
FROM
|
||||||
|
tab_profile a `
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *profileRepo) parseSet(rows *sql.Rows, err error) ([]entity.Profile, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.Profile, 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 *profileRepo) parseEntity(row scanner) (retVal entity.Profile, err error) {
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.Name, &retVal.Key, &retVal.Description, &retVal.Created, &retVal.Updated, &retVal.Active, &retVal.Visible)
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *profileRepo) GetAll() ([]entity.Profile, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *profileRepo) GetByKey(key string) (entity.Profile, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+"WHERE a.active = 1 AND a.key = ?", key))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *profileRepo) GetVisibles(visible bool) ([]entity.Profile, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+"WHERE a.active = 1 AND a.visible = ?", visible))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *profileRepo) GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery()+" INNER JOIN tab_organization_type_profile b ON a.profile_id = b.profile_id WHERE a.active = 1 AND a.visible = 1 AND b.organization_type_id = ?", organizationTypeID))
|
||||||
|
}
|
||||||
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
|
||||||
|
}
|
||||||
826
data/datamysql/ride.go
Normal file
826
data/datamysql/ride.go
Normal file
@@ -0,0 +1,826 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"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 rideRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRideRepo(conn executor) *rideRepo {
|
||||||
|
return &rideRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) getQuery() string {
|
||||||
|
const query = `SELECT
|
||||||
|
a.ride_id,
|
||||||
|
a.ride_uuid,
|
||||||
|
b.user_id,
|
||||||
|
b.user_uuid,
|
||||||
|
b.name,
|
||||||
|
b.member,
|
||||||
|
c.ride_status_id,
|
||||||
|
c.ride_status,
|
||||||
|
c.key ride_status_key,
|
||||||
|
d.ride_type_id,
|
||||||
|
d.value ride_type,
|
||||||
|
d.key ride_type_key,
|
||||||
|
a.notes,
|
||||||
|
e.first_name,
|
||||||
|
e.last_name,
|
||||||
|
e.image_url,
|
||||||
|
e.phone_number,
|
||||||
|
e.internal_user_id,
|
||||||
|
IFNULL(f.name, '') driver_name,
|
||||||
|
IFNULL(f.phone_number, '') driver_phone_number,
|
||||||
|
IFNULL(f.image_url, '') driver_image_url,
|
||||||
|
IFNULL(f.rating, '') driver_rating,
|
||||||
|
IFNULL(g.color, '') vehicle_color,
|
||||||
|
IFNULL(g.image_url, '') vehicle_image_url,
|
||||||
|
IFNULL(g.license_plate, '') vehicle_license_plate,
|
||||||
|
IFNULL(g.license_plate_state, '') vehicle_license_state,
|
||||||
|
IFNULL(g.make, '') vehicle_make,
|
||||||
|
IFNULL(g.model, '') vehicle_model,
|
||||||
|
IFNULL(g.year, 0) vehicle_year,
|
||||||
|
h.origin_name,
|
||||||
|
h.origin_address,
|
||||||
|
h.origin_lat,
|
||||||
|
h.origin_lng,
|
||||||
|
h.destination_name,
|
||||||
|
h.destination_address,
|
||||||
|
h.destination_lat,
|
||||||
|
h.destination_lng,
|
||||||
|
IFNULL(h.route_kml, '') route_kml,
|
||||||
|
IFNULL(h.distance, 0) distance,
|
||||||
|
IFNULL(h.duration, 0) duration,
|
||||||
|
IFNULL(h.eta, 0) eta,
|
||||||
|
a.pickup_time,
|
||||||
|
a.visit_date,
|
||||||
|
a.visit_time,
|
||||||
|
a.ride_internal_id,
|
||||||
|
a.visit_id,
|
||||||
|
i.visit_uuid,
|
||||||
|
IFNULL(i.pickup_id, '') visit_pickup_id,
|
||||||
|
IFNULL(i.pickup_address_id, 0) pickup_address_id,
|
||||||
|
IFNULL(i.address_id, 0) address_id,
|
||||||
|
IFNULL(i.provider_id, 0) provider_id,
|
||||||
|
IFNULL(o.provider_uuid, '') provider_uuid,
|
||||||
|
IFNULL(o.provider_internal_id, '') provider_internal_id,
|
||||||
|
IFNULL(o.provider_muk_id, '') provider_muk_id,
|
||||||
|
IFNULL(o.provider_name, '') provider_name,
|
||||||
|
-- i.pickup_name visit_pickup_name,
|
||||||
|
-- i.pickup_address visit_pickup_address,
|
||||||
|
-- i.pickup_lat visit_pickup_lat,
|
||||||
|
-- i.pickup_lng visit_pickup_lng,
|
||||||
|
-- IFNULL(i.destination_id, '') visit_destination_id,
|
||||||
|
-- i.destination_name visit_destination_name,
|
||||||
|
-- i.destination_address visit_destination_address,
|
||||||
|
-- i.destination_lat visit_destination_lat,
|
||||||
|
-- i.destination_lng visit_destination_lng,
|
||||||
|
IFNULL(i.visit_external_id, '') visit_external_id,
|
||||||
|
i.created_user_id,
|
||||||
|
j.user_uuid created_user_uuid,
|
||||||
|
j.name created_name,
|
||||||
|
IFNULL(k.phone_number, '') created_user_phone_number,
|
||||||
|
IFNULL(k.email, '') created_user_email,
|
||||||
|
IFNULL(l.phone_number, '') user_phone_number,
|
||||||
|
IFNULL(l.email, '') user_email,
|
||||||
|
a.create_date,
|
||||||
|
a.update_date,
|
||||||
|
m.trip_type_id,
|
||||||
|
m.trip_type_key,
|
||||||
|
m.trip_type,
|
||||||
|
n.trip_type_id visit_trip_type_id,
|
||||||
|
n.trip_type_key visit_trip_type_key,
|
||||||
|
n.trip_type visit_trip_type_key,
|
||||||
|
i.return_date
|
||||||
|
FROM tab_ride a
|
||||||
|
INNER JOIN tab_user b
|
||||||
|
ON a.user_id = b.user_id
|
||||||
|
INNER JOIN tab_ride_status c
|
||||||
|
ON c.ride_status_id = a.ride_status_id
|
||||||
|
INNER JOIN tab_ride_type d
|
||||||
|
ON d.ride_type_id = a.ride_type_id
|
||||||
|
INNER JOIN tab_ride_passenger e
|
||||||
|
ON e.ride_id = a.ride_id
|
||||||
|
LEFT JOIN tab_ride_driver f
|
||||||
|
ON f.ride_id = a.ride_id
|
||||||
|
LEFT JOIN tab_ride_vehicle g
|
||||||
|
ON g.ride_id = a.ride_id
|
||||||
|
INNER JOIN tab_ride_route h
|
||||||
|
ON h.ride_id = a.ride_id
|
||||||
|
INNER JOIN tab_visit i
|
||||||
|
ON i.visit_id = a.visit_id
|
||||||
|
INNER JOIN tab_user j
|
||||||
|
ON j.user_id = i.created_user_id
|
||||||
|
INNER JOIN tab_login k
|
||||||
|
ON k.user_id = j.user_id
|
||||||
|
INNER JOIN tab_login l
|
||||||
|
ON l.user_id = a.user_id
|
||||||
|
INNER JOIN tab_trip_type m
|
||||||
|
ON m.trip_type_id = a.trip_type_id
|
||||||
|
INNER JOIN tab_trip_type n
|
||||||
|
ON n.trip_type_id = i.trip_type_id
|
||||||
|
INNER JOIN tab_provider o
|
||||||
|
ON i.provider_id = o.provider_id `
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) 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_visit_provider o ON a.ride_id = o.ride_id`
|
||||||
|
where = fmt.Sprintf(` AND (o.organization_uuid = '%s' OR o.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 *rideRepo) Update(hook entity.WebhookResponse, user entity.User) (retVal entity.Ride, err error) {
|
||||||
|
oldRide, err := c.GetByUUID(hook.Ride.UUID, user)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.updateHeader(hook.Ride)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.updateLocation(hook.Ride)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// retVal, err = c.updatePassenger(hook.Ride)
|
||||||
|
// if err != nil {
|
||||||
|
// return retVal, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
if oldRide.Driver.Name != "" {
|
||||||
|
retVal, err = c.updateDriver(hook.Ride)
|
||||||
|
} else {
|
||||||
|
retVal, err = c.saveDriver(hook.Ride)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldRide.Vehicle.LicensePlate != "" {
|
||||||
|
retVal, err = c.updateVehicle(hook.Ride)
|
||||||
|
} else {
|
||||||
|
retVal, err = c.saveVehicle(hook.Ride)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := c.saveHistory(hook)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save history: " + err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) updateVehicle(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_ride_vehicle
|
||||||
|
SET
|
||||||
|
color = ?,
|
||||||
|
image_url = ?,
|
||||||
|
license_plate = ?,
|
||||||
|
license_plate_state = ?,
|
||||||
|
make = ?,
|
||||||
|
model = ?,
|
||||||
|
year = ?
|
||||||
|
WHERE ride_id = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
_, err = c.conn.Exec(query, ride.Vehicle.Color, ride.Vehicle.ImageURL, ride.Vehicle.LicensePlate, ride.Vehicle.LicensePlateState, ride.Vehicle.Make, ride.Vehicle.Model, ride.Vehicle.Year, ride.ID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) updateDriver(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_ride_driver
|
||||||
|
SET
|
||||||
|
name = ?,
|
||||||
|
image_url = ?,
|
||||||
|
phone_number = ?,
|
||||||
|
rating = ?
|
||||||
|
WHERE ride_id = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
_, err = c.conn.Exec(query, ride.Driver.Name, ride.Driver.ImageURL, ride.Driver.PhoneNumber, ride.Driver.Rating, ride.ID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) updatePassenger(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = `UPDATE tab_ride_passenger
|
||||||
|
SET
|
||||||
|
first_name = ?,
|
||||||
|
last_name = ?,
|
||||||
|
image_url = ?,
|
||||||
|
phone_number = ?,
|
||||||
|
internal_user_id = ?
|
||||||
|
WHERE ride_id = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
_, err = c.conn.Exec(query, ride.Passenger.FirstName, ride.Passenger.LastName, ride.Passenger.ImageURL, ride.Passenger.PhoneNumber, ride.Passenger.InternalID, ride.ID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) updateLocation(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
query := `UPDATE tab_ride_route
|
||||||
|
SET
|
||||||
|
origin_address = ?,
|
||||||
|
origin_lat = ?,
|
||||||
|
origin_lng = ?,
|
||||||
|
destination_address = ?,
|
||||||
|
destination_lat = ?,
|
||||||
|
destination_lng = ?,
|
||||||
|
route_kml = ?,
|
||||||
|
distance = ?,
|
||||||
|
duration = ?,
|
||||||
|
eta = ?`
|
||||||
|
where := ` WHERE ride_id = ?;`
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
params := make([]interface{}, 0)
|
||||||
|
params = append(params, ride.Route.Origin.Address, ride.Route.Origin.Latitude, ride.Route.Origin.Longitude, ride.Route.Destination.Address, ride.Route.Destination.Latitude, ride.Route.Destination.Longitude, ride.Route.RouteKML, ride.Route.Distance, ride.Route.Duration, ride.Route.ETA)
|
||||||
|
|
||||||
|
if retVal.Route.Origin.Name != "" {
|
||||||
|
query += " , origin_name = ? "
|
||||||
|
params = append(params, ride.Route.Origin.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Route.Destination.Name != "" {
|
||||||
|
query += " , destination_name = ? "
|
||||||
|
params = append(params, ride.Route.Destination.Name)
|
||||||
|
}
|
||||||
|
params = append(params, ride.ID)
|
||||||
|
|
||||||
|
_, err = c.conn.Exec(query+where, params...)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) updateHeader(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
statusQuery = "SELECT ride_status_id FROM tab_ride_status WHERE `key` = ?"
|
||||||
|
query = `UPDATE tab_ride
|
||||||
|
SET
|
||||||
|
ride_status_id = ?,
|
||||||
|
ride_type_id = ?,
|
||||||
|
ride_internal_id = ?,
|
||||||
|
request_date = ?,
|
||||||
|
request_ms = ?,
|
||||||
|
generate_date = ?,
|
||||||
|
generate_ms = ?,
|
||||||
|
route_kml = ?,
|
||||||
|
notes = ?,
|
||||||
|
primetime_percentage = ?,
|
||||||
|
pickup_time = ?,
|
||||||
|
visit_date = ?,
|
||||||
|
visit_time = ?,
|
||||||
|
visit_id = ?
|
||||||
|
WHERE ride_uuid = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(statusQuery, ride.Status.Key)
|
||||||
|
err = row.Scan(&ride.Status.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to get status")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
_, err = c.conn.Exec(query, ride.Status.ID, ride.Type.ID, ride.InternalID, ride.RequestDate, ride.RequestMiliseconds, ride.GenerateDate, ride.GenerateMiliseconds, ride.Route.RouteKML, ride.Note, ride.PrimetimePercentage, ride.PickupTime, ride.VisitDate, ride.VisitTime, ride.Visit.ID, ride.UUID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ride, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) Save(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
retVal, err = c.saveHeader(ride)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save header")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.saveLocation(retVal)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save location")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.savePassenger(retVal)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save passenger")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.saveDriver(retVal)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save driver")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.saveVehicle(retVal)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save vehicle")
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
hook := entity.WebhookResponse{
|
||||||
|
Ride: retVal,
|
||||||
|
}
|
||||||
|
err = c.saveHistory(hook)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save history: ", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveHistory(hook entity.WebhookResponse) error {
|
||||||
|
rideHistoryID, err := c.saveHistoryHeader(hook)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error to save header history")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.saveLocationHistory(rideHistoryID, hook.Ride.Route); err != nil {
|
||||||
|
fmt.Println("Error to save location history")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.savePassengerHistory(rideHistoryID, hook.Ride.Passenger); err != nil {
|
||||||
|
fmt.Println("Error to save passenger history")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.saveDriverHistory(rideHistoryID, hook.Ride.Driver); err != nil {
|
||||||
|
fmt.Println("Error to save driver history")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.saveVehicleHistory(rideHistoryID, hook.Ride.Vehicle); err != nil {
|
||||||
|
fmt.Println("Error to save vehicle history")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveVehicleHistory(rideHistoryID int64, vehicle entity.RideVehicle) error {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_ride_vehicle_history(ride_history_id,color,image_url,license_plate,license_plate_state,make,model,`year`) VALUES(?,?,?,?,?,?,?,?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
if vehicle.Make != "" && vehicle.Model != "" && vehicle.Color != "" && vehicle.Year > 0 {
|
||||||
|
_, err := c.conn.Exec(query, rideHistoryID, vehicle.Color, vehicle.ImageURL, vehicle.LicensePlate, vehicle.LicensePlateState, vehicle.Make, vehicle.Model, vehicle.Year)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveDriverHistory(rideHistoryID int64, driver entity.RideDriver) error {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_ride_driver_history(ride_history_id,name,image_url,phone_number,rating) VALUES(?,?,?,?,?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
if driver.Name != "" && driver.PhoneNumber != "" {
|
||||||
|
_, err := c.conn.Exec(query, rideHistoryID, driver.Name, driver.ImageURL, driver.PhoneNumber, driver.Rating)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) savePassengerHistory(rideHistoryID int64, passenger entity.RidePassenger) error {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_ride_passenger_history(ride_history_id,first_name,last_name,image_url,phone_number,internal_user_id) VALUES(?,?,?,?,?,?)"
|
||||||
|
)
|
||||||
|
|
||||||
|
_, err := c.conn.Exec(query, rideHistoryID, passenger.FirstName, passenger.LastName, "", passenger.PhoneNumber, passenger.InternalID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveLocationHistory(rideHistoryID int64, route entity.RideRoute) error {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_ride_route_history(ride_history_id,origin_name,origin_address,origin_lat,origin_lng,destination_name,destination_address,destination_lat,destination_lng,route_kml,distance,duration,eta)
|
||||||
|
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
if route.Origin.Latitude != 0 && route.Origin.Longitude != 0 && route.Destination.Latitude != 0 && route.Destination.Longitude != 0 {
|
||||||
|
_, err := c.conn.Exec(query, rideHistoryID, route.Origin.Name, route.Origin.Address, route.Origin.Latitude, route.Origin.Longitude, route.Destination.Name, route.Destination.Address, route.Destination.Latitude, route.Destination.Longitude, route.RouteKML, route.Distance, route.Duration, route.ETA)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveHistoryHeader(hook entity.WebhookResponse) (int64, error) {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_ride_history(ride_history_uuid,ride_id,event_id,href,occurred_at,event_type,ride_internal_id,ride_status_id,ride_type_id,request_date,request_ms,generate_date,generate_ms,route_kml,notes, primetime_percentage, pickup_time, visit_date, visit_time, visit_id)
|
||||||
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
sUUID := UUID.String()
|
||||||
|
|
||||||
|
if hook.OccurredAt.IsZero() {
|
||||||
|
hook.OccurredAt = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := c.conn.Exec(query, sUUID, hook.Ride.ID, hook.EventID, hook.HREF, hook.OccurredAt, hook.EventType, hook.Ride.InternalID, hook.Ride.Status.ID, hook.Ride.Type.ID, hook.Ride.RequestDate, hook.Ride.RequestMiliseconds, hook.Ride.GenerateDate, hook.Ride.GenerateMiliseconds, hook.Ride.Route.RouteKML, hook.Ride.Note, hook.Ride.PrimetimePercentage, hook.Ride.PickupTime, hook.Ride.VisitDate, hook.Ride.VisitTime, hook.Ride.Visit.ID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.LastInsertId()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveHeader(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
dataQuery = `SELECT
|
||||||
|
a.user_id user_id,
|
||||||
|
a.name,
|
||||||
|
a.member,
|
||||||
|
b.ride_status_id,
|
||||||
|
b.ride_status,
|
||||||
|
c.ride_type_id,
|
||||||
|
c.value ride_type,
|
||||||
|
d.user_id created_user_id,
|
||||||
|
d.name created_name,
|
||||||
|
IFNULL(d.member, '') created_member,
|
||||||
|
e.trip_type_id,
|
||||||
|
e.trip_type_key,
|
||||||
|
e.trip_type
|
||||||
|
FROM tab_user a,
|
||||||
|
tab_ride_status b,
|
||||||
|
tab_ride_type c,
|
||||||
|
tab_user d,
|
||||||
|
tab_trip_type e
|
||||||
|
WHERE
|
||||||
|
a.user_uuid = ?
|
||||||
|
AND b.key = ?
|
||||||
|
AND c.key = ?
|
||||||
|
AND d.user_uuid = ?
|
||||||
|
AND e.trip_type_key = ?;`
|
||||||
|
|
||||||
|
query = `INSERT INTO tab_ride(ride_uuid, user_id, ride_status_id, ride_type_id, ride_internal_id, request_date, request_ms, generate_date, generate_ms, notes, primetime_percentage, pickup_time, visit_date, visit_time, visit_id, created_user_id, trip_type_id)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
retVal.UUID = UUID.String()
|
||||||
|
|
||||||
|
if retVal.Status.Key == "" {
|
||||||
|
retVal.Status.Key = "accepted"
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Type.Key == "" {
|
||||||
|
retVal.Type.Key = "lyft"
|
||||||
|
}
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(dataQuery, retVal.User.UUID, retVal.Status.Key, retVal.Type.Key, retVal.CreatedUser.UUID, retVal.TripType.Key)
|
||||||
|
if err = row.Scan(&retVal.User.ID, &retVal.User.Name, &retVal.User.Member, &retVal.Status.ID, &retVal.Status.Value, &retVal.Type.ID, &retVal.Type.Value, &retVal.CreatedUser.ID, &retVal.CreatedUser.Name, &retVal.CreatedUser.Member, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value); err != nil {
|
||||||
|
fmt.Println("Error to get base data: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := c.conn.Exec(query, retVal.UUID, retVal.User.ID, retVal.Status.ID, retVal.Type.ID, retVal.InternalID, retVal.RequestDate, retVal.RequestMiliseconds, retVal.GenerateDate, retVal.GenerateMiliseconds, retVal.Note, retVal.PrimetimePercentage, retVal.PickupTime, retVal.VisitDate, retVal.VisitTime, retVal.Visit.ID, retVal.CreatedUser.ID, retVal.TripType.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ID int64
|
||||||
|
ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Getting the ID: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.ID = ID
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveLocation(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_ride_route(ride_id,origin_name,origin_address,origin_lat,origin_lng,destination_name,destination_address,destination_lat,destination_lng,route_kml,distance,duration,eta)
|
||||||
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
results, err := c.conn.Exec(query, retVal.ID, retVal.Route.Origin.Name, retVal.Route.Origin.Address, retVal.Route.Origin.Latitude, retVal.Route.Origin.Longitude, retVal.Route.Destination.Name, retVal.Route.Destination.Address, retVal.Route.Destination.Latitude, retVal.Route.Destination.Longitude, retVal.Route.RouteKML, retVal.Route.Distance, retVal.Route.Duration, retVal.Route.ETA)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ID int64
|
||||||
|
ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Getting the ID: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Route.ID = ID
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) savePassenger(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_ride_passenger(ride_id,first_name,last_name,image_url,phone_number,internal_user_id)
|
||||||
|
VALUES(?,?,?,?,?,?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
results, err := c.conn.Exec(query, retVal.ID, ride.Passenger.FirstName, ride.Passenger.LastName, ride.Passenger.ImageURL, ride.Passenger.PhoneNumber, ride.Passenger.InternalID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ID int64
|
||||||
|
ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Getting the ID: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Passenger.ID = ID
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveDriver(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_ride_driver(ride_id,`name`,image_url,phone_number,rating) VALUES(?,?,?,?,?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
if retVal.Driver.Name != "" && retVal.Driver.PhoneNumber != "" {
|
||||||
|
results, err := c.conn.Exec(query, retVal.ID, ride.Driver.Name, ride.Driver.ImageURL, ride.Driver.PhoneNumber, ride.Driver.Rating)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ID int64
|
||||||
|
ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Getting the ID: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
retVal.Driver.ID = ID
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) saveVehicle(ride entity.Ride) (retVal entity.Ride, err error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_ride_vehicle(ride_id,color,image_url,license_plate,license_plate_state,make,model,`year`) VALUES(?,?,?,?,?,?,?,?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal = ride
|
||||||
|
if retVal.Vehicle.Color != "" && retVal.Vehicle.LicensePlate != "" && retVal.Vehicle.Make != "" && retVal.Vehicle.Model != "" && retVal.Vehicle.Year > 0 {
|
||||||
|
results, err := c.conn.Exec(query, retVal.ID, ride.Vehicle.Color, ride.Vehicle.ImageURL, ride.Vehicle.LicensePlate, ride.Vehicle.LicensePlateState, ride.Vehicle.Make, ride.Vehicle.Model, ride.Vehicle.Year)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ID int64
|
||||||
|
ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error Getting the ID: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Vehicle.ID = ID
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE a.ride_uuid = ? " + where
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, uuid))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByID(id int64, user entity.User) (entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE a.ride_id = ? " + where
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.ride_uuid = ? AND b.user_uuid = ?", UUID, userUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error) {
|
||||||
|
query := c.getQuery() + ` WHERE c.ride_status IN ('accepted', 'arrived', 'scheduled', 'pending')
|
||||||
|
AND l.phone_number = ?
|
||||||
|
ORDER BY a.create_date DESC
|
||||||
|
LIMIT 1;`
|
||||||
|
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, phoneNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error) {
|
||||||
|
query := c.getQuery() + ` WHERE c.ride_status IN ('accepted', 'arrived', 'scheduled', 'pending')
|
||||||
|
AND IFNULL(f.phone_number, '') = ?
|
||||||
|
ORDER BY a.create_date DESC
|
||||||
|
LIMIT 1;`
|
||||||
|
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, phoneNumber))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByInternalID(internalID string) (entity.Ride, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE a.ride_internal_id = ?", internalID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error) {
|
||||||
|
return c.parseEntity(c.conn.QueryRow(c.getQuery()+" WHERE e.internal_user_id = ?", internalPassengerID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByUserID(userID int64, user entity.User) ([]entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE b.user_id = ? " + where
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(query, userID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE b.user_uuid = ? " + where
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(query, userUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE b.user_id = ? " + where
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(query, visitUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE i.visit_uuid = ? AND m.trip_type_key = ? " + where
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, visitUUID, tripTypeKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) parseSet(rows *sql.Rows, err error) ([]entity.Ride, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.Ride, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseEntity(rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result = append(result, entity)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) parseEntity(row scanner) (r entity.Ride, err error) {
|
||||||
|
var returnDate mysql.NullTime
|
||||||
|
|
||||||
|
err = row.Scan(&r.ID, &r.UUID, &r.User.ID, &r.User.UUID, &r.User.Name, &r.User.Member, &r.Status.ID, &r.Status.Value, &r.Status.Key, &r.Type.ID, &r.Type.Value, &r.Type.Key, &r.Note, &r.Passenger.FirstName, &r.Passenger.LastName, &r.Passenger.ImageURL, &r.Passenger.PhoneNumber, &r.Passenger.InternalID, &r.Driver.Name, &r.Driver.PhoneNumber, &r.Driver.ImageURL, &r.Driver.Rating, &r.Vehicle.Color, &r.Vehicle.ImageURL, &r.Vehicle.LicensePlate, &r.Vehicle.LicensePlateState, &r.Vehicle.Make, &r.Vehicle.Model, &r.Vehicle.Year, &r.Route.Origin.Name, &r.Route.Origin.Address, &r.Route.Origin.Latitude, &r.Route.Origin.Longitude, &r.Route.Destination.Name, &r.Route.Destination.Address, &r.Route.Destination.Latitude, &r.Route.Destination.Longitude, &r.Route.RouteKML, &r.Route.Distance, &r.Route.Duration, &r.Route.ETA, &r.PickupTime, &r.VisitDate, &r.VisitTime, &r.InternalID, &r.Visit.ID, &r.Visit.UUID, &r.Visit.Pickup.ID, &r.Visit.PickupAddressID, &r.Visit.DestinationAddressID, &r.Visit.Provider.ProviderID, &r.Visit.Provider.ProviderUUID, &r.Visit.Provider.InternalID, &r.Visit.Provider.MukID, &r.Visit.Provider.Name, &r.Visit.ExternalID, &r.Visit.CreatedUser.ID, &r.Visit.CreatedUser.UUID, &r.Visit.CreatedUser.Name, &r.Visit.CreatedUser.PhoneNumber, &r.Visit.CreatedUser.Email, &r.User.PhoneNumber, &r.User.Email, &r.Created, &r.Updated, &r.TripType.ID, &r.TripType.Key, &r.TripType.Value, &r.Visit.TripType.ID, &r.Visit.TripType.Key, &r.Visit.TripType.Value, &returnDate)
|
||||||
|
if err != nil {
|
||||||
|
return r, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.CreatedUser = r.Visit.CreatedUser
|
||||||
|
if returnDate.Valid {
|
||||||
|
r.Visit.ReturnDate = &returnDate.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) UpdateStatus(rideUUID string, status string) error {
|
||||||
|
const (
|
||||||
|
statusQuery = "SELECT ride_status_id FROM tab_ride_status WHERE `key` = ?"
|
||||||
|
query = "UPDATE tab_ride SET ride_status_id = ? WHERE ride_uuid = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rideStatusID int64
|
||||||
|
row := c.conn.QueryRow(statusQuery, status)
|
||||||
|
err := row.Scan(&rideStatusID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.conn.Exec(query, rideStatusID, rideUUID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *rideRepo) GetAll(user entity.User) ([]entity.Ride, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE 1 = 1 AND b.active = 1 " + where
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(query))
|
||||||
|
}
|
||||||
87
data/datamysql/transaction.go
Normal file
87
data/datamysql/transaction.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type transaction struct {
|
||||||
|
tx *sql.Tx
|
||||||
|
users *userRepo
|
||||||
|
rides *rideRepo
|
||||||
|
visits *visitRepo
|
||||||
|
provider *providerRepo
|
||||||
|
notification *notificationRepo
|
||||||
|
profile *profileRepo
|
||||||
|
organization *organizationRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTransaction(tx *sql.Tx) *transaction {
|
||||||
|
|
||||||
|
t := new(transaction)
|
||||||
|
|
||||||
|
t.tx = tx
|
||||||
|
t.users = newUserRepo(tx)
|
||||||
|
t.rides = newRideRepo(tx)
|
||||||
|
t.visits = newVisitRepo(tx)
|
||||||
|
t.provider = newProviderRepo(tx)
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Users returns the users set
|
||||||
|
func (t transaction) Users() contract.UserRepo {
|
||||||
|
return t.users
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rides returns the rides set
|
||||||
|
func (t transaction) Rides() contract.RideRepo {
|
||||||
|
return t.rides
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rides returns the rides set
|
||||||
|
func (t transaction) Visits() contract.VisitRepo {
|
||||||
|
return t.visits
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (t transaction) Provider() contract.ProviderRepo {
|
||||||
|
return t.provider
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (t transaction) Profile() contract.ProfileRepo {
|
||||||
|
return t.profile
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (t transaction) Notification() contract.NotificationRepo {
|
||||||
|
return t.notification
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider returns the rides set
|
||||||
|
func (t transaction) Organization() contract.OrganizationRepo {
|
||||||
|
return t.organization
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transaction) Commit() error {
|
||||||
|
|
||||||
|
err := t.tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transaction) Rollback() error {
|
||||||
|
|
||||||
|
err := t.tx.Rollback()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
825
data/datamysql/user.go
Normal file
825
data/datamysql/user.go
Normal file
@@ -0,0 +1,825 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userRepo maps methods to database
|
||||||
|
type userRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUserRepo(conn executor) *userRepo {
|
||||||
|
return &userRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetByUUID(uuid string, profile string) (entity.User, error) {
|
||||||
|
params := make([]interface{}, 0)
|
||||||
|
params = append(params, uuid)
|
||||||
|
finalQuery := c.getQuery() + " AND a.user_uuid = ? "
|
||||||
|
if profile == "US" {
|
||||||
|
finalQuery += " AND e.key = ? "
|
||||||
|
params = append(params, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := c.parseSet(c.conn.Query(finalQuery, params...))
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user) > 0 {
|
||||||
|
retVal := user[0]
|
||||||
|
retVal.Contacts, err = c.GetContacts(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Addresses = nil
|
||||||
|
retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
} else {
|
||||||
|
return entity.User{}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetContacts(userID int64) ([]entity.ContactInfo, error) {
|
||||||
|
const (
|
||||||
|
query = `
|
||||||
|
SELECT
|
||||||
|
a.contact_id,
|
||||||
|
a.contact,
|
||||||
|
a.user_id,
|
||||||
|
b.contact_type_id,
|
||||||
|
b.key contact_type_key,
|
||||||
|
b.name contact_type_name
|
||||||
|
FROM tab_contact a
|
||||||
|
INNER JOIN tab_contact_type b
|
||||||
|
ON a.contact_type_id = b.contact_type_id
|
||||||
|
WHERE a.user_id = ?;
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
rows, err := c.conn.Query(query, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal := make([]entity.ContactInfo, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
contact := entity.ContactInfo{}
|
||||||
|
err = rows.Scan(&contact.ID, &contact.Value, &contact.UserID, &contact.Type.ID, &contact.Type.Key, &contact.Type.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
retVal = append(retVal, contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetUsersByProfile(profile string) ([]entity.User, error) {
|
||||||
|
query := c.getQuery()
|
||||||
|
if profile == "" {
|
||||||
|
query += "AND e.key <> 'US' "
|
||||||
|
return c.parseSet(c.conn.Query(query))
|
||||||
|
} else {
|
||||||
|
return c.parseSet(c.conn.Query(query+"AND e.key = ? AND a.active = 1 ", profile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) parseSet(rows *sql.Rows, err error) ([]entity.User, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.User, 0)
|
||||||
|
var lastUser entity.User
|
||||||
|
for rows.Next() {
|
||||||
|
entity, err := c.parseEntity(rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entity.UUID == lastUser.UUID {
|
||||||
|
lastUser.Profiles = append(lastUser.Profiles, entity.Profiles...)
|
||||||
|
} else {
|
||||||
|
if lastUser.UUID != "" {
|
||||||
|
result = append(result, lastUser)
|
||||||
|
}
|
||||||
|
lastUser = entity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, lastUser)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetContactType() (retVal []entity.ContactType, err error) {
|
||||||
|
const (
|
||||||
|
query = `
|
||||||
|
SELECT
|
||||||
|
a.contact_type_id,
|
||||||
|
a.key,
|
||||||
|
a.name
|
||||||
|
FROM tab_contact_type a
|
||||||
|
WHERE a.visible = 1 `
|
||||||
|
)
|
||||||
|
|
||||||
|
rows, err := c.conn.Query(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = make([]entity.ContactType, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
var contactType entity.ContactType
|
||||||
|
err = rows.Scan(&contactType.ID, &contactType.Key, &contactType.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = append(retVal, contactType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseEntity parses a result to an entity
|
||||||
|
func (c *userRepo) parseEntity(row scanner) (retVal entity.User, err error) {
|
||||||
|
var profile entity.Profile
|
||||||
|
var birthDate mysql.NullTime
|
||||||
|
|
||||||
|
var homeAddress entity.Address
|
||||||
|
var workAddress entity.Address
|
||||||
|
|
||||||
|
err = row.Scan(&retVal.ID, &retVal.UUID, &retVal.Name, &retVal.Member, &birthDate, &retVal.LoginID, &retVal.LoginUUID, &retVal.Email, &retVal.PhoneNumber, &retVal.LoginKey, &retVal.Gender, &retVal.Active, &retVal.Created, &retVal.Updated, &profile.ID, &profile.Name, &profile.Key, &profile.Active, &profile.Blocked, &profile.Suspended, &profile.Created, &profile.Updated, &profile.Organization.ID, &profile.Organization.UUID, &profile.Organization.Type.ID, &profile.Organization.Type.Name, &profile.Organization.Type.Key, &profile.Organization.Type.Description, &profile.Organization.Name, &profile.Organization.Description, &profile.Organization.ReferenceID, &profile.Organization.ParentID, &profile.Organization.Main,
|
||||||
|
&homeAddress.ID, &homeAddress.UUID, &homeAddress.AddressType.ID, &homeAddress.AddressType.Key, &homeAddress.AddressType.Name, &homeAddress.Name, &homeAddress.Address, &homeAddress.Latitude, &homeAddress.Longitude,
|
||||||
|
&workAddress.ID, &workAddress.UUID, &workAddress.AddressType.ID, &workAddress.AddressType.Key, &workAddress.AddressType.Name, &workAddress.Name, &workAddress.Address, &workAddress.Latitude, &workAddress.Longitude)
|
||||||
|
if err != nil {
|
||||||
|
if err != sql.ErrNoRows {
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if birthDate.Valid {
|
||||||
|
retVal.BirthDate = birthDate.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Profiles = append(retVal.Profiles, profile)
|
||||||
|
if homeAddress.ID > 0 {
|
||||||
|
retVal.Addresses = append(retVal.Addresses, homeAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
if workAddress.ID > 0 {
|
||||||
|
retVal.Addresses = append(retVal.Addresses, workAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) FullLogin(loginType string, key string, pass string, profile string) (user entity.User, err error) {
|
||||||
|
return c.login(loginType, key, pass, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Login return a user based on email and password with the default `User` profile
|
||||||
|
func (c *userRepo) Login(email string, pass string) (user entity.User, err error) {
|
||||||
|
return c.FullLogin("email", email, pass, "US")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getQuery() string {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.user_id,
|
||||||
|
a.user_uuid,
|
||||||
|
a.name,
|
||||||
|
IFNULL(a.member, '') member,
|
||||||
|
a.birth_date,
|
||||||
|
b.login_id,
|
||||||
|
b.login_uuid,
|
||||||
|
IFNULL(b.email, '') email,
|
||||||
|
IFNULL(b.phone_number, '') phone_number,
|
||||||
|
b.key login_key,
|
||||||
|
IFNULL(a.gender, 'U') gender,
|
||||||
|
(IFNULL(a.active, b'0') = b'1') active,
|
||||||
|
a.create_time,
|
||||||
|
a.update_time,
|
||||||
|
e.profile_id,
|
||||||
|
e.name profile_name,
|
||||||
|
e.key profile_key,
|
||||||
|
(IFNULL(c.active, b'0') = b'1') profile_active,
|
||||||
|
(IFNULL(c.blocked, b'0') = b'1') profile_blocked,
|
||||||
|
(IFNULL(c.suspended, b'0') = b'1') profile_suspended,
|
||||||
|
c.create_date profile_createat,
|
||||||
|
c.update_date profile_updateat,
|
||||||
|
IFNULL(f.organization_id, 0) organization_id,
|
||||||
|
IFNULL(f.organization_uuid, '') organization_uuid,
|
||||||
|
IFNULL(f.organization_type_id, 0) organization_type_id,
|
||||||
|
IFNULL(g.organization_type, '') organization_type,
|
||||||
|
IFNULL(g.organization_type_key, '') organization_type_key,
|
||||||
|
IFNULL(g.description, '') organization_type_desc,
|
||||||
|
IFNULL(f.organization_name, '') organization_name,
|
||||||
|
IFNULL(f.organization_description, '') organization_desc,
|
||||||
|
IFNULL(f.organization_reference_id, 0) organization_reference_id,
|
||||||
|
IFNULL(f.organization_parent_id, 0) organization_parent_id,
|
||||||
|
(IFNULL(f.main_organization, b'0') = b'1') main_organization,
|
||||||
|
IFNULL(h.address_id, 0) home_address_id,
|
||||||
|
IFNULL(h.address_uuid, '') home_address_uuid,
|
||||||
|
IFNULL(h.address_type_id, 0) home_address_type_id,
|
||||||
|
IFNULL(h.address_type_key, '') home_address_type_key,
|
||||||
|
IFNULL(h.address_type_name, '') home_address_type_name,
|
||||||
|
IFNULL(h.name, '') home_name,
|
||||||
|
IFNULL(h.address, '') home_address,
|
||||||
|
IFNULL(h.lat, 0) home_lat,
|
||||||
|
IFNULL(h.long, 0) home_long,
|
||||||
|
IFNULL(i.address_id, 0) work_address_id,
|
||||||
|
IFNULL(i.address_uuid, '') work_address_uuid,
|
||||||
|
IFNULL(i.address_type_id, 0) work_address_type_id,
|
||||||
|
IFNULL(i.address_type_key, '') work_address_type_key,
|
||||||
|
IFNULL(i.address_type_name, '') work_address_type_name,
|
||||||
|
IFNULL(i.name, '') work_name,
|
||||||
|
IFNULL(i.address, '') work_address,
|
||||||
|
IFNULL(i.lat, 0) work_lat,
|
||||||
|
IFNULL(i.long, 0) work_long
|
||||||
|
FROM
|
||||||
|
tab_user a
|
||||||
|
INNER JOIN
|
||||||
|
tab_login b ON a.user_id = b.user_id
|
||||||
|
INNER JOIN
|
||||||
|
tab_profile_login c ON c.login_id = b.login_id
|
||||||
|
INNER JOIN
|
||||||
|
tab_profile e ON e.profile_id = c.profile_id
|
||||||
|
LEFT JOIN
|
||||||
|
tab_organization f ON f.organization_id = IFNULL(c.organization_id, 0)
|
||||||
|
LEFT JOIN
|
||||||
|
tab_organization_type g ON IFNULL(g.organization_type_id, 0) = IFNULL(f.organization_type_id, 0)
|
||||||
|
LEFT JOIN
|
||||||
|
viw_address_home h ON a.user_id = h.user_id
|
||||||
|
LEFT JOIN
|
||||||
|
viw_address_work i ON a.user_id = i.user_id
|
||||||
|
WHERE
|
||||||
|
a.active = b.active
|
||||||
|
AND b.active = c.active
|
||||||
|
AND c.active = e.active `
|
||||||
|
)
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) login(loginType string, key string, pass string, profile string) (user entity.User, err error) {
|
||||||
|
if loginType == "" {
|
||||||
|
return user, errors.NewNullArgumentError("loginType")
|
||||||
|
}
|
||||||
|
|
||||||
|
if loginType != "phone_number" && loginType != "email" {
|
||||||
|
return user, errors.NewValidationError("loginType", "invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
query := fmt.Sprintf(c.getQuery()+`
|
||||||
|
AND a.active = 1
|
||||||
|
AND b.%s = ?
|
||||||
|
AND b.password = sha2(?, 512) `, loginType)
|
||||||
|
|
||||||
|
users, err := c.parseSet(c.conn.Query(query, key, pass))
|
||||||
|
if err != nil {
|
||||||
|
return user, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) Create(user entity.User) (retVal entity.User, err error) {
|
||||||
|
retVal = user
|
||||||
|
|
||||||
|
if retVal.Member != "" {
|
||||||
|
retVal, err = c.getUserByMember(retVal)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.ID == 0 || retVal.Member == "" {
|
||||||
|
userID, guid, err := c.createUser(user)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
retVal.UUID = guid
|
||||||
|
retVal.ID = userID
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, err = c.getUserLogin(retVal)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.LoginID == 0 {
|
||||||
|
loginID, loginGUID, err := c.createLogin(retVal)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
retVal.LoginUUID = loginGUID
|
||||||
|
retVal.LoginID = loginID
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range user.Profiles {
|
||||||
|
companyProfileID, err := c.getCompanyProfile(p.Key)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user.Organizations) > 0 {
|
||||||
|
for _, o := range user.Organizations {
|
||||||
|
err = c.addProfileToUser(retVal.LoginID, companyProfileID, o)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = c.addProfileToUser(retVal.LoginID, companyProfileID, entity.Organization{})
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.Email != "" {
|
||||||
|
contact := entity.ContactInfo{
|
||||||
|
Type: entity.ContactType{Key: "email"},
|
||||||
|
Value: retVal.Email,
|
||||||
|
UserID: retVal.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
contact, err = c.addContactInfo(contact)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if retVal.PhoneNumber != "" {
|
||||||
|
contact := entity.ContactInfo{
|
||||||
|
Type: entity.ContactType{Key: "phone"},
|
||||||
|
Value: retVal.PhoneNumber,
|
||||||
|
UserID: retVal.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
contact, err = c.addContactInfo(contact)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.GetByUUID(retVal.UUID, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
|
||||||
|
return c.addContactInfo(contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
|
||||||
|
SELECT a.contact_type_id, ? user_id, ? contact
|
||||||
|
FROM
|
||||||
|
tab_contact_type a
|
||||||
|
LEFT JOIN tab_contact b
|
||||||
|
ON a.contact_type_id = b.contact_type_id
|
||||||
|
AND b.user_id = ?
|
||||||
|
AND b.contact = ?
|
||||||
|
WHERE a.key = ?
|
||||||
|
AND b.contact_id IS NULL;`
|
||||||
|
)
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
|
||||||
|
if err != nil {
|
||||||
|
return contact, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal := contact
|
||||||
|
retVal.ID, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return contact, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) addContactInfo(contact entity.ContactInfo) (entity.ContactInfo, error) {
|
||||||
|
const (
|
||||||
|
query = `INSERT INTO tab_contact(contact_type_id, user_id, contact)
|
||||||
|
SELECT a.contact_type_id, ? user_id, ? contact
|
||||||
|
FROM
|
||||||
|
tab_contact_type a
|
||||||
|
LEFT JOIN tab_contact b
|
||||||
|
ON a.contact_type_id = b.contact_type_id
|
||||||
|
AND b.user_id = ?
|
||||||
|
AND b.contact = ?
|
||||||
|
WHERE a.key = ?
|
||||||
|
AND b.contact_id IS NULL;`
|
||||||
|
)
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, contact.UserID, contact.Value, contact.UserID, contact.Value, contact.Type.Key)
|
||||||
|
if err != nil {
|
||||||
|
return contact, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal := contact
|
||||||
|
retVal.ID, err = result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return contact, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getUserByLoginAndProfile(loginID int64) (user entity.User, err error) {
|
||||||
|
finalQuery := c.getQuery() + " AND a.active = 1 AND b.login_Id = ? "
|
||||||
|
|
||||||
|
users, err := c.parseSet(c.conn.Query(finalQuery, loginID))
|
||||||
|
if err != nil {
|
||||||
|
return user, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return users[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) addProfileToUser(loginID int64, profileID int64, organization entity.Organization) error {
|
||||||
|
const query = "INSERT INTO tab_profile_login(profile_id, login_id, active, blocked, suspended, organization_id) VALUES(?, ?, 1, 0, 0, ?) ON DUPLICATE KEY UPDATE profile_id = ?, login_id = ?, organization_id = ?;"
|
||||||
|
const checkQuery = "SELECT COUNT(1) has_profile FROM tab_profile_login a WHERE a.login_id = ? AND a.profile_id = ? AND IFNULL(a.organization_id, 0) = ?;"
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
row := c.conn.QueryRow(checkQuery, loginID, profileID, organization.ID)
|
||||||
|
err := row.Scan(&total)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if total < 1 {
|
||||||
|
_, err := c.conn.Exec(query, profileID, loginID, organization.ID, profileID, loginID, toNullInt64(organization.ID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getUserByMember(u entity.User) (user entity.User, err error) {
|
||||||
|
user = u
|
||||||
|
users, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.active = 1 AND e.key = 'US' AND IFNULL(a.member, '') = ?;", u.Member))
|
||||||
|
if err != nil {
|
||||||
|
return user, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if users[0].ID != 0 {
|
||||||
|
user = users[0]
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getCompanyProfile(profile string) (int64, error) {
|
||||||
|
const (
|
||||||
|
query = "SELECT a.profile_id FROM tab_profile a WHERE a.key = ?;"
|
||||||
|
)
|
||||||
|
var companyProfileID int64
|
||||||
|
row := c.conn.QueryRow(query, profile)
|
||||||
|
err := row.Scan(&companyProfileID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return companyProfileID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getUserLogin(u entity.User) (user entity.User, err error) {
|
||||||
|
const (
|
||||||
|
query = "SELECT login_id, login_uuid, user_id, IFNULL(phone_number, '') phone_number, IFNULL(email, '') email, `key`, `password` FROM tab_login WHERE user_id = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(query, user.Member)
|
||||||
|
err = row.Scan(&user.LoginID, &user.LoginUUID, &user.ID, &user.PhoneNumber, &user.Email, &user.LoginKey, &user.Pass)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return u, nil
|
||||||
|
} else {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) createLogin(user entity.User) (int64, string, error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_login (login_uuid, user_id, phone_number, email, `key`, `password`) VALUES(?, ?, ?, ?, ?, sha2(?, 512)) ON DUPLICATE KEY UPDATE login_uuid = ?, user_id = ?, phone_number = ?, email = ?, `key` = ?, `password` = sha2(?, 512);"
|
||||||
|
)
|
||||||
|
guid, _ := uuid.NewV4()
|
||||||
|
key, _ := uuid.NewV4()
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, guid.String(), user.ID, toNullString(user.PhoneNumber), toNullString(user.Email), key.String(), user.Pass, guid.String(), user.ID, user.PhoneNumber, user.Email, key.String(), user.Pass)
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
loginID, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return loginID, guid.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) createUser(user entity.User) (int64, string, error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_user(user_uuid, `name`, member, birth_date, gender) VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE user_uuid = ?, `name` = ?, member = ?, birth_date = ?, gender = ?;"
|
||||||
|
)
|
||||||
|
guid, _ := uuid.NewV4()
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender), guid.String(), user.Name, toNullString(user.Member), toNullTime(user.BirthDate), toNullString(user.Gender))
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return userID, guid.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) RemoveAddress(addressUUID string) error {
|
||||||
|
const (
|
||||||
|
query = "UPDATE tab_address SET active = 0 WHERE address_uuid = ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
_, err := c.conn.Exec(query, addressUUID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) SaveAddress(address entity.Address) (entity.Address, error) {
|
||||||
|
const (
|
||||||
|
query = "INSERT INTO tab_address(address_uuid,address_type_id,address_origin_id,user_id,internal_id,`name`,address,lat,`long`,created_user_id) VALUES (?,?,?,?,?,?,?,?,?,?);"
|
||||||
|
)
|
||||||
|
|
||||||
|
address, err := c.getAddressSecondaryData(address)
|
||||||
|
if err != nil {
|
||||||
|
return address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid, _ := uuid.NewV4()
|
||||||
|
address.UUID = uuid.String()
|
||||||
|
|
||||||
|
result, err := c.conn.Exec(query, address.UUID, address.AddressType.ID, address.Origin.ID, address.User.ID, address.InternalID, address.Name, address.Address, address.Latitude, address.Longitude, address.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addressID, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.getAddressByID(addressID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getAddressByUserID(userID int64) ([]entity.Address, error) {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.address_id,
|
||||||
|
a.address_uuid,
|
||||||
|
a.address_type_id,
|
||||||
|
d.key address_type_key,
|
||||||
|
d.name address_type_name,
|
||||||
|
a.address_origin_id,
|
||||||
|
e.key address_origin_key,
|
||||||
|
e.name address_origin_name,
|
||||||
|
b.user_id,
|
||||||
|
b.user_uuid,
|
||||||
|
b.name user_name,
|
||||||
|
a.internal_id,
|
||||||
|
a.name,
|
||||||
|
a.address,
|
||||||
|
a.lat,
|
||||||
|
a.long,
|
||||||
|
c.user_id created_user_id,
|
||||||
|
c.user_uuid created_user_uuid,
|
||||||
|
c.name created_user_name
|
||||||
|
FROM
|
||||||
|
tab_address a
|
||||||
|
INNER JOIN tab_user b
|
||||||
|
ON a.user_id = b.user_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON a.created_user_id = c.user_id
|
||||||
|
INNER JOIN tab_address_type d
|
||||||
|
ON a.address_type_id = d.address_type_id
|
||||||
|
INNER JOIN tab_address_origin e
|
||||||
|
ON a.address_origin_id = e.address_origin_id
|
||||||
|
WHERE
|
||||||
|
a.user_id = ? and a.active = 1;`
|
||||||
|
)
|
||||||
|
|
||||||
|
var addresses []entity.Address
|
||||||
|
rows, err := c.conn.Query(query, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var address entity.Address
|
||||||
|
err := rows.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
|
||||||
|
&address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
|
||||||
|
&address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
|
||||||
|
&address.CreatedUser.UUID, &address.CreatedUser.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
addresses = append(addresses, address)
|
||||||
|
}
|
||||||
|
return addresses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getAddressByID(addressID int64) (entity.Address, error) {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.address_id,
|
||||||
|
a.address_uuid,
|
||||||
|
a.address_type_id,
|
||||||
|
d.key address_type_key,
|
||||||
|
d.name address_type_name,
|
||||||
|
a.address_origin_id,
|
||||||
|
e.key address_origin_key,
|
||||||
|
e.name address_origin_name,
|
||||||
|
b.user_id,
|
||||||
|
b.user_uuid,
|
||||||
|
b.name user_name,
|
||||||
|
a.internal_id,
|
||||||
|
a.name,
|
||||||
|
a.address,
|
||||||
|
a.lat,
|
||||||
|
a.long,
|
||||||
|
c.user_id created_user_id,
|
||||||
|
c.user_uuid created_user_uuid,
|
||||||
|
c.name created_user_name
|
||||||
|
FROM
|
||||||
|
tab_address a
|
||||||
|
INNER JOIN tab_user b
|
||||||
|
ON a.user_id = b.user_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON a.created_user_id = c.user_id
|
||||||
|
INNER JOIN tab_address_type d
|
||||||
|
ON a.address_type_id = d.address_type_id
|
||||||
|
INNER JOIN tab_address_origin e
|
||||||
|
ON a.address_origin_id = e.address_origin_id
|
||||||
|
WHERE
|
||||||
|
a.address_id = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
var address entity.Address
|
||||||
|
row := c.conn.QueryRow(query, addressID)
|
||||||
|
err := row.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
|
||||||
|
&address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
|
||||||
|
&address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
|
||||||
|
&address.CreatedUser.UUID, &address.CreatedUser.Name)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Address{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) GetAddressByUUID(addressUUID string) (entity.Address, error) {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.address_id,
|
||||||
|
a.address_uuid,
|
||||||
|
a.address_type_id,
|
||||||
|
d.key address_type_key,
|
||||||
|
d.name address_type_name,
|
||||||
|
a.address_origin_id,
|
||||||
|
e.key address_origin_key,
|
||||||
|
e.name address_origin_name,
|
||||||
|
b.user_id,
|
||||||
|
b.user_uuid,
|
||||||
|
b.name user_name,
|
||||||
|
a.internal_id,
|
||||||
|
a.name,
|
||||||
|
a.address,
|
||||||
|
a.lat,
|
||||||
|
a.long,
|
||||||
|
c.user_id created_user_id,
|
||||||
|
c.user_uuid created_user_uuid,
|
||||||
|
c.name created_user_name
|
||||||
|
FROM
|
||||||
|
tab_address a
|
||||||
|
INNER JOIN tab_user b
|
||||||
|
ON a.user_id = b.user_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON a.created_user_id = c.user_id
|
||||||
|
INNER JOIN tab_address_type d
|
||||||
|
ON a.address_type_id = d.address_type_id
|
||||||
|
INNER JOIN tab_address_origin e
|
||||||
|
ON a.address_origin_id = e.address_origin_id
|
||||||
|
WHERE
|
||||||
|
a.address_uuid = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
var address entity.Address
|
||||||
|
row := c.conn.QueryRow(query, addressUUID)
|
||||||
|
err := row.Scan(&address.ID, &address.UUID, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name,
|
||||||
|
&address.Origin.ID, &address.Origin.Key, &address.Origin.Name, &address.User.ID, &address.User.UUID, &address.User.Name,
|
||||||
|
&address.InternalID, &address.Name, &address.Address, &address.Latitude, &address.Longitude, &address.CreatedUser.ID,
|
||||||
|
&address.CreatedUser.UUID, &address.CreatedUser.Name)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Address{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *userRepo) getAddressSecondaryData(address entity.Address) (entity.Address, error) {
|
||||||
|
const (
|
||||||
|
query = `SELECT
|
||||||
|
a.user_id,
|
||||||
|
a.user_uuid,
|
||||||
|
a.name user_name,
|
||||||
|
b.user_id created_user_id,
|
||||||
|
b.user_uuid created_user_uuid,
|
||||||
|
b.name created_user_name,
|
||||||
|
c.address_type_id,
|
||||||
|
c.key address_type_key,
|
||||||
|
c.name address_type_name,
|
||||||
|
d.address_origin_id,
|
||||||
|
d.key address_origin_key,
|
||||||
|
d.name address_origin_name
|
||||||
|
FROM
|
||||||
|
tab_user a,
|
||||||
|
tab_user b,
|
||||||
|
tab_address_type c,
|
||||||
|
tab_address_origin d
|
||||||
|
WHERE
|
||||||
|
a.user_uuid = ?
|
||||||
|
AND b.user_uuid = ?
|
||||||
|
AND c.key = ?
|
||||||
|
AND d.key = ?;`
|
||||||
|
)
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(query, address.User.UUID, address.CreatedUser.UUID, address.AddressType.Key, address.Origin.Key)
|
||||||
|
err := row.Scan(&address.User.ID, &address.User.UUID, &address.User.Name, &address.CreatedUser.ID, &address.CreatedUser.UUID, &address.CreatedUser.Name, &address.AddressType.ID, &address.AddressType.Key, &address.AddressType.Name, &address.Origin.ID, &address.Origin.Key, &address.Origin.Name)
|
||||||
|
if err != nil {
|
||||||
|
return address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll returns a list of all active cards
|
||||||
|
func (c *userRepo) GetAll() (list []entity.User, err error) {
|
||||||
|
return c.parseSet(c.conn.Query(c.getQuery() + " WHERE a.active = 1 "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID returns a single card data by its ID
|
||||||
|
func (c *userRepo) GetByID(userID int64) (retVal entity.User, err error) {
|
||||||
|
user, err := c.parseSet(c.conn.Query(c.getQuery()+" AND a.user_id = ? ", userID))
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(user) > 0 {
|
||||||
|
retVal := user[0]
|
||||||
|
retVal.Contacts, err = c.GetContacts(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.Addresses = nil
|
||||||
|
retVal.Addresses, err = c.getAddressByUserID(retVal.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.User{}, err
|
||||||
|
}
|
||||||
|
return retVal, nil
|
||||||
|
} else {
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNullString(s string) sql.NullString {
|
||||||
|
return sql.NullString{String: s, Valid: s != ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNullInt64(i int64) sql.NullInt64 {
|
||||||
|
return sql.NullInt64{Int64: i, Valid: i > 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNullTime(date time.Time) mysql.NullTime {
|
||||||
|
return mysql.NullTime{Time: date, Valid: !date.IsZero()}
|
||||||
|
}
|
||||||
15
data/datamysql/utils.go
Normal file
15
data/datamysql/utils.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type scanner interface {
|
||||||
|
Scan(dest ...interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type executor interface {
|
||||||
|
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||||
|
QueryRow(query string, args ...interface{}) *sql.Row
|
||||||
|
Query(query string, args ...interface{}) (*sql.Rows, error)
|
||||||
|
}
|
||||||
210
data/datamysql/visit.go
Normal file
210
data/datamysql/visit.go
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
package datamysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// visitRepo maps methods to database
|
||||||
|
type visitRepo struct {
|
||||||
|
conn executor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVisitRepo(conn executor) *visitRepo {
|
||||||
|
return &visitRepo{
|
||||||
|
conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *visitRepo) 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_visit_provider f
|
||||||
|
ON f.visit_id = a.visit_id `
|
||||||
|
where = fmt.Sprintf(` AND (f.organization_uuid = '%s' OR f.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 *visitRepo) getQuery() string {
|
||||||
|
return `SELECT
|
||||||
|
a.visit_id,
|
||||||
|
a.visit_uuid,
|
||||||
|
a.visit_status_id,
|
||||||
|
b.visit_status_key,
|
||||||
|
b.visit_status,
|
||||||
|
a.user_id,
|
||||||
|
c.user_uuid,
|
||||||
|
c.name user_name,
|
||||||
|
c.member user_member,
|
||||||
|
c.birth_date user_birth_date,
|
||||||
|
c.gender user_gender,
|
||||||
|
a.visit_datetime,
|
||||||
|
a.pickup_datetime,
|
||||||
|
IFNULL(a.notes, '') notes,
|
||||||
|
a.created_user_id,
|
||||||
|
d.user_uuid created_user_uuid,
|
||||||
|
d.name created_user_name,
|
||||||
|
a.created_date,
|
||||||
|
a.updated_date,
|
||||||
|
IFNULL(a.visit_duration, 0) visit_duration,
|
||||||
|
a.visit_external_id,
|
||||||
|
e.trip_type_id,
|
||||||
|
e.trip_type_key,
|
||||||
|
e.trip_type,
|
||||||
|
IFNULL(a.pickup_id, '') visit_pickup_id,
|
||||||
|
IFNULL(a.pickup_address_id, 0) pickup_address_id,
|
||||||
|
IFNULL(a.address_id, 0) address_id,
|
||||||
|
IFNULL(a.provider_id, 0) provider_id,
|
||||||
|
IFNULL(f.provider_uuid, '') provider_uuid,
|
||||||
|
IFNULL(f.provider_internal_id, '') provider_internal_id,
|
||||||
|
IFNULL(f.provider_muk_id, '') provider_muk_id,
|
||||||
|
IFNULL(f.provider_name, '') provider_name
|
||||||
|
FROM
|
||||||
|
tab_visit a
|
||||||
|
INNER JOIN tab_visit_status b
|
||||||
|
ON a.visit_status_id = b.visit_status_id
|
||||||
|
INNER JOIN tab_user c
|
||||||
|
ON c.user_id = a.user_id
|
||||||
|
INNER JOIN tab_user d
|
||||||
|
ON d.user_id = a.created_user_id
|
||||||
|
INNER JOIN tab_trip_type e
|
||||||
|
ON e.trip_type_id = a.trip_type_id
|
||||||
|
INNER JOIN tab_provider f
|
||||||
|
ON f.provider_id = a.provider_id `
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *visitRepo) GetAll(user entity.User) ([]entity.Visit, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE 1 = 1 and c.active = 1 " + where
|
||||||
|
|
||||||
|
return c.parseSet(c.conn.Query(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *visitRepo) GetByUUID(visitUUID string, user entity.User) (entity.Visit, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE a.visit_uuid = ? " + where
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, visitUUID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *visitRepo) GetByID(visitID int64, user entity.User) (entity.Visit, error) {
|
||||||
|
query, where, err := c.getProfileQuery(user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
query = c.getQuery() + query + " WHERE a.visit_id = ? " + where
|
||||||
|
return c.parseEntity(c.conn.QueryRow(query, visitID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseSet parses a result set result to an entity array
|
||||||
|
func (c *visitRepo) parseSet(rows *sql.Rows, err error) ([]entity.Visit, error) {
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
result := make([]entity.Visit, 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 *visitRepo) parseEntity(row scanner) (retVal entity.Visit, err error) {
|
||||||
|
var birthDate mysql.NullTime
|
||||||
|
var gender sql.NullString
|
||||||
|
|
||||||
|
err = row.Scan(
|
||||||
|
&retVal.ID, &retVal.UUID, &retVal.Status.ID, &retVal.Status.Key, &retVal.Status.Value, &retVal.User.ID, &retVal.User.UUID, &retVal.User.Name, &retVal.User.Member, &birthDate, &gender, &retVal.VisitDatetime, &retVal.PickupDatetime, &retVal.Notes, &retVal.CreatedUser.ID, &retVal.CreatedUser.UUID, &retVal.CreatedUser.Name, &retVal.Created, &retVal.Updated, &retVal.VisitDuration, &retVal.ExternalID, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value, &retVal.Pickup.ID, &retVal.PickupAddressID, &retVal.DestinationAddressID, &retVal.Provider.ProviderID, &retVal.Provider.ProviderUUID, &retVal.Provider.InternalID, &retVal.Provider.MukID, &retVal.Provider.Name)
|
||||||
|
|
||||||
|
if birthDate.Valid {
|
||||||
|
retVal.User.BirthDate = birthDate.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
if gender.Valid {
|
||||||
|
retVal.User.Gender = gender.String
|
||||||
|
} else {
|
||||||
|
retVal.User.Gender = "U"
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *visitRepo) Create(visit entity.Visit) (entity.Visit, error) {
|
||||||
|
const (
|
||||||
|
statusQuery = `SELECT a.visit_status_id, a.visit_status_key, a.visit_status, b.user_id, b.name user_name, c.user_id create_user_id, c.name create_user_name, d.trip_type_id, d.trip_type_key, d.trip_type FROM tab_visit_status a, tab_user b, tab_user c, tab_trip_type d WHERE a.visit_status_key = ? AND b.user_uuid = ? AND c.user_uuid = ? AND d.trip_type_key = ?;`
|
||||||
|
query = `INSERT INTO tab_visit(visit_uuid, visit_status_id, user_id, visit_datetime, pickup_datetime, notes, created_user_id, visit_duration, visit_external_id, return_date, trip_type_id, pickup_id, pickup_address_id, address_id, provider_id)
|
||||||
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`
|
||||||
|
)
|
||||||
|
|
||||||
|
retVal := visit
|
||||||
|
|
||||||
|
returnDate := mysql.NullTime{
|
||||||
|
Valid: (retVal.ReturnDate != nil),
|
||||||
|
}
|
||||||
|
if retVal.ReturnDate != nil {
|
||||||
|
returnDate.Time = *retVal.ReturnDate
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID, _ := uuid.NewV4()
|
||||||
|
retVal.UUID = UUID.String()
|
||||||
|
|
||||||
|
if retVal.Status.Key == "" {
|
||||||
|
retVal.Status.Key = "accepted"
|
||||||
|
}
|
||||||
|
|
||||||
|
row := c.conn.QueryRow(statusQuery, retVal.Status.Key, retVal.User.UUID, retVal.CreatedUser.UUID, retVal.TripType.Key)
|
||||||
|
if err := row.Scan(&retVal.Status.ID, &retVal.Status.Key, &retVal.Status.Value, &retVal.User.ID, &retVal.User.Name, &retVal.CreatedUser.ID, &retVal.CreatedUser.Name, &retVal.TripType.ID, &retVal.TripType.Key, &retVal.TripType.Value); err != nil {
|
||||||
|
fmt.Println("Error to get base data: ", err.Error())
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := c.conn.Exec(query, retVal.UUID, retVal.Status.ID, retVal.User.ID, retVal.VisitDatetime, retVal.PickupDatetime, retVal.Notes, retVal.CreatedUser.ID, toNullInt64(retVal.VisitDuration), retVal.ExternalID, returnDate, retVal.TripType.ID, retVal.Pickup.ID, retVal.PickupAddressID, retVal.DestinationAddressID, retVal.Provider.ProviderID)
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal.ID, err = results.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Visit ID: ", retVal.ID)
|
||||||
|
return retVal, nil
|
||||||
|
}
|
||||||
1211
docs/swagger/nemt-portal-api.yaml
Normal file
1211
docs/swagger/nemt-portal-api.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1244
docs/swagger/nemt-portal-api_2.yaml
Normal file
1244
docs/swagger/nemt-portal-api_2.yaml
Normal file
File diff suppressed because it is too large
Load Diff
13
docs/wiki/01 - Definitions.md
Normal file
13
docs/wiki/01 - Definitions.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Definitions
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
- `build`: compilation and project preparation step
|
||||||
|
- `run`: execution step
|
||||||
|
|
||||||
|
## Environments
|
||||||
|
|
||||||
|
- `loc`: local
|
||||||
|
- `dev`: development
|
||||||
|
- `stg`: staging
|
||||||
|
- `prd`: production
|
||||||
21
docs/wiki/02 - Environments.md
Normal file
21
docs/wiki/02 - Environments.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Environments
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
- Local (`loc`)
|
||||||
|
|
||||||
|
Your local machine.
|
||||||
|
|
||||||
|
- Development (`dev`)
|
||||||
|
|
||||||
|
Useful for us to test the implementation without messing with
|
||||||
|
the partners experience.
|
||||||
|
|
||||||
|
- Staging (`stg`)
|
||||||
|
|
||||||
|
Used to simulate production and as homologation version.
|
||||||
|
Works as the last step before production.
|
||||||
|
|
||||||
|
- Production (`prd`)
|
||||||
|
|
||||||
|
Production server.
|
||||||
64
docs/wiki/03 - Folders.md
Normal file
64
docs/wiki/03 - Folders.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Folders
|
||||||
|
|
||||||
|
## Reason
|
||||||
|
|
||||||
|
The goals for a common project's folder structure is to mantain the organization
|
||||||
|
and to promote a common language between the programmers, decreasing the new
|
||||||
|
members' learning curve.
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
- `domain`:
|
||||||
|
|
||||||
|
- `service`:
|
||||||
|
contains the business logic and persistence, i.e. validating values based on business
|
||||||
|
rules
|
||||||
|
|
||||||
|
- `contract`:
|
||||||
|
contains the interfaces for the whole app; useful for mocking dependencies on
|
||||||
|
the tests and also decoupling the packages from each other, making the code independent
|
||||||
|
from external technologies, e.g. databases
|
||||||
|
|
||||||
|
- `entity`:
|
||||||
|
represents the values our domain understands
|
||||||
|
|
||||||
|
- `infra`:
|
||||||
|
contains utilities that will be used across the whole app
|
||||||
|
|
||||||
|
- `data`:
|
||||||
|
contains the connection with the database or any other way to do the persistence
|
||||||
|
|
||||||
|
- `data*`:
|
||||||
|
an "implementation"
|
||||||
|
|
||||||
|
- `application`:
|
||||||
|
represents our application as a whole
|
||||||
|
|
||||||
|
- `applicationservice`:
|
||||||
|
contains the application logic, i.e. parses and validates the data received, calls
|
||||||
|
many domain's services, parses the output data and sends it
|
||||||
|
|
||||||
|
- `entitymapping`:
|
||||||
|
contains the functions that parses the application's view model to the domain's
|
||||||
|
entities, and vice-versa
|
||||||
|
|
||||||
|
- `viewmodel`:
|
||||||
|
the data that will be sent and received from the app; it differs from the entity
|
||||||
|
because it does not represent the values of our app, but rather the values the
|
||||||
|
front-end server will understand
|
||||||
|
|
||||||
|
- `server`:
|
||||||
|
contains the definitions for the web server
|
||||||
|
|
||||||
|
- `router`:
|
||||||
|
defines the routes and its handlers; contains no logic, only calls the application
|
||||||
|
package
|
||||||
|
|
||||||
|
- `serverconfig`:
|
||||||
|
defines the middlewares and the server's configurations
|
||||||
|
|
||||||
|
- `static`:
|
||||||
|
not required; mostly used for static files, such as large texts, email templates,
|
||||||
|
static values, etc, or temporary files (commonly in `static/temp`)
|
||||||
31
docs/wiki/04 - Dockerfile.md
Normal file
31
docs/wiki/04 - Dockerfile.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Dockerfile
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
There are two `Dockerfile`s, one for each step of execution set in
|
||||||
|
the [definitions document][definitions-doc].
|
||||||
|
|
||||||
|
## Containers
|
||||||
|
|
||||||
|
- Build
|
||||||
|
|
||||||
|
Defined in `Dockerfile.build`
|
||||||
|
|
||||||
|
Has installed every program that is needed to build the code.
|
||||||
|
Gets the source, install the dependencies and makes the final binary
|
||||||
|
of our app.
|
||||||
|
|
||||||
|
The reason for us to have a container just for the building process is
|
||||||
|
that it demands lots of programs and dependencies to set up the Go
|
||||||
|
environment and build everything, which aren't needed in the server for
|
||||||
|
our app to run. Without it, the container for the running process would
|
||||||
|
be huge, full of useless binaries and softwares.
|
||||||
|
|
||||||
|
- Run
|
||||||
|
|
||||||
|
Defined in `Dockerfile.run`
|
||||||
|
|
||||||
|
This is the container that will run in the servers. Contains nothing,
|
||||||
|
but our app and what it need to make it run.
|
||||||
|
|
||||||
|
[definitions-doc]: https://bitbucket.org/nemt/nemt-portal-api/blob/master/docs/wiki/01%20-%20Definitions.md
|
||||||
67
docs/wiki/05 - Makefile.md
Normal file
67
docs/wiki/05 - Makefile.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Makefile
|
||||||
|
|
||||||
|
## Reason
|
||||||
|
|
||||||
|
Great to simplify and standardize commons and repetitive tasks.
|
||||||
|
|
||||||
|
## Definitions
|
||||||
|
|
||||||
|
Following the patterns of the [definitions document][definitions-doc], every task related to
|
||||||
|
the compilation os preparation of the server for execution will `build` as part of the name,
|
||||||
|
while tasks related to the execution itself will be call `run`.
|
||||||
|
|
||||||
|
## Common instructions
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
- `create-build-container`: creates the container for building, using `Dockerfile.build`
|
||||||
|
|
||||||
|
- `build`: build the server inside the container and gets the binary
|
||||||
|
|
||||||
|
- `build-loc`: calls `build` using local (`loc`) environment
|
||||||
|
|
||||||
|
- `build-dev`: calls `build` using development (`dev`) environment
|
||||||
|
|
||||||
|
- `build-stg`: calls `build` using staging (`stg`) environment
|
||||||
|
|
||||||
|
- `build-prd`: calls `build` using production (`prd`) environment
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
- `create-run-container`: creates the container for execution, using `Dockerfile.run`
|
||||||
|
|
||||||
|
- `run`: executes the app inside the container
|
||||||
|
|
||||||
|
- `run-loc`: calls `run` using local (`loc`) environment
|
||||||
|
|
||||||
|
- `run-dev`: calls `run` using development (`dev`) environment
|
||||||
|
|
||||||
|
- `run-stg`: calls `run` using staging (`stg`) environment
|
||||||
|
|
||||||
|
- `run-prd`: calls `run` using production (`prd`) environment
|
||||||
|
|
||||||
|
- `run-host`: executes the app without a container, directly on the local host
|
||||||
|
|
||||||
|
### Environment
|
||||||
|
|
||||||
|
- `set-loc`: defines the environment as "local" (`loc`)
|
||||||
|
|
||||||
|
- `set-dev`: defines the environment as "development" (`dev`)
|
||||||
|
|
||||||
|
- `set-stg`: defines the environment as "staging" (`stg`)
|
||||||
|
|
||||||
|
- `set-prd`: defines the environment as "production" (`prd`)
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
- `migrate`: executes the full migration of the database
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- `test`: executes the whole battery of tests
|
||||||
|
|
||||||
|
### Others
|
||||||
|
|
||||||
|
- `clean`: remove binaries and compiled files
|
||||||
|
|
||||||
|
[definitions-doc]: https://bitbucket.org/nemt/nemt-portal-api/blob/master/docs/wiki/01%20-%20Definitions.md
|
||||||
15
domain/constants.go
Normal file
15
domain/constants.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
type errorString string
|
||||||
|
|
||||||
|
func (err errorString) Error() string {
|
||||||
|
return string(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrCacheMiss indicates a cache miss when fetching an item from CacheManager.
|
||||||
|
const ErrCacheMiss = errorString("cache miss: key not found")
|
||||||
|
|
||||||
|
// Used to log errors with communication and operation of cache implementation
|
||||||
|
const LogProblemGettingFromCache = "Getting from cache is not working correctly: %v"
|
||||||
|
const LogProblemPuttingToCache = "Putting to cache is not working correctly: %v"
|
||||||
|
const LogProblemExpiringCache = "Expiring cache key is not working correctly: %v"
|
||||||
19
domain/contract/cache.go
Normal file
19
domain/contract/cache.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// CacheManager defines the main caching interface
|
||||||
|
// - Get methods can return domain.ErrCacheMiss
|
||||||
|
type CacheManager interface {
|
||||||
|
GetItem(key string) ([]byte, error)
|
||||||
|
SetItem(key string, data []byte) error
|
||||||
|
|
||||||
|
GetString(key string) (string, error)
|
||||||
|
SetString(key string, data string) error
|
||||||
|
|
||||||
|
GetStruct(key string, data interface{}) error
|
||||||
|
SetStruct(key string, data interface{}) error
|
||||||
|
|
||||||
|
GetExpiration(key string) (time.Duration, error)
|
||||||
|
SetExpiration(key string, expiration time.Duration) error
|
||||||
|
}
|
||||||
16
domain/contract/data.go
Normal file
16
domain/contract/data.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
// DataManager holds the methods that manipulates the main data.
|
||||||
|
type DataManager interface {
|
||||||
|
repoManager
|
||||||
|
Begin() (TransactionManager, error)
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionManager holds the methods that manipulates the main
|
||||||
|
// data, from within a transaction.
|
||||||
|
type TransactionManager interface {
|
||||||
|
repoManager
|
||||||
|
Rollback() error
|
||||||
|
Commit() error
|
||||||
|
}
|
||||||
104
domain/contract/repo.go
Normal file
104
domain/contract/repo.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type repoManager interface {
|
||||||
|
Users() UserRepo
|
||||||
|
Rides() RideRepo
|
||||||
|
Visits() VisitRepo
|
||||||
|
Provider() ProviderRepo
|
||||||
|
Notification() NotificationRepo
|
||||||
|
Profile() ProfileRepo
|
||||||
|
Organization() OrganizationRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserRepo defines the data set for users
|
||||||
|
type UserRepo interface {
|
||||||
|
GetAll() (list []entity.User, err error)
|
||||||
|
GetByID(userID int64) (retVal entity.User, err error)
|
||||||
|
GetByUUID(uuid string, profile string) (entity.User, error)
|
||||||
|
Login(email string, pass string) (entity.User, error)
|
||||||
|
FullLogin(loginType string, key string, pass string, profile string) (entity.User, error)
|
||||||
|
Create(user entity.User) (entity.User, error)
|
||||||
|
GetUsersByProfile(profile string) ([]entity.User, error)
|
||||||
|
SaveAddress(address entity.Address) (entity.Address, error)
|
||||||
|
GetAddressByUUID(addressUUID string) (entity.Address, error)
|
||||||
|
GetContactType() (retVal []entity.ContactType, err error)
|
||||||
|
RemoveAddress(addressUUID string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideRepo defines the data set for Rides
|
||||||
|
type RideRepo interface {
|
||||||
|
Save(ride entity.Ride) (entity.Ride, error)
|
||||||
|
GetAll(user entity.User) ([]entity.Ride, error)
|
||||||
|
GetByID(id int64, user entity.User) (entity.Ride, error)
|
||||||
|
GetByUUID(uuid string, user entity.User) (entity.Ride, error)
|
||||||
|
GetByInternalID(internalID string) (entity.Ride, error)
|
||||||
|
GetByUserID(userID int64, user entity.User) ([]entity.Ride, error)
|
||||||
|
GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error)
|
||||||
|
GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error)
|
||||||
|
UpdateStatus(rideUUID string, status string) error
|
||||||
|
Update(hook entity.WebhookResponse, user entity.User) (entity.Ride, error)
|
||||||
|
GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error)
|
||||||
|
GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error)
|
||||||
|
GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error)
|
||||||
|
GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error)
|
||||||
|
GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderRepo defines the data set for Provider
|
||||||
|
type ProviderRepo interface {
|
||||||
|
Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error)
|
||||||
|
GetAll(user entity.User) ([]entity.Provider, error)
|
||||||
|
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)
|
||||||
|
GetByMukID(mukID string, user entity.User) (entity.Provider, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotificationRepo defines the data set for Notification
|
||||||
|
type NotificationRepo interface {
|
||||||
|
Create(notification entity.Notification) (entity.Notification, error)
|
||||||
|
GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error)
|
||||||
|
GetByUserUUID(userUUID string, status string) ([]entity.Notification, error)
|
||||||
|
ReadStatus(notificationUUID string, readed bool) error
|
||||||
|
GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderRepo defines the data set for Rides
|
||||||
|
type OrganizationRepo interface {
|
||||||
|
GetAllTypes() ([]entity.OrganizationType, error)
|
||||||
|
GetByType(organizationTypeKey string) ([]entity.Organization, error)
|
||||||
|
GetByUUID(organizationUUID string) (entity.Organization, error)
|
||||||
|
GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error)
|
||||||
|
GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error)
|
||||||
|
GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error)
|
||||||
|
GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error)
|
||||||
|
GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error)
|
||||||
|
GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error)
|
||||||
|
GetByID(organizationID int64) (entity.Organization, error)
|
||||||
|
GetChildsByID(organizationID int64) ([]entity.Organization, error)
|
||||||
|
GetByName(name string, searchType string) ([]entity.Organization, error)
|
||||||
|
SetParentOrganization(organizationID int64, parentOrganizationID int64) error
|
||||||
|
InactivateOrganizationAddress(address entity.OrganizationAddress) error
|
||||||
|
SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error)
|
||||||
|
InactivateOrganizationContact(contact entity.OrganizationContact) error
|
||||||
|
SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error)
|
||||||
|
AddOrganization(organization entity.Organization) (entity.Organization, error)
|
||||||
|
GetTypeByKey(key string) (entity.OrganizationType, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisitRepo defines the data set for Rides
|
||||||
|
type VisitRepo interface {
|
||||||
|
Create(visit entity.Visit) (entity.Visit, error)
|
||||||
|
GetAll(user entity.User) ([]entity.Visit, error)
|
||||||
|
GetByUUID(visitUUID string, user entity.User) (entity.Visit, error)
|
||||||
|
GetByID(visitID int64, user entity.User) (entity.Visit, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProfileRepo interface {
|
||||||
|
GetAll() ([]entity.Profile, error)
|
||||||
|
GetByKey(key string) (entity.Profile, error)
|
||||||
|
GetVisibles(visible bool) ([]entity.Profile, error)
|
||||||
|
GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error)
|
||||||
|
}
|
||||||
12
domain/contract/tnc.go
Normal file
12
domain/contract/tnc.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
type tncManager interface {
|
||||||
|
TNC() TNCManager
|
||||||
|
}
|
||||||
|
|
||||||
|
//TNCManager defines the integration with any TNC
|
||||||
|
type TNCManager interface {
|
||||||
|
GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error)
|
||||||
|
GetDrivers(lag float64, log float64) (interface{}, error)
|
||||||
|
GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error)
|
||||||
|
}
|
||||||
21
domain/entity/address.go
Normal file
21
domain/entity/address.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
ID int64
|
||||||
|
UUID string
|
||||||
|
InternalID string
|
||||||
|
Name string
|
||||||
|
Address string
|
||||||
|
AddressType Params
|
||||||
|
Latitude float64
|
||||||
|
Longitude float64
|
||||||
|
Origin Params
|
||||||
|
User User
|
||||||
|
CreatedUser User
|
||||||
|
}
|
||||||
|
|
||||||
|
type Params struct {
|
||||||
|
ID int64
|
||||||
|
Key string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
252
domain/entity/eligibility.go
Normal file
252
domain/entity/eligibility.go
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
type Interchange struct {
|
||||||
|
ISA ISA
|
||||||
|
Division Division
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISA struct {
|
||||||
|
ISA01 string
|
||||||
|
ISA02 string
|
||||||
|
ISA03 string
|
||||||
|
ISA04 string
|
||||||
|
ISA05 string
|
||||||
|
ISA06 string
|
||||||
|
ISA07 string
|
||||||
|
ISA08 string
|
||||||
|
ISA09 string
|
||||||
|
ISA10 string
|
||||||
|
ISA11 string
|
||||||
|
ISA12 string
|
||||||
|
ISA13 string
|
||||||
|
ISA14 string
|
||||||
|
ISA15 string
|
||||||
|
ISA16 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Division struct {
|
||||||
|
GS GS
|
||||||
|
HealthCareEligibilityBenefitResponse HealthCareEligibilityBenefitResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
type GS struct {
|
||||||
|
GS01 string
|
||||||
|
GS02 string
|
||||||
|
GS03 string
|
||||||
|
GS04 string
|
||||||
|
GS05 string
|
||||||
|
GS06 string
|
||||||
|
GS07 string
|
||||||
|
GS08 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type HealthCareEligibilityBenefitResponse struct {
|
||||||
|
ST0010 ST0010
|
||||||
|
BHT0020 BHT0020
|
||||||
|
LoopHL0030 LoopHL0030
|
||||||
|
}
|
||||||
|
|
||||||
|
type ST0010 struct {
|
||||||
|
ST01 string
|
||||||
|
ST02 string
|
||||||
|
ST03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type BHT0020 struct {
|
||||||
|
BHT01 string
|
||||||
|
BHT02 string
|
||||||
|
BHT03 string
|
||||||
|
BHT04 string
|
||||||
|
BHT05 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopHL0030 struct {
|
||||||
|
HL0030 HL0030
|
||||||
|
LoopNM10060 LoopNM10060
|
||||||
|
LoopHL0460 LoopHL0460
|
||||||
|
}
|
||||||
|
|
||||||
|
type HL0030 struct {
|
||||||
|
HL01 string
|
||||||
|
HL02 string
|
||||||
|
HL03 string
|
||||||
|
HL04 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopNM10060 struct {
|
||||||
|
NM10060 NM10060
|
||||||
|
}
|
||||||
|
|
||||||
|
type NM10060 struct {
|
||||||
|
NM101 string
|
||||||
|
NM102 string
|
||||||
|
NM103 string
|
||||||
|
NM104 string
|
||||||
|
NM105 string
|
||||||
|
NM106 string
|
||||||
|
NM107 string
|
||||||
|
NM108 string
|
||||||
|
NM109 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopHL0460 struct {
|
||||||
|
HL0460 HL0460
|
||||||
|
LoopNM10490 LoopNM10490
|
||||||
|
LoopHL0890 LoopHL0890
|
||||||
|
}
|
||||||
|
|
||||||
|
type HL0460 struct {
|
||||||
|
HL01 string
|
||||||
|
HL02 string
|
||||||
|
HL03 string
|
||||||
|
HL04 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopNM10490 struct {
|
||||||
|
NM10490 NM10490
|
||||||
|
}
|
||||||
|
|
||||||
|
type NM10490 struct {
|
||||||
|
NM101 string
|
||||||
|
NM102 string
|
||||||
|
NM103 string
|
||||||
|
NM104 string
|
||||||
|
NM105 string
|
||||||
|
NM106 string
|
||||||
|
NM107 string
|
||||||
|
NM108 string
|
||||||
|
NM109 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopHL0890 struct {
|
||||||
|
HL0890 HL0890
|
||||||
|
TRN0900 TRN0900
|
||||||
|
LoopNM10920 LoopNM10920
|
||||||
|
}
|
||||||
|
|
||||||
|
type HL0890 struct {
|
||||||
|
HL01 string
|
||||||
|
HL02 string
|
||||||
|
HL03 string
|
||||||
|
HL04 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TRN0900 struct {
|
||||||
|
TRN01 string
|
||||||
|
TRN02 string
|
||||||
|
TRN03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopNM10920 struct {
|
||||||
|
NM10920 NM10920
|
||||||
|
REF0930 REF0930
|
||||||
|
N30950 N30950
|
||||||
|
N40960 N40960
|
||||||
|
DMG1000 DMG1000
|
||||||
|
DTP1030 DTP1030
|
||||||
|
LoopEB1050 []LoopEB1050
|
||||||
|
}
|
||||||
|
|
||||||
|
type NM10920 struct {
|
||||||
|
NM101 string
|
||||||
|
NM102 string
|
||||||
|
NM103 string
|
||||||
|
NM104 string
|
||||||
|
NM105 string
|
||||||
|
NM106 string
|
||||||
|
NM107 string
|
||||||
|
NM108 string
|
||||||
|
NM109 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type REF0930 struct {
|
||||||
|
REF01 string
|
||||||
|
REF02 string
|
||||||
|
REF03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type N30950 struct {
|
||||||
|
N301 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type N40960 struct {
|
||||||
|
N401 string
|
||||||
|
N402 string
|
||||||
|
N403 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DMG1000 struct {
|
||||||
|
DMG01 string
|
||||||
|
DMG02 string
|
||||||
|
DMG03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DTP1030 struct {
|
||||||
|
DTP01 string
|
||||||
|
DTP02 string
|
||||||
|
DTP03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopEB1050 struct {
|
||||||
|
EB1050 EB1050
|
||||||
|
REF1070 REF1070
|
||||||
|
MSG1180 MSG1180
|
||||||
|
LoopIII1190 LoopIII1190
|
||||||
|
LS1260 LS1260
|
||||||
|
LoopNM11270 LoopNM11270
|
||||||
|
}
|
||||||
|
|
||||||
|
type EB1050 struct {
|
||||||
|
EB01 string
|
||||||
|
EB02 string
|
||||||
|
EB03 string
|
||||||
|
EB04 string
|
||||||
|
EB05 string
|
||||||
|
EB06 string
|
||||||
|
EB07 string
|
||||||
|
EB08 string
|
||||||
|
EB09 string
|
||||||
|
EB10 string
|
||||||
|
EB11 string
|
||||||
|
EB12 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type REF1070 struct {
|
||||||
|
REF01 string
|
||||||
|
REF02 string
|
||||||
|
REF03 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MSG1180 struct {
|
||||||
|
MSG01 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LS1260 struct {
|
||||||
|
LS01 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopIII1190 struct {
|
||||||
|
III1190 III1190
|
||||||
|
}
|
||||||
|
|
||||||
|
type III1190 struct {
|
||||||
|
III01 string
|
||||||
|
III02 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoopNM11270 struct {
|
||||||
|
NM11270 NM11270
|
||||||
|
PER1310 PER1310
|
||||||
|
}
|
||||||
|
|
||||||
|
type NM11270 struct {
|
||||||
|
NM101 string
|
||||||
|
NM102 string
|
||||||
|
NM103 string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PER1310 struct {
|
||||||
|
PER01 string
|
||||||
|
PER02 string
|
||||||
|
PER03 string
|
||||||
|
}
|
||||||
20
domain/entity/notification.go
Normal file
20
domain/entity/notification.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Notification struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
From string `json:"to"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
TypeID int64 `json:"type_id"`
|
||||||
|
Subject string `json:"subject"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
MessageType string `json:"message_type"`
|
||||||
|
Ride Ride `json:"ride"`
|
||||||
|
User User `json:"user"`
|
||||||
|
CreatedUser User `json:"created_user"`
|
||||||
|
Created time.Time `json:"create_at"`
|
||||||
|
Read bool `json:"read"`
|
||||||
|
}
|
||||||
68
domain/entity/organization.go
Normal file
68
domain/entity/organization.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrganizationType struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Organization struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Type OrganizationType `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
ReferenceID int64 `json:"-"`
|
||||||
|
ParentID int64 `json:"-"`
|
||||||
|
Main bool `json:"main"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
Suspended bool `json:"suspended"`
|
||||||
|
Author User `json:"author"`
|
||||||
|
LastEditor User `json:"last_editor"`
|
||||||
|
Contacts []OrganizationContact `json:"contacts"`
|
||||||
|
Addresses []OrganizationAddress `json:"addresses"`
|
||||||
|
ChildOrgs []Organization `json:"childs"`
|
||||||
|
Parent *Organization `json:"parent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrganizationContact struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
|
Type ContactType `json:"type"`
|
||||||
|
Contact string `json:"contact"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
CreatedUser User `json:"author"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
UpdatedUser User `json:"last_editor"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrganizationAddress struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
|
InternalID string `json:"internal_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Latitude float64 `json:"lat"`
|
||||||
|
Longitude float64 `json:"long"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
CreatedUser User `json:"author"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
UpdatedUser User `json:"last_editor"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
17
domain/entity/profile.go
Normal file
17
domain/entity/profile.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Profile struct {
|
||||||
|
ID int64 `json:"-"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Description string `json:"desc"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
Suspended bool `json:"suspended"`
|
||||||
|
Visible bool `json:"visible"`
|
||||||
|
Organization Organization `json:"organization"`
|
||||||
|
}
|
||||||
126
domain/entity/provider.go
Normal file
126
domain/entity/provider.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Provider struct {
|
||||||
|
ProviderID int64 `json:"-"`
|
||||||
|
ProviderUUID string `json:"provider_uuid"`
|
||||||
|
InternalID string `json:"internal_id"`
|
||||||
|
InternalSuffixID string `json:"internal_suffix_id"`
|
||||||
|
MukID string `json:"muk_id"`
|
||||||
|
OrganizatioName string `json:"org_name"`
|
||||||
|
Gender string `json:"gender"`
|
||||||
|
AcceptNewPatients string `json:"accept_new_patients"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
FirstName string `json:"first"`
|
||||||
|
MiddleName string `json:"middle"`
|
||||||
|
LastName string `json:"last"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
CreateDate time.Time `json:"create_at"`
|
||||||
|
UpdateDate time.Time `json:"update_at"`
|
||||||
|
CreatedUser User `json:"created_user"`
|
||||||
|
Keys []ProviderKey `json:"keys"`
|
||||||
|
Address ProviderAddress `json:"address"`
|
||||||
|
Distance float64 `json:"distance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderKey struct {
|
||||||
|
ProviderKeyID int64 `json:"-"`
|
||||||
|
Provider Provider `json:"provider"`
|
||||||
|
InternalID string `json:"internal_id"`
|
||||||
|
InternalSuffixID string `json:"internal_suffix_id"`
|
||||||
|
LocationSeqNumber string `json:"location_seq_number"`
|
||||||
|
PlanCode string `json:"plan_code"`
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
TreatmentCategoryCode string `json:"treatment_category_code"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
CreateDate time.Time `json:"create_at"`
|
||||||
|
UpdateDate time.Time `json:"update_at"`
|
||||||
|
CreatedUser User `json:"created_user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderAddress struct {
|
||||||
|
StreetAddress1 string `json:"street_address_1"`
|
||||||
|
StreetAddress2 string `json:"street_address_2"`
|
||||||
|
CityName string `json:"city"`
|
||||||
|
State string `json:"state"`
|
||||||
|
ZipCode string `json:"zipcode"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
Latitude float64 `json:"lat"`
|
||||||
|
Longitude float64 `json:"long"`
|
||||||
|
PhoneNumber string `json:"phone_number"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
116
domain/entity/ride.go
Normal file
116
domain/entity/ride.go
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//WebhookResponse has the data and events from the webhook
|
||||||
|
type WebhookResponse struct {
|
||||||
|
EventID string `json:"event_id,omitempty"`
|
||||||
|
HREF string `json:"href,omitempty"`
|
||||||
|
OccurredAt time.Time `json:"occurred_at,omitempty"`
|
||||||
|
EventType string `json:"event_type,omitempty"`
|
||||||
|
Ride Ride `json:"event,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ride entity data
|
||||||
|
type Ride struct {
|
||||||
|
ID int64 `db:"ride_id" json:"-"`
|
||||||
|
UUID string `db:"ride_uuid" json:"ride_uuid"`
|
||||||
|
User User `db:"user" json:"user"`
|
||||||
|
Status RideStatus `db:"status" json:"status"`
|
||||||
|
Type RideType `db:"type" json:"type"`
|
||||||
|
InternalID string `db:"internal_id" json:"internal_id"`
|
||||||
|
RequestDate *time.Time `db:"request_date" json:"request_date"`
|
||||||
|
RequestMiliseconds *int64 `db:"request_ms" json:"request_ms"`
|
||||||
|
GenerateDate *time.Time `db:"generate_date" json:"generate_date"`
|
||||||
|
GenerateMiliseconds *int64 `db:"generate_ms" json:"generate_ms"`
|
||||||
|
Note string `db:"notes" json:"notes"`
|
||||||
|
PrimetimePercentage string `db:"primetime_percentage" json:"primetime_percentage"`
|
||||||
|
Passenger RidePassenger `db:"passenger" json:"passenger"`
|
||||||
|
Driver RideDriver `db:"driver" json:"driver"`
|
||||||
|
Vehicle RideVehicle `db:"vehicle" json:"vehicle"`
|
||||||
|
Route RideRoute `db:"route" json:"route"`
|
||||||
|
VisitDate *time.Time `db:"visit_date" json:"visit_date"`
|
||||||
|
VisitTime *time.Time `db:"visit_time" json:"visit_time"`
|
||||||
|
PickupTime *time.Time `db:"pickup_time" json:"pickup_time"`
|
||||||
|
Created time.Time `db:"create_at" json:"create_at"`
|
||||||
|
Updated time.Time `db:"update_at" json:"update_at"`
|
||||||
|
Visit Visit `db:"visit" json:"visit"`
|
||||||
|
CreatedUser User `db:"created_user" json:"created_user"`
|
||||||
|
TripType TripType `db:"trip_type" json:"trip_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RidePassenger entity data
|
||||||
|
type RidePassenger struct {
|
||||||
|
ID int64 `db:"ride_passenger_id" json:"-"`
|
||||||
|
FirstName string `db:"first_name" json:"first_name"`
|
||||||
|
LastName string `db:"last_name" json:"last_name"`
|
||||||
|
ImageURL *string `db:"image_url" json:"image_url"`
|
||||||
|
PhoneNumber string `db:"phone_number" json:"phone_number"`
|
||||||
|
InternalID *string `db:"internal_id" json:"internal_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideStatus entity data
|
||||||
|
type RideStatus struct {
|
||||||
|
ID int64 `db:"ride_status_id" json:"-"`
|
||||||
|
Key string `db:"key" json:"key"`
|
||||||
|
Value string `db:"value" json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideStatus entity data
|
||||||
|
type TripType struct {
|
||||||
|
ID int64 `db:"trip_type_id" json:"-"`
|
||||||
|
Key string `db:"trip_type_key" json:"key"`
|
||||||
|
Value string `db:"trip_type" json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideType entity data
|
||||||
|
type RideType struct {
|
||||||
|
ID int64 `db:"ride_type_id" json:"-"`
|
||||||
|
Key string `db:"key" json:"key"`
|
||||||
|
Value string `db:"value" json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideRoute entity data
|
||||||
|
type RideRoute struct {
|
||||||
|
ID int64 `db:"ride_route_id" json:"-"`
|
||||||
|
Origin Location `db:"origin" json:"origin"`
|
||||||
|
Destination Location `db:"destination" json:"destination"`
|
||||||
|
RouteKML *string `db:"route_kml" json:"route_kml"`
|
||||||
|
Distance float64 `db:"distance" json:"distance"`
|
||||||
|
Duration int64 `db:"duration" json:"duration"`
|
||||||
|
ETA int64 `db:"eta" json:"eta"`
|
||||||
|
Created time.Time `db:"create_at" json:"create_at"`
|
||||||
|
Updated time.Time `db:"update_at" json:"update_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location entity data
|
||||||
|
type Location struct {
|
||||||
|
ID string `db:"id" json:"id"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Address string `db:"address" json:"address"`
|
||||||
|
Latitude float64 `db:"lat" json:"lat"`
|
||||||
|
Longitude float64 `db:"lng" json:"lng"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideDriver entity data
|
||||||
|
type RideDriver struct {
|
||||||
|
ID int64 `db:"ride_driver_id" json:"-"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
ImageURL *string `db:"image_url" json:"image_url"`
|
||||||
|
PhoneNumber string `db:"phone_number" json:"phone_number"`
|
||||||
|
Rating *string `db:"rating" json:"rating"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RideVehicle entity data
|
||||||
|
type RideVehicle struct {
|
||||||
|
ID int64 `db:"ride_vehicle_id" json:"-"`
|
||||||
|
Color string `db:"color" json:"color"`
|
||||||
|
ImageURL string `db:"image_url" json:"image_url"`
|
||||||
|
LicensePlate string `db:"license_plate" json:"license_plate"`
|
||||||
|
LicensePlateState string `db:"license_plate_state" json:"license_plate_state"`
|
||||||
|
Make string `db:"make" json:"make"`
|
||||||
|
Model string `db:"model" json:"model"`
|
||||||
|
Year int64 `db:"year" json:"year"`
|
||||||
|
}
|
||||||
55
domain/entity/user.go
Normal file
55
domain/entity/user.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User entity data
|
||||||
|
type User struct {
|
||||||
|
ID int64 `db:"user_id" json:"-"`
|
||||||
|
UUID string `db:"user_uuid" json:"uuid"`
|
||||||
|
Name string `db:"name" json:"name"`
|
||||||
|
Member string `db:"member" json:"member"`
|
||||||
|
BirthDate time.Time `db:"birth_date" json:"birthdate"`
|
||||||
|
LoginID int64 `db:"login_id" json:"-"`
|
||||||
|
LoginUUID string `db:"login_uuid" json:"loginuuid"`
|
||||||
|
Email string `db:"email" json:"email"`
|
||||||
|
PhoneNumber string `db:"phone_number" json:"phonenumber"`
|
||||||
|
Pass string `db:"password" json:"pass"`
|
||||||
|
LoginKey string `db:"login_key" json:"loginkey"`
|
||||||
|
Gender string `db:"gender" json:"gender"`
|
||||||
|
Active bool `db:"active" json:"active"`
|
||||||
|
Created time.Time `db:"createat" json:"createat"`
|
||||||
|
Updated time.Time `db:"updateat" json:"updateat"`
|
||||||
|
Contacts []ContactInfo `db:"contacts" json:"contacts"`
|
||||||
|
Rides []Ride `db:"rides" json:"rides"`
|
||||||
|
Addresses []Address `db:"addresses" json:"addresses"`
|
||||||
|
Profiles []Profile `json:"profiles,omitempty"`
|
||||||
|
Types []OrganizationType `json:"types,omitempty"`
|
||||||
|
Organizations []Organization `json:"organizations,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContactInfo struct {
|
||||||
|
ID int64 `db:"contact_id" json:"contact_id"`
|
||||||
|
Type ContactType `db:"contact_type" json:"contact_type"`
|
||||||
|
UserID int64 `db:"user_id" json:"-"`
|
||||||
|
Value string `db:"value" json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContactType struct {
|
||||||
|
ID int64 `db:"contact_type_id" json:"contact_type_id"`
|
||||||
|
Key string `db:"contact_type_key" json:"contact_type_key"`
|
||||||
|
Value string `db:"contact_type_value" json:"contact_type_value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates the user entity state
|
||||||
|
func (entity *User) Validate() error {
|
||||||
|
if strings.TrimSpace(entity.Name) == "" {
|
||||||
|
return errors.NewValidationError("name", "Nome do usuário é obrigatório")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
35
domain/entity/visit.go
Normal file
35
domain/entity/visit.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VisitStatus entity data
|
||||||
|
type VisitStatus struct {
|
||||||
|
ID int64 `db:"visit_status_id" json:"-"`
|
||||||
|
Key string `db:"key" json:"key"`
|
||||||
|
Value string `db:"value" json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit entity data
|
||||||
|
type Visit struct {
|
||||||
|
ID int64 `db:"visit_id" json:"-"`
|
||||||
|
UUID string `db:"visit_uuid" json:"-"`
|
||||||
|
Status VisitStatus `db:"visit_status" json:"-"`
|
||||||
|
User User `db:"user" json:"-"`
|
||||||
|
VisitDuration int64 `db:"visit_duration" json:"-"`
|
||||||
|
VisitDatetime time.Time `db:"visit_datetime" json:"-"`
|
||||||
|
PickupDatetime time.Time `db:"pickup_datetime" json:"-"`
|
||||||
|
Notes *string `db:"notes" json:"-"`
|
||||||
|
PickupAddressID int64 `db:"pickup_address_id" json:"-"`
|
||||||
|
DestinationAddressID int64 `db:"destination_address_id" json:"-"`
|
||||||
|
Pickup Location `db:"pickup" json:"-"`
|
||||||
|
Provider Provider `db:"provider" json:"-"`
|
||||||
|
CreatedUser User `db:"created_user" json:"-"`
|
||||||
|
Created time.Time `db:"created_date" json:"-"`
|
||||||
|
Updated time.Time `db:"updated_date" json:"-"`
|
||||||
|
ReturnDate *time.Time `db:"return_date" json:"-"`
|
||||||
|
TripType TripType `db:"trip_type" json:"-"`
|
||||||
|
ExternalID string `db:"visit_external_id" json:"-"`
|
||||||
|
Rides []Ride `db:"rides" json:"-"`
|
||||||
|
}
|
||||||
36
domain/service/notification.go
Normal file
36
domain/service/notification.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import "bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type notificationService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newNotificationService(svc *Service) *notificationService {
|
||||||
|
return ¬ificationService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *notificationService) Create(notification entity.Notification) (entity.Notification, error) {
|
||||||
|
return s.svc.db.Notification().Create(notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationService) GetByUserUUIDAndReadStatus(userUUID string, status string, isRead bool) ([]entity.Notification, error) {
|
||||||
|
return c.svc.db.Notification().GetByUserUUIDAndReadStatus(userUUID, status, isRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationService) GetByUserUUID(userUUID string, status string) ([]entity.Notification, error) {
|
||||||
|
return c.svc.db.Notification().GetByUserUUID(userUUID, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationService) ReadStatus(notificationUUID string, isRead bool) error {
|
||||||
|
return c.svc.db.Notification().ReadStatus(notificationUUID, isRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *notificationService) GetLastNotificationFromPhoneNumber(notificationType string, phoneNumber string, status string) (entity.Notification, error) {
|
||||||
|
return c.svc.db.Notification().GetLastNotificationFromPhoneNumber(notificationType, phoneNumber, status)
|
||||||
|
}
|
||||||
113
domain/service/organization.go
Normal file
113
domain/service/organization.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type organizationService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newOrganizationService(svc *Service) *organizationService {
|
||||||
|
return &organizationService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetAllTypes() ([]entity.OrganizationType, error) {
|
||||||
|
return s.svc.db.Organization().GetAllTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByType(organizationTypeKey string) ([]entity.Organization, error) {
|
||||||
|
return s.svc.db.Organization().GetByType(organizationTypeKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByName(name string, searchType string) ([]entity.Organization, error) {
|
||||||
|
return s.svc.db.Organization().GetByName(name, searchType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetByUUID(organizationUUID string) (entity.Organization, error) {
|
||||||
|
organization, err := s.svc.db.Organization().GetByUUID(organizationUUID)
|
||||||
|
if err != nil {
|
||||||
|
return organization, err
|
||||||
|
}
|
||||||
|
|
||||||
|
organization.Contacts, err = s.GetContactsByOrganizationID(organization.ID)
|
||||||
|
if err != nil {
|
||||||
|
return organization, err
|
||||||
|
}
|
||||||
|
|
||||||
|
organization.Addresses, err = s.GetAddressByOrganizationID(organization.ID)
|
||||||
|
if err != nil {
|
||||||
|
return organization, err
|
||||||
|
}
|
||||||
|
|
||||||
|
organization.ChildOrgs, err = s.svc.db.Organization().GetChildsByID(organization.ID)
|
||||||
|
if err != nil {
|
||||||
|
return organization, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization.ParentID > 0 {
|
||||||
|
parent, err := s.svc.db.Organization().GetByID(organization.ParentID)
|
||||||
|
if err != nil {
|
||||||
|
return organization, err
|
||||||
|
}
|
||||||
|
organization.Parent = &parent
|
||||||
|
}
|
||||||
|
|
||||||
|
return organization, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetParentOrganization(organizationID int64, parentOrganizationID int64) error {
|
||||||
|
return s.svc.db.Organization().SetParentOrganization(organizationID, parentOrganizationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetContactsByOrganizationUUID(organizationUUID string) ([]entity.OrganizationContact, error) {
|
||||||
|
return s.svc.db.Organization().GetContactsByOrganizationUUID(organizationUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetContactsByOrganizationID(organizationID int64) ([]entity.OrganizationContact, error) {
|
||||||
|
return s.svc.db.Organization().GetContactsByOrganizationID(organizationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetContactsByUUID(contactUUID string) (entity.OrganizationContact, error) {
|
||||||
|
return s.svc.db.Organization().GetContactsByUUID(contactUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetAddressByOrganizationUUID(organizationUUID string) ([]entity.OrganizationAddress, error) {
|
||||||
|
return s.svc.db.Organization().GetAddressByOrganizationUUID(organizationUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetAddressByOrganizationID(organizationID int64) ([]entity.OrganizationAddress, error) {
|
||||||
|
return s.svc.db.Organization().GetAddressByOrganizationID(organizationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetAddressByUUID(contactUUID string) (entity.OrganizationAddress, error) {
|
||||||
|
return s.svc.db.Organization().GetAddressByUUID(contactUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) InactivateOrganizationAddress(address entity.OrganizationAddress) error {
|
||||||
|
return s.svc.db.Organization().InactivateOrganizationAddress(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetOrganizationAddress(address entity.OrganizationAddress) (entity.OrganizationAddress, error) {
|
||||||
|
return s.svc.db.Organization().SetOrganizationAddress(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) InactivateOrganizationContact(contact entity.OrganizationContact) error {
|
||||||
|
return s.svc.db.Organization().InactivateOrganizationContact(contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) SetOrganizationContact(contact entity.OrganizationContact) (entity.OrganizationContact, error) {
|
||||||
|
return s.svc.db.Organization().SetOrganizationContact(contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) AddOrganization(organization entity.Organization) (entity.Organization, error) {
|
||||||
|
return s.svc.db.Organization().AddOrganization(organization)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *organizationService) GetTypeByKey(key string) (entity.OrganizationType, error) {
|
||||||
|
return s.svc.db.Organization().GetTypeByKey(key)
|
||||||
|
}
|
||||||
33
domain/service/profile.go
Normal file
33
domain/service/profile.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type profileService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newProfileService(svc *Service) *profileService {
|
||||||
|
return &profileService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetAll() ([]entity.Profile, error) {
|
||||||
|
return s.svc.db.Profile().GetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetByKey(key string) (entity.Profile, error) {
|
||||||
|
return s.svc.db.Profile().GetByKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetVisibles(visible bool) ([]entity.Profile, error) {
|
||||||
|
return s.svc.db.Profile().GetVisibles(visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *profileService) GetByOrganizationType(organizationTypeID int64) ([]entity.Profile, error) {
|
||||||
|
return s.svc.db.Profile().GetByOrganizationType(organizationTypeID)
|
||||||
|
}
|
||||||
46
domain/service/provider.go
Normal file
46
domain/service/provider.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type providerService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newProviderService(svc *Service) *providerService {
|
||||||
|
return &providerService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *providerService) Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error) {
|
||||||
|
tx, err := s.svc.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newProviders, err := tx.Provider().Save(providers, user)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tx.Commit()
|
||||||
|
|
||||||
|
return newProviders, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) GetAll(user entity.User) ([]entity.Provider, error) {
|
||||||
|
return s.svc.db.Provider().GetAll(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) 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) {
|
||||||
|
return s.svc.db.Provider().Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *providerService) GetByMukID(mukID string, user entity.User) (entity.Provider, error) {
|
||||||
|
return s.svc.db.Provider().GetByMukID(mukID, user)
|
||||||
|
}
|
||||||
103
domain/service/ride.go
Normal file
103
domain/service/ride.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type rideService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newRideService(svc *Service) *rideService {
|
||||||
|
return &rideService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *rideService) Save(ride entity.Ride) (entity.Ride, error) {
|
||||||
|
ride, err := s.svc.db.Rides().Save(ride)
|
||||||
|
if err != nil {
|
||||||
|
return ride, err
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.svc.db.Users().GetByID(ride.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return ride, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetByUUID(ride.UUID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) Update(hook entity.WebhookResponse) (entity.Ride, error) {
|
||||||
|
user, err := s.svc.db.Users().GetByID(hook.Ride.CreatedUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Ride{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ride, err := s.svc.db.Rides().Update(hook, user)
|
||||||
|
if err != nil {
|
||||||
|
return ride, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetByUUID(ride.UUID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll return all rides
|
||||||
|
func (s *rideService) GetAll(user entity.User) ([]entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetAll(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByID(id int64, user entity.User) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByID(id, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUUID return a specific ride
|
||||||
|
func (s *rideService) GetByUUID(uuid string, user entity.User) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByUUID(uuid, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUUID return a specific ride
|
||||||
|
func (s *rideService) GetByUUIDAndUserUUID(UUID string, userUUID string) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByUUIDAndUserUUID(UUID, userUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUUID return a specific ride
|
||||||
|
func (s *rideService) GetByInternalID(internalID string) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByInternalID(internalID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUserID return a list of rides
|
||||||
|
func (s *rideService) GetByUserID(userID int64, user entity.User) ([]entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByUserID(userID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByUserUUID(userUUID string, user entity.User) ([]entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByUserUUID(userUUID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) UpdateStatus(rideUUID string, status string) error {
|
||||||
|
return s.svc.db.Rides().UpdateStatus(rideUUID, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetLastRideByPhoneNumber(phoneNumber string) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetLastRideByPhoneNumber(phoneNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetLastRideByDriversNumber(phoneNumber string) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetLastRideByDriversNumber(phoneNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByInternalPassengerID(internalPassengerID string) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByInternalPassengerID(internalPassengerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByVisitUUID(visitUUID string, user entity.User) ([]entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByVisitUUID(visitUUID, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *rideService) GetByVisitUUIDAndTripType(visitUUID string, tripTypeKey string, user entity.User) (entity.Ride, error) {
|
||||||
|
return s.svc.db.Rides().GetByVisitUUIDAndTripType(visitUUID, tripTypeKey, user)
|
||||||
|
}
|
||||||
45
domain/service/service.go
Normal file
45
domain/service/service.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *Service
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// Service holds the domain service repositories
|
||||||
|
type Service struct {
|
||||||
|
db contract.DataManager
|
||||||
|
cache contract.CacheManager
|
||||||
|
tnc contract.TNCManager
|
||||||
|
Users *userService
|
||||||
|
Rides *rideService
|
||||||
|
Visits *visitService
|
||||||
|
Provider *providerService
|
||||||
|
Notification *notificationService
|
||||||
|
Profile *profileService
|
||||||
|
Organization *organizationService
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new domain Service instance
|
||||||
|
func New(db contract.DataManager, cache contract.CacheManager, cfg *config.Config, log *logger.Logger) (*Service, error) {
|
||||||
|
once.Do(func() {
|
||||||
|
instance = &Service{db: db, cache: cache}
|
||||||
|
|
||||||
|
instance.Users = newUserService(instance)
|
||||||
|
instance.Rides = newRideService(instance)
|
||||||
|
instance.Visits = newVisitService(instance)
|
||||||
|
instance.Provider = newProviderService(instance)
|
||||||
|
instance.Notification = newNotificationService(instance)
|
||||||
|
instance.Profile = newProfileService(instance)
|
||||||
|
instance.Organization = newOrganizationService(instance)
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance, nil
|
||||||
|
}
|
||||||
28
domain/service/tnc.go
Normal file
28
domain/service/tnc.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
// tncService is the domain service for transportation network operations
|
||||||
|
type tncService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTncService returns an instance of tncService
|
||||||
|
func newTncService(svc *Service) *tncService {
|
||||||
|
return &tncService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetETA will return the list of ETA's for the current location
|
||||||
|
func (s *tncService) GetETA(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
|
||||||
|
return s.svc.tnc.GetETA(lag, log, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetDrivers return the drivers for the current location
|
||||||
|
func (s *tncService) GetDrivers(lag float64, log float64) (interface{}, error) {
|
||||||
|
return s.svc.tnc.GetDrivers(lag, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetTypes will return the available types of ride for the current location
|
||||||
|
func (s *tncService) GetTypes(lag float64, log float64, params map[string]interface{}) (interface{}, error) {
|
||||||
|
return s.svc.tnc.GetTypes(lag, log, params)
|
||||||
|
}
|
||||||
92
domain/service/user.go
Normal file
92
domain/service/user.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type userService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newUserService(svc *Service) *userService {
|
||||||
|
return &userService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll returns a list of users
|
||||||
|
func (s *userService) GetAll() (list []entity.User, err error) {
|
||||||
|
return s.svc.db.Users().GetAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID returns a specific user by its ID
|
||||||
|
func (s *userService) GetByID(userID int64) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().GetByID(userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID returns a specific user by its ID
|
||||||
|
func (s *userService) GetByUUID(uuid string, profile string) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().GetByUUID(uuid, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login returns a specific user by email and pass
|
||||||
|
func (s *userService) Login(email string, pass string) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().Login(email, pass)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login returns a specific user by email and pass
|
||||||
|
func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().FullLogin(loginType, key, pass, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login returns a specific user by email and pass
|
||||||
|
func (s *userService) Create(user entity.User) (entity.User, error) {
|
||||||
|
return s.svc.db.Users().Create(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) CreateBulk(users []entity.User) ([]entity.User, error) {
|
||||||
|
tx, err := s.svc.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, _ := range users {
|
||||||
|
users[i], err = tx.Users().Create(users[i])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(fmt.Sprintf("Email %s got error: %s", users[i].Email, err.Error()))
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println(fmt.Sprintf("Email %s created", users[i].Email))
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Commit()
|
||||||
|
return users, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUsersByProfile returns a list of users by profile
|
||||||
|
func (s *userService) GetUsersByProfile(profile string) ([]entity.User, error) {
|
||||||
|
return s.svc.db.Users().GetUsersByProfile(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) RemoveAddress(addressUUID string) error {
|
||||||
|
return s.svc.db.Users().RemoveAddress(addressUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveAddress returns a list of users by profile
|
||||||
|
func (s *userService) SaveAddress(address entity.Address) (entity.Address, error) {
|
||||||
|
return s.svc.db.Users().SaveAddress(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAddressByUUID returns a list of users by profile
|
||||||
|
func (s *userService) GetAddressByUUID(addressUUID string) (entity.Address, error) {
|
||||||
|
return s.svc.db.Users().GetAddressByUUID(addressUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) GetContactType() (retVal []entity.ContactType, err error) {
|
||||||
|
return s.svc.db.Users().GetContactType()
|
||||||
|
}
|
||||||
81
domain/service/visit.go
Normal file
81
domain/service/visit.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/entity"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// userService is the domain service for user operations
|
||||||
|
type visitService struct {
|
||||||
|
svc *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUserService returns an instance of userService
|
||||||
|
func newVisitService(svc *Service) *visitService {
|
||||||
|
return &visitService{
|
||||||
|
svc: svc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *visitService) Create(visit entity.Visit) (entity.Visit, error) {
|
||||||
|
return s.svc.db.Visits().Create(visit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *visitService) GetAll(user entity.User) ([]entity.Visit, error) {
|
||||||
|
visit, err := s.svc.db.Visits().GetAll(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rides, err := s.svc.db.Rides().GetAll(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ridesByVisit := make(map[int64][]entity.Ride)
|
||||||
|
for _, r := range rides {
|
||||||
|
rides := ridesByVisit[r.Visit.ID]
|
||||||
|
rides = append(rides, r)
|
||||||
|
ridesByVisit[r.Visit.ID] = rides
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range visit {
|
||||||
|
visit[i].Rides = ridesByVisit[v.ID]
|
||||||
|
}
|
||||||
|
|
||||||
|
return visit, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *visitService) GetByUUID(visitUUID string, user entity.User) (entity.Visit, error) {
|
||||||
|
visit, err := s.svc.db.Visits().GetByUUID(visitUUID, user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rides, err := s.svc.db.Rides().GetByVisitUUID(visitUUID, user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
visit.Rides = rides
|
||||||
|
|
||||||
|
return visit, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the ride for a expected user
|
||||||
|
func (s *visitService) GetByID(visitID int64, user entity.User) (entity.Visit, error) {
|
||||||
|
visit, err := s.svc.db.Visits().GetByID(visitID, user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rides, err := s.svc.db.Rides().GetByVisitUUID(visit.UUID, user)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Visit{}, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
visit.Rides = rides
|
||||||
|
|
||||||
|
return visit, nil
|
||||||
|
}
|
||||||
35
ecs.dev.json
Normal file
35
ecs.dev.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"containerDefinitions": [
|
||||||
|
{
|
||||||
|
"name": "api-development",
|
||||||
|
"image": "xxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/dev.nemt-portal-api:latest",
|
||||||
|
"cpu": 128,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true,
|
||||||
|
"logConfiguration": {
|
||||||
|
"logDriver": "awslogs",
|
||||||
|
"options": {
|
||||||
|
"awslogs-group": "nemt-portal-api",
|
||||||
|
"awslogs-region": "sa-east-1",
|
||||||
|
"awslogs-stream-prefix": "development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portMappings": [
|
||||||
|
{
|
||||||
|
"containerPort": 5100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": [
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_NAME",
|
||||||
|
"value": "portal-api"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_TAG",
|
||||||
|
"value": "api"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"family": "api-development"
|
||||||
|
}
|
||||||
35
ecs.prd.json
Normal file
35
ecs.prd.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"containerDefinitions": [
|
||||||
|
{
|
||||||
|
"name": "portal-api-prod",
|
||||||
|
"image": "105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:prod",
|
||||||
|
"cpu": 128,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true,
|
||||||
|
"logConfiguration": {
|
||||||
|
"logDriver": "awslogs",
|
||||||
|
"options": {
|
||||||
|
"awslogs-group": "portal-api",
|
||||||
|
"awslogs-region": "us-east-2",
|
||||||
|
"awslogs-stream-prefix": "prod"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portMappings": [
|
||||||
|
{
|
||||||
|
"containerPort": 5100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": [
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_NAME",
|
||||||
|
"value": "portal-api"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_TAGS",
|
||||||
|
"value": "api"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"family": "portal-api-prod"
|
||||||
|
}
|
||||||
35
ecs.stg.json
Normal file
35
ecs.stg.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"containerDefinitions": [
|
||||||
|
{
|
||||||
|
"name": "portal-api-dev",
|
||||||
|
"image": "105690980714.dkr.ecr.us-east-2.amazonaws.com/nemt-portal-api:dev",
|
||||||
|
"cpu": 128,
|
||||||
|
"memory": 128,
|
||||||
|
"essential": true,
|
||||||
|
"logConfiguration": {
|
||||||
|
"logDriver": "awslogs",
|
||||||
|
"options": {
|
||||||
|
"awslogs-group": "portal-api",
|
||||||
|
"awslogs-region": "us-east-2",
|
||||||
|
"awslogs-stream-prefix": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"portMappings": [
|
||||||
|
{
|
||||||
|
"containerPort": 5100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": [
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_NAME",
|
||||||
|
"value": "portal-api"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SERVICE_5100_TAGS",
|
||||||
|
"value": "api"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"family": "portal-api-dev"
|
||||||
|
}
|
||||||
44
glide.yaml
Normal file
44
glide.yaml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package: bitbucket.org/nemt/nemt-portal-api
|
||||||
|
import:
|
||||||
|
- package: github.com/Sirupsen/logrus
|
||||||
|
version: ~1.0.2
|
||||||
|
- package: github.com/dgrijalva/jwt-go
|
||||||
|
version: ~3.0.0
|
||||||
|
- package: github.com/go-sql-driver/mysql
|
||||||
|
version: ~1.3.0
|
||||||
|
- package: github.com/labstack/echo
|
||||||
|
version: ~3.2.1
|
||||||
|
subpackages:
|
||||||
|
- middleware
|
||||||
|
- package: github.com/labstack/gommon
|
||||||
|
version: ~0.2.2
|
||||||
|
subpackages:
|
||||||
|
- log
|
||||||
|
- package: github.com/spf13/viper
|
||||||
|
- package: gopkg.in/redis.v5
|
||||||
|
version: ~5.2.9
|
||||||
|
- package: github.com/didip/tollbooth
|
||||||
|
- package: github.com/lyft/lyft-go-sdk
|
||||||
|
subpackages:
|
||||||
|
- lyft
|
||||||
|
- package: github.com/pquerna/ffjson
|
||||||
|
- package: github.com/graarh/golang-socketio
|
||||||
|
- package: github.com/gorilla/websocket
|
||||||
|
- package: github.com/justwatchcom/goat
|
||||||
|
- package: googlemaps.github.io/maps
|
||||||
|
- package: gopkg.in/gomail.v2
|
||||||
|
version: ~2.0.0
|
||||||
|
- package: github.com/srajelli/ses-go
|
||||||
|
- package: github.com/aws/aws-sdk-go
|
||||||
|
version: ~1.12.66
|
||||||
|
- package: google.golang.org/api
|
||||||
|
subpackages:
|
||||||
|
- urlshortener/v1
|
||||||
|
- package: golang.org/x/oauth2
|
||||||
|
subpackages:
|
||||||
|
- google
|
||||||
|
- package: github.com/ttacon/libphonenumber
|
||||||
|
version: ~1.0.0
|
||||||
|
- package: github.com/ttacon/builder
|
||||||
|
- package: github.com/casbin/casbin
|
||||||
|
version: ~1.5.0
|
||||||
153
infra/auth/auth.go
Normal file
153
infra/auth/auth.go
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pquerna/ffjson/ffjson"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AppKeyHeaderName is the header name for application keys
|
||||||
|
AppKeyHeaderName = "App"
|
||||||
|
// AppTokenHeaderName is the header name for application token
|
||||||
|
AppTokenHeaderName = "Token"
|
||||||
|
// TokenExpiration is the auth token default expiration time
|
||||||
|
TokenExpiration = 24 * time.Hour
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TokenSigningMethod is the auth token signing algorithm
|
||||||
|
TokenSigningMethod = jwt.SigningMethodRS256
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetAppKeyFromContext returns the application key from request header
|
||||||
|
func GetAppKeyFromContext(ctx echo.Context) (appKey string, err error) {
|
||||||
|
appKey = ctx.Request().Header.Get(AppKeyHeaderName)
|
||||||
|
|
||||||
|
if strings.TrimSpace(appKey) == "" {
|
||||||
|
return "", errors.NewNotAuthorizedError("Application key not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return appKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAppKey validates the presence and validity of App key
|
||||||
|
func ValidateAppKey(ctx echo.Context, cfg *config.Config) (err error) {
|
||||||
|
appKey, err := GetAppKeyFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if appKey != cfg.HTTP.Auth.AppKey {
|
||||||
|
return errors.NewNotAuthorizedError("Invalid API Key")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCertPrivateKey returns the private key for the token authentication certificate
|
||||||
|
func GetCertPrivateKey(path string) (pk *rsa.PrivateKey, err error) {
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pk, err = jwt.ParseRSAPrivateKeyFromPEM(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCertPublicKey returns the public key for the token authentication certificate
|
||||||
|
func GetCertPublicKey(path string) (pk *rsa.PublicKey, err error) {
|
||||||
|
privateKey, err := GetCertPrivateKey(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &privateKey.PublicKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateToken creates a token based on certificate
|
||||||
|
func GenerateToken(cfg *config.Config, data interface{}) (tokenString string, err error) {
|
||||||
|
key, _ := GetCertPrivateKey(cfg.HTTP.Auth.CertificatePath)
|
||||||
|
|
||||||
|
claims := jwt.MapClaims{
|
||||||
|
"iat": time.Now().Unix(),
|
||||||
|
"exp": time.Now().Add(TokenExpiration).Unix(),
|
||||||
|
"iss": "BDC",
|
||||||
|
"sub": "NEMT",
|
||||||
|
"data": data,
|
||||||
|
}
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(TokenSigningMethod, claims)
|
||||||
|
tokenString, err = token.SignedString(key)
|
||||||
|
if err != nil {
|
||||||
|
return tokenString, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTokenDetail(ctx echo.Context, cfg *config.Config) (interface{}, error) {
|
||||||
|
key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
|
||||||
|
|
||||||
|
tokenString := ctx.Request().Header.Get("Token")
|
||||||
|
tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
|
||||||
|
|
||||||
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||||
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||||
|
return claims["data"], nil
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserDetail(ctx echo.Context, cfg *config.Config) (viewmodel.User, error) {
|
||||||
|
key, _ := GetCertPublicKey(cfg.HTTP.Auth.CertificatePath)
|
||||||
|
|
||||||
|
tokenString := ctx.Request().Header.Get("Token")
|
||||||
|
tokenString = strings.Replace(tokenString, "Bearer ", "", -1)
|
||||||
|
|
||||||
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||||
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||||
|
byteData, _ := ffjson.Marshal(claims["data"])
|
||||||
|
user := viewmodel.User{}
|
||||||
|
err = ffjson.Unmarshal(byteData, &user)
|
||||||
|
if err != nil {
|
||||||
|
return viewmodel.User{}, err
|
||||||
|
} else {
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return viewmodel.User{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
109
infra/aws/aws.go
Normal file
109
infra/aws/aws.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ssm"
|
||||||
|
)
|
||||||
|
|
||||||
|
//AWSUtil return the methods to interact with AWS Services
|
||||||
|
type AWSUtil struct {
|
||||||
|
configApp *config.Config
|
||||||
|
awsConfig *aws.Config
|
||||||
|
s3Service *s3.S3
|
||||||
|
ssmService *ssm.SSM
|
||||||
|
awsSession *session.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
//New return an instance of AWSUtil
|
||||||
|
func New(configApp *config.Config) *AWSUtil {
|
||||||
|
cfg := aws.NewConfig().WithRegion("sa-east-1")
|
||||||
|
cfg.DisableRestProtocolURICleaning = aws.Bool(true)
|
||||||
|
|
||||||
|
return &AWSUtil{
|
||||||
|
configApp: configApp,
|
||||||
|
awsConfig: cfg,
|
||||||
|
s3Service: s3.New(session.New(), cfg),
|
||||||
|
ssmService: ssm.New(session.New(), cfg),
|
||||||
|
awsSession: session.New(cfg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//DownloadFromS3Bucket will return the file on the S3 Bucket
|
||||||
|
func (a AWSUtil) DownloadFromS3Bucket(filePath string) ([]byte, error) {
|
||||||
|
downloader := s3manager.NewDownloader(a.awsSession)
|
||||||
|
|
||||||
|
b := &aws.WriteAtBuffer{}
|
||||||
|
_, err := downloader.Download(b, &s3.GetObjectInput{
|
||||||
|
Bucket: aws.String(a.configApp.Aws.S3Bucket),
|
||||||
|
Key: aws.String(filePath),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
} else {
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//UploadToS3Bucket will upload a file to the S3 Bucket
|
||||||
|
func (a AWSUtil) UploadToS3Bucket(filePath string, fileName string, buff []byte) error {
|
||||||
|
fileBytes := bytes.NewReader(buff)
|
||||||
|
fileType := http.DetectContentType(buff)
|
||||||
|
|
||||||
|
fullPath := path.Join(filePath, fileName)
|
||||||
|
|
||||||
|
params := &s3.PutObjectInput{
|
||||||
|
Bucket: aws.String(a.configApp.Aws.S3Bucket),
|
||||||
|
Key: aws.String(fullPath),
|
||||||
|
Body: fileBytes,
|
||||||
|
ContentLength: aws.Int64(int64(len(buff))),
|
||||||
|
ContentType: aws.String(fileType),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := a.s3Service.PutObject(params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//SsmPutParameter put parameter to SSM
|
||||||
|
func (a AWSUtil) SsmPutParameter(parameterName string, parameterValue string) error {
|
||||||
|
params := &ssm.PutParameterInput{
|
||||||
|
Name: aws.String(parameterName),
|
||||||
|
Type: aws.String("SecureString"),
|
||||||
|
Value: aws.String(parameterValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := a.ssmService.PutParameter(params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//SsmGetParameter get parameter from SSM
|
||||||
|
func (a AWSUtil) SsmGetParameter(parameterName string, withDecryption bool) (string, error) {
|
||||||
|
params := &ssm.GetParameterInput{
|
||||||
|
Name: aws.String(parameterName),
|
||||||
|
WithDecryption: aws.Bool(withDecryption),
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := a.ssmService.GetParameter(params)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*output.Parameter.Value), nil
|
||||||
|
}
|
||||||
144
infra/cache/cache.go
vendored
Normal file
144
infra/cache/cache.go
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
redis "gopkg.in/redis.v5"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/domain/contract"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/config"
|
||||||
|
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
instance *RedisCache
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// RedisCache implements the CacheManager interface
|
||||||
|
type RedisCache struct {
|
||||||
|
cfg *config.Config
|
||||||
|
redis *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance returns a CacheManager instance
|
||||||
|
func Instance(cfg *config.Config) contract.CacheManager {
|
||||||
|
once.Do(func() {
|
||||||
|
client := redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
|
MasterName: "master01",
|
||||||
|
SentinelAddrs: []string{fmt.Sprintf("%s:%v", cfg.Cache.Server, cfg.Cache.Port)},
|
||||||
|
Password: cfg.Cache.Pass,
|
||||||
|
DB: cfg.Cache.DB,
|
||||||
|
})
|
||||||
|
|
||||||
|
instance = &RedisCache{cfg, client}
|
||||||
|
})
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisCache) buildKey(key string) string {
|
||||||
|
return fmt.Sprintf("%s-%s", r.cfg.Cache.Prefix, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetItem returns an Item from cache
|
||||||
|
func (r *RedisCache) GetItem(key string) (data []byte, err error) {
|
||||||
|
val, err := r.redis.Get(r.buildKey(key)).Bytes()
|
||||||
|
if err == redis.Nil {
|
||||||
|
return val, domain.ErrCacheMiss
|
||||||
|
} else if err != nil {
|
||||||
|
return val, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetItem sets an item in cache
|
||||||
|
func (r *RedisCache) SetItem(key string, data []byte) error {
|
||||||
|
err := r.redis.Set(r.buildKey(key), data, r.cfg.Cache.DefaultExpiration).Err()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetString returns an string from cache
|
||||||
|
func (r *RedisCache) GetString(key string) (data string, err error) {
|
||||||
|
val, err := r.GetItem(key)
|
||||||
|
if err == domain.ErrCacheMiss {
|
||||||
|
return data, domain.ErrCacheMiss
|
||||||
|
} else if err != nil {
|
||||||
|
return data, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(val), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetString sets an item in cache
|
||||||
|
func (r *RedisCache) SetString(key string, data string) error {
|
||||||
|
err := r.SetItem(key, []byte(data))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStruct returns an struct from cache
|
||||||
|
func (r *RedisCache) GetStruct(key string, data interface{}) (err error) {
|
||||||
|
val, err := r.GetItem(key)
|
||||||
|
if err == domain.ErrCacheMiss {
|
||||||
|
return domain.ErrCacheMiss
|
||||||
|
} else if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(val, &data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStruct sets an item in cache
|
||||||
|
func (r *RedisCache) SetStruct(key string, data interface{}) error {
|
||||||
|
dataString, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.SetItem(key, dataString)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExpiration returns the expiration time for a key
|
||||||
|
func (r *RedisCache) GetExpiration(key string) (expiration time.Duration, err error) {
|
||||||
|
expiration, err = r.redis.TTL(r.buildKey(key)).Result()
|
||||||
|
if err != nil {
|
||||||
|
return expiration, errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return expiration, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExpiration sets the expiration time for a key
|
||||||
|
func (r *RedisCache) SetExpiration(key string, expiration time.Duration) (err error) {
|
||||||
|
err = r.redis.Expire(r.buildKey(key), expiration).Err()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
249
infra/config/config.go
Normal file
249
infra/config/config.go
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config represents the configuration values for the whole service.
|
||||||
|
type Config struct {
|
||||||
|
App AppConfig
|
||||||
|
DB DBConfig
|
||||||
|
HTTP HTTPConfig
|
||||||
|
Log LogConfig
|
||||||
|
Aws AwsConfig
|
||||||
|
Cache CacheConfig
|
||||||
|
Twilio TwilioConfig
|
||||||
|
Lyft LyftConfig
|
||||||
|
LyftProd LyftProdConfig
|
||||||
|
BXE BXEConfig
|
||||||
|
Blue365 Blue365Config
|
||||||
|
Email EmailConfig
|
||||||
|
GoogleShortener GoogleShortenerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppConfig represents the configuration values about the application.
|
||||||
|
type AppConfig struct {
|
||||||
|
Name string
|
||||||
|
Debug bool
|
||||||
|
Docs DocsConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// TwilioConfig represents the configuration values about the twilio.
|
||||||
|
type TwilioConfig struct {
|
||||||
|
Account string
|
||||||
|
Token string
|
||||||
|
Sender string
|
||||||
|
TwiMLSID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LyftConfig represents the configuration values about the lyft.
|
||||||
|
type LyftConfig struct {
|
||||||
|
Client string
|
||||||
|
Secret string
|
||||||
|
RefreshToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
type LyftProdConfig struct {
|
||||||
|
Lyft LyftConfig
|
||||||
|
UserUUID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BXEConfig represents the configuration values about the BXE.
|
||||||
|
type BXEConfig struct {
|
||||||
|
URL string
|
||||||
|
APIKey string
|
||||||
|
Secret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blue365Config represents the configuration values about the Blue 365.
|
||||||
|
type Blue365Config struct {
|
||||||
|
URL string
|
||||||
|
APIKey string
|
||||||
|
Secret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBConfig represents the configuration values about the DB.
|
||||||
|
type DBConfig struct {
|
||||||
|
User string
|
||||||
|
Pass string
|
||||||
|
Name string
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
MaxLifeInMinutes int
|
||||||
|
MaxIdleConns int
|
||||||
|
MaxOpenConns int
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPConfig represents the configuration values about the HTTP server.
|
||||||
|
type HTTPConfig struct {
|
||||||
|
Port int
|
||||||
|
Prefix string
|
||||||
|
Auth HTTPAuthConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPAuthConfig represents the configuration values about the HTTP authentication (JWT and CORS).
|
||||||
|
type HTTPAuthConfig struct {
|
||||||
|
AppKey string
|
||||||
|
CertificatePath string
|
||||||
|
FrontendURLs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogConfig represents the configuration values about the logging config.
|
||||||
|
type LogConfig struct {
|
||||||
|
LogToFile bool
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// AwsConfig represents the configuration values about the aws config.
|
||||||
|
type AwsConfig struct {
|
||||||
|
S3Bucket string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocsConfig represents the configuration values about the documentation config.
|
||||||
|
type DocsConfig struct {
|
||||||
|
YAMLPath string
|
||||||
|
SwaggerPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheConfig represents the configuration values about the documentation config.
|
||||||
|
type CacheConfig struct {
|
||||||
|
Server string
|
||||||
|
Port int
|
||||||
|
DB int
|
||||||
|
Pass string
|
||||||
|
Prefix string
|
||||||
|
DefaultExpiration time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheConfig represents the configuration values about the documentation config.
|
||||||
|
type EmailConfig struct {
|
||||||
|
Server string
|
||||||
|
Port int
|
||||||
|
User string
|
||||||
|
Pass string
|
||||||
|
Sender string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoogleShortenerConfig struct {
|
||||||
|
APIKey string
|
||||||
|
ClientID string
|
||||||
|
SecretKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read returns the configuration values,
|
||||||
|
// based on the configuration files and environment variables.
|
||||||
|
func Read() (*Config, error) {
|
||||||
|
setup()
|
||||||
|
err := viper.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
if err == os.ErrNotExist {
|
||||||
|
viper.SetConfigName("config.local")
|
||||||
|
err = viper.ReadInConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Config{
|
||||||
|
App: AppConfig{
|
||||||
|
Name: viper.GetString("app.name"),
|
||||||
|
Debug: viper.GetBool("app.debug"),
|
||||||
|
Docs: DocsConfig{
|
||||||
|
YAMLPath: viper.GetString("app.docs.yaml-path"),
|
||||||
|
SwaggerPath: viper.GetString("app.docs.swagger-path"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DB: DBConfig{
|
||||||
|
User: viper.GetString("db.user"),
|
||||||
|
Pass: viper.GetString("db.pass"),
|
||||||
|
Name: viper.GetString("db.name"),
|
||||||
|
Host: viper.GetString("db.host"),
|
||||||
|
Port: viper.GetInt("db.port"),
|
||||||
|
MaxLifeInMinutes: viper.GetInt("db.max-life-minutes"),
|
||||||
|
MaxIdleConns: viper.GetInt("db.max-idle-conns"),
|
||||||
|
MaxOpenConns: viper.GetInt("db.max-open-conns"),
|
||||||
|
},
|
||||||
|
HTTP: HTTPConfig{
|
||||||
|
Port: viper.GetInt("http.port"),
|
||||||
|
Prefix: viper.GetString("http.prefix"),
|
||||||
|
Auth: HTTPAuthConfig{
|
||||||
|
AppKey: viper.GetString("http.auth.app-key"),
|
||||||
|
CertificatePath: viper.GetString("http.auth.certificate-path"),
|
||||||
|
FrontendURLs: viper.GetStringSlice("http.auth.frontend-urls"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Log: LogConfig{
|
||||||
|
LogToFile: viper.GetBool("log.log-to-file"),
|
||||||
|
Path: viper.GetString("log.path"),
|
||||||
|
},
|
||||||
|
Aws: AwsConfig{
|
||||||
|
S3Bucket: viper.GetString("aws.s3-bucket"),
|
||||||
|
},
|
||||||
|
Cache: CacheConfig{
|
||||||
|
Server: viper.GetString("cache.server"),
|
||||||
|
Port: viper.GetInt("cache.port"),
|
||||||
|
DB: viper.GetInt("cache.db"),
|
||||||
|
Pass: viper.GetString("cache.pass"),
|
||||||
|
Prefix: viper.GetString("cache.prefix"),
|
||||||
|
DefaultExpiration: viper.GetDuration("cache.default-expiration"),
|
||||||
|
},
|
||||||
|
Lyft: LyftConfig{
|
||||||
|
Client: viper.GetString("lyft.key"),
|
||||||
|
Secret: viper.GetString("lyft.secret"),
|
||||||
|
RefreshToken: viper.GetString("lyft.token"),
|
||||||
|
},
|
||||||
|
LyftProd: LyftProdConfig{
|
||||||
|
Lyft: LyftConfig{
|
||||||
|
Client: viper.GetString("lyft-prod.key"),
|
||||||
|
Secret: viper.GetString("lyft-prod.secret"),
|
||||||
|
RefreshToken: viper.GetString("lyft-prod.token"),
|
||||||
|
},
|
||||||
|
UserUUID: viper.GetString("lyft-prod.user-uuid"),
|
||||||
|
},
|
||||||
|
Twilio: TwilioConfig{
|
||||||
|
Account: viper.GetString("twilio.account"),
|
||||||
|
Token: viper.GetString("twilio.token"),
|
||||||
|
Sender: viper.GetString("twilio.sender"),
|
||||||
|
TwiMLSID: viper.GetString("twilio.twiml-sid"),
|
||||||
|
},
|
||||||
|
BXE: BXEConfig{
|
||||||
|
URL: viper.GetString("bxe.url"),
|
||||||
|
APIKey: viper.GetString("bxe.key"),
|
||||||
|
Secret: viper.GetString("bxe.secret"),
|
||||||
|
},
|
||||||
|
Blue365: Blue365Config{
|
||||||
|
URL: viper.GetString("blue365.url"),
|
||||||
|
APIKey: viper.GetString("blue365.key"),
|
||||||
|
Secret: viper.GetString("blue365.secret"),
|
||||||
|
},
|
||||||
|
Email: EmailConfig{
|
||||||
|
Server: viper.GetString("email.server"),
|
||||||
|
Port: viper.GetInt("email.port"),
|
||||||
|
User: viper.GetString("email.user"),
|
||||||
|
Pass: viper.GetString("email.pass"),
|
||||||
|
Sender: viper.GetString("email.sender"),
|
||||||
|
},
|
||||||
|
GoogleShortener: GoogleShortenerConfig{
|
||||||
|
APIKey: viper.GetString("google-shortener.api-key"),
|
||||||
|
ClientID: viper.GetString("google-shortener.client-id"),
|
||||||
|
SecretKey: viper.GetString("google-shortener.secret-key"),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup() {
|
||||||
|
viper.SetEnvPrefix("api")
|
||||||
|
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
|
||||||
|
viper.SetConfigName("config")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user