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 }