Files
2026-04-22 09:11:46 +07:00

156 lines
4.4 KiB
Go

package aplicare
import (
"api-service/internal/database"
"context"
"database/sql"
"fmt"
)
type Ruangan struct {
No int `db:"no"`
Nama string `db:"nama"`
JumlahTT int `db:"jumlah_tt"`
KodeRuang sql.NullString `db:"kode_aplicare"` // diisi manual, dikirim ke BPJS
NamaRuang sql.NullString `db:"nama_ruang"` // diisi manual, dikirim ke BPJS
KelasRuang sql.NullString `db:"kode_kelas"` // diisi manual, dikirim ke BPJS
}
// BedDetail adalah data dari tabel m_detail_tempat_tidur
// Setiap row = 1 bed yang sedang terisi
// idxruang bertipe varchar di DB, relasi ke m_ruang.no (integer)
type BedDetail struct {
IdxRuang string `db:"idxruang"`
}
// =============================================
// SIMRS READER
// =============================================
type SimrsDB struct {
db database.Service
}
func NewSimrsDB(db database.Service) *SimrsDB {
return &SimrsDB{db: db}
}
// GetRuangan membaca semua ruangan aktif dari m_ruang
// Hanya ruangan yang sudah di-mapping manual (kode_ruang + kode_kelas tidak kosong)
func (s *SimrsDB) GetRuangan(ctx context.Context) ([]Ruangan, error) {
db, err := s.db.GetDB("simrs")
if err != nil {
return nil, fmt.Errorf("koneksi simrs gagal: %w", err)
}
query := `
SELECT no, nama, jumlah_tt,kode_aplicare, nama_ruang, kode_kelas
FROM m_ruang
where st_aktif = 1 AND kode_aplicare IS NOT NULL
ORDER BY no
`
rows, err := db.QueryContext(ctx, query)
if err != nil {
return nil, fmt.Errorf("query m_ruang gagal: %w", err)
}
defer rows.Close()
var result []Ruangan
for rows.Next() {
var r Ruangan
if err := rows.Scan(
&r.No, &r.Nama, &r.JumlahTT,
&r.KodeRuang, &r.NamaRuang, &r.KelasRuang,
); err != nil {
return nil, fmt.Errorf("scan m_ruang gagal: %w", err)
}
result = append(result, r)
}
return result, rows.Err()
}
// GetBedDetails membaca semua bed yang terisi dari m_detail_tempat_tidur
// Return map[idxruang][]BedDetail — dikelompokkan per ruangan
// Setiap row = 1 bed terisi, COUNT per idxruang = total terisi
func (s *SimrsDB) GetBedDetails(ctx context.Context) (map[string][]BedDetail, error) {
db, err := s.db.GetDB("simrs")
if err != nil {
return nil, fmt.Errorf("koneksi simrs gagal: %w", err)
}
query := `
SELECT idxruang
FROM m_detail_tempat_tidur
WHERE status IN (1, 5)
ORDER BY idxruang
`
rows, err := db.QueryContext(ctx, query)
if err != nil {
return nil, fmt.Errorf("query m_detail_tempat_tidur gagal: %w", err)
}
defer rows.Close()
result := make(map[string][]BedDetail)
for rows.Next() {
var d BedDetail
if err := rows.Scan(&d.IdxRuang); err != nil {
return nil, fmt.Errorf("scan m_detail_tempat_tidur gagal: %w", err)
}
result[d.IdxRuang] = append(result[d.IdxRuang], d)
}
return result, rows.Err()
}
// =============================================
// TRANSFORM
// =============================================
// BedData adalah hasil agregasi per ruangan — siap kirim ke BPJS
type BedData struct {
No int `json:"no"`
KodeKelas string `json:"kodekelas"`
KodeRuang string `json:"koderuang"`
NamaRuang string `json:"namaruang"`
Kapasitas int `json:"kapasitas"`
Tersedia int `json:"tersedia"`
TersediaPria int `json:"tersediapria"`
TersediaWanita int `json:"tersediawanita"`
TersediaPriaWanita int `json:"tersediapriawanita"`
}
// buildBedData mengubah data SIMRS menjadi BedData siap kirim ke BPJS
// tersedia = jumlah_tt - COUNT(row di m_detail per ruangan)
// karena setiap row di m_detail = 1 bed yang terisi
func buildBedData(ruangans []Ruangan, detailMap map[string][]BedDetail) []BedData {
var result []BedData
for _, r := range ruangans {
// detailMap berisi semua bed yang tidak tersedia (status != 0)
// tersedia = jumlah_tt - jumlah yang tidak tersedia
terisi := len(detailMap[fmt.Sprintf("%d", r.No)])
tersedia := r.JumlahTT - terisi
if tersedia < 0 {
tersedia = 0
}
// Skip ruangan dengan kapasitas 0 — tidak valid untuk dikirim ke BPJS
if r.JumlahTT == 0 {
continue
}
result = append(result, BedData{
No: r.No,
KodeKelas: r.KelasRuang.String,
KodeRuang: r.KodeRuang.String,
NamaRuang: r.NamaRuang.String,
Kapasitas: r.JumlahTT,
Tersedia: tersedia,
TersediaPria: 0,
TersediaWanita: 0,
TersediaPriaWanita: tersedia,
})
}
return result
}