mastering bridging

This commit is contained in:
gigihshs
2025-11-24 09:13:08 +07:00
commit e1b99f8f38
115 changed files with 12298 additions and 0 deletions

9
.env-example Normal file
View File

@@ -0,0 +1,9 @@
AUTH_URL=
BASE_URL=
CONSENT_URL=
KFA_URL=
CLIENT_ID=
CLIENT_SECRET=
ORGANIZATION_ID=
HTTP_PORT=8080

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
.vscode

32
Dockerfile Normal file
View File

@@ -0,0 +1,32 @@
# Build stage
FROM golang:1.21 AS build-env
ENV GO111MODULE=on
# Set /app as the working directory
WORKDIR /app
# Copy all files to /app
COPY . .
COPY .env .env
# Install dependencies
RUN go mod download && go mod verify
RUN go mod tidy -v
# Build the Go application
RUN CGO_ENABLED=0 GOOS=linux go build -v -installsuffix cgo -o app cmd/main.go
# final
FROM ubuntu:20.04
RUN apt-get update -y
RUN apt-get -y install wget
COPY --from=build-env /app/app .
EXPOSE 8080
# Define the command to run the application
CMD ["./app"]

1
README.md Normal file
View File

@@ -0,0 +1 @@
# satusehat-bridge

5
builder-api.sh Normal file
View File

@@ -0,0 +1,5 @@
sudo docker build -t satusehat-bridge:1.0 .
sudo docker stop satusehat-bridge_satusehat-bridge_1
sudo docker-compose down --volumes --remove-orphans
sudo docker-compose --env-file .env up --build

6
builder-swag.sh Normal file
View File

@@ -0,0 +1,6 @@
cd openapi/
sudo docker stop swagger-satusehat
sudo docker rm swagger-satusehat
sudo docker build -t openapi:1.0 .
sudo docker run --name swagger-satusehat -p 8081:8080 openapi:1.0

146
cmd/main.go Normal file
View File

@@ -0,0 +1,146 @@
package main
import (
"fmt"
"log"
"net/http"
"os"
"satusehat-rssa/internal/config"
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/midleware"
"satusehat-rssa/internal/routes"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
func main() {
var err error
// load environment
if err := godotenv.Load(); err != nil {
log.Println("No .env file found or error loading it")
}
// init gin engine
e := gin.Default()
err = e.SetTrustedProxies(nil)
if err != nil {
panic(err)
}
// cors middleware
e.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization")
// log to ensure the middleware is being executed
c.Writer.Header().Set("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Content-Disposition")
if c.Request.Method == "OPTIONS" {
c.Writer.Header().Set("Access-Control-Max-Age", "86400")
c.AbortWithStatus(http.StatusOK)
return
}
c.Next()
})
// health check
e.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "ok",
})
})
// route for handling 404
e.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{"message": "Hello in API Satu Sehat Integration"})
})
//Load Akses
akses := config.LoadConfig()
authMiddleware := midleware.AuthMiddleware{}
oa := integration.NewOauthRequestRepo(akses)
at := integration.NewAllergancyToleranRepo(akses)
cp := integration.NewCarePlanRepo(akses)
qr := integration.NewQuestionnaireResponseRepo(akses)
ms := integration.NewMedicationStatementRepo(akses)
im := integration.NewImmunizationRepo(akses)
is := integration.NewImagingStudyRepo(akses)
mr := integration.NewMedicationRequestRepo(akses)
md := integration.NewMedicationDispenseRepo(akses)
gl := integration.NewGoalRepo(akses)
medic := integration.NewMedicineKfaRepo(akses)
patient := integration.NewPatientRepo(akses)
practioner := integration.NewPracticionerRepo(akses)
encounter := integration.NewEncounterRepo(akses)
clinicalImpression := integration.NewClinicalImpressionRepo(akses)
observation := integration.NewObservationRepo(akses)
organization := integration.NewOrganizationRepo(akses)
condition := integration.NewConditionRepo(akses)
dianosisReport := integration.NewDiagnosisReportRepo(akses)
serviceRequest := integration.NewServiceRequestRepository(akses)
specimen := integration.NewSpecimenRepository(akses)
episodeOfCare := integration.NewEpisodeOfCareRepo(akses)
procedure := integration.NewProcedureRepo(akses)
composition := integration.NewCompositionRepo(akses)
oahandler := handler.NewOuathHandler(oa)
athandler := handler.NewAllergancyToleranHandler(at)
cphandler := handler.NewCarePlanHandler(cp)
qrhandler := handler.NewQuestionnaireResponseHandler(qr)
mshandler := handler.NewMedicationStatementHandler(ms)
imhandler := handler.NewImmunizationHandler(im)
ishandler := handler.NewImagingStudyHandler(is)
mrhandler := handler.NewMedicationRequestHandler(mr)
mdhandler := handler.NewMedicationDispenseHandler(md)
glhandler := handler.NewGoalHandler(gl)
medicineHandler := handler.NewMedicineHandler(medic)
patientHandler := handler.NewPatientHandler(patient)
practicionerHandler := handler.NewPracticionerHandler(practioner)
encounterHandler := handler.NewEncounterHandler(encounter)
clinicalImpressionHandler := handler.NewClinicalImpressionHandler(clinicalImpression)
observationHandler := handler.NewObservationHandler(observation)
organizationHandler := handler.NewOrganizationHandler(organization)
conditionHandler := handler.NewConditionHandler(condition)
diagnosisReportHandler := handler.NewDiagnosisReportHandler(dianosisReport)
serviceRequestHandler := handler.NewServiceRequestHandler(serviceRequest)
specimenHandler := handler.NewSpecimenHandler(specimen)
episodeOfCareHandler := handler.NewEpisodeOfCareHandler(episodeOfCare)
procedureHandler := handler.NewProcedureHandler(procedure)
compositionHandler := handler.NewCompositionHandler(composition)
routes.Oauth(e, oahandler, authMiddleware)
routes.AllergancyToleran(e, athandler, authMiddleware)
routes.CarePlan(e, cphandler, authMiddleware)
routes.QuestionnaireResponse(e, qrhandler, authMiddleware)
routes.MedicationStatement(e, mshandler, authMiddleware)
routes.Immunization(e, imhandler, authMiddleware)
routes.ImagingStudy(e, ishandler, authMiddleware)
routes.MedicationRequest(e, mrhandler, authMiddleware)
routes.MedicationDispense(e, mdhandler, authMiddleware)
routes.Goal(e, glhandler, authMiddleware)
routes.MedicineKfa(e, medicineHandler, authMiddleware)
routes.Patient(e, patientHandler, authMiddleware)
routes.Practicioner(e, practicionerHandler, authMiddleware)
routes.Encounter(e, encounterHandler, authMiddleware)
routes.ClinicalImpression(e, clinicalImpressionHandler, authMiddleware)
routes.Observation(e, observationHandler, authMiddleware)
routes.Organization(e, organizationHandler, authMiddleware)
routes.Condition(e, conditionHandler, authMiddleware)
routes.DiagnosisReport(e, diagnosisReportHandler, authMiddleware)
routes.ServiceRequest(e, serviceRequestHandler, authMiddleware)
routes.Specimen(e, specimenHandler, authMiddleware)
routes.EpisodeOfCare(e, episodeOfCareHandler, authMiddleware)
routes.Procedure(e, procedureHandler, authMiddleware)
routes.Composition(e, compositionHandler, authMiddleware)
port := fmt.Sprintf(":%s", os.Getenv("HTTP_PORT"))
if err = e.Run(port); err != nil {
panic(err)
}
}

10
docker-compose.yaml Normal file
View File

@@ -0,0 +1,10 @@
version: '3.8'
services:
satusehat-bridge:
image: satusehat-bridge:1.0
ports:
- "8080:8080"
env_file:
- .env
restart: unless-stopped

37
go.mod Normal file
View File

@@ -0,0 +1,37 @@
module satusehat-rssa
go 1.21.12
require (
github.com/gin-gonic/gin v1.10.1
github.com/go-playground/validator/v10 v10.26.0
github.com/joho/godotenv v1.5.1
)
require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

93
go.sum Normal file
View File

@@ -0,0 +1,93 @@
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -0,0 +1,18 @@
package config
import (
"os"
"satusehat-rssa/internal/model"
)
func LoadConfig() *model.Akses {
return &model.Akses{
AuthUrl: os.Getenv("AUTH_URL"),
BaseUrl: os.Getenv("BASE_URL"),
ConsentUrl: os.Getenv("CONSENT_URL"),
KfaUrl: os.Getenv("KFA_URL"),
ClientId: os.Getenv("CLIENT_ID"),
ClientSecret: os.Getenv("CLIENT_SECRET"),
}
}

View File

@@ -0,0 +1,29 @@
package constant
const (
AllergyIntoleranceResourceType = "AllergyIntolerance"
ClinicalImpressionResourceType = "ClinicalImpression"
ServiceRequestResourceType = "ServiceRequest"
EpisodeOfCareResourceType = "EpisodeOfCare"
SpecimenResourceType = "Specimen"
DiagnosticReportResourceType = "DiagnosticReport"
ObservationResourceType = "Observation"
OrganizationResourceType = "Organization"
CarePlanResourceType = "CarePlan"
QuestionnaireResponseResourceType = "QuestionnaireResponse"
MedicationStatementResourceType = "MedicationStatement"
ImmunizationResourceType = "Immunization"
ImagingStudyResourceType = "ImagingStudy"
MedicationRequestResourceType = "MedicationRequest"
MedicationDispenseResourceType = "MedicationDispense"
ProcedureResourceType = "Procedure"
GoalResourceType = "Goal"
PatientResourceType = "Patient"
EncounterResourceType = "Encounter"
)
const (
ContentTypeFHIRJSON = "application/fhir+json"
PatientProfile = "https://fhir.kemkes.go.id/r4/StructureDefinition/Patient"
FHIRMedicationProfile = "https://fhir.kemkes.go.id/r4/StructureDefinition/Medication"
)

View File

