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
@@ -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,
}
}
@@ -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
}
@@ -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}
}
@@ -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,
}
}
@@ -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(),
})
}
@@ -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}
}
@@ -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(),
})
}
@@ -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,
}
}
+221
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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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,
}
}
+54
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,
}
}
@@ -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}
}
@@ -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}
}
+146
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}
}
@@ -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
}
@@ -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,
}
}
@@ -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
}
@@ -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}
}
@@ -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}
}