Files
satusehat-service/internal/worker/satusehat/encounter/repository.go
T
2026-04-14 01:23:34 +00:00

188 lines
5.8 KiB
Go

package encounter
import (
"context"
"fmt"
"service/internal/infrastructure/database"
"service/pkg/utils/query"
)
// Repository mendefinisikan kontrak akses database untuk worker encounter
type Repository interface {
GetNextPendaftaran(ctx context.Context, lastID int64) (*PendaftaranDB, error)
SaveSatuSehatID(ctx context.Context, idxdaftar int64, encounterID string) error
SaveSyncLog(ctx context.Context, logData EncounterSyncLog) error
}
type repository struct {
dbManager database.Service
}
func NewRepository(dbManager database.Service) Repository {
return &repository{dbManager: dbManager}
}
func (r *repository) GetNextPendaftaran(ctx context.Context, lastID int64) (*PendaftaranDB, error) {
var p PendaftaranDB
// 1. Ambil koneksi database SQLX SIMRS (PostgreSQL)
simrsDB, err := r.dbManager.GetSQLXDB("simrs")
if err != nil {
return nil, err
}
// Inisiasi Query Builder (Disable security check untuk penggunaan internal & static)
qb := query.NewSQLQueryBuilder(query.DBTypePostgreSQL).SetSecurityOptions(false, 0)
// 2. Ambil data Pendaftaran Utama dari SIMRS menggunakan Query Builder
qSimrs := query.DynamicQuery{
From: "public.t_pendaftaran",
Aliases: "p", // Alias untuk tabel pendaftaran
Fields: []query.SelectField{
{Expression: "p.idxdaftar"},
{Expression: "p.nomr"},
{Expression: "p.tglreg"},
{Expression: "p.kddokter"},
{Expression: "p.kdpoly"},
{Expression: "p.kdcarabayar"},
{Expression: "p.status"},
{Expression: "p.batal"},
{Expression: "p.jamreg"},
{Expression: "p.masukpoly"},
{Expression: "p.keluarpoly"},
{Expression: "m.nama"},
{Expression: "COALESCE(NULLIF(m.noktp_baru, ''), m.noktp) AS nik"},
},
Joins: []query.Join{
{
Type: "LEFT",
Table: "public.m_pasien",
Alias: "m", // Alias untuk tabel master pasien
OnConditions: query.FilterGroup{
Filters: []query.DynamicFilter{
// Relasi antar kolom: p.nomr = m.nomr
query.CreateEqualFilter("p.nomr", "m.nomr"),
},
},
},
},
Filters: []query.FilterGroup{
{
Filters: []query.DynamicFilter{
query.CreateFilter("p.idxdaftar", query.OpGreaterThan, lastID),
},
},
},
Sort: []query.SortField{
query.CreateAscSort("p.idxdaftar"),
},
Limit: 1,
}
err = qb.ExecuteQueryRow(ctx, simrsDB, qSimrs, &p)
if err != nil {
return nil, err
}
// 3. Lengkapi referensi IHS Number dari tabel master SATUDATA menggunakan Query Builder
satuDataDB, err := r.dbManager.GetSQLXDB("satudata")
if err != nil {
return nil, fmt.Errorf("gagal koneksi ke database satudata: %w", err)
}
if p.NoMR.Valid && p.NoMR.String != "" {
qPasien := query.DynamicQuery{
From: "public.data_pasien",
Fields: []query.SelectField{{Expression: "\"Nomor_satusehat\""}},
Filters: []query.FilterGroup{{Filters: []query.DynamicFilter{query.CreateEqualFilter("\"Nomor_rekamedik\"", p.NoMR.String)}}},
Limit: 1,
}
_ = qb.ExecuteQueryRow(ctx, satuDataDB, qPasien, &p.PatientIHS)
}
if p.KdDokter.Valid {
qDokter := query.DynamicQuery{
From: "public.data_pegawai",
Fields: []query.SelectField{
{Expression: "\"Kode_satusehat\"", Alias: "practitioner_ihs"},
{Expression: "nik", Alias: "practitioner_nik"}, // Sesuaikan "nik" jika nama kolom di DB Anda menggunakan huruf besar "\"NIK\""
},
Filters: []query.FilterGroup{{Filters: []query.DynamicFilter{query.CreateEqualFilter("\"Kode_DPJP\"", fmt.Sprintf("%d", p.KdDokter.Int64))}}},
Limit: 1,
}
_ = qb.ExecuteQueryRow(ctx, satuDataDB, qDokter, &p)
}
if p.KdPoly.Valid {
qPoly := query.DynamicQuery{
From: "public.daftar_lokasi_ruang",
Fields: []query.SelectField{{Expression: "\"Kode_satusehat\""}},
Filters: []query.FilterGroup{{Filters: []query.DynamicFilter{query.CreateEqualFilter("\"ID_ruang_simgos\"", fmt.Sprintf("%d", p.KdPoly.Int64))}}},
Limit: 1,
}
_ = qb.ExecuteQueryRow(ctx, satuDataDB, qPoly, &p.LocationIHS)
}
return &p, nil
}
func (r *repository) SaveSatuSehatID(ctx context.Context, idxdaftar int64, encounterID string) error {
simrsDB, err := r.dbManager.GetSQLXDB("simrs")
if err != nil {
return err
}
// Menggunakan transaksi DB
tx, err := simrsDB.BeginTxx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback() // Otomatis rollback bila gagal (atau tidak di-commit)
qb := query.NewSQLQueryBuilder(query.DBTypePostgreSQL).SetSecurityOptions(false, 0)
updateData := query.UpdateData{
Columns: []string{"status_bridging"},
Values: []interface{}{encounterID},
}
filters := []query.FilterGroup{
query.CreateAndFilterGroup([]query.DynamicFilter{query.CreateEqualFilter("idxdaftar", idxdaftar)}),
}
// Eksekusi Update via Query Builder (melempar tx, bukan db, agar terbawa ke transaksi)
_, err = qb.ExecuteUpdate(ctx, tx, "public.t_pendaftaran", updateData, filters)
if err != nil {
return err
}
// Terapkan data
return tx.Commit()
}
// SaveSyncLog menyimpan histori pengiriman (Request & Response) ke tabel log
func (r *repository) SaveSyncLog(ctx context.Context, logData EncounterSyncLog) error {
simrsDB, err := r.dbManager.GetSQLXDB("simrs")
if err != nil {
return err
}
qb := query.NewSQLQueryBuilder(query.DBTypePostgreSQL).SetSecurityOptions(false, 0)
insertData := query.InsertData{
Columns: []string{"idxdaftar", "encounter_id", "request_payload", "response_payload", "status", "error_message"},
Values: []interface{}{
logData.IdxDaftar, logData.EncounterID, logData.RequestPayload,
logData.ResponsePayload, logData.Status, logData.ErrorMessage,
},
}
// Menggunakan UPSERT (ON CONFLICT) agar jika kita mengirim ulang (resend), log otomatis diperbarui
conflictCols := []string{"idxdaftar"}
updateCols := []string{"encounter_id", "request_payload", "response_payload", "status", "error_message"}
_, err = qb.ExecuteUpsert(ctx, simrsDB, "public.log_satusehat_encounter", insertData, conflictCols, updateCols)
return err
}