@@ -0,0 +1,5 @@
package constant
const (
ErrGenerateToken = "failed to generate access token"
)

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type AllergancyToleranHandler struct {
AllergancyToleran integration.AllergancyToleranInterface
}
func NewAllergancyToleranHandler(AllergancyToleran integration.AllergancyToleranInterface) *AllergancyToleranHandler {
return &AllergancyToleranHandler{AllergancyToleran: AllergancyToleran}
}
func (a AllergancyToleranHandler) CreateAllergancyToleran(c *gin.Context) {
var bodyParam model.AllergancyToleranRequest
if err := c.ShouldBindJSON(&bodyParam); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
res, err := a.AllergancyToleran.CreateAllergancyToleran(bodyParam)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (a AllergancyToleranHandler) UpdateAllergancyToleran(c *gin.Context) {
var bodyParam model.AllergancyToleranRequest
if err := c.ShouldBindJSON(&bodyParam); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
bodyParam.Id = c.Param("id")
res, err := a.AllergancyToleran.UpdateAllergancyToleran(bodyParam)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type CarePlanHandler struct {
CarePlan integration.CarePlanInterface
}
func NewCarePlanHandler(CarePlan integration.CarePlanInterface) *CarePlanHandler {
return &CarePlanHandler{CarePlan: CarePlan}
}
func (h CarePlanHandler) CreateCarePlan(c *gin.Context) {
var req model.CarePlanRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.CarePlan.CreateCarePlan(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h CarePlanHandler) UpdateCarePlan(c *gin.Context) {
var req model.CarePlanRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.CarePlan.CreateCarePlan(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,62 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type ClinicalImpressionHandler struct {
// Define fields for ClinicalImpressionHandler
ClinicalImpression integration.ClinicalImppressionInterface
}
func NewClinicalImpressionHandler(ClinicalImpression integration.ClinicalImppressionInterface) *ClinicalImpressionHandler {
return &ClinicalImpressionHandler{ClinicalImpression: ClinicalImpression}
}
func (c *ClinicalImpressionHandler) CreateClinicalImpression(ctx *gin.Context) {
var bodyParam model.ClinicalImpressionRequest
if err := ctx.ShouldBindJSON(&bodyParam); err != nil {
ctx.JSON(http.StatusBadRequest, err)
return
}
bodyParam.Identifier = append(bodyParam.Identifier, common.GetIdentifier("clinicalImpression"))
res, err := c.ClinicalImpression.CreateClinicalImpression(bodyParam)
if err != nil {
if res != nil {
ctx.JSON(http.StatusInternalServerError, res)
return
}
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, res)
}
func (c *ClinicalImpressionHandler) UpdateClinicalImpression(ctx *gin.Context) {
var bodyParam model.ClinicalImpressionRequest
if err := ctx.ShouldBindJSON(&bodyParam); err != nil {
ctx.JSON(http.StatusBadRequest, err)
return
}
bodyParam.Id = ctx.Param("id")
bodyParam.Identifier = append(bodyParam.Identifier, common.GetIdentifier("clinicalImpression"))
res, err := c.ClinicalImpression.UpdateClinicalImpression(bodyParam)
if err != nil {
if res != nil {
ctx.JSON(http.StatusInternalServerError, res)
return
}
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,62 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type CompositionHandler struct {
Composition integration.CompositionInterface
}
func NewCompositionHandler(composition integration.CompositionInterface) *CompositionHandler {
return &CompositionHandler{
Composition: composition,
}
}
func (ch *CompositionHandler) CreateComposition(c *gin.Context) {
var req model.CompositionRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Identifier = common.GetIdentifier("composition")
resp, err := ch.Composition.CreateComposition(req)
if err != nil {
if resp != nil {
c.JSON(http.StatusInternalServerError, resp)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, resp)
}
func (ch *CompositionHandler) UpdateComposition(c *gin.Context) {
var req model.CompositionRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Identifier = common.GetIdentifier("composition")
req.Id = c.Param("id")
resp, err := ch.Composition.UpdateComposition(req)
if err != nil {
if resp != nil {
c.JSON(http.StatusInternalServerError, resp)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, resp)
}

View File

@@ -0,0 +1,75 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type ConditionHandler struct {
// Define fields for ConditionHandler
Condition integration.ConditionInterface
}
func NewConditionHandler(condition integration.ConditionInterface) *ConditionHandler {
return &ConditionHandler{Condition: condition}
}
func (c *ConditionHandler) CreateCondition(ctx *gin.Context) {
var bodyParam model.ConditionRequest
if err := ctx.ShouldBindJSON(&bodyParam); err != nil {
ctx.JSON(http.StatusBadRequest, err)
return
}
res, err := c.Condition.CreateCondition(bodyParam)
if err != nil {
if res != nil {
ctx.JSON(http.StatusInternalServerError, res)
return
}
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, res)
}
func (c *ConditionHandler) GetConditionByPatient(ctx *gin.Context) {
patientId := ctx.Query("subject")
if patientId == "" {
ctx.JSON(http.StatusBadRequest, "patientId is required")
return
}
res, err := c.Condition.GetConditionByPatient(patientId)
if err != nil {
if res != nil {
ctx.JSON(http.StatusInternalServerError, res)
return
}
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, res)
}
func (c *ConditionHandler) UpdateCondition(ctx *gin.Context) {
var bodyParam model.ConditionRequest
if err := ctx.ShouldBindJSON(&bodyParam); err != nil {
ctx.JSON(http.StatusBadRequest, err)
return
}
bodyParam.Id = ctx.Param("id")
res, err := c.Condition.UpdateCondition(bodyParam)
if err != nil {
if res != nil {
ctx.JSON(http.StatusInternalServerError, res)
return
}
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,62 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type DiagnosisReportHandler struct {
DiagnosisReport integration.DiagnosisReportInterface
}
func NewDiagnosisReportHandler(diagnosisReport integration.DiagnosisReportInterface) *DiagnosisReportHandler {
return &DiagnosisReportHandler{DiagnosisReport: diagnosisReport}
}
func (d *DiagnosisReportHandler) CreateDiagnosisReport(c *gin.Context) {
var req model.DiagnosticReportRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
identifier := common.GetIdentifier("diagnostic")
identifier.System += "/lab"
req.Identifier = append(req.Identifier, identifier)
res, err := d.DiagnosisReport.CreateDiagnosisReport(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (d *DiagnosisReportHandler) UpdateDiagnosisReport(c *gin.Context) {
var req model.DiagnosticReportRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
identifier := common.GetIdentifier("diagnostic")
identifier.System += "/lab"
req.Identifier = append(req.Identifier, identifier)
res, err := d.DiagnosisReport.UpdateDiagnosisReport(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,81 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type EncounterHandler struct {
// Define any dependencies needed for the handler
Encounter integration.EncounterInterface
}
func NewEncounterHandler(encounter integration.EncounterInterface) *EncounterHandler {
return &EncounterHandler{Encounter: encounter}
}
// Add methods for handling encounter-related requests here
func (e *EncounterHandler) CreateEncounter(c *gin.Context) {
var req model.EncounterRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := e.Encounter.CreateEncounter(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (e *EncounterHandler) GetEncounterByPatient(c *gin.Context) {
id := c.Query("subject")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Subject is required"})
return
}
encounter, err := e.Encounter.GetEncounterByPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if encounter == nil {
c.JSON(http.StatusNotFound, gin.H{"message": "Encounter not found"})
return
}
c.JSON(http.StatusOK, encounter)
}
func (e *EncounterHandler) UpdateEncounter(c *gin.Context) {
var req model.EncounterUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// set id for param
id := c.Param("id")
req.ID = id
res, err := e.Encounter.UpdateEncounter(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,80 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type EpisodeOfCareHandler struct {
// Define any dependencies needed for the handler
EpisodeOfCare integration.EpisodeOfCareInterface
}
func NewEpisodeOfCareHandler(episodeOfCare integration.EpisodeOfCareInterface) *EpisodeOfCareHandler {
return &EpisodeOfCareHandler{EpisodeOfCare: episodeOfCare}
}
// Add methods for handling episode of care-related requests here
func (e *EpisodeOfCareHandler) CreateEpisodeOfCare(c *gin.Context) {
var req model.EpisodeOfCareRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Identifier = append(req.Identifier, common.GetIdentifier("episode-of-care"))
res, err := e.EpisodeOfCare.CreateEpisodeOfCare(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (e *EpisodeOfCareHandler) GetEpisodeOfCareByPatient(c *gin.Context) {
id := c.Query("patient")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Patient is required"})
return
}
episodeOfCare, err := e.EpisodeOfCare.GetEpisodeOfCareByPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if episodeOfCare == nil {
c.JSON(http.StatusNotFound, gin.H{"message": "Episode of care not found"})
return
}
c.JSON(http.StatusOK, episodeOfCare)
}
func (e *EpisodeOfCareHandler) UpdateEpisodeOfCare(c *gin.Context) {
var req model.EpisodeOfCareRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
req.Identifier = append(req.Identifier, common.GetIdentifier("episode-of-care"))
res, err := e.EpisodeOfCare.UpdateEpisodeOfCare(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type GoalHandler struct {
Goal integration.GoalInterface
}
func NewGoalHandler(Goal integration.GoalInterface) *GoalHandler {
return &GoalHandler{Goal: Goal}
}
func (h GoalHandler) CreateGoal(c *gin.Context) {
var req model.GoalRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.Goal.CreateGoal(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h GoalHandler) UpdateGoal(c *gin.Context) {
var req model.GoalRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.Goal.CreateGoal(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,97 @@
package handler
import (
"fmt"
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type ImagingStudyHandler struct {
ImagingStudy integration.ImagingStudyInterface
}
func NewImagingStudyHandler(ImagingStudy integration.ImagingStudyInterface) *ImagingStudyHandler {
return &ImagingStudyHandler{ImagingStudy: ImagingStudy}
}
func (h ImagingStudyHandler) CreateImagingStudy(c *gin.Context) {
var req model.ImagingStudyRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if len(req.Identifier) < 1 {
c.JSON(http.StatusBadRequest, gin.H{"error": "identifier is required."})
return
}
if len(req.Identifier) > 0 {
for k, i := range req.Identifier {
if k == 0 && i.Value == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("identifier[%d].value (ACSN) required", k)})
return
}
// if k == 1 && i.Value == "" {
// c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("identifier[%d].value (urn:dicom:uid) required", k)})
// return
// }
}
}
res, err := h.ImagingStudy.CreateImagingStudy(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h ImagingStudyHandler) UpdateImagingStudy(c *gin.Context) {
var req model.ImagingStudyRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if len(req.Identifier) < 1 {
c.JSON(http.StatusBadRequest, gin.H{"error": "identifier is required."})
return
}
if len(req.Identifier) > 0 {
for k, i := range req.Identifier {
if k == 0 && i.Value == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("identifier[%d].value (ACSN) required", k)})
return
}
// if k == 1 && i.Value == "" {
// c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("identifier[%d].value (urn:dicom:uid) required", k)})
// return
// }
}
}
req.Id = c.Param("id")
res, err := h.ImagingStudy.CreateImagingStudy(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type ImmunizationHandler struct {
Immunization integration.ImmunizationInterface
}
func NewImmunizationHandler(Immunization integration.ImmunizationInterface) *ImmunizationHandler {
return &ImmunizationHandler{Immunization: Immunization}
}
func (h ImmunizationHandler) CreateImmunization(c *gin.Context) {
var req model.ImmunizationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.Immunization.CreateImmunization(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h ImmunizationHandler) UpdateImmunization(c *gin.Context) {
var req model.ImmunizationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.Immunization.CreateImmunization(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type MedicationDispenseHandler struct {
MedicationDispense integration.MedicationDispenseInterface
}
func NewMedicationDispenseHandler(MedicationDispense integration.MedicationDispenseInterface) *MedicationDispenseHandler {
return &MedicationDispenseHandler{MedicationDispense: MedicationDispense}
}
func (h MedicationDispenseHandler) CreateMedicationDispense(c *gin.Context) {
var req model.MedicationDispenseRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.MedicationDispense.CreateMedicationDispense(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h MedicationDispenseHandler) UpdateMedicationDispense(c *gin.Context) {
var req model.MedicationDispenseRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.MedicationDispense.CreateMedicationDispense(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type MedicationRequestHandler struct {
MedicationRequest integration.MedicationRequestInterface
}
func NewMedicationRequestHandler(MedicationRequest integration.MedicationRequestInterface) *MedicationRequestHandler {
return &MedicationRequestHandler{MedicationRequest: MedicationRequest}
}
func (h MedicationRequestHandler) CreateMedicationRequest(c *gin.Context) {
var req model.MedicationRequestRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.MedicationRequest.CreateMedicationRequest(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h MedicationRequestHandler) UpdateMedicationRequest(c *gin.Context) {
var req model.MedicationRequestRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.MedicationRequest.CreateMedicationRequest(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,60 @@
package handler
import (
"fmt"
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type MedicationStatementHandler struct {
MedicationStatement integration.MedicationStatementInterface
}
func NewMedicationStatementHandler(MedicationStatement integration.MedicationStatementInterface) *MedicationStatementHandler {
return &MedicationStatementHandler{MedicationStatement: MedicationStatement}
}
func (h MedicationStatementHandler) CreateMedicationStatement(c *gin.Context) {
var req model.MedicationStatementRequest
if err := c.ShouldBindJSON(&req); err != nil {
fmt.Println(err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.MedicationStatement.CreateMedicationStatement(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h MedicationStatementHandler) UpdateMedicationStatement(c *gin.Context) {
var req model.MedicationStatementRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.MedicationStatement.CreateMedicationStatement(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,40 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type MedicineHandler struct {
Medicine integration.MedicineIntegrationInterface
}
func NewMedicineHandler(medicine integration.MedicineIntegrationInterface) *MedicineHandler {
return &MedicineHandler{Medicine: medicine}
}
func (m MedicineHandler) GetMedicineKfa(c *gin.Context) {
var req model.MedicineKfaRequest
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := m.Medicine.GetMedicineKfa(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (m MedicineHandler) GetMedicineByKfaCode(c *gin.Context) {
kfaCode := c.Param("kfa_code")
res, err := m.Medicine.GetMedicineByKfaCode(kfaCode)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,33 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type OauthHandler struct {
Oauth integration.OauthInterface
}
func NewOuathHandler(Oauth integration.OauthInterface) *OauthHandler {
return &OauthHandler{Oauth: Oauth}
}
func (oh OauthHandler) GenerateToken(c *gin.Context) {
var bodyParam model.OauthRequest
if err := c.ShouldBindJSON(&bodyParam); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
res, err := oh.Oauth.GenerateToken(bodyParam)
if err != nil {
c.JSON(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,78 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type ObservationHandler struct {
// Define any dependencies needed for the handler
Observation integration.ObservationInterface
}
func NewObservationHandler(observation integration.ObservationInterface) *ObservationHandler {
return &ObservationHandler{Observation: observation}
}
// Add methods for handling observation-related requests here
func (o *ObservationHandler) CreateObservation(c *gin.Context) {
var req model.ObservationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := o.Observation.CreateObservation(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (o *ObservationHandler) GetObservationByPatient(c *gin.Context) {
id := c.Query("subject")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Subject is required"})
return
}
observation, err := o.Observation.GetObservationByPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if observation == nil {
c.JSON(http.StatusNotFound, gin.H{"message": "Observation not found"})
return
}
c.JSON(http.StatusOK, observation)
}
func (o *ObservationHandler) UpdateObservation(c *gin.Context) {
var req model.ObservationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := o.Observation.UpdateObservation(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,54 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type OrganizationHandler struct {
Organization integration.OrganizationInterface
}
func NewOrganizationHandler(organization integration.OrganizationInterface) *OrganizationHandler {
return &OrganizationHandler{Organization: organization}
}
func (o OrganizationHandler) CreateOrganization(c *gin.Context) {
var bodyParam model.OrganizationRequest
if err := c.ShouldBindJSON(&bodyParam); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
bodyParam.Identifier = append(bodyParam.Identifier, common.GetIdentifier("organization"))
res, err := o.Organization.CreateOrganization(bodyParam)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (o OrganizationHandler) GetOrganizationPatient(c *gin.Context) {
id := c.Query("subject")
if id == "" {
c.JSON(http.StatusBadRequest, "Patient ID is required")
return
}
res, err := o.Organization.GetOrganizationPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,47 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type PatientHandler struct {
// Define any dependencies or services needed for the PatientHandler
Patient integration.PatientInterface
}
func NewPatientHandler(patient integration.PatientInterface) *PatientHandler {
return &PatientHandler{Patient: patient}
}
// Add methods for handling patient-related requests here
func (p *PatientHandler) GetPatientByNIK(c *gin.Context) {
param := c.Query("identifier")
res, err := p.Patient.GetPatientByNIK(param)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (p *PatientHandler) CreatePatient(c *gin.Context) {
var req model.PatientRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := p.Patient.CreataPatient(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,37 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"github.com/gin-gonic/gin"
)
type PracticionerHandler struct {
Practicioner integration.PracticionerInterface
}
func NewPracticionerHandler(practicioner integration.PracticionerInterface) *PracticionerHandler {
return &PracticionerHandler{Practicioner: practicioner}
}
func (p PracticionerHandler) GetPracticionerByNik(c *gin.Context) {
nik := c.Query("identifier")
if nik == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "identifier is required"})
return
}
practicioner, err := p.Practicioner.GetPracticionerByNIK(nik)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if practicioner == nil {
c.JSON(http.StatusNotFound, gin.H{"message": "Practicioner not found"})
return
}
c.JSON(http.StatusOK, practicioner)
}

View File

@@ -0,0 +1,71 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type ProcedureHandler struct {
Procedure integration.ProcedureInterface
}
func NewProcedureHandler(procedure integration.ProcedureInterface) *ProcedureHandler {
return &ProcedureHandler{
Procedure: procedure,
}
}
func (p *ProcedureHandler) CreateProcedure(c *gin.Context) {
var req model.ProcedureRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := p.Procedure.CreateProcedure(req)
if err != nil {
if result != nil {
c.JSON(http.StatusInternalServerError, result)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
func (p *ProcedureHandler) GetProcedure(c *gin.Context) {
id := c.Param("id")
result, err := p.Procedure.GetProcedure(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
func (p *ProcedureHandler) UpdateProcedure(c *gin.Context) {
var req model.ProcedureRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := p.Procedure.UpdateProcedure(req)
if err != nil {
if result != nil {
c.JSON(http.StatusInternalServerError, result)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}

View File

@@ -0,0 +1,58 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"github.com/gin-gonic/gin"
)
type QuestionnaireResponseHandler struct {
QuestionnaireResponse integration.QuestionnaireResponseInterface
}
func NewQuestionnaireResponseHandler(QuestionnaireResponse integration.QuestionnaireResponseInterface) *QuestionnaireResponseHandler {
return &QuestionnaireResponseHandler{QuestionnaireResponse: QuestionnaireResponse}
}
func (h QuestionnaireResponseHandler) CreateQuestionnaireResponse(c *gin.Context) {
var req model.QuestionnaireResponseRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.QuestionnaireResponse.CreateQuestionnaireResponse(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (h QuestionnaireResponseHandler) UpdateQuestionnaireResponse(c *gin.Context) {
var req model.QuestionnaireResponseRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
res, err := h.QuestionnaireResponse.CreateQuestionnaireResponse(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,77 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type ServiceRequestHandler struct {
repo integration.ServiceRequestInterface
}
func NewServiceRequestHandler(repo integration.ServiceRequestInterface) *ServiceRequestHandler {
return &ServiceRequestHandler{repo: repo}
}
func (h *ServiceRequestHandler) CreateServiceRequest(c *gin.Context) {
var req model.ServiceRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Identifier = append(req.Identifier, common.GetIdentifier("servicerequest"))
data, err := h.repo.CreateServiceRequest(req)
if err != nil {
if data != nil {
c.JSON(http.StatusInternalServerError, data)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
}
func (h *ServiceRequestHandler) GetServiceRequestByPatient(c *gin.Context) {
id := c.Query("subject")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Patient ID is required"})
return
}
data, err := h.repo.GetServiceRequestByPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
}
func (h *ServiceRequestHandler) UpdateServiceRequest(c *gin.Context) {
var req model.ServiceRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
req.Identifier = append(req.Identifier, common.GetIdentifier("servicerequest"))
data, err := h.repo.UpdateServiceRequest(req)
if err != nil {
if data != nil {
c.JSON(http.StatusInternalServerError, data)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, data)
}

View File

@@ -0,0 +1,77 @@
package handler
import (
"net/http"
"satusehat-rssa/internal/integration"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"github.com/gin-gonic/gin"
)
type SpecimenHandler struct {
Specimen integration.SpecimenInterface
}
func NewSpecimenHandler(specimen integration.SpecimenInterface) *SpecimenHandler {
return &SpecimenHandler{Specimen: specimen}
}
func (s *SpecimenHandler) CreateSpecimen(c *gin.Context) {
var req model.SpecimenRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Identifier = append(req.Identifier, common.GetIdentifier("specimen"))
res, err := s.Specimen.CreateSpecimen(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}
func (s *SpecimenHandler) GetSpecimenByPatient(c *gin.Context) {
id := c.Query("subject")
if id == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Subject is required"})
return
}
specimen, err := s.Specimen.GetSpecimenByPatient(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if specimen == nil {
c.JSON(http.StatusNotFound, gin.H{"message": "Specimen not found"})
return
}
c.JSON(http.StatusOK, specimen)
}
func (s *SpecimenHandler) UpdateSpecimen(c *gin.Context) {
var req model.SpecimenRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
req.Id = c.Param("id")
req.Identifier = append(req.Identifier, common.GetIdentifier("specimen"))
res, err := s.Specimen.UpdateSpecimen(req)
if err != nil {
if res != nil {
c.JSON(http.StatusInternalServerError, res)
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, res)
}

View File

@@ -0,0 +1,262 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type AllergancyToleranInterface interface {
// Define methods for AllergancyToleranInterface
CreateAllergancyToleran(req model.AllergancyToleranRequest) (*model.AllergancyToleranResponse, error)
UpdateAllergancyToleran(req model.AllergancyToleranRequest) (map[string]interface{}, error)
GetAllergytoleranByPatient(id string) (map[string]interface{}, error)
HandleCheckAllergancyToleran(id string) ([]string, bool, error)
}
type AllergancyToleranRepository struct {
// Define fields for AllergancyToleranRepository
akses *model.Akses
}
// GetAllergytoleranByPatient implements AllergancyToleranInterface.
func (a *AllergancyToleranRepository) GetAllergytoleranByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := a.akses.BaseUrl + "/AllergyIntolerance?patient=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: a.akses.ClientId,
ClientSecret: a.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(a.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckAllergancyToleran implements AllergancyToleranInterface.
func (a *AllergancyToleranRepository) HandleCheckAllergancyToleran(id string) ([]string, bool, error) {
allergy, err := a.GetAllergytoleranByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := allergy["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (allergy)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateAllergancyToleran implements AllergancyToleranInterface.
func (a *AllergancyToleranRepository) CreateAllergancyToleran(req model.AllergancyToleranRequest) (*model.AllergancyToleranResponse, error) {
var data *model.AllergancyToleranResponse
req.ResourceType = constant.AllergyIntoleranceResourceType
req.Identifier = append(req.Identifier, &model.IdentifierObject{
Use: "official",
System: "http://sys-ids.kemkes.go.id/allergy/" + os.Getenv("ORGANIZATION_ID"), // Set this if needed, or remove if not present in IdentifierObject
Value: os.Getenv("ORGANIZATION_ID"),
})
patient, err := a.setupPatient(&req)
if err != nil {
return nil, err
}
err = a.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = a.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
url := a.akses.BaseUrl + "/AllergyIntolerance"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: a.akses.ClientId,
ClientSecret: a.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(a.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (a *AllergancyToleranRepository) UpdateAllergancyToleran(req model.AllergancyToleranRequest) (map[string]interface{}, error) {
req.ResourceType = constant.AllergyIntoleranceResourceType
req.Identifier = append(req.Identifier, &model.IdentifierObject{
Use: "official",
System: "http://sys-ids.kemkes.go.id/allergy/" + os.Getenv("ORGANIZATION_ID"), // Set this if needed, or remove if not present in IdentifierObject
Value: os.Getenv("ORGANIZATION_ID"),
})
patient, err := a.setupPatient(&req)
if err != nil {
return nil, err
}
err = a.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = a.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: a.akses.ClientId,
ClientSecret: a.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(a.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := a.akses.BaseUrl + fmt.Sprintf("/AllergyIntolerance/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
// setupPatient handles patient reference logic.
func (a *AllergancyToleranRepository) setupPatient(req *model.AllergancyToleranRequest) (string, error) {
if req.Patient.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(a.akses)
patient, err := patientInterface.HandleCheckPatient(req.Patient.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Patient.Reference = "Patient/" + patient
}
return patient, nil
}
// setupEncounter handles encounter reference logic.
func (a *AllergancyToleranRepository) setupEncounter(req *model.AllergancyToleranRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(a.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
}
return nil
}
// setupPractitioner handles practitioner reference logic.
func (a *AllergancyToleranRepository) setupPractitioner(req *model.AllergancyToleranRequest) error {
if req.Recorder.Reference == "" {
return nil
}
practicionerInterface := NewPracticionerRepo(a.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.Recorder.Reference)
if err != nil {
return err
}
if ref != "" {
req.Recorder.Reference = "Practitioner/" + ref
req.Recorder.Display = display
}
return nil
}
func NewAllergancyToleranRepo(akses *model.Akses) AllergancyToleranInterface {
return &AllergancyToleranRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,224 @@
package integration
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type CarePlanInterface interface {
// Define methods for CarePlanInterface
CreateCarePlan(req model.CarePlanRequest) (map[string]interface{}, error)
UpdateCarePlan(req model.CarePlanRequest) (map[string]interface{}, error)
GetCareplanByPatient(id string) (map[string]interface{}, error)
HandleCheckCarePlan(id string) ([]string, bool, error)
}
type CarePlanRepository struct {
// Define fields for CarePlanRepository
akses *model.Akses
}
// GetCareplanByPatient implements CarePlanInterface.
func (c *CarePlanRepository) GetCareplanByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/CarePlan?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckCarePlan implements CarePlanInterface.
func (c *CarePlanRepository) HandleCheckCarePlan(id string) ([]string, bool, error) {
careplan, err := c.GetCareplanByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := careplan["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (careplan)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
func NewCarePlanRepo(akses *model.Akses) CarePlanInterface {
return &CarePlanRepository{
akses: akses,
}
}
// CreateCarePlan implements CarePlanInterface.
func (c *CarePlanRepository) CreateCarePlan(req model.CarePlanRequest) (map[string]interface{}, error) {
req.ResourceType = constant.CarePlanResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/CarePlan"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *CarePlanRepository) UpdateCarePlan(req model.CarePlanRequest) (map[string]interface{}, error) {
req.ResourceType = constant.CarePlanResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupPractitioner(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/CarePlan/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *CarePlanRepository) setupPatient(req *model.CarePlanRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *CarePlanRepository) setupEncounter(req *model.CarePlanRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
}
return nil
}
// setupPractitioner handles practitioner reference logic.
func (c *CarePlanRepository) setupPractitioner(req *model.CarePlanRequest) error {
if req.Author.Reference == "" {
return nil
}
practicionerInterface := NewPracticionerRepo(c.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.Author.Reference)
if err != nil {
return err
}
if ref != "" {
req.Author.Reference = "Practitioner/" + ref
req.Author.Display = display
}
return nil
}

View File

@@ -0,0 +1,326 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ClinicalImppressionInterface interface {
// Define methods for ClinicalImpressionInterface
CreateClinicalImpression(req model.ClinicalImpressionRequest) (map[string]interface{}, error)
UpdateClinicalImpression(req model.ClinicalImpressionRequest) (map[string]interface{}, error)
GetClinicalImpressionByPatient(id string) (map[string]interface{}, error)
HandleCheckClinicalImpression(id string) ([]string, bool, error)
}
type ClinicalImpressionRepository struct {
akses *model.Akses
}
// GetClinicalImpressionByPatient implements ClinicalImppressionInterface.
func (c *ClinicalImpressionRepository) GetClinicalImpressionByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/ClinicalImpression?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckClinicalImpression implements ClinicalImppressionInterface.
func (c *ClinicalImpressionRepository) HandleCheckClinicalImpression(id string) ([]string, bool, error) {
clinical, err := c.GetClinicalImpressionByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := clinical["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (clinical)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateClinicalImpression implements ClinicalImppressionInterface.
func (c *ClinicalImpressionRepository) CreateClinicalImpression(req model.ClinicalImpressionRequest) (map[string]interface{}, error) {
var (
data map[string]interface{}
)
req.ResourceType = constant.ClinicalImpressionResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(c.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
// Setup Practitioner
// if req.Assessor.Reference != "" {
// practitionerInterface := NewPracticionerRepo(c.akses)
// practitionerId, _, err := practitionerInterface.HandleCheckPartitioner(req.Assessor.Reference)
// if err != nil {
// return nil, err
// }
// if practitionerId != "" {
// req.Assessor.Reference = "Practitioner/" + practitionerId
// } else {
// return nil, errors.New("practitioner not found")
// }
// }
if len(req.Investigation) > 0 {
//Setup Condition
if patient != "" {
conditionInterface := NewConditionRepo(c.akses)
conditionId, conditionExist, err := conditionInterface.HandleCheckCondition(patient)
if err != nil {
return nil, err
}
req.Problem = append(req.Problem, model.Reference{
Reference: "Condition/" + conditionId,
})
if !conditionExist {
return nil, errors.New("condition not found")
}
}
//Setup Observation
if patient != "" {
observationInterface := NewObservationRepo(c.akses)
observationId, observationExist, err := observationInterface.HandleCheckObservation(patient)
if err != nil {
return nil, err
}
for _, id := range observationId {
req.Investigation = append(req.Investigation, model.Investigation{
Item: []model.InvestigationItem{
{Reference: "Observation/" + id},
},
})
}
if !observationExist {
return nil, errors.New("observation not found")
}
}
}
url := c.akses.BaseUrl + "/ClinicalImpression"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
// Assuming the access token is stored in a field of the akses struct
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(c.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (c *ClinicalImpressionRepository) UpdateClinicalImpression(req model.ClinicalImpressionRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ClinicalImpressionResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(c.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
// Setup Practitioner
if req.Assessor.Reference != "" {
practitionerInterface := NewPracticionerRepo(c.akses)
practitionerId, _, err := practitionerInterface.HandleCheckPartitioner(req.Assessor.Reference)
if err != nil {
return nil, err
}
if practitionerId != "" {
req.Assessor.Reference = "Practitioner/" + practitionerId
} else {
return nil, errors.New("practitioner not found")
}
//Setup Condition
if patient != "" {
conditionInterface := NewConditionRepo(c.akses)
conditionId, conditionExist, err := conditionInterface.HandleCheckCondition(patient)
if err != nil {
return nil, err
}
req.Problem = append(req.Problem, model.Reference{
Reference: "Condition/" + conditionId,
})
if !conditionExist {
return nil, errors.New("condition not found")
}
}
//Setup Observation
if patient != "" {
observationInterface := NewObservationRepo(c.akses)
observationId, observationExist, err := observationInterface.HandleCheckObservation(patient)
if err != nil {
return nil, err
}
for _, id := range observationId {
req.Investigation = append(req.Investigation, model.Investigation{
Item: []model.InvestigationItem{
{Reference: "Observation/" + id},
},
})
}
if !observationExist {
return nil, errors.New("observation not found")
}
}
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/ClinicalImpression/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
func NewClinicalImpressionRepo(akses *model.Akses) ClinicalImppressionInterface {
return &ClinicalImpressionRepository{akses: akses}
}

View File

@@ -0,0 +1,835 @@
package integration
import (
"errors"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type CompositionInterface interface {
CreateComposition(req model.CompositionRequest) (map[string]interface{}, error)
UpdateComposition(req model.CompositionRequest) (map[string]interface{}, error)
GetCompositionByID(id string) (map[string]interface{}, error)
}
type CompositionRepository struct {
akses *model.Akses
}
// CreateComposition implements CompositionInterface.
func (c *CompositionRepository) CreateComposition(req model.CompositionRequest) (map[string]interface{}, error) {
req.ResourceType = "Composition"
req.Identifier = model.Identifier{
Use: "official",
System: "http://sys-ids.kemkes.go.id/composition/" + os.Getenv("ORGANIZATION_ID"),
Value: os.Getenv("ORGANIZATION_ID"),
}
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupOrganization(&req)
if err != nil {
return nil, err
}
// section setup
if req.Anamnesis == "" {
req.Anamnesis = "default anamnesis"
}
if req.PemeriksaanFisik == "" {
req.PemeriksaanFisik = "default pemeriksaan fisik"
}
if req.PemeriksaanPenunjang == "" {
req.PemeriksaanPenunjang = "default pemeriksaan penunjang"
}
if req.Medikamentosa == "" {
req.Medikamentosa = "default medikamentosa"
}
if req.LanjutanPenatalaksanaan == "" {
req.LanjutanPenatalaksanaan = "default lanjutan penatalaksanaan"
}
req.Section = append(req.Section, model.SectionRequest{
Title: "Anamnesis",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000003",
Display: "Anamnesis",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.Anamnesis,
},
})
allergyId := c.setupAllergyIntollerance(patient)
section := model.SectionRequest{
Title: "Riwayat Alergi",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "18776-5",
Display: "Riwayat Alergi",
},
},
},
}
if allergyId != "" {
section.Entry = []model.Reference{
{Reference: "AllergyIntolerance/" + allergyId},
}
}
req.Section = append(req.Section, section)
/* Observation disabled for Now
req.Section = append(req.Section, model.SectionRequest{
Title: "Pemeriksaan Fisik",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000007",
Display: "Pemeriksaan Fisik",
},
},
},
Section: []model.SectionRequest{
{
Title: "Tanda Vital",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "8716-3",
Display: "Vital signs",
},
},
},
Entry: c.setupObservation(patient),
},
{
Title: "Hasil Pemeriksaan",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000007",
Display: "Pemeriksaan Fisik",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.PemeriksaanFisik,
},
},
},
})
*/
var entry []model.Reference
clinicalId := c.setupClinicalImpression(patient)
goalId := c.setupGoal(patient)
carePlanId := c.setupCarePlan(patient)
if clinicalId != "" {
entry = append(entry, model.Reference{Reference: "ClinicalImpression/" + clinicalId})
}
if goalId != "" {
entry = append(entry, model.Reference{Reference: "Goal/" + goalId})
}
if carePlanId != "" {
entry = append(entry, model.Reference{Reference: "CarePlan/" + carePlanId})
}
req.Section = append(req.Section, model.SectionRequest{
Title: "Perencanaan Perawatan",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "18776-5",
Display: "Plan of care note",
},
},
},
Entry: entry,
})
var entryLab, entryRad []model.Reference
serviceRequestIdLab := c.setupServiceRequestCategory(patient, "LAB")
specimenIdLab := c.setupSpecimenCategory(patient)
diagnosticReportIdLab := c.setupDiagnosticCategory(patient, "LAB")
observationIdLab := c.setupObservationCategory(patient, "LAB")
serviceRequestIdRad := c.setupServiceRequestCategory(patient, "RAD")
imagingStudyRad := c.setupImagingStudy(patient)
diagnosticReportIdRad := c.setupDiagnosticCategory(patient, "RAD")
observationIdRad := c.setupObservationCategory(patient, "RAD")
if serviceRequestIdLab != "" {
entryLab = append(entryLab, model.Reference{Reference: "ServiceRequest/" + serviceRequestIdLab})
}
if specimenIdLab != "" {
entryLab = append(entryLab, model.Reference{Reference: "Specimen/" + specimenIdLab})
}
if diagnosticReportIdLab != "" {
entryLab = append(entryLab, model.Reference{Reference: "DiagnosticReport/" + diagnosticReportIdLab})
}
if observationIdLab != "" {
entryLab = append(entryLab, model.Reference{Reference: "Observation/" + observationIdLab})
}
if serviceRequestIdRad != "" {
entryRad = append(entryRad, model.Reference{Reference: "ServiceRequest/" + serviceRequestIdRad})
}
if imagingStudyRad != "" {
entryRad = append(entryRad, model.Reference{Reference: "ImagingStudy/" + imagingStudyRad})
}
if diagnosticReportIdRad != "" {
entryRad = append(entryRad, model.Reference{Reference: "DiagnosticReport/" + diagnosticReportIdRad})
}
if observationIdRad != "" {
entryRad = append(entryRad, model.Reference{Reference: "Observation/" + observationIdRad})
}
if len(entryLab) != 0 && len(entryRad) != 0 {
req.Section = append(req.Section, model.SectionRequest{
Title: "Pemeriksaan Penunjang",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000009",
Display: "Hasil Pemeriksaan Penunjang",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.PemeriksaanPenunjang,
},
Section: []model.SectionRequest{
{
Title: "Hasil Pemeriksaan Laboratorium",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "11502-2",
Display: "Laboratory report",
},
},
},
Entry: entryLab,
},
{
Title: "Hasil Pemeriksaan Radiologi",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "18782-3",
Display: "Radiology Study observation (narrative)",
},
},
},
Entry: entryRad,
},
},
})
} else if len(entryLab) != 0 && len(entryRad) == 0 {
req.Section = append(req.Section, model.SectionRequest{
Title: "Pemeriksaan Penunjang",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000009",
Display: "Hasil Pemeriksaan Penunjang",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.PemeriksaanPenunjang,
},
Section: []model.SectionRequest{
{
Title: "Hasil Pemeriksaan Laboratorium",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "11502-2",
Display: "Laboratory report",
},
},
},
Entry: entryLab,
},
},
})
} else if len(entryLab) == 0 && len(entryRad) != 0 {
req.Section = append(req.Section, model.SectionRequest{
Title: "Pemeriksaan Penunjang",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000009",
Display: "Hasil Pemeriksaan Penunjang",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.PemeriksaanPenunjang,
},
Section: []model.SectionRequest{
{
Title: "Hasil Pemeriksaan Radiologi",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "18782-3",
Display: "Radiology Study observation (narrative)",
},
},
},
Entry: entryRad,
},
},
})
}
var entryCondition []model.Reference
conditionId := c.setupCondition(patient)
if conditionId != "" {
entryCondition = append(entryCondition, model.Reference{Reference: "Condition/" + conditionId})
}
req.Section = append(req.Section, model.SectionRequest{
Title: "Diagnosa",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000004",
Display: "Diagnosis",
},
},
},
Section: []model.SectionRequest{
{
Title: "Diagnosa Utama",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "78375-3",
Display: "Discharge diagnosis Narrative",
},
},
},
Entry: entryCondition,
},
},
})
var entryProcedure []model.Reference
procedureId := c.setupProcedure(patient)
if procedureId != "" {
entryProcedure = append(entryProcedure, model.Reference{Reference: "Procedure/" + procedureId})
}
req.Section = append(req.Section, model.SectionRequest{
Title: "Tindakan Operatif/Non Operatif Utama",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000005",
Display: "Tindakan/Prosedur Medis",
},
},
},
Entry: entryProcedure,
})
var medication []model.Reference
medicationRequestId := c.setupMedicationRequest(patient)
if medicationRequestId != "" {
medication = append(medication, model.Reference{Reference: "MedicationRequest/" + medicationRequestId})
}
medicationDispenseId := c.setupMedicationDispense(patient)
if medicationDispenseId != "" {
medication = append(medication, model.Reference{Reference: "MedicationDispense/" + medicationDispenseId})
}
/* Farmasi section disabled for Now
req.Section = append(req.Section, model.SectionRequest{
Title: "Farmasi",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id",
Code: "TK000013",
Display: "Obat",
},
},
},
Section: []model.SectionRequest{
/*{
Title: "Obat Saat Kunjungan",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "42346-7",
Display: "Medications on admission (narrative)",
},
},
},
Entry: []model.Reference{
{Reference: "MedicationAdministration/"},
{Reference: "MedicationRequest/"},
{Reference: "MedicationDispense/"},
},
},*/
/* {
Title: "Obat Pulang",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "75311-1",
Display: "Discharge medications Narrative",
},
},
},
Entry: medication,
},
},
})
*/
req.Section = append(req.Section, model.SectionRequest{
Title: "Medikamentosa",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "18776-5",
Display: "Plan of treatment (narrative)",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.Medikamentosa,
},
})
req.Section = append(req.Section, model.SectionRequest{
Title: "Lanjutan Penatalaksanaan",
Code: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://loinc.org",
Code: "8653-8",
Display: "Hospital Discharge instructions",
},
},
},
Text: &model.SectionText{
Status: "additional",
Div: req.LanjutanPenatalaksanaan,
},
})
//remove field unused
req.Anamnesis = ""
req.PemeriksaanFisik = ""
req.PemeriksaanPenunjang = ""
req.Medikamentosa = ""
req.LanjutanPenatalaksanaan = ""
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
// b, err := json.MarshalIndent(req, "", " ")
// if err != nil {
// log.Println("error marshal:", err)
// } else {
// log.Println(string(b))
// }
url := c.akses.BaseUrl + "/Composition"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
// GetCompositionByID implements CompositionInterface.
func (c *CompositionRepository) GetCompositionByID(id string) (map[string]interface{}, error) {
panic("unimplemented")
}
// UpdateComposition implements CompositionInterface.
func (c *CompositionRepository) UpdateComposition(req model.CompositionRequest) (map[string]interface{}, error) {
req.ResourceType = "Composition"
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupOrganization(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/Composition/" + req.Id
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
func (c *CompositionRepository) setupPatient(req *model.CompositionRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
// setupEncounter extracts encounter setup logic from CreateDiagnosisReport.
func (c *CompositionRepository) setupEncounter(req *model.CompositionRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
//Buat dulu encounter
}
return nil
}
func (c *CompositionRepository) setupOrganization(req *model.CompositionRequest) error {
req.Custodian.Reference = "Organization/" + os.Getenv("ORGANIZATION_ID")
return nil
}
func (c *CompositionRepository) setupPractitioner(req *model.CompositionRequest) error {
if len(req.Author) == 0 {
return nil
}
practicionerInterface := NewPracticionerRepo(c.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.Author[0].Reference)
if err != nil {
return err
}
if ref != "" {
req.Author[0].Reference = "Practitioner/" + ref
req.Author[0].Display = display
}
return nil
}
func (c *CompositionRepository) setupAllergyIntollerance(patient string) string {
if patient == "" {
return ""
}
allergyInterface := NewAllergancyToleranRepo(c.akses)
allergyId, allergyExist, err := allergyInterface.HandleCheckAllergancyToleran(patient)
if err != nil {
return ""
}
if allergyExist {
return allergyId[0]
}
return ""
}
func (c *CompositionRepository) setupObservation(patient string) []model.Reference {
if patient == "" {
return nil
}
observationInterface := NewObservationRepo(c.akses)
observationId, observationExist, err := observationInterface.HandleCheckObservation(patient)
if err != nil {
return nil
}
if observationExist {
var references []model.Reference
for _, id := range observationId {
references = append(references, model.Reference{Reference: "Observation/" + id})
}
return references
}
return nil
}
func (c *CompositionRepository) setupClinicalImpression(patient string) string {
if patient == "" {
return ""
}
clinicalInterface := NewClinicalImpressionRepo(c.akses)
clinicalId, clinicalExist, err := clinicalInterface.HandleCheckClinicalImpression(patient)
if err != nil {
return ""
}
if clinicalExist {
return clinicalId[0]
}
return ""
}
func (c *CompositionRepository) setupGoal(patient string) string {
if patient == "" {
return ""
}
goalInterface := NewGoalRepo(c.akses)
goalId, goalExist, err := goalInterface.HandleCheckGoal(patient)
if err != nil {
return ""
}
if goalExist {
return goalId[0]
}
return ""
}
func (c *CompositionRepository) setupCarePlan(patient string) string {
if patient == "" {
return ""
}
careplanInterface := NewCarePlanRepo(c.akses)
careplanId, careplanExist, err := careplanInterface.HandleCheckCarePlan(patient)
if err != nil {
return ""
}
if careplanExist {
return careplanId[0]
}
return ""
}
func (c *CompositionRepository) setupServiceRequestCategory(patient string, category string) string {
if patient == "" {
return ""
}
if category == "LAB" {
category = "108252007"
} else if category == "RAD" {
category = "363679005"
}
serviceRequestInterface := NewServiceRequestRepository(c.akses)
serviceRequestId, serviceRequestExist, err := serviceRequestInterface.HandleCheckServiceRequestByCategory(patient, category)
if err != nil {
return ""
}
if serviceRequestExist {
return serviceRequestId[0]
}
return ""
}
func (c *CompositionRepository) setupSpecimenCategory(patient string) string {
if patient == "" {
return ""
}
specimenInterface := NewSpecimenRepository(c.akses)
specimenId, specimenExist, err := specimenInterface.HandleCheckSpecimen(patient)
if err != nil {
return ""
}
if specimenExist {
return specimenId[0]
}
return ""
}
func (c *CompositionRepository) setupImagingStudy(patient string) string {
if patient == "" {
return ""
}
imagingInterface := NewImagingStudyRepo(c.akses)
imagingId, imagingExist, err := imagingInterface.HandleCheckImagingStudy(patient)
if err != nil {
return ""
}
if imagingExist {
return imagingId[0]
}
return ""
}
func (c *CompositionRepository) setupObservationCategory(patient string, category string) string {
if patient == "" {
return ""
}
if category == "LAB" {
category = "laboratory"
} else if category == "RAD" {
category = "imaging"
}
observationInterface := NewObservationRepo(c.akses)
observationId, observationExist, err := observationInterface.HandleCheckObservationCategory(patient, category)
if err != nil {
return ""
}
if observationExist {
return observationId[0]
}
return ""
}
func (c *CompositionRepository) setupDiagnosticCategory(patient string, category string) string {
if patient == "" {
return ""
}
if category == "LAB" {
category = "LAB"
} else if category == "RAD" {
category = "RAD"
}
observationInterface := NewObservationRepo(c.akses)
observationId, observationExist, err := observationInterface.HandleCheckObservationCategory(patient, category)
if err != nil {
return ""
}
if observationExist {
return observationId[0]
}
return ""
}
func (c *CompositionRepository) setupCondition(patient string) string {
if patient == "" {
return ""
}
conditionInterface := NewConditionRepo(c.akses)
conditionId, conditionExist, err := conditionInterface.HandleCheckCondition(patient)
if err != nil {
return ""
}
if conditionExist {
return conditionId
}
return ""
}
func (c *CompositionRepository) setupProcedure(patient string) string {
if patient == "" {
return ""
}
procedureInterface := NewProcedureRepo(c.akses)
procedureId, procedureExist, err := procedureInterface.HandleCheckProcedure(patient)
if err != nil {
return ""
}
if procedureExist {
return procedureId[0]
}
return ""
}
func (c *CompositionRepository) setupMedicationRequest(patient string) string {
if patient == "" {
return ""
}
medicationRequestInterface := NewMedicationRequestRepo(c.akses)
medicationRequestId, medicationRequestExist, err := medicationRequestInterface.HandleCheckMedicationRequest(patient, "")
if err != nil {
return ""
}
if medicationRequestExist {
return medicationRequestId[0]
}
return ""
}
func (c *CompositionRepository) setupMedicationDispense(patient string) string {
if patient == "" {
return ""
}
medicationDispenseInterface := NewMedicationDispenseRepo(c.akses)
medicationDispenseId, medicationDispenseExist, err := medicationDispenseInterface.HandleCheckMedicationDispense(patient, "")
if err != nil {
return ""
}
if medicationDispenseExist {
return medicationDispenseId[0]
}
return ""
}
func NewCompositionRepo(akses *model.Akses) CompositionInterface {
return &CompositionRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,230 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ConditionInterface interface {
CreateCondition(request model.ConditionRequest) (map[string]interface{}, error)
GetConditionByPatient(id string) (map[string]interface{}, error)
HandleCheckCondition(id string) (string, bool, error)
UpdateCondition(request model.ConditionRequest) (map[string]interface{}, error)
}
type ConditionRepository struct {
akses *model.Akses
}
// HandleCheckCondition implements ConditionInterface.
func (c *ConditionRepository) HandleCheckCondition(id string) (string, bool, error) {
condition, err := c.GetConditionByPatient(id)
if err != nil {
return "", false, err
}
// You can process 'encounter' here if needed
if entries, ok := condition["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (condition)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
return id, true, nil
}
}
}
}
return "", true, nil
}
return "", false, nil
}
func NewConditionRepo(akses *model.Akses) ConditionInterface {
return &ConditionRepository{akses: akses}
}
// Implement the ConditionInterface methods for ConditionRepository
func (c *ConditionRepository) CreateCondition(req model.ConditionRequest) (map[string]interface{}, error) {
// TODO: implement the logic here
var (
data map[string]interface{}
)
req.ClinicalStatus.Coding = append(req.ClinicalStatus.Coding, model.Coding{
System: "http://terminology.hl7.org/CodeSystem/condition-clinical",
Code: "active",
Display: "Active",
})
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(c.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
url := c.akses.BaseUrl + "/Condition"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(c.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (c *ConditionRepository) GetConditionByPatient(id string) (map[string]interface{}, error) {
// TODO: implement the logic here
var (
data map[string]interface{}
)
url := c.akses.BaseUrl + "/Condition?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(c.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (c *ConditionRepository) UpdateCondition(req model.ConditionRequest) (map[string]interface{}, error) {
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(c.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/Condition/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}

View File

@@ -0,0 +1,363 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
"strings"
)
type DiagnosisReportInterface interface {
// Define methods for DiagnosisReportInterface
CreateDiagnosisReport(req model.DiagnosticReportRequest) (map[string]interface{}, error)
GetDiagnosisReportByPatient(id string) (map[string]interface{}, error)
GetDiagnosisReportByPatientCategory(id string, category string) (map[string]interface{}, error)
HandleCheckDiagnosisReport(id string) (string, bool, error)
HandleCheckDiagnosisReportCategory(id string, category string) ([]string, bool, error)
UpdateDiagnosisReport(req model.DiagnosticReportRequest) (map[string]interface{}, error)
}
type DiagnosisReportRepository struct {
akses *model.Akses
}
// GetDiagnosisReportByPatientCategory implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) GetDiagnosisReportByPatientCategory(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := d.akses.BaseUrl + "/DiagnosticReport?subject=" + id + "&category=" + category
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: d.akses.ClientId,
ClientSecret: d.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(d.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckDiagnosisReportCategory implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) HandleCheckDiagnosisReportCategory(id string, category string) ([]string, bool, error) {
diagnosis, err := d.GetDiagnosisReportByPatientCategory(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := diagnosis["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (diagnosis)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateDiagnosisReport implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) CreateDiagnosisReport(req model.DiagnosticReportRequest) (map[string]interface{}, error) {
var data map[string]interface{}
req.ResourceType = constant.DiagnosticReportResourceType
req.Identifier = append(req.Identifier, model.Identifier{
Use: "official",
System: "http://sys-ids.kemkes.go.id/diagnostic/" + os.Getenv("ORGANIZATION_ID") + "/lab",
Value: os.Getenv("ORGANIZATION_ID"),
})
patient, err := d.setupPatient(&req)
if err != nil {
return nil, err
}
err = d.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
//Setup Performer
err = d.setupPractitioner(&req)
if err != nil {
return nil, err
}
err = d.setupOrganization(&req)
if err != nil {
return nil, err
}
//Setup Result
err = d.setupObserver(&req, patient)
if err != nil {
return nil, err
}
//Setup Specimen
err = d.setupSpecimen(&req, patient)
if err != nil {
return nil, err
}
//Setup BasedOn
url := d.akses.BaseUrl + "/DiagnosticReport"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: d.akses.ClientId,
ClientSecret: d.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(d.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// CreateDiagnosisReport implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) UpdateDiagnosisReport(req model.DiagnosticReportRequest) (map[string]interface{}, error) {
patient, err := d.setupPatient(&req)
if err != nil {
return nil, err
}
err = d.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
//Setup Performer
err = d.setupPractitioner(&req)
if err != nil {
return nil, err
}
err = d.setupOrganization(&req)
if err != nil {
return nil, err
}
//Setup Result
err = d.setupObserver(&req, patient)
if err != nil {
return nil, err
}
//Setup Specimen
err = d.setupSpecimen(&req, patient)
if err != nil {
return nil, err
}
//Setup BasedOn
oauth := model.OauthRequest{
ClientId: d.akses.ClientId,
ClientSecret: d.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(d.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := d.akses.BaseUrl + fmt.Sprintf("/DiagnosticReport/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
// setupPatient extracts patient setup logic from CreateDiagnosisReport.
func (d *DiagnosisReportRepository) setupPatient(req *model.DiagnosticReportRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(d.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
// setupEncounter extracts encounter setup logic from CreateDiagnosisReport.
func (d *DiagnosisReportRepository) setupEncounter(req *model.DiagnosticReportRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(d.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
//Buat dulu encounter
}
return nil
}
func (d *DiagnosisReportRepository) setupSpecimen(req *model.DiagnosticReportRequest, patient string) error {
if patient == "" {
return nil
}
specimenInterface := NewSpecimenRepository(d.akses)
ids, exist, err := specimenInterface.HandleCheckSpecimen(patient)
if err != nil {
return err
}
if exist {
for i := range req.Specimen {
req.Specimen[i].Reference = "Specimen/" + ids[i]
}
}
return nil
}
func (d *DiagnosisReportRepository) setupBasedOn(req *model.DiagnosticReportRequest, patient string) error {
if patient == "" {
return nil
}
basedOnInterface := NewServiceRequestRepository(d.akses)
ids, exist, err := basedOnInterface.HandleCheckServiceRequest(patient)
if err != nil {
return err
}
if exist {
for i := range req.BasedOn {
req.BasedOn[i].Reference = "ServiceRequest/" + ids[i]
}
}
return nil
}
// GetDiagnosisReportByPatient implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) GetDiagnosisReportByPatient(id string) (map[string]interface{}, error) {
panic("unimplemented")
}
// HandleCheckDiagnosisReport implements DiagnosisReportInterface.
func (d *DiagnosisReportRepository) HandleCheckDiagnosisReport(id string) (string, bool, error) {
panic("unimplemented")
}
// setupPractitioner handles practitioner reference logic.
func (d *DiagnosisReportRepository) setupPractitioner(req *model.DiagnosticReportRequest) error {
if len(req.Performer) == 0 {
return nil
}
for _, performer := range req.Performer {
if strings.Contains(performer.Reference, "Practitioner/") {
temp := strings.Split(performer.Reference, "/")
practicionerInterface := NewPracticionerRepo(d.akses)
ref, _, err := practicionerInterface.HandleCheckPartitioner(temp[1])
if err != nil {
return err
}
if ref != "" {
performer.Reference = "Practitioner/" + ref
}
}
}
return nil
}
func (d *DiagnosisReportRepository) setupOrganization(req *model.DiagnosticReportRequest) error {
if len(req.Performer) == 0 {
return nil
}
for _, performer := range req.Performer {
if strings.Contains(performer.Reference, "Organization/") {
performer.Reference = "Organization/" + os.Getenv("ORGANIZATION_ID")
}
}
return nil
}
func (d *DiagnosisReportRepository) setupObserver(req *model.DiagnosticReportRequest, patient string) error {
observerInterface := NewObservationRepo(d.akses)
//temp := strings.Split(req.Subject.Reference, "/")
ids, valid, err := observerInterface.HandleCheckObservation(patient)
if err != nil {
return err
}
if len(ids) > 0 && valid {
for _, id := range ids {
req.Result = append(req.Result, model.Reference{Reference: "Observation/" + id})
}
}
return nil
}
func NewDiagnosisReportRepo(akses *model.Akses) DiagnosisReportInterface {
return &DiagnosisReportRepository{akses: akses}
}

View File

@@ -0,0 +1,183 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type EncounterInterface interface {
// Define methods for encounter integration
CreateEncounter(req model.EncounterRequest) (map[string]interface{}, error)
GetEncounterByPatient(id string) (map[string]interface{}, error)
HandleCheckEncounter(patientID string) (string, bool, error)
UpdateEncounter(req model.EncounterUpdateRequest) (map[string]interface{}, error)
}
type EncounterRepository struct {
akses *model.Akses
}
// HandleCheckEncounter implements EncounterInterface.
func (e *EncounterRepository) HandleCheckEncounter(patientID string) (string, bool, error) {
encounter, err := e.GetEncounterByPatient(patientID)
if err != nil {
return "", false, err
}
// You can process 'encounter' here if needed
if entries, ok := encounter["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (encounter)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
return id, true, nil
}
}
}
}
return "", true, nil
}
return "", false, nil
}
// GetEncounterByPatient implements EncounterInterface.
func (e *EncounterRepository) GetEncounterByPatient(id string) (map[string]interface{}, error) {
var (
data *map[string]interface{}
)
url := e.akses.BaseUrl + "/Encounter?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(e.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, errors.New("failed to get encounter by patient: " + res.Status)
}
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
if data == nil {
return nil, errors.New("no encounter found for patient")
}
return *data, nil
}
func NewEncounterRepo(akses *model.Akses) EncounterInterface {
return &EncounterRepository{akses: akses}
}
// CreateEncounter implements EncounterInterface.
func (e *EncounterRepository) CreateEncounter(req model.EncounterRequest) (map[string]interface{}, error) {
var (
data *map[string]interface{}
)
req.ResourceType = constant.EncounterResourceType
req.Identifier = append(req.Identifier, model.IdentifierEncounter{
System: "http://sys-ids.kemkes.go.id/encounter/" + os.Getenv("ORGANIZATION_ID"),
Value: os.Getenv("ORGANIZATION_ID"),
})
req.ServiceProvider.Reference = "Organization/" + os.Getenv("ORGANIZATION_ID")
url := e.akses.BaseUrl + "/Encounter"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(e.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return *data, nil
}
// UpdateEncounter implements EncounterInterface.
func (e *EncounterRepository) UpdateEncounter(req model.EncounterUpdateRequest) (map[string]interface{}, error) {
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(e.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := e.akses.BaseUrl + fmt.Sprintf("/Encounter/%s", req.ID)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}

View File

@@ -0,0 +1,353 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type EpisodeOfCareInterface interface {
// Define methods for EpisodeOfCareInterface
CreateEpisodeOfCare(req model.EpisodeOfCareRequest) (map[string]interface{}, error)
GetEpisodeOfCareByPatient(id string) (map[string]interface{}, error)
HandleCheckEpisodeOfCare(id string) ([]string, bool, error)
UpdateEpisodeOfCare(req model.EpisodeOfCareRequest) (map[string]interface{}, error)
}
type EpisodeOfCareRepository struct {
akses *model.Akses
}
// CreateEpisodeOfCare implements EpisodeOfCareInterface.
func (e *EpisodeOfCareRepository) CreateEpisodeOfCare(req model.EpisodeOfCareRequest) (map[string]interface{}, error) {
var data map[string]interface{}
req.ResourceType = constant.EpisodeOfCareResourceType
req.Identifier = []model.Identifier{
{
System: "http://sys-ids.kemkes.go.id/episode-of-care/" + os.Getenv("ORGANIZATION_ID"),
Value: os.Getenv("ORGANIZATION_ID"),
},
}
// Setup Patient
var patient string
if req.Patient.Reference != "" {
patientInterface := NewPatientRepo(e.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Patient.Reference)
if err != nil {
return nil, err
}
if patient != "" {
req.Patient.Reference = "Patient/" + patient
}
}
// Setup Organization
req.ManagingOrganization.Reference = "Organization/" + os.Getenv("ORGANIZATION_ID")
req.ManagingOrganization.Display = os.Getenv("ORGANIZATION_NAME")
var conditionReference model.Reference
condition := e.setupCondition(patient)
if condition != "" {
conditionReference = model.Reference{
Reference: "Condition/" + condition,
}
} else {
return nil, errors.New("condition not found for the patient")
}
req.Diagnosis = append(req.Diagnosis, model.Diagnosis{
Condition: conditionReference,
})
// Setup CareManager
// if req.CareManager.Reference != "" {
// careManagerInterface := NewPracticionerRepo(e.akses)
// careManagerId, _, err := careManagerInterface.HandleCheckPartitioner(req.CareManager.Reference)
// if err != nil {
// return nil, err
// }
// req.CareManager.Reference = "Practitioner/" + careManagerId
// }
// Setup Type
url := e.akses.BaseUrl + "/EpisodeOfCare"
method := "POST"
jsonData, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(e.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
return nil, err
}
if !hasOperationOutcomeIssue(data) {
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(e.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
data["encounter"] = map[string]interface{}{
"reference": "Encounter/" + encounterId,
}
} else {
return nil, errors.New("encounter not found")
}
}
}
return data, nil
}
// GetEpisodeOfCareByPatient implements EpisodeOfCareInterface.
func (e *EpisodeOfCareRepository) GetEpisodeOfCareByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
// Validate the patient ID
if id == "" {
return nil, errors.New("patient ID cannot be empty")
}
// Construct the URL with query parameters
url := e.akses.BaseUrl + "/EpisodeOfCare?patient=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(e.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err := json.NewDecoder(response.Body).Decode(&data); err != nil {
return nil, err
}
return data, nil
}
// HandleCheckEpisodeOfCare implements EpisodeOfCareInterface.
func (e *EpisodeOfCareRepository) HandleCheckEpisodeOfCare(id string) ([]string, bool, error) {
eoc, err := e.GetEpisodeOfCareByPatient(id)
if err != nil {
return nil, false, err
}
// You can process 'eoc' here if needed
var ids []string
if entries, ok := eoc["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (eoc)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
func (e *EpisodeOfCareRepository) UpdateEpisodeOfCare(req model.EpisodeOfCareRequest) (map[string]interface{}, error) {
req.ResourceType = constant.EpisodeOfCareResourceType
// Setup Patient
var patient string
if req.Patient.Reference != "" {
patientInterface := NewPatientRepo(e.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Patient.Reference)
if err != nil {
return nil, err
}
if patient != "" {
req.Patient.Reference = "Patient/" + patient
}
}
// Setup Organization
if req.ManagingOrganization.Reference != "" {
orgInterface := NewOrganizationRepo(e.akses)
orgName, _, err := orgInterface.HandleCheckOrganization(req.ManagingOrganization.Reference)
if err != nil {
return nil, err
}
req.ManagingOrganization.Reference = "Organization/" + req.ManagingOrganization.Reference
req.ManagingOrganization.Display = orgName
}
// Get id existing EpisodeOfCare
data, err := e.setupPutEpisodeOfCare(&req, patient)
if err != nil {
return nil, err
}
if len(data["entry"].([]interface{})) == 0 {
return nil, errors.New("episode of care not found")
}
// Setup CareManager
// if req.CareManager.Reference != "" {
// careManagerInterface := NewPracticionerRepo(e.akses)
// careManagerId, _, err := careManagerInterface.HandleCheckPartitioner(req.CareManager.Reference)
// if err != nil {
// return nil, err
// }
// req.CareManager.Reference = "Practitioner/" + careManagerId
// }
// Setup Type
oauth := model.OauthRequest{
ClientId: e.akses.ClientId,
ClientSecret: e.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(e.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := e.akses.BaseUrl + fmt.Sprintf("/EpisodeOfCare/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
func (e *EpisodeOfCareRepository) setupCondition(patient string) string {
if patient == "" {
return ""
}
conditionInterface := NewConditionRepo(e.akses)
conditionId, conditionExist, err := conditionInterface.HandleCheckCondition(patient)
if err != nil {
return ""
}
if conditionExist {
return conditionId
}
return ""
}
func (e *EpisodeOfCareRepository) setupPutEpisodeOfCare(req *model.EpisodeOfCareRequest, patient string) (map[string]interface{}, error) {
data, err := e.GetEpisodeOfCareByPatient(patient)
if err != nil {
return nil, err
}
if entries, ok := data["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (data)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
req.Id = id
}
}
}
}
}
return data, nil
}
// hasOperationOutcomeIssue returns true when the response is an OperationOutcome
// with at least one issue that includes diagnostics or details.text.
func hasOperationOutcomeIssue(resp map[string]interface{}) bool {
if resp == nil {
return false
}
rt, ok := resp["resourceType"].(string)
if !ok || rt != "OperationOutcome" {
return false
}
issues, ok := resp["issue"].([]interface{})
if !ok || len(issues) == 0 {
return false
}
for _, it := range issues {
m, ok := it.(map[string]interface{})
if !ok {
continue
}
if diag, _ := m["diagnostics"].(string); diag != "" {
return true
}
if details, ok := m["details"].(map[string]interface{}); ok {
if txt, _ := details["text"].(string); txt != "" {
return true
}
}
}
return false
}
func NewEpisodeOfCareRepo(akses *model.Akses) EpisodeOfCareInterface {
return &EpisodeOfCareRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,221 @@
package integration
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type GoalInterface interface {
// Define methods for GoalInterface
CreateGoal(req model.GoalRequest) (map[string]interface{}, error)
UpdateGoal(req model.GoalRequest) (map[string]interface{}, error)
GetGoalByPatient(id string) (map[string]interface{}, error)
HandleCheckGoal(id string) ([]string, bool, error)
}
type GoalRepository struct {
// Define fields for GoalRepository
akses *model.Akses
}
// GetGoalByPatient implements GoalInterface.
func (c *GoalRepository) GetGoalByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/Goal?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckGoal implements GoalInterface.
func (c *GoalRepository) HandleCheckGoal(id string) ([]string, bool, error) {
goal, err := c.GetGoalByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := goal["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (goal)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
func NewGoalRepo(akses *model.Akses) GoalInterface {
return &GoalRepository{
akses: akses,
}
}
// CreateGoal implements GoalInterface.
func (c *GoalRepository) CreateGoal(req model.GoalRequest) (map[string]interface{}, error) {
req.ResourceType = constant.GoalResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/Goal"
data, err := httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
if err != nil {
return nil, err
}
if !isOperationOutcomeError(data) {
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
data["encounter"] = map[string]interface{}{
"reference": "Encounter/" + encounterId,
}
} else {
return nil, errors.New("encounter not found")
}
}
}
return data, nil
}
func (c *GoalRepository) UpdateGoal(req model.GoalRequest) (map[string]interface{}, error) {
req.ResourceType = constant.GoalResourceType
_, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/Goal/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *GoalRepository) setupPatient(req *model.GoalRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
// setupPractitioner handles practitioner reference logic.
func (c *GoalRepository) setupPractitioner(req *model.GoalRequest) error {
if req.ExpressedBy.Reference == "" {
return nil
}
practicionerInterface := NewPracticionerRepo(c.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.ExpressedBy.Reference)
if err != nil {
return err
}
if ref != "" {
req.ExpressedBy.Reference = "Practitioner/" + ref
req.ExpressedBy.Display = display
}
return nil
}

View File

@@ -0,0 +1,284 @@
package integration
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ImagingStudyInterface interface {
// Define methods for ImagingStudyInterface
CreateImagingStudy(req model.ImagingStudyRequest) (map[string]interface{}, error)
UpdateImagingStudy(req model.ImagingStudyRequest) (map[string]interface{}, error)
GetImagingStudyByPatient(id string) (map[string]interface{}, error)
HandleCheckImagingStudy(id string) ([]string, bool, error)
}
type ImagingStudyRepository struct {
// Define fields for ImagingStudyRepository
akses *model.Akses
}
func NewImagingStudyRepo(akses *model.Akses) ImagingStudyInterface {
return &ImagingStudyRepository{
akses: akses,
}
}
// GetImagingStudyByPatient implements ImagingStudyInterface.
func (c *ImagingStudyRepository) GetImagingStudyByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/ImagingStudy?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckImagingStudy implements ImagingStudyInterface.
func (c *ImagingStudyRepository) HandleCheckImagingStudy(id string) ([]string, bool, error) {
imaging, err := c.GetImagingStudyByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := imaging["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (imaging)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateImagingStudy implements ImagingStudyInterface.
func (c *ImagingStudyRepository) CreateImagingStudy(req model.ImagingStudyRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ImagingStudyResourceType
if len(req.Identifier) > 0 {
identifier := []model.Identifier{}
for k, i := range req.Identifier {
if k == 0 {
identifier = append(identifier, model.Identifier{
Use: "official",
System: "http://sys-ids.kemkes.go.id/acsn/" + os.Getenv("ORGANIZATION_ID"), // Set this if needed, or remove if not present in IdentifierObject
Value: i.Value,
Type: &model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.hl7.org/CodeSystem/v2-0203",
Code: "ACSN",
},
},
},
})
}
// if k == 1 {
// identifier = append(identifier, model.Identifier{
// System: "urn:dicom:uid",
// Value: i.Value,
// })
// }
}
req.Identifier = identifier
}
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
// Setup Service Request
err = c.setupServiceRequest(&req, patient)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/ImagingStudy"
data, err := httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
if err != nil {
return nil, err
}
if !isOperationOutcomeError(data) {
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
data["encounter"] = map[string]interface{}{
"reference": "Encounter/" + encounterId,
}
} else {
return nil, errors.New("encounter not found")
}
}
}
return data, nil
}
func (c *ImagingStudyRepository) UpdateImagingStudy(req model.ImagingStudyRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ImagingStudyResourceType
if len(req.Identifier) > 0 {
identifier := []model.Identifier{}
for k, i := range req.Identifier {
if k == 0 {
identifier = append(identifier, model.Identifier{
Use: "official",
System: "http://sys-ids.kemkes.go.id/acsn/" + os.Getenv("ORGANIZATION_ID"), // Set this if needed, or remove if not present in IdentifierObject
Value: i.Value,
Type: &model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.hl7.org/CodeSystem/v2-0203",
Code: "ACSN",
},
},
},
})
}
// if k == 1 {
// identifier = append(identifier, model.Identifier{
// System: "urn:dicom:uid",
// Value: i.Value,
// })
// }
}
req.Identifier = identifier
}
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
// Setup Service Request
err = c.setupServiceRequest(&req, patient)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/ImagingStudy/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *ImagingStudyRepository) setupPatient(req *model.ImagingStudyRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *ImagingStudyRepository) setupServiceRequest(req *model.ImagingStudyRequest, patient string) error {
if patient == "" {
return nil
}
serviceReq := NewServiceRequestRepository(c.akses)
ids, _, err := serviceReq.HandleCheckServiceRequest(patient)
if err != nil {
return err
}
if len(ids) > 0 {
req.BasedOn = []model.Reference{
{
Reference: "ServiceRequest/" + ids[0],
},
}
}
return nil
}

View File

@@ -0,0 +1,130 @@
package integration
import (
"errors"
"fmt"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ImmunizationInterface interface {
// Define methods for ImmunizationInterface
CreateImmunization(req model.ImmunizationRequest) (map[string]interface{}, error)
UpdateImmunization(req model.ImmunizationRequest) (map[string]interface{}, error)
}
type ImmunizationRepository struct {
// Define fields for ImmunizationRepository
akses *model.Akses
}
func NewImmunizationRepo(akses *model.Akses) ImmunizationInterface {
return &ImmunizationRepository{
akses: akses,
}
}
// CreateImmunization implements ImmunizationInterface.
func (c *ImmunizationRepository) CreateImmunization(req model.ImmunizationRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ImmunizationResourceType
//setup primarySource default true karena vaksin bersumber dari orang yg melakukan vaksin
req.PrimarySource = true
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/Immunization"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *ImmunizationRepository) UpdateImmunization(req model.ImmunizationRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ImmunizationResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/Immunization/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *ImmunizationRepository) setupPatient(req *model.ImmunizationRequest) (string, error) {
if req.Patient.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Patient.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Patient.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *ImmunizationRepository) setupEncounter(req *model.ImmunizationRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
}
return nil
}

View File

@@ -0,0 +1,240 @@
package integration
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"satusehat-rssa/pkg/httputil"
"strings"
)
type MedicationDispenseInterface interface {
// Define methods for MedicationDispenseInterface
CreateMedicationDispense(req model.MedicationDispenseRequest) (map[string]interface{}, error)
UpdateMedicationDispense(req model.MedicationDispenseRequest) (map[string]interface{}, error)
GetMedicationDispenseByPatient(id string, category string) (map[string]interface{}, error)
HandleCheckMedicationDispense(id string, category string) ([]string, bool, error)
}
type MedicationDispenseRepository struct {
// Define fields for MedicationDispenseRepository
akses *model.Akses
}
func NewMedicationDispenseRepo(akses *model.Akses) MedicationDispenseInterface {
return &MedicationDispenseRepository{
akses: akses,
}
}
// GetMedicationDispenseByPatient implements MedicationDispenseInterface.
func (c *MedicationDispenseRepository) GetMedicationDispenseByPatient(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/MedicationDispense?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil,
err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckMedicationDispense implements MedicationDispenseInterface.
func (c *MedicationDispenseRepository) HandleCheckMedicationDispense(id string, category string) ([]string, bool, error) {
medicationDispense, err := c.GetMedicationDispenseByPatient(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := medicationDispense["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (medicationDispense)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateMedicationDispense implements MedicationDispenseInterface.
func (c *MedicationDispenseRepository) CreateMedicationDispense(req model.MedicationDispenseRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationDispenseResourceType
req.Identifier = append(req.Identifier, common.GetIdentifier("prescription"))
identifierItem := common.GetIdentifier("prescription-item")
identifierItem.Value += "-1"
req.Identifier = append(req.Identifier, identifierItem)
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/MedicationDispense"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationDispenseRepository) UpdateMedicationDispense(req model.MedicationDispenseRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationDispenseResourceType
req.Identifier = append(req.Identifier, common.GetIdentifier("prescription"))
identifierItem := common.GetIdentifier("prescription-item")
identifierItem.Value += "-1"
req.Identifier = append(req.Identifier, identifierItem)
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/MedicationDispense/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationDispenseRepository) setupPatient(req *model.MedicationDispenseRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *MedicationDispenseRepository) setupEncounter(req *model.MedicationDispenseRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Context.Reference = "Encounter/" + encounterId
}
return nil
}
// setupPractitioner handles practitioner reference logic.
func (c *MedicationDispenseRepository) setupPractitioner(req *model.MedicationDispenseRequest) error {
if len(req.Performer) == 0 {
return nil
}
for k, performer := range req.Performer {
if strings.Contains(performer.Actor.Reference, "Practitioner/") {
temp := strings.Split(performer.Actor.Reference, "/")
practicionerInterface := NewPracticionerRepo(c.akses)
ref, _, err := practicionerInterface.HandleCheckPartitioner(temp[1])
if err != nil {
return err
}
if ref != "" {
req.Performer[k].Actor.Reference = "Practitioner/" + ref
}
}
}
return nil
}

View File

@@ -0,0 +1,260 @@
package integration
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"satusehat-rssa/pkg/httputil"
)
type MedicationRequestInterface interface {
// Define methods for MedicationRequestInterface
CreateMedicationRequest(req model.MedicationRequestRequest) (map[string]interface{}, error)
UpdateMedicationRequest(req model.MedicationRequestRequest) (map[string]interface{}, error)
GetMedicationRequestByPatient(id string, category string) (map[string]interface{}, error)
HandleCheckMedicationRequest(id string, category string) ([]string, bool, error)
}
type MedicationRequestRepository struct {
// Define fields for MedicationRequestRepository
akses *model.Akses
}
func NewMedicationRequestRepo(akses *model.Akses) MedicationRequestInterface {
return &MedicationRequestRepository{
akses: akses,
}
}
// GetMedicationRequestByPatient implements MedicationRequestInterface.
func (c *MedicationRequestRepository) GetMedicationRequestByPatient(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := c.akses.BaseUrl + "/MedicationRequest?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckMedicationRequest implements MedicationRequestInterface.
func (c *MedicationRequestRepository) HandleCheckMedicationRequest(id string, category string) ([]string, bool, error) {
medicationReq, err := c.GetMedicationRequestByPatient(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := medicationReq["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (medicationReq)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateMedicationRequest implements MedicationRequestInterface.
func (c *MedicationRequestRepository) CreateMedicationRequest(req model.MedicationRequestRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationRequestResourceType
req.Identifier = append(req.Identifier, common.GetIdentifier("prescription"))
identifierItem := common.GetIdentifier("prescription-item")
identifierItem.Value += "-1"
req.Identifier = append(req.Identifier, identifierItem)
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupMedication(&req)
if err != nil {
return nil, err
}
req.DispenseRequest.Performer.Reference = "Organization/" + os.Getenv("ORGANIZATION_ID")
req.MedicationRequest = nil
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/MedicationRequest"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationRequestRepository) UpdateMedicationRequest(req model.MedicationRequestRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationRequestResourceType
req.Identifier = append(req.Identifier, common.GetIdentifier("prescription"))
identifierItem := common.GetIdentifier("prescription-item")
identifierItem.Value += "-1"
req.Identifier = append(req.Identifier, identifierItem)
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/MedicationRequest/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationRequestRepository) setupPatient(req *model.MedicationRequestRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *MedicationRequestRepository) setupEncounter(req *model.MedicationRequestRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
}
return nil
}
// setupPractitioner handles practitioner reference logic.
func (c *MedicationRequestRepository) setupPractitioner(req *model.MedicationRequestRequest) error {
if req.Requester.Reference == "" {
return nil
}
practicionerInterface := NewPracticionerRepo(c.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.Requester.Reference)
if err != nil {
return err
}
if ref != "" {
req.Requester.Reference = "Practitioner/" + ref
req.Requester.Display = display
}
return nil
}
func (c *MedicationRequestRepository) setupMedication(req *model.MedicationRequestRequest) error {
if req.MedicationRequest == nil {
return errors.New("Need Medication Request")
}
MedicationInterface := NewMedicineKfaRepo(c.akses)
medication, err := MedicationInterface.MedicationCreate(*req.MedicationRequest)
if err != nil {
return err
}
if idRaw, ok := medication["id"].(string); ok {
if idRaw == "" {
return errors.New("medication id is empty")
}
req.MedicationReference.Reference = "Medication/" + idRaw
}
return nil
}

View File

@@ -0,0 +1,173 @@
package integration
import (
"errors"
"fmt"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/common"
"satusehat-rssa/pkg/httputil"
)
type MedicationStatementInterface interface {
// Define methods for MedicationStatementInterface
CreateMedicationStatement(req model.MedicationStatementRequest) (map[string]interface{}, error)
UpdateMedicationStatement(req model.MedicationStatementRequest) (map[string]interface{}, error)
}
type MedicationStatementRepository struct {
// Define fields for MedicationStatementRepository
akses *model.Akses
}
func NewMedicationStatementRepo(akses *model.Akses) MedicationStatementInterface {
return &MedicationStatementRepository{
akses: akses,
}
}
// CreateMedicationStatement implements MedicationStatementInterface.
func (c *MedicationStatementRepository) CreateMedicationStatement(req model.MedicationStatementRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationStatementResourceType
// inject identifier to contained
if len(req.Contained) > 0 {
for k, c := range req.Contained {
identifier := common.GetIdentifier("medication")
identifier.Value = c.ID
req.Contained[k].Identifier = append(req.Contained[k].Identifier, identifier)
}
}
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupSource(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/MedicationStatement"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationStatementRepository) UpdateMedicationStatement(req model.MedicationStatementRequest) (map[string]interface{}, error) {
req.ResourceType = constant.MedicationStatementResourceType
// inject identifier to contained
if len(req.Contained) > 0 {
for k, c := range req.Contained {
identifier := common.GetIdentifier("medication")
identifier.Value = c.ID
req.Contained[k].Identifier = append(req.Contained[k].Identifier, identifier)
}
}
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupSource(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/MedicationStatement/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *MedicationStatementRepository) setupPatient(req *model.MedicationStatementRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *MedicationStatementRepository) setupSource(req *model.MedicationStatementRequest) error {
if req.InformationSource.Reference == "" {
return nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.InformationSource.Reference)
if err != nil {
return err
}
if patient != "" {
req.InformationSource.Reference = "Patient/" + patient
}
return nil
}
func (c *MedicationStatementRepository) setupEncounter(req *model.MedicationStatementRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Context.Reference = "Encounter/" + encounterId
}
return nil
}

View File

@@ -0,0 +1,196 @@
package integration
import (
"encoding/json"
"errors"
"net/http"
"os"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
"strconv"
)
type MedicineIntegrationInterface interface {
GetMedicineKfa(req model.MedicineKfaRequest) ([]model.MedicineKfaResponse, error)
MedicationCreate(req model.MedicationRequest) (map[string]interface{}, error)
GetMedicineByKfaCode(kfaCode string) (map[string]interface{}, error)
}
type MedicineKfaRepository struct {
akses *model.Akses
}
// GetMedicineByKfaCode implements MedicineIntegrationInterface.
func (m *MedicineKfaRepository) GetMedicineByKfaCode(kfaCode string) (map[string]interface{}, error) {
var data map[string]interface{}
url := m.akses.KfaUrl + "/products"
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
// Assuming the access token is stored in a field of the akses struct
oauth := model.OauthRequest{
ClientId: m.akses.ClientId,
ClientSecret: m.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(m.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", "application/json")
q := request.URL.Query()
q.Add("code", kfaCode)
q.Add("identifier", "kfa")
request.URL.RawQuery = q.Encode()
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
return data, nil
}
// MedicationCreate implements MedicineIntegrationInterface.
func (m *MedicineKfaRepository) MedicationCreate(req model.MedicationRequest) (map[string]interface{}, error) {
req.ResourceType = "Medication"
req.Meta = model.Meta{
Profile: []string{constant.FHIRMedicationProfile},
}
req.Identifier = []model.Identifier{
{
System: "http://sys-ids.kemkes.go.id/medication/" + os.Getenv("ORGANIZATION_ID"),
Value: os.Getenv("ORGANIZATION_ID"),
Use: "official",
},
}
req.Manufacturer = model.Reference{
Reference: "Organization/" + os.Getenv("ORGANIZATION_ID"),
}
req.Extension = []model.ExtensionMedication{
{
URL: "https://fhir.kemkes.go.id/r4/StructureDefinition/MedicationType",
ValueCodeableConcept: model.CodeableConcept{
Coding: []model.Coding{
{
System: "http://terminology.kemkes.go.id/CodeSystem/medication-type",
Code: "NC",
Display: "Non-compound",
},
},
},
},
}
url := m.akses.BaseUrl + "/Medication"
oauth := model.OauthRequest{
ClientId: m.akses.ClientId,
ClientSecret: m.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(m.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
data, err := httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
if err != nil {
return nil, err
}
return data, nil
}
// GetMedicineKfa implements MedicineIntegrationInterface.
func (m *MedicineKfaRepository) GetMedicineKfa(req model.MedicineKfaRequest) ([]model.MedicineKfaResponse, error) {
var (
data map[string]interface{}
)
url := m.akses.KfaUrl + "/products/all"
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
// Assuming the access token is stored in a field of the akses struct
oauth := model.OauthRequest{
ClientId: m.akses.ClientId,
ClientSecret: m.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(m.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", "application/json")
q := request.URL.Query()
q.Add("page", strconv.Itoa(req.Page))
q.Add("size", strconv.Itoa(req.Size))
q.Add("product_type", req.ProdustType)
q.Add("keyword", req.Keyword)
request.URL.RawQuery = q.Encode()
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, errors.New("failed to fetch data: " + res.Status)
}
var response []model.MedicineKfaResponse
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
if items, ok := data["items"].(map[string]interface{}); ok {
for _, item := range items {
if itemMap, ok := item.([]interface{}); ok {
for _, med := range itemMap {
if medMap, ok := med.(map[string]interface{}); ok {
medicine := model.MedicineKfaResponse{
Name: medMap["name"].(string),
KfaCode: medMap["kfa_code"].(string),
}
response = append(response, medicine)
} else {
return nil, errors.New("invalid item format")
}
}
}
}
} else {
return nil, errors.New("invalid response format")
}
return response, nil
}
func NewMedicineKfaRepo(akses *model.Akses) MedicineIntegrationInterface {
return &MedicineKfaRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,54 @@
package integration
import (
"encoding/json"
"net/http"
"satusehat-rssa/internal/model"
"strings"
)
type OauthInterface interface {
GenerateToken(req model.OauthRequest) (*model.OauthResponse, error)
}
type OauthRepository struct {
akses *model.Akses
}
// GenerateToken implements OauthInterface.
func (o *OauthRepository) GenerateToken(req model.OauthRequest) (*model.OauthResponse, error) {
var (
data *model.OauthResponse
)
url := o.akses.AuthUrl + "/accesstoken?grant_type=client_credentials"
method := "POST"
req_data := "client_id=" + req.ClientId + "&client_secret=" + req.ClientSecret
payload := strings.NewReader(req_data)
client := &http.Client{}
request, err := http.NewRequest(method, url, payload)
if err != nil {
return nil, err
}
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func NewOauthRequestRepo(akses *model.Akses) OauthInterface {
return &OauthRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,382 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ObservationInterface interface {
CreateObservation(req model.ObservationRequest) (map[string]interface{}, error)
GetObservationByPatient(id string) (map[string]interface{}, error)
GetObservationByPatientCategory(id string, category string) (map[string]interface{}, error)
HandleCheckObservation(id string) ([]string, bool, error)
HandleCheckObservationCategory(id string, category string) ([]string, bool, error)
UpdateObservation(req model.ObservationRequest) (map[string]interface{}, error)
}
type ObservationRepository struct {
akses *model.Akses
}
// GetObservationByPatientCategory implements ObservationInterface.
func (o *ObservationRepository) GetObservationByPatientCategory(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := o.akses.BaseUrl + "/Observation?subject=" + id + "&category=" + category
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckObservationCategory implements ObservationInterface.
func (o *ObservationRepository) HandleCheckObservationCategory(id string, category string) ([]string, bool, error) {
observation, err := o.GetObservationByPatientCategory(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := observation["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (observation)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// HandleCheckObservation implements ObservationInterface.
func (o *ObservationRepository) HandleCheckObservation(id string) ([]string, bool, error) {
observation, err := o.GetObservationByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := observation["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (observation)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// GetObservationByPatient implements ObservationInterface.
func (o *ObservationRepository) GetObservationByPatient(id string) (map[string]interface{}, error) {
var (
data map[string]interface{}
)
url := o.akses.BaseUrl + "/Observation?subject=" + id
method := "GET"
client := http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// CreateObservation implements ObservationInterface.
func (o *ObservationRepository) CreateObservation(req model.ObservationRequest) (map[string]interface{}, error) {
var (
data = make(map[string]interface{})
)
req.ResourceType = constant.ObservationResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(o.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
//Setup Practitioner
// if req.Performer != nil && len(req.Performer) > 0 {
// practitionerInterface := NewPracticionerRepo(o.akses)
// practitionerId, _, err := practitionerInterface.HandleCheckPartitioner(req.Performer[0].Reference)
// if err != nil {
// return nil, err
// }
// if practitionerId != "" {
// req.Performer = []model.Reference{
// {Reference: "Practitioner/" + practitionerId},
// }
// } else {
// return nil, errors.New("practitioner not found")
// }
// }
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(o.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
//setup service request
err := o.setupServiceRequest(&req, patient)
if err != nil {
return nil, errors.New("service request not found")
}
if req.Category[0].Coding[0].Code == "laboratory" {
//setup specimen
err = o.setupSpecimen(&req, patient)
if err != nil {
return nil, errors.New("specimen not found")
}
}
url := o.akses.BaseUrl + "/Observation"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (o *ObservationRepository) UpdateObservation(req model.ObservationRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ObservationResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(o.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
//Setup Practitioner
// if req.Performer != nil && len(req.Performer) > 0 {
// practitionerInterface := NewPracticionerRepo(o.akses)
// practitionerId, _, err := practitionerInterface.HandleCheckPartitioner(req.Performer[0].Reference)
// if err != nil {
// return nil, err
// }
// if practitionerId != "" {
// req.Performer = []model.Reference{
// {Reference: "Practitioner/" + practitionerId},
// }
// } else {
// return nil, errors.New("practitioner not found")
// }
// }
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(o.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(o.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := o.akses.BaseUrl + fmt.Sprintf("/Observation/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
func (o *ObservationRepository) setupServiceRequest(req *model.ObservationRequest, patient string) error {
if patient == "" {
return nil
}
serviceReq := NewServiceRequestRepository(o.akses)
ids, _, err := serviceReq.HandleCheckServiceRequest(patient)
if err != nil {
return err
}
if len(ids) > 0 {
req.BasedOn = []model.Reference{
{
Reference: "ServiceRequest/" + ids[0],
},
}
}
return nil
}
func (o *ObservationRepository) setupSpecimen(req *model.ObservationRequest, patient string) error {
if patient == "" {
return nil
}
specimenInterface := NewSpecimenRepository(o.akses)
ids, exist, err := specimenInterface.HandleCheckSpecimen(patient)
if err != nil {
return err
}
if exist {
req.Specimen = &model.Reference{}
req.Specimen.Reference = "Specimen/" + ids[0]
} else {
return errors.New("specimen not found")
}
return nil
}
func NewObservationRepo(akses *model.Akses) ObservationInterface {
return &ObservationRepository{akses: akses}
}

View File

@@ -0,0 +1,164 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
)
type OrganizationInterface interface {
// Define methods for OrganizationInterface
CreateOrganization(req model.OrganizationRequest) (map[string]interface{}, error)
GetOrganizationPatient(id string) (map[string]interface{}, error)
HandleCheckOrganization(id string) (string, bool, error)
}
type OrganizationRepository struct {
akses *model.Akses
}
// CreateOrganization implements OrganizationInterface.
func (o *OrganizationRepository) CreateOrganization(req model.OrganizationRequest) (map[string]interface{}, error) {
var data map[string]interface{}
req.ResourceType = constant.OrganizationResourceType
url := o.akses.BaseUrl + "/Organization"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// GetDiagnosisReportByPatient implements OrganizationInterface.
func (o *OrganizationRepository) GetOrganizationPatient(id string) (map[string]interface{}, error) {
url := o.akses.BaseUrl + "/DiagnosticReport?patient=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, errors.New("failed to get diagnosis report")
}
var data map[string]interface{}
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckOrganization implements OrganizationInterface.
func (o *OrganizationRepository) HandleCheckOrganization(id string) (string, bool, error) {
url := o.akses.BaseUrl + "/Organization/" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return "", false, err
}
oauth := model.OauthRequest{
ClientId: o.akses.ClientId,
ClientSecret: o.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(o.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return "", false, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
response, err := client.Do(request)
if err != nil {
return "", false, err
}
defer response.Body.Close()
if response.StatusCode == http.StatusNotFound {
return "", false, nil
} else if response.StatusCode != http.StatusOK {
return "", false, errors.New("failed to check organization")
}
var data map[string]interface{}
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return "", false, err
}
name, ok := data["name"].(string)
if !ok {
return "", false, errors.New("organization name not found")
}
return name, true, nil
}
func NewOrganizationRepo(akses *model.Akses) OrganizationInterface {
return &OrganizationRepository{akses: akses}
}

View File

@@ -0,0 +1,146 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
)
type PatientInterface interface {
// Define methods for PartientInterface
CreataPatient(req model.PatientRequest) (*map[string]interface{}, error)
GetPatientByNIK(identifier string) (*map[string]interface{}, error)
HandleCheckPatient(nik string) (string, error)
}
type PatientRepository struct {
akses *model.Akses
}
// HandleCheckPatient implements PatientInterface.
func (p *PatientRepository) HandleCheckPatient(nik string) (string, error) {
nik = "https://fhir.kemkes.go.id/id/nik|" + nik
patient, err := p.GetPatientByNIK(nik)
if err != nil {
return "", err
}
if entries, ok := (*patient)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
return id, nil
}
}
}
}
return "", nil
}
// CreataPatient implements PatientInterface.
func (p *PatientRepository) CreataPatient(req model.PatientRequest) (*map[string]interface{}, error) {
var (
data *map[string]interface{}
)
req.ResourceType = constant.PatientResourceType
req.Meta = model.Meta{
Profile: []string{constant.PatientProfile},
}
url := p.akses.BaseUrl + "/Patient"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
// Assuming the access token is stored in a field of the akses struct
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(p.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// GetPatientByNIK implements PatientInterface.
func (p *PatientRepository) GetPatientByNIK(identifier string) (*map[string]interface{}, error) {
var (
data *map[string]interface{}
)
url := p.akses.BaseUrl + "/Patient?identifier=" + identifier
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
// Assuming the access token is stored in a field of the akses struct
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(p.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// CreataPatient implements PartientInterface.
func NewPatientRepo(akses *model.Akses) PatientInterface {
return &PatientRepository{akses: akses}
}

View File

@@ -0,0 +1,105 @@
package integration
import (
"encoding/json"
"errors"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
)
type PracticionerInterface interface {
// Add fields as necessary for the integration
GetPracticionerByNIK(nik string) (*map[string]interface{}, error)
HandleCheckPartitioner(nik string) (string, string, error)
}
type PracticionerRepository struct {
akses *model.Akses
}
// HandleCheckPartitioner implements PracticionerInterface.
func (p *PracticionerRepository) HandleCheckPartitioner(nik string) (string, string, error) {
practitioner, err := p.GetPracticionerByNIK("https://fhir.kemkes.go.id/id/nik|" + nik)
if err != nil {
return "", "", err
}
if practitioner != nil {
id := ""
nameText := ""
if entriesRaw, ok := (*practitioner)["entry"]; ok {
if entries, ok := entriesRaw.([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
// Ambil id
if idRaw, ok := resource["id"].(string); ok {
id = idRaw
}
// Ambil name[0].text
if namesRaw, ok := resource["name"]; ok {
if names, ok := namesRaw.([]interface{}); ok && len(names) > 0 {
if nameObj, ok := names[0].(map[string]interface{}); ok {
if text, ok := nameObj["text"].(string); ok {
nameText = text
}
}
}
}
}
}
}
}
return id, nameText, nil
} else {
return "", "", errors.New("practitioner not found")
}
}
func NewPracticionerRepo(akses *model.Akses) PracticionerInterface {
return &PracticionerRepository{akses: akses}
}
func (p *PracticionerRepository) GetPracticionerByNIK(nik string) (*map[string]interface{}, error) {
var (
data *map[string]interface{}
)
url := p.akses.BaseUrl + "/Practitioner?identifier=" + nik
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(p.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Add("Authorization", "Bearer "+token.AccessToken)
} else {
return nil, errors.New(constant.ErrGenerateToken)
}
request.Header.Set("Accept", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}

View File

@@ -0,0 +1,236 @@
package integration
import (
"encoding/json"
"errors"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
"strings"
)
type ProcedureInterface interface {
CreateProcedure(req model.ProcedureRequest) (map[string]interface{}, error)
GetProcedure(id string) (map[string]interface{}, error)
UpdateProcedure(req model.ProcedureRequest) (map[string]interface{}, error)
GetProcedureByPatient(id string) (map[string]interface{}, error)
HandleCheckProcedure(id string) ([]string, bool, error)
}
type ProcedureRepository struct {
akses *model.Akses
}
// GetProcedureByPatient implements ProcedureInterface.
func (p *ProcedureRepository) GetProcedureByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := p.akses.BaseUrl + "/Procedure?subject=" + id
method := "GET"
client := &http.Client{}
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(p.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckProcedure implements ProcedureInterface.
func (p *ProcedureRepository) HandleCheckProcedure(id string) ([]string, bool, error) {
procedure, err := p.GetProcedureByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := procedure["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (procedure)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateProcedure implements ProcedureInterface.
func (p *ProcedureRepository) CreateProcedure(req model.ProcedureRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ProcedureResourceType
patient, err := p.setupPatient(&req)
if err != nil {
return nil, err
}
err = p.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
//Setup Performer
err = p.setupPractitioner(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(p.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := p.akses.BaseUrl + "/Procedure"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
// GetProcedure implements ProcedureInterface.
func (p *ProcedureRepository) GetProcedure(id string) (map[string]interface{}, error) {
panic("unimplemented")
}
// UpdateProcedure implements ProcedureInterface.
func (p *ProcedureRepository) UpdateProcedure(req model.ProcedureRequest) (map[string]interface{}, error) {
patient, err := p.setupPatient(&req)
if err != nil {
return nil, err
}
err = p.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
//Setup Performer
err = p.setupPractitioner(&req)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: p.akses.ClientId,
ClientSecret: p.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(p.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := p.akses.BaseUrl + "/Procedure/" + req.ID
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
BearerToken: token.AccessToken,
Body: req,
})
}
func (p *ProcedureRepository) setupPatient(req *model.ProcedureRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(p.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
// setupEncounter extracts encounter setup logic from CreateDiagnosisReport.
func (p *ProcedureRepository) setupEncounter(req *model.ProcedureRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(p.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
//Buat dulu encounter
}
return nil
}
func (p *ProcedureRepository) setupPractitioner(req *model.ProcedureRequest) error {
if len(req.Performer) == 0 {
return nil
}
for _, performer := range req.Performer {
if strings.Contains(performer.Actor.Reference, "Practitioner/") {
temp := strings.Split(performer.Actor.Reference, "/")
practicionerInterface := NewPracticionerRepo(p.akses)
ref, _, err := practicionerInterface.HandleCheckPartitioner(temp[1])
if err != nil {
return err
}
if ref != "" {
performer.Actor.Reference = "Practitioner/" + ref
}
}
}
return nil
}
func NewProcedureRepo(akses *model.Akses) ProcedureInterface {
return &ProcedureRepository{
akses: akses,
}
}

View File

@@ -0,0 +1,181 @@
package integration
import (
"errors"
"fmt"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type QuestionnaireResponseInterface interface {
// Define methods for QuestionnaireResponseInterface
CreateQuestionnaireResponse(req model.QuestionnaireResponseRequest) (map[string]interface{}, error)
UpdateQuestionnaireResponse(req model.QuestionnaireResponseRequest) (map[string]interface{}, error)
}
type QuestionnaireResponseRepository struct {
// Define fields for QuestionnaireResponseRepository
akses *model.Akses
}
func NewQuestionnaireResponseRepo(akses *model.Akses) QuestionnaireResponseInterface {
return &QuestionnaireResponseRepository{
akses: akses,
}
}
// CreateQuestionnaireResponse implements QuestionnaireResponseInterface.
func (c *QuestionnaireResponseRepository) CreateQuestionnaireResponse(req model.QuestionnaireResponseRequest) (map[string]interface{}, error) {
req.ResourceType = constant.QuestionnaireResponseResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupSource(&req)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + "/QuestionnaireResponse"
return httputil.DoRequest(httputil.RequestOption{
Method: "POST",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *QuestionnaireResponseRepository) UpdateQuestionnaireResponse(req model.QuestionnaireResponseRequest) (map[string]interface{}, error) {
req.ResourceType = constant.QuestionnaireResponseResourceType
patient, err := c.setupPatient(&req)
if err != nil {
return nil, err
}
err = c.setupEncounter(&req, patient)
if err != nil {
return nil, err
}
err = c.setupSource(&req)
if err != nil {
return nil, err
}
// err = c.setupPractitioner(&req)
// if err != nil {
// return nil, err
// }
oauth := model.OauthRequest{
ClientId: c.akses.ClientId,
ClientSecret: c.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(c.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := c.akses.BaseUrl + fmt.Sprintf("/QuestionnaireResponse/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
Headers: httputil.DefaultFHIRHeaders(),
})
}
func (c *QuestionnaireResponseRepository) setupPatient(req *model.QuestionnaireResponseRequest) (string, error) {
if req.Subject.Reference == "" {
return "", nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return "", err
}
if patient != "" {
req.Subject.Reference = "Patient/" + patient
}
return patient, nil
}
func (c *QuestionnaireResponseRepository) setupSource(req *model.QuestionnaireResponseRequest) error {
if req.Source.Reference == "" {
return nil
}
patientInterface := NewPatientRepo(c.akses)
patient, err := patientInterface.HandleCheckPatient(req.Source.Reference)
if err != nil {
return err
}
if patient != "" {
req.Source.Reference = "Patient/" + patient
}
return nil
}
func (c *QuestionnaireResponseRepository) setupEncounter(req *model.QuestionnaireResponseRequest, patient string) error {
if patient == "" {
return nil
}
encounterInterface := NewEncounterRepo(c.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
}
return nil
}
// setupPractitioner handles practitioner reference logic.
func (c *QuestionnaireResponseRepository) setupPractitioner(req *model.QuestionnaireResponseRequest) error {
if req.Author.Reference == "" {
return nil
}
practicionerInterface := NewPracticionerRepo(c.akses)
ref, display, err := practicionerInterface.HandleCheckPartitioner(req.Author.Reference)
if err != nil {
return err
}
if ref != "" {
req.Author.Reference = "Practitioner/" + ref
req.Author.Display = display
}
return nil
}

View File

@@ -0,0 +1,288 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type ServiceRequestInterface interface {
CreateServiceRequest(req model.ServiceRequest) (map[string]interface{}, error)
GetServiceRequestByPatient(id string) (map[string]interface{}, error)
GetServiceRequestByPatientCategory(id string, category string) (map[string]interface{}, error)
HandleCheckServiceRequest(id string) ([]string, bool, error)
HandleCheckServiceRequestByCategory(id string, category string) ([]string, bool, error)
UpdateServiceRequest(req model.ServiceRequest) (map[string]interface{}, error)
}
type ServiceRequestRepository struct {
akses *model.Akses
}
// GetServiceRequestByPatientCategory implements ServiceRequestInterface.
func (s *ServiceRequestRepository) GetServiceRequestByPatientCategory(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := s.akses.BaseUrl + "/ServiceRequest?subject=" + id + "&category=" + category
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckServiceRequestByCategory implements ServiceRequestInterface.
func (s *ServiceRequestRepository) HandleCheckServiceRequestByCategory(id string, category string) ([]string, bool, error) {
servicereq, err := s.GetServiceRequestByPatientCategory(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := servicereq["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (servicereq)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateServiceRequest implements ServiceRequestInterface.
func (s *ServiceRequestRepository) CreateServiceRequest(req model.ServiceRequest) (map[string]interface{}, error) {
var data map[string]interface{}
req.ResourceType = constant.ServiceRequestResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(s.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(s.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
url := s.akses.BaseUrl + "/ServiceRequest"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
func (s *ServiceRequestRepository) UpdateServiceRequest(req model.ServiceRequest) (map[string]interface{}, error) {
req.ResourceType = constant.ServiceRequestResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(s.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(s.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
req.Encounter.Reference = "Encounter/" + encounterId
} else {
return nil, errors.New("encounter not found")
}
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(s.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := s.akses.BaseUrl + fmt.Sprintf("/ServiceRequest/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
// GetServiceRequestByPatient implements ServiceRequestInterface.
func (s *ServiceRequestRepository) GetServiceRequestByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := s.akses.BaseUrl + "/ServiceRequest?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckServiceRequest implements ServiceRequestInterface.
func (s *ServiceRequestRepository) HandleCheckServiceRequest(id string) ([]string, bool, error) {
servicereq, err := s.GetServiceRequestByPatient(id)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := servicereq["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (servicereq)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
func NewServiceRequestRepository(akses *model.Akses) ServiceRequestInterface {
return &ServiceRequestRepository{akses: akses}
}

View File

@@ -0,0 +1,336 @@
package integration
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"satusehat-rssa/internal/constant"
"satusehat-rssa/internal/model"
"satusehat-rssa/pkg/httputil"
)
type SpecimenInterface interface {
CreateSpecimen(req model.SpecimenRequest) (map[string]interface{}, error)
GetSpecimenByPatient(id string) (map[string]interface{}, error)
GetSpecimenByPatientCategory(id string, category string) (map[string]interface{}, error)
HandleCheckSpecimen(id string) ([]string, bool, error)
HandleCheckSpecimenCategory(id string, category string) ([]string, bool, error)
UpdateSpecimen(req model.SpecimenRequest) (map[string]interface{}, error)
}
type SpecimenRepository struct {
akses *model.Akses
}
// GetSpecimenByPatientCategory implements SpecimenInterface.
func (s *SpecimenRepository) GetSpecimenByPatientCategory(id string, category string) (map[string]interface{}, error) {
var data map[string]interface{}
url := s.akses.BaseUrl + "/Specimen?subject=" + id + "&category=" + category
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
request.Header.Set("Content-Type", constant.ContentTypeFHIRJSON)
res, err := client.Do(request)
if err != nil {
return nil, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// HandleCheckSpecimenCategory implements SpecimenInterface.
func (s *SpecimenRepository) HandleCheckSpecimenCategory(id string, category string) ([]string, bool, error) {
specimen, err := s.GetSpecimenByPatientCategory(id, category)
if err != nil {
return nil, false, err
}
var ids []string
if entries, ok := specimen["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (specimen)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
// CreateSpecimen implements SpecimenInterface.
func (s *SpecimenRepository) CreateSpecimen(req model.SpecimenRequest) (map[string]interface{}, error) {
var data map[string]interface{}
req.ResourceType = constant.SpecimenResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(s.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Service Request
err := s.setupServiceRequest(&req, patient)
if err != nil {
return nil, err
}
url := s.akses.BaseUrl + "/Specimen"
method := "POST"
payload, err := json.Marshal(req)
if err != nil {
return nil, err
}
client := &http.Client{}
request, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
request.Header.Set("Content-Type", "application/json")
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
if !isOperationOutcomeError(data) {
// Setup Encounter
if patient != "" {
encounterInterface := NewEncounterRepo(s.akses)
encounterId, encounterExist, err := encounterInterface.HandleCheckEncounter(patient)
if err != nil {
return nil, err
}
if encounterExist {
data["encounter"] = map[string]interface{}{
"reference": "Encounter/" + encounterId,
}
} else {
return nil, errors.New("encounter not found")
}
}
}
return data, nil
}
// GetSpecimenByPatient implements SpecimenInterface.
func (s *SpecimenRepository) GetSpecimenByPatient(id string) (map[string]interface{}, error) {
var data map[string]interface{}
url := s.akses.BaseUrl + "/Specimen?subject=" + id
method := "GET"
client := &http.Client{}
request, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
OauthInterface := NewOauthRequestRepo(s.akses)
token, err := OauthInterface.GenerateToken(oauth)
if err != nil {
return nil, err
}
if token != nil {
request.Header.Set("Authorization", "Bearer "+token.AccessToken)
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
err = json.NewDecoder(response.Body).Decode(&data)
if err != nil {
return nil, err
}
return data, nil
}
// isOperationOutcomeError returns true when the response is an OperationOutcome
// with at least one issue that includes diagnostics or details.text.
func isOperationOutcomeError(resp map[string]interface{}) bool {
if resp == nil {
return false
}
if rt, ok := resp["resourceType"].(string); !ok || rt != "OperationOutcome" {
return false
}
issues, ok := resp["issue"].([]interface{})
if !ok || len(issues) == 0 {
return false
}
for _, it := range issues {
if m, ok := it.(map[string]interface{}); ok {
if diag, ok := m["diagnostics"].(string); ok && diag != "" {
return true
}
if details, ok := m["details"].(map[string]interface{}); ok {
if txt, ok := details["text"].(string); ok && txt != "" {
return true
}
}
}
}
return false
}
func (s *SpecimenRepository) setupServiceRequest(req *model.SpecimenRequest, patient string) error {
if patient == "" {
return nil
}
serviceReq := NewServiceRequestRepository(s.akses)
ids, _, err := serviceReq.HandleCheckServiceRequest(patient)
if err != nil {
return err
}
if len(ids) > 0 {
req.Request = []model.Reference{
{
Reference: "ServiceRequest/" + ids[0],
},
}
}
return nil
}
// HandleCheckSpecimen implements SpecimenInterface.
func (s *SpecimenRepository) HandleCheckSpecimen(id string) ([]string, bool, error) {
specimen, err := s.GetSpecimenByPatient(id)
if err != nil {
return nil, false, err
}
// You can process 'specimen' here if needed
var ids []string
if entries, ok := specimen["entry"].([]interface{}); ok && len(entries) != 0 {
if entries, ok := (specimen)["entry"].([]interface{}); ok && len(entries) > 0 {
if entryMap, ok := entries[0].(map[string]interface{}); ok {
if resource, ok := entryMap["resource"].(map[string]interface{}); ok {
if id, ok := resource["id"].(string); ok {
//fmt.Println("resource.id:", id)
ids = append(ids, id)
return ids, true, nil
}
}
}
}
return nil, true, nil
}
return nil, false, nil
}
func (s *SpecimenRepository) UpdateSpecimen(req model.SpecimenRequest) (map[string]interface{}, error) {
req.ResourceType = constant.SpecimenResourceType
// Setup Patient
var patient string
if req.Subject.Reference != "" {
patientInterface := NewPatientRepo(s.akses)
var err error
patient, err = patientInterface.HandleCheckPatient(req.Subject.Reference)
if err != nil {
return nil, err
}
if patient == "" { // Belum ada di satu sehat
return nil, errors.New("patient not found")
} else {
req.Subject.Reference = "Patient/" + patient
}
}
// Setup Service Request
err := s.setupServiceRequest(&req, patient)
if err != nil {
return nil, err
}
oauth := model.OauthRequest{
ClientId: s.akses.ClientId,
ClientSecret: s.akses.ClientSecret,
}
token, err := NewOauthRequestRepo(s.akses).GenerateToken(oauth)
if err != nil {
return nil, err
}
if token == nil {
return nil, errors.New(constant.ErrGenerateToken)
}
url := s.akses.BaseUrl + fmt.Sprintf("/Specimen/%s", req.Id)
return httputil.DoRequest(httputil.RequestOption{
Method: "PUT",
URL: url,
Body: req,
BearerToken: token.AccessToken,
})
}
func NewSpecimenRepository(akses *model.Akses) SpecimenInterface {
return &SpecimenRepository{akses: akses}
}

View File

@@ -0,0 +1,4 @@
package midleware
type AuthMiddleware struct {
}

View File

@@ -0,0 +1,71 @@
package model
type AllergancyToleranRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []*IdentifierObject `json:"identifier"`
ClinicalStatus *ClinicalStatusObject `json:"clinicalStatus"`
VerificationStatus *ClinicalStatusObject `json:"verificationStatus"`
Category []string `json:"category"`
Code *CodeObject `json:"code"`
Patient *PatientObject `json:"patient"`
Encounter *PatientObject `json:"encounter"`
RecordedDate string `json:"recordedDate"`
Recorder *PatientObject `json:"recorder"`
}
type AllergancyToleranResponse struct {
ResourceType string `json:"resourceType"`
Identifier []*IdentifierObject `json:"identifier"`
ClinicalStatus *ClinicalStatusObject `json:"clinicalStatus"`
VerificationStatus *ClinicalStatusObject `json:"verificationStatus"`
Category []string `json:"category"`
Code *CodeObject `json:"code"`
Patient *PatientObject `json:"patient"`
Encounter *PatientObject `json:"encounter"`
RecordedDate string `json:"recordedDate"`
Recorder *PatientObject `json:"recorder"`
ID string `json:"id"`
Meta *MetaObject `json:"meta"`
Issue []*IssuerObject `json:"issue`
}
type IdentifierObject struct {
System string `json:"system"`
Use string `json:"use"`
Value string `json:"value"`
}
type ClinicalStatusObject struct {
Coding []*CodingObject `json:"coding"`
}
type CodeObject struct {
Coding []*CodingObject `json:"coding"`
Text string `json:"text"`
}
type PatientObject struct {
Reference string `json:"reference"`
Display string `json:"display"`
}
type CodingObject struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
}
type MetaObject struct {
VersionId string `json:"versionId"`
LastUpdated string `json:"lastUpdated"`
}
type IssuerObject struct {
Saverity string `json:"severity"`
Code string `json:"code"`
Details *DetailObject `json:"details"`
}
type DetailObject struct {
Text string `json:"text"`
}

View File

@@ -0,0 +1,16 @@
package model
type CarePlanRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Status string `json:"status" binding:"required"`
Intent string `json:"intent" binding:"required"`
Category []Category `json:"category" binding:"required"`
Title string `json:"title" binding:"required"`
Description string `json:"description" binding:"required"`
Subject Reference `json:"subject" binding:"required"`
Encounter Reference `json:"encounter"`
Created string `json:"created" binding:"required"`
Author Reference `json:"author" binding:"required"`
Goal []Reference `json:"goal"`
}

View File

@@ -0,0 +1,56 @@
package model
// Reference to another FHIR resource
type Reference struct {
Reference string `json:"reference"`
Display string `json:"display,omitempty"`
}
// Coding for codeable concepts
type Coding struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
}
// CodeableConcept for coded fields
type CodeableConcept struct {
Coding []Coding `json:"coding"`
Text string `json:"text,omitempty"`
}
// Investigation item reference
type InvestigationItem struct {
Reference string `json:"reference"`
}
// Investigation structure
type Investigation struct {
Code CodeableConcept `json:"code"`
Item []InvestigationItem `json:"item"`
}
// Finding structure
type Finding struct {
ItemCodeableConcept *CodeableConcept `json:"itemCodeableConcept,omitempty"`
ItemReference *Reference `json:"itemReference,omitempty"`
}
// ClinicalImpressionRequest for the request body
type ClinicalImpressionRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status"`
Description string `json:"description"`
Subject Reference `json:"subject"`
Encounter Reference `json:"encounter"`
EffectiveDateTime string `json:"effectiveDateTime"`
Date string `json:"date"`
Assessor Reference `json:"assessor"`
Problem []Reference `json:"problem"`
Investigation []Investigation `json:"investigation"`
Summary string `json:"summary"`
Finding []Finding `json:"finding"`
PrognosisCodeableConcept []CodeableConcept `json:"prognosisCodeableConcept"`
}

View File

@@ -0,0 +1,40 @@
package model
type CompositionRequest struct {
ResourceType string `json:"resourceType"`
Identifier Identifier `json:"identifier"`
Status string `json:"status"`
Category []CodeableConcept `json:"category"`
Type CodeableConcept `json:"type"`
Subject Reference `json:"subject"`
Date string `json:"date"`
Title string `json:"title"`
Author []Reference `json:"author"`
Custodian Reference `json:"custodian"`
Encounter Reference `json:"encounter"`
Section []SectionRequest `json:"section"`
Id string `json:"id,omitempty"`
Anamnesis string `json:"anamnesis,omitempty"`
PemeriksaanFisik string `json:"pemeriksaanFisik,omitempty"`
PemeriksaanPenunjang string `json:"pemeriksaanPenunjang,omitempty"`
Medikamentosa string `json:"medikamentosa,omitempty"`
LanjutanPenatalaksanaan string `json:"lanjutanPenatalaksanaan,omitempty"`
}
type SectionRequest struct {
Title string `json:"title,omitempty"`
Code CodeableConcept `json:"code"`
Text *SectionText `json:"text,omitempty"`
Entry []Reference `json:"entry,omitempty"`
Section []SectionRequest `json:"section,omitempty"`
}
type Section struct {
Code CodeableConcept `json:"code"`
Text SectionText `json:"text"`
}
type SectionText struct {
Status string `json:"status"`
Div string `json:"div"`
}

View File

@@ -0,0 +1,11 @@
package model
type ConditionRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
ClinicalStatus CodeableConcept `json:"clinicalStatus"`
Category []CodeableConcept `json:"category"`
Code CodeableConcept `json:"code"`
Subject Reference `json:"subject"`
Encounter Reference `json:"encounter"`
}

View File

@@ -0,0 +1,20 @@
package model
// DiagnosticReportRequest defines the structure for a diagnostic report request
type DiagnosticReportRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status"`
Category []CodeableConcept `json:"category"`
Code CodeableConcept `json:"code"`
Subject Reference `json:"subject"`
Encounter Reference `json:"encounter"`
EffectiveDateTime string `json:"effectiveDateTime"`
Issued string `json:"issued"`
Performer []Reference `json:"performer"`
Result []Reference `json:"result"`
Specimen []Reference `json:"specimen"`
BasedOn []Reference `json:"basedOn"`
ConclusionCode []CodeableConcept `json:"conclusionCode"`
}

View File

@@ -0,0 +1,82 @@
package model
type EncounterRequest struct {
ResourceType string `json:"resourceType"`
Status string `json:"status"`
Class Class `json:"class"`
Subject Subject `json:"subject"`
Participant []Participant `json:"participant"`
Period struct {
Start string `json:"start"`
} `json:"end"`
Location []Location `json:"location"`
StatusHistory []StatusHistory `json:"statusHistory"`
ServiceProvider struct {
Reference string `json:"reference"`
} `json:"serviceProvider"`
Identifier []IdentifierEncounter `json:"identifier"`
}
type Class struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
}
type Subject struct {
Reference string `json:"reference"`
Display string `json:"display"`
}
type Participant struct {
Type []struct {
Coding []Class `json:"coding"`
} `json:"type"`
Individual Subject `json:"individual"`
}
type Location struct {
Location Reference `json:"location"`
}
type StatusHistory struct {
Status string `json:"status"`
Period struct {
Start string `json:"start"`
} `json:"period"`
}
type EncounterUpdateRequest struct {
ResourceType string `json:"resourceType"`
ID string `json:"id"`
Status string `json:"status"`
Class Class `json:"class"`
Subject Subject `json:"subject"`
Participant []Participant `json:"participant"`
Period Period `json:"period"`
Location []Location `json:"location"`
StatusHistory []StatusHistory `json:"statusHistory"`
ServiceProvider struct {
Reference string `json:"reference"`
} `json:"serviceProvider"`
Identifier []IdentifierEncounter `json:"identifier"`
Hospitalization Hospitalization `json:"hospitalization"`
Diagnosis []DiagnosisEncounter `json:"diagnosis"`
}
type Hospitalization struct {
DischargeDisposition struct {
Coding []Class `json:"coding"`
Text string `json:"text"`
} `json:"dischargeDisposition"`
}
type DiagnosisEncounter struct {
Condition Reference `json:"condition"`
Use Type `json:"use"`
Rank int `json:"rank"`
}
type IdentifierEncounter struct {
System string `json:"system"`
Value string `json:"value"`
}

View File

@@ -0,0 +1,30 @@
package model
type EpisodeOfCareRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status"`
StatusHistory []StatusHistory `json:"statusHistory,omitempty"`
Type []Type `json:"type"`
Diagnosis []Diagnosis `json:"diagnosis"`
Patient Reference `json:"patient"`
ManagingOrganization Reference `json:"managingOrganization"`
Period Period `json:"period"`
CareManager Reference `json:"careManager"`
}
type Period struct {
Start string `json:"start"`
End string `json:"end"`
}
type Type struct {
Coding []Coding `json:"coding"`
}
type Diagnosis struct {
Condition Reference `json:"condition"`
Role Type `json:"role,omitempty"`
Rank int `json:"rank,omitempty"`
}

20
internal/model/goal.go Normal file
View File

@@ -0,0 +1,20 @@
package model
type GoalRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
LifecycleStatus string `json:"lifecycleStatus"`
Category []Category `json:"category,omitempty"`
Description Category `json:"description"`
Subject Reference `json:"subject"`
Target []GoalTarget `json:"target,omitempty"`
StatusDate string `json:"statusDate,omitempty"`
ExpressedBy Reference `json:"expressedBy,omitempty"`
Addresses []Reference `json:"addresses,omitempty"`
}
type GoalTarget struct {
Measure Category `json:"measure,omitempty"`
DetailCodeableConcept Category `json:"detailCodeableConcept,omitempty"`
DueDate string `json:"dueDate,omitempty"`
}

View File

@@ -0,0 +1,31 @@
package model
type ImagingStudyRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier" binding:"required"`
Status string `json:"status" binding:"required"`
Modality []Coding `json:"modality"`
Subject Reference `json:"subject" binding:"required"`
Started string `json:"started" binding:"required"`
BasedOn []Reference `json:"basedOn"` //binding:"required"
NumberOfSeries int `json:"numberOfSeries,omitempty"`
NumberOfInstances int `json:"numberOfInstances,omitempty"`
Series []ImagingStudySeries `json:"series,omitempty"` //binding:"required"
}
type ImagingStudySeries struct {
UID string `json:"uid"`
Number int `json:"number"`
Modality Coding `json:"modality"`
NumberOfInstances int `json:"numberOfInstances"`
Started string `json:"started"`
Instance []ImagingStudySeriesInstance `json:"instance"`
}
type ImagingStudySeriesInstance struct {
UID string `json:"uid"`
SOPClass Coding `json:"sopClass"`
Number int `json:"number"`
Title string `json:"title"`
}

View File

@@ -0,0 +1,30 @@
package model
type ImmunizationRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Status string `json:"status" binding:"required"`
VaccineCode CodeableConcept `json:"vaccineCode" binding:"required"`
Patient Reference `json:"patient" binding:"required"`
Encounter Reference `json:"encounter"`
OccurrenceDateTime string `json:"occurrenceDateTime" binding:"required"`
ExpirationDate string `json:"expirationDate" binding:"required"`
Recorded string `json:"recorded" binding:"required"`
PrimarySource bool `json:"primarySource"`
Location Reference `json:"location" binding:"required"`
LotNumber string `json:"lotNumber" binding:"required"`
Route CodeableConcept `json:"route" binding:"required"`
DoseQuantity Quantity `json:"doseQuantity" binding:"required"`
Performer []Performers `json:"performer" binding:"required"`
ReasonCode []CodeableConcept `json:"reasonCode" binding:"required"`
ProtocolApplied []ProtocolApplied `json:"protocolApplied" binding:"required"`
}
type Performers struct {
Function CodeableConcept `json:"function"`
Actor Reference `json:"actor"`
}
type ProtocolApplied struct {
DoseNumberPositiveInt int `json:"doseNumberPositiveInt"`
}

View File

@@ -0,0 +1,46 @@
package model
type MedicationDispenseRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status" binding:"required"`
Category Category `json:"category"`
MedicationReference Reference `json:"medicationReference" binding:"required"`
Subject Reference `json:"subject" binding:"required"`
Context Reference `json:"context"`
Performer []Performer `json:"performer"`
Location Reference `json:"location" binding:"required"`
AuthorizingPrescription []Reference `json:"authorizingPrescription" binding:"required"`
Quantity Quantity `json:"quantity" binding:"required"`
DaysSupply DaysSupply `json:"daysSupply" binding:"required"`
WhenPrepared string `json:"whenPrepared" binding:"required"`
WhenHandedOver string `json:"whenHandedOver" binding:"required"`
DosageInstruction []Dosage `json:"dosageInstruction"`
}
type DaysSupply struct {
Value float64 `json:"value"`
Unit string `json:"unit"`
System string `json:"system"`
Code string `json:"code"`
}
type Dosage struct {
Sequence *int `json:"sequence,omitempty"`
Text string `json:"text"`
Timing Timing `json:"timing"`
DoseAndRate []DoseAndRate `json:"doseAndRate,omitempty"`
}
type DoseAndRate struct {
Type Category `json:"type"`
DoseQuantity DoseQuantity `json:"doseQuantity"`
}
type DoseQuantity struct {
Value float64 `json:"value"`
Unit string `json:"unit"`
System string `json:"system"`
Code string `json:"code"`
}

View File

@@ -0,0 +1,44 @@
package model
type MedicationRequestRequest struct {
Id string `json:"id,omitempty"`
MedicationRequest *MedicationRequest `json:"medicationRequest,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status" binding:"required"`
Intent string `json:"intent" binding:"required"`
Category []Category `json:"category"`
Priority string `json:"priority" binding:"required"`
MedicationReference Reference `json:"medicationReference" binding:"required"`
Subject Reference `json:"subject" binding:"required"`
Encounter Reference `json:"encounter"`
AuthoredOn string `json:"authoredOn"`
Requester Reference `json:"requester"`
ReasonCode []Category `json:"reasonCode"`
CourseOfTherapyType Category `json:"courseOfTherapyType"`
DosageInstruction []DosageMR `json:"dosageInstruction"`
DispenseRequest DispenseRequest `json:"dispenseRequest" binding:"required"`
}
type DosageMR struct {
Sequence int `json:"sequence"`
Text string `json:"text"`
AdditionalInstruction []AdditionalText `json:"additionalInstruction,omitempty"`
PatientInstruction string `json:"patientInstruction,omitempty"`
Timing Timing `json:"timing"`
Route Category `json:"route,omitempty"`
DoseAndRate []DoseAndRate `json:"doseAndRate,omitempty"`
}
type AdditionalText struct {
Text string `json:"text"`
}
type DispenseRequest struct {
DispenseInterval Quantity `json:"dispenseInterval"`
ValidityPeriod Period `json:"validityPeriod"`
NumberOfRepeatsAllowed int `json:"numberOfRepeatsAllowed"`
Quantity Quantity `json:"quantity"`
ExpectedSupplyDuration Quantity `json:"expectedSupplyDuration"`
Performer Reference `json:"performer"`
}

View File

@@ -0,0 +1,60 @@
package model
type MedicationStatementRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Contained []Medication `json:"contained" binding:"required"`
Status string `json:"status" binding:"required"`
Category Category `json:"category"`
MedicationReference Reference `json:"medicationReference" binding:"required"`
Subject Reference `json:"subject" binding:"required"`
Dosage []Dosage `json:"dosage"`
EffectiveDateTime string `json:"effectiveDateTime" binding:"required"`
DateAsserted string `json:"dateAsserted" binding:"required"`
InformationSource Reference `json:"informationSource" binding:"required"`
Context Reference `json:"context"`
}
type Medication struct {
Code CodeableConcept `json:"code"`
Extension []MedicationExtension `json:"extension"`
Form CodeableConcept `json:"form"`
ID string `json:"id"`
Identifier []Identifier `json:"identifier"`
Ingredient []MedicationIngredient `json:"ingredient"`
Batch MedicationBatch `json:"batch"`
Meta Meta `json:"meta"`
ResourceType string `json:"resourceType"`
Status string `json:"status"`
}
type MedicationExtension struct {
URL string `json:"url"`
ValueCodeableConcept CodeableConcept `json:"valueCodeableConcept"`
}
type MedicationIngredient struct {
IsActive bool `json:"isActive"`
ItemCodeableConcept CodeableConcept `json:"itemCodeableConcept"`
Strength MedicationStrength `json:"strength"`
}
type MedicationStrength struct {
Denominator Quantity `json:"denominator"`
Numerator Quantity `json:"numerator"`
}
type MedicationBatch struct {
LotNumber string `json:"lotNumber"`
ExpirationDate string `json:"expirationDate"`
}
type Timing struct {
Repeat TimingRepeat `json:"repeat"`
}
type TimingRepeat struct {
Frequency int `json:"frequency"`
Period float64 `json:"period"`
PeriodUnit string `json:"periodUnit"`
}

View File

@@ -0,0 +1,33 @@
package model
type MedicineKfaRequest struct {
Page int `form:"page"`
Size int `form:"size"`
ProdustType string `form:"product_type"`
Keyword string `form:"keyword"`
}
type MedicineKfaResponse struct {
Name string `json:"name"`
KfaCode string `json:"kfa_code"`
}
type MedicationRequest struct {
ResourceType string `json:"resourceType"`
Meta Meta `json:"meta"`
Identifier []Identifier `json:"identifier"`
Code CodeableConcept `json:"code"`
Status string `json:"status"`
Manufacturer Reference `json:"manufacturer"`
Form CodeableConcept `json:"form"`
Extension []ExtensionMedication `json:"extension"`
}
type ExtensionMedication struct {
URL string `json:"url"`
ValueCodeableConcept CodeableConcept `json:"valueCodeableConcept"`
}
// Shared types Meta, Identifier, Coding, CodeableConcept, Reference, and Extension
// are defined in other model files (e.g. patient.go and clinicalImpression.go).
// This file intentionally references those types to avoid redeclaration.

View File

@@ -0,0 +1,23 @@
package model
type OauthRequest struct {
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
}
type OauthResponse struct {
RefreshTokenExpiresIn string `json:"refresh_token_expires_in"`
APIProductList string `json:"api_product_list"`
APIProductListJson []string `json:"api_product_list_json"`
OrganizationName string `json:"organization_name"`
DeveloperEmail string `json:"developer.email"`
TokenType string `json:"token_type"`
IssuedAt string `json:"issued_at"`
ClientID string `json:"client_id"`
AccessToken string `json:"access_token"`
ApplicationName string `json:"application_name"`
Scope string `json:"scope"`
ExpiresIn string `json:"expires_in"`
RefreshCount string `json:"refresh_count"`
Status string `json:"status"`
}

View File

@@ -0,0 +1,24 @@
package model
type Quantity struct {
Value float64 `json:"value"`
Unit string `json:"unit"`
System string `json:"system"`
Code string `json:"code"`
}
type ObservationRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Status string `json:"status"`
Category []CodeableConcept `json:"category"`
Code CodeableConcept `json:"code"`
Subject Reference `json:"subject"`
Performer []Reference `json:"performer"`
Specimen *Reference `json:"specimen,omitempty"`
BasedOn []Reference `json:"basedOn"`
Encounter Reference `json:"encounter"`
EffectiveDateTime string `json:"effectiveDateTime"`
Issued string `json:"issued"`
ValueQuantity *Quantity `json:"valueQuantity,omitempty"`
}

View File

@@ -0,0 +1,38 @@
package model
type Telecom struct {
System string `json:"system"`
Value string `json:"value"`
Use string `json:"use"`
}
type AddressExtensionValue struct {
Url string `json:"url"`
ValueCode string `json:"valueCode,omitempty"`
}
type AddressExtension struct {
Url string `json:"url"`
Extension []AddressExtensionValue `json:"extension"`
}
type Address struct {
Use string `json:"use"`
Type string `json:"type"`
Line []string `json:"line"`
City string `json:"city"`
PostalCode string `json:"postalCode"`
Country string `json:"country"`
Extension []AddressExtension `json:"extension"`
}
type OrganizationRequest struct {
ResourceType string `json:"resourceType"`
Active bool `json:"active"`
Identifier []Identifier `json:"identifier"`
Type []CodeableConcept `json:"type"`
Name string `json:"name"`
Telecom []Telecom `json:"telecom"`
Address []Address `json:"address"`
PartOf Reference `json:"partOf"`
}

90
internal/model/patient.go Normal file
View File

@@ -0,0 +1,90 @@
package model
type PatientRequest struct {
ResourceType string `json:"resourceType"`
Meta Meta `json:"meta"`
Identifier []Identifier `json:"identifier"`
Active bool `json:"active"`
Name []HumanName `json:"name"`
Telecom []Identifier `json:"telecom"`
Gender string `json:"gender"`
BirthDate string `json:"birthDate"`
DeceasedBoolean bool `json:"deceasedBoolean"`
Address []AddressObject `json:"address"`
MaritalStatus MaritalStatus `json:"maritalStatus"`
MultipleBirthInteger int `json:"multipleBirthInteger"`
Contact []ContactObject `json:"contact"`
Communication []CommunicationObject `json:"communication"`
Extension []Extension `json:"extension"`
}
type Meta struct {
Profile []string `json:"profile"`
}
type Identifier struct {
Use string `json:"use,omitempty"`
Type *CodeableConcept `json:"type,omitempty"`
System string `json:"system,omitempty"`
Value string `json:"value"`
}
type HumanName struct {
Use string `json:"use"`
Text string `json:"text"`
}
type AddressObject struct {
Use string `json:"use"`
Line []string `json:"line"`
City string `json:"city"`
PostalCode string `json:"postalCode"`
Country string `json:"country"`
Extension []ExtensionObject `json:"extension"`
}
type Extension struct {
URL string `json:"url"`
Extension []struct {
URL string `json:"url"`
ValueCode string `json:"valueCode"`
} `json:"extension"`
}
type MaritalStatus struct {
Coding []struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
} `json:"coding"`
Text string `json:"text"`
}
type ContactObject struct {
Relationship []struct {
Coding []struct {
System string `json:"system"`
Code string `json:"code"`
} `json:"coding"`
}
Name HumanName `json:"name"`
Telecom []Identifier `json:"telecom"`
}
type CommunicationObject struct {
Language struct {
Coding []struct {
System string `json:"system"`
Code string `json:"code"`
Display string `json:"display"`
} `json:"coding"`
Text string `json:"text"`
} `json:"language"`
Preferred bool `json:"preferred"`
}
type ExtensionObject struct {
URL string `json:"url"`
ValueCode *string `json:"valueCode"`
ValueAddress *struct {
Country string `json:"country"`
City string `json:"city"`
} `json:"valueAddress"`
}

View File

@@ -0,0 +1 @@
package model

View File

@@ -0,0 +1,24 @@
package model
type ProcedureRequest struct {
ID string `json:"id"`
ResourceType string `json:"resourceType"`
Status string `json:"status"`
Category CodeableConcept `json:"category"`
Code CodeableConcept `json:"code"`
Subject Reference `json:"subject"`
Encounter Reference `json:"encounter"`
PerformedPeriod Period `json:"performedPeriod"`
Performer []Performer `json:"performer"`
ReasonCode []CodeableConcept `json:"reasonCode"`
BodySite []CodeableConcept `json:"bodySite"`
Note []Annotation `json:"note"`
}
type Performer struct {
Actor Reference `json:"actor"`
}
type Annotation struct {
Text string `json:"text"`
}

View File

@@ -0,0 +1,24 @@
package model
type QuestionnaireResponseRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Questionnaire string `json:"questionnaire" binding:"required"`
Status string `json:"status" binding:"required"`
Subject Reference `json:"subject" binding:"required"`
Encounter Reference `json:"encounter"`
Authored string `json:"authored" binding:"required"`
Author Reference `json:"author" binding:"required"`
Source Reference `json:"source" binding:"required"`
Item []QRItem `json:"item" binding:"required"`
}
type QRItem struct {
LinkID string `json:"linkId"`
Text string `json:"text"`
Answer []QRAnswer `json:"answer"`
}
type QRAnswer struct {
ValueCoding Coding `json:"valueCoding"`
}

View File

@@ -0,0 +1,10 @@
package model
type Akses struct {
AuthUrl string
BaseUrl string
ConsentUrl string
KfaUrl string
ClientId string
ClientSecret string
}

View File

@@ -0,0 +1,40 @@
package model
type ServiceRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status"`
Intent string `json:"intent"`
Priority string `json:"priority"`
Category []Category `json:"category"`
Code Code `json:"code"`
Subject Reference `json:"subject"`
Encounter Reference `json:"encounter"`
OccurrenceDateTime string `json:"occurrenceDateTime"`
AuthoredOn string `json:"authoredOn"`
Requester Reference `json:"requester"`
Performer []Reference `json:"performer"`
ReasonCode []ReasonCode `json:"reasonCode"`
LocationCode []LocationCode `json:"locationCode"`
LocationReference []Reference `json:"locationReference"`
PatientInstruction string `json:"patientInstruction"`
}
type Category struct {
Coding []Coding `json:"coding"`
}
type Code struct {
Coding []Coding `json:"coding"`
Text string `json:"text"`
}
type ReasonCode struct {
Coding []Coding `json:"coding"`
Text string `json:"text"`
}
type LocationCode struct {
Coding []Coding `json:"coding"`
}

View File

@@ -0,0 +1,33 @@
package model
type SpecimenRequest struct {
Id string `json:"id,omitempty"`
ResourceType string `json:"resourceType"`
Identifier []Identifier `json:"identifier"`
Status string `json:"status"`
Type SpecimenType `json:"type"`
Collection SpecimenCollection `json:"collection"`
Subject Reference `json:"subject"`
Request []Reference `json:"request"`
ReceivedTime string `json:"receivedTime"`
Extension []SpecimenExtension `json:"extension"`
}
type SpecimenType struct {
Coding []Coding `json:"coding"`
}
type SpecimenCollection struct {
CollectedDateTime string `json:"collectedDateTime"`
Extension []SpecimenCollectionExtension `json:"extension"`
}
type SpecimenCollectionExtension struct {
URL string `json:"url"`
ValueReference Reference `json:"valueReference"`
}
type SpecimenExtension struct {
URL string `json:"url"`
ValueDateTime string `json:"valueDateTime,omitempty"`
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func AllergancyToleran(e *gin.Engine, allergancyToleranHandler *handler.AllergancyToleranHandler, m midleware.AuthMiddleware) {
r := e.Group("AllergyIntolerance")
r.POST("/", allergancyToleranHandler.CreateAllergancyToleran)
r.PUT("/:id", allergancyToleranHandler.UpdateAllergancyToleran)
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func CarePlan(e *gin.Engine, cphandler *handler.CarePlanHandler, m midleware.AuthMiddleware) {
r := e.Group("CarePlan")
r.POST("/", cphandler.CreateCarePlan)
r.PUT("/:id", cphandler.UpdateCarePlan)
}

View File

@@ -0,0 +1,15 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func ClinicalImpression(e *gin.Engine, clinicalImpressionHandler *handler.ClinicalImpressionHandler, m midleware.AuthMiddleware) {
r := e.Group("ClinicalImpression")
r.POST("/", clinicalImpressionHandler.CreateClinicalImpression)
r.PUT("/:id", clinicalImpressionHandler.UpdateClinicalImpression)
// Add more routes as needed
}

View File

@@ -0,0 +1,13 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func Composition(r *gin.Engine, h *handler.CompositionHandler, m midleware.AuthMiddleware) {
r.POST("/compositions/", h.CreateComposition)
r.PUT("/compositions/:id", h.UpdateComposition)
}

View File

@@ -0,0 +1,16 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func Condition(e *gin.Engine, conditionHandler *handler.ConditionHandler, m midleware.AuthMiddleware) {
r := e.Group("Condition")
r.POST("/", conditionHandler.CreateCondition)
r.GET("/", conditionHandler.GetConditionByPatient)
r.PUT("/:id", conditionHandler.UpdateCondition)
// Add more routes as needed
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func DiagnosisReport(e *gin.Engine, h *handler.DiagnosisReportHandler, m midleware.AuthMiddleware) {
group := e.Group("/diagnosis-report")
group.POST("/", h.CreateDiagnosisReport)
group.PUT("/:id", h.UpdateDiagnosisReport)
}

View File

@@ -0,0 +1,15 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func Encounter(e *gin.Engine, encounterHandler *handler.EncounterHandler, m midleware.AuthMiddleware) {
r := e.Group("Encounter")
r.POST("/", encounterHandler.CreateEncounter)
r.GET("/", encounterHandler.GetEncounterByPatient)
r.PUT("/:id", encounterHandler.UpdateEncounter)
}

View File

@@ -0,0 +1,15 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func EpisodeOfCare(e *gin.Engine, episodeOfCareHandler *handler.EpisodeOfCareHandler, m midleware.AuthMiddleware) {
r := e.Group("EpisodeOfCare")
r.POST("/", episodeOfCareHandler.CreateEpisodeOfCare)
r.GET("/", episodeOfCareHandler.GetEpisodeOfCareByPatient)
r.PUT("/:id", episodeOfCareHandler.UpdateEpisodeOfCare)
}

14
internal/routes/goal.go Normal file
View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func Goal(e *gin.Engine, cphandler *handler.GoalHandler, m midleware.AuthMiddleware) {
r := e.Group("Goal")
r.POST("/", cphandler.CreateGoal)
r.PUT("/:id", cphandler.UpdateGoal)
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func ImagingStudy(e *gin.Engine, handler *handler.ImagingStudyHandler, m midleware.AuthMiddleware) {
r := e.Group("ImagingStudy")
r.POST("/", handler.CreateImagingStudy)
r.PUT("/:id", handler.UpdateImagingStudy)
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func Immunization(e *gin.Engine, cphandler *handler.ImmunizationHandler, m midleware.AuthMiddleware) {
r := e.Group("Immunization")
r.POST("/", cphandler.CreateImmunization)
r.PUT("/:id", cphandler.UpdateImmunization)
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func MedicationDispense(e *gin.Engine, cphandler *handler.MedicationDispenseHandler, m midleware.AuthMiddleware) {
r := e.Group("MedicationDispense")
r.POST("/", cphandler.CreateMedicationDispense)
r.PUT("/:id", cphandler.UpdateMedicationDispense)
}

View File

@@ -0,0 +1,14 @@
package routes
import (
"satusehat-rssa/internal/handler"
"satusehat-rssa/internal/midleware"
"github.com/gin-gonic/gin"
)
func MedicationRequest(e *gin.Engine, cphandler *handler.MedicationRequestHandler, m midleware.AuthMiddleware) {
r := e.Group("MedicationRequest")
r.POST("/", cphandler.CreateMedicationRequest)
r.PUT("/:id", cphandler.UpdateMedicationRequest)
}

Some files were not shown because too many files have changed in this diff Show More