123 lines
4.3 KiB
Go
123 lines
4.3 KiB
Go
package encounter
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"service/internal/interfaces/satusehat"
|
|
"service/pkg/errors"
|
|
)
|
|
|
|
type Service interface {
|
|
Create(ctx context.Context, req EncounterRequest) (*satusehat.FHIRResponse, error)
|
|
Update(ctx context.Context, id string, req EncounterRequest) (*satusehat.FHIRResponse, error)
|
|
Patch(ctx context.Context, id string, req EncounterPatchRequest) (*satusehat.FHIRResponse, error)
|
|
GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error)
|
|
Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error)
|
|
SyncFromSIMRS(ctx context.Context, idxdaftar int64) (*satusehat.FHIRResponse, error)
|
|
}
|
|
|
|
type service struct {
|
|
repo Repository
|
|
}
|
|
|
|
func NewService(repo Repository) Service {
|
|
return &service{repo: repo}
|
|
}
|
|
|
|
func (s *service) Create(ctx context.Context, req EncounterRequest) (*satusehat.FHIRResponse, error) {
|
|
fhirPayload := MapRequestToFHIR(req)
|
|
return s.repo.Create(ctx, fhirPayload)
|
|
}
|
|
|
|
func (s *service) Update(ctx context.Context, id string, req EncounterRequest) (*satusehat.FHIRResponse, error) {
|
|
if id == "" {
|
|
return nil, errors.NewValidationError().Message("Encounter ID is required").Build()
|
|
}
|
|
|
|
fhirPayload := MapRequestToFHIR(req)
|
|
fhirPayload.Set("id", id) // Untuk Update (PUT), parameter ID di payload diwajibkan oleh standar API Kemenkes
|
|
|
|
return s.repo.Update(ctx, id, fhirPayload)
|
|
}
|
|
|
|
func (s *service) Patch(ctx context.Context, id string, req EncounterPatchRequest) (*satusehat.FHIRResponse, error) {
|
|
if id == "" {
|
|
return nil, errors.NewValidationError().Message("Encounter ID is required").Build()
|
|
}
|
|
if len(req) == 0 {
|
|
return nil, errors.NewValidationError().Message("Patch payload cannot be empty").Build()
|
|
}
|
|
return s.repo.Patch(ctx, id, req)
|
|
}
|
|
|
|
func (s *service) GetByID(ctx context.Context, id string) (*satusehat.FHIRResponse, error) {
|
|
if id == "" {
|
|
return nil, errors.NewValidationError().Message("Encounter ID is required").Build()
|
|
}
|
|
return s.repo.GetByID(ctx, id)
|
|
}
|
|
|
|
func (s *service) Search(ctx context.Context, queryParams url.Values) (*satusehat.FHIRResponse, error) {
|
|
// Bisa ditambahkan validasi query params wajib di sini jika perlu
|
|
return s.repo.Search(ctx, queryParams)
|
|
}
|
|
|
|
func (s *service) SyncFromSIMRS(ctx context.Context, idxdaftar int64) (*satusehat.FHIRResponse, error) {
|
|
// 1. Ambil data dari database SIMRS
|
|
pendaftaran, err := s.repo.GetPendaftaranByID(ctx, idxdaftar)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("gagal mengambil data pendaftaran: %w", err)
|
|
}
|
|
|
|
// 2. Ambil Organization ID RS Anda (Bisa dari environment variable atau parameter config)
|
|
orgID := os.Getenv("SATUSEHAT_ORGANIZATION_ID") // Sesuaikan bila ada package config terpisah
|
|
|
|
// 3. Persiapkan Patient ID (IHS) dengan fallback pencarian ke NIK
|
|
patientIHS := pendaftaran.PatientIHS.String
|
|
if patientIHS == "" && pendaftaran.PasienNIK.Valid && pendaftaran.PasienNIK.String != "" {
|
|
resp, err := s.repo.SearchPatientByNIK(ctx, pendaftaran.PasienNIK.String)
|
|
if err == nil && resp != nil {
|
|
patientIHS = extractIDFromBundle(resp.RawResponse)
|
|
}
|
|
}
|
|
if patientIHS == "" { // Fallback terakhir (jaga-jaga agar mapping tak panic)
|
|
patientIHS = pendaftaran.NoMR.String
|
|
}
|
|
|
|
// 4. Persiapkan Practitioner ID (IHS) dengan fallback pencarian ke NIK
|
|
practitionerIHS := pendaftaran.PractitionerIHS.String
|
|
if practitionerIHS == "" && pendaftaran.DokterNIK.Valid && pendaftaran.DokterNIK.String != "" {
|
|
resp, err := s.repo.SearchPractitionerByNIK(ctx, pendaftaran.DokterNIK.String)
|
|
if err == nil && resp != nil {
|
|
practitionerIHS = extractIDFromBundle(resp.RawResponse)
|
|
}
|
|
}
|
|
if practitionerIHS == "" { // Fallback terakhir
|
|
practitionerIHS = pendaftaran.DokterIDHFIS.String
|
|
}
|
|
|
|
// 5. Mapping data database ke struktur Request Encounter API
|
|
req := MapPendaftaranToRequest(*pendaftaran, orgID, patientIHS, practitionerIHS)
|
|
|
|
// 6. Proses Create/Kirim ke Satu Sehat menggunakan fungsi Create yang sudah ada
|
|
return s.Create(ctx, req)
|
|
}
|
|
|
|
// extractIDFromBundle mem-parsing raw response FHIR Bundle untuk mengambil ID resource pertama
|
|
func extractIDFromBundle(data []byte) string {
|
|
var bundle struct {
|
|
Entry []struct {
|
|
Resource struct {
|
|
ID string `json:"id"`
|
|
} `json:"resource"`
|
|
} `json:"entry"`
|
|
}
|
|
if err := json.Unmarshal(data, &bundle); err == nil && len(bundle.Entry) > 0 {
|
|
return bundle.Entry[0].Resource.ID
|
|
}
|
|
return ""
|
|
}
|