674 lines
20 KiB
Go
674 lines
20 KiB
Go
package services
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
"time"
|
|
|
|
"backendcareit/database"
|
|
"backendcareit/models"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Ambil ID_tarif_RS dari nama Tindakan_RS
|
|
func GetTarifRSByTindakan(tindakans []string) ([]models.TarifRS, error) {
|
|
var tarifList []models.TarifRS
|
|
|
|
if err := database.DB.
|
|
Where("\"Tindakan_RS\" IN ?", tindakans).
|
|
Find(&tarifList).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return tarifList, nil
|
|
}
|
|
|
|
// GetPasienByID - Cari pasien berdasarkan ID nya
|
|
func GetPasienByID(id int) (*models.Pasien, error) {
|
|
var pasien models.Pasien
|
|
|
|
if err := database.DB.Where("\"ID_Pasien\" = ?", id).First(&pasien).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &pasien, nil
|
|
}
|
|
|
|
// GetPasienByNama - Cari pasien berdasarkan nama mereka
|
|
func GetPasienByNama(nama string) (*models.Pasien, error) {
|
|
var pasien models.Pasien
|
|
|
|
if err := database.DB.Where("\"Nama_Pasien\" = ?", nama).First(&pasien).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &pasien, nil
|
|
}
|
|
|
|
// SearchPasienByNama - Pencarian pasien pake nama (bisa partial)
|
|
func SearchPasienByNama(nama string) ([]models.Pasien, error) {
|
|
var pasien []models.Pasien
|
|
|
|
err := database.DB.
|
|
Where("\"Nama_Pasien\" LIKE ?", "%"+nama+"%").
|
|
Find(&pasien).Error
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return pasien, nil
|
|
}
|
|
|
|
// GetBillingDetailAktifByNama - Ambil data billing lengkap (billing, tindakan, ICD, dokter, INACBG, DPJP) buat satu pasien dari nama
|
|
// Return: billing, tindakan, icd9, icd10, dokter, inacbgRI, inacbgRJ, dpjp, error
|
|
func GetBillingDetailAktifByNama(namaPasien string) (*models.BillingPasien, []string, []string, []string, []string, []string, []string, int, error) {
|
|
// Cari pasien dulu
|
|
var pasien models.Pasien
|
|
if err := database.DB.Where("\"Nama_Pasien\" = ?", namaPasien).First(&pasien).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
|
|
// Cari billing aktif terakhir pasien ini (yang belum ditutup, Tanggal_Keluar IS NULL)
|
|
var billing models.BillingPasien
|
|
if err := database.DB.
|
|
Where("\"ID_Pasien\" = ? AND \"Tanggal_Keluar\" IS NULL", pasien.ID_Pasien).
|
|
Order("\"ID_Billing\" DESC").
|
|
First(&billing).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
|
|
// Ambil semua tindakan (join billing_tindakan -> tarif_rs)
|
|
var tindakanJoin []struct {
|
|
Nama string `gorm:"column:Tindakan_RS"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_tindakan\" bt").
|
|
Select("tr.\"Tindakan_RS\"").
|
|
Joins("JOIN \"tarif_rs\" tr ON bt.\"ID_Tarif_RS\" = tr.\"ID_Tarif_RS\"").
|
|
Where("bt.\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Scan(&tindakanJoin).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
tindakanNames := make([]string, 0, len(tindakanJoin))
|
|
for _, t := range tindakanJoin {
|
|
tindakanNames = append(tindakanNames, t.Nama)
|
|
}
|
|
|
|
// Ambil semua ICD9
|
|
var icd9Join []struct {
|
|
Prosedur string `gorm:"column:Prosedur"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_icd9\" bi").
|
|
Select("i.\"Prosedur\"").
|
|
Joins("JOIN \"icd9\" i ON bi.\"ID_ICD9\" = i.\"ID_ICD9\"").
|
|
Where("bi.\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Scan(&icd9Join).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
icd9Names := make([]string, 0, len(icd9Join))
|
|
for _, i := range icd9Join {
|
|
icd9Names = append(icd9Names, i.Prosedur)
|
|
}
|
|
|
|
// Ambil semua ICD10
|
|
var icd10Join []struct {
|
|
Diagnosa string `gorm:"column:Diagnosa"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_icd10\" bi").
|
|
Select("i.\"Diagnosa\"").
|
|
Joins("JOIN \"icd10\" i ON bi.\"ID_ICD10\" = i.\"ID_ICD10\"").
|
|
Where("bi.\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Scan(&icd10Join).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
icd10Names := make([]string, 0, len(icd10Join))
|
|
for _, i := range icd10Join {
|
|
icd10Names = append(icd10Names, i.Diagnosa)
|
|
}
|
|
|
|
// Ambil semua dokter dari billing_dokter dengan tanggal
|
|
var dokterJoin []struct {
|
|
Nama string `gorm:"column:Nama_Dokter"`
|
|
Tanggal *time.Time `gorm:"column:Tanggal"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_dokter\"").
|
|
Select("\"Nama_Dokter\", \"tanggal\"").
|
|
Joins("JOIN \"dokter\" ON \"billing_dokter\".\"ID_Dokter\" = \"dokter\".\"ID_Dokter\"").
|
|
Where("\"billing_dokter\".\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Order("tanggal ASC").
|
|
Scan(&dokterJoin).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
dokterNames := make([]string, 0, len(dokterJoin))
|
|
for _, d := range dokterJoin {
|
|
dokterNames = append(dokterNames, d.Nama)
|
|
}
|
|
|
|
// Ambil semua INACBG RI
|
|
var inacbgRIJoin []struct {
|
|
Kode string `gorm:"column:ID_INACBG_RI"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_inacbg_ri\"").
|
|
Select("\"ID_INACBG_RI\"").
|
|
Where("\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Scan(&inacbgRIJoin).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
inacbgRINames := make([]string, 0, len(inacbgRIJoin))
|
|
for _, row := range inacbgRIJoin {
|
|
inacbgRINames = append(inacbgRINames, row.Kode)
|
|
}
|
|
|
|
// Ambil semua INACBG RJ
|
|
var inacbgRJJoin []struct {
|
|
Kode string `gorm:"column:ID_INACBG_RJ"`
|
|
}
|
|
if err := database.DB.
|
|
Table("\"billing_inacbg_rj\"").
|
|
Select("\"ID_INACBG_RJ\"").
|
|
Where("\"ID_Billing\" = ?", billing.ID_Billing).
|
|
Scan(&inacbgRJJoin).Error; err != nil {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
inacbgRJNames := make([]string, 0, len(inacbgRJJoin))
|
|
for _, row := range inacbgRJJoin {
|
|
inacbgRJNames = append(inacbgRJNames, row.Kode)
|
|
}
|
|
|
|
// Ambil DPJP (Doctor In Charge) dari billing_dpjp
|
|
var dpjpRow struct {
|
|
ID_DPJP int `gorm:"column:ID_DPJP"`
|
|
}
|
|
var idDPJP int
|
|
if err := database.DB.
|
|
Table("\"billing_dpjp\"").
|
|
Select("\"ID_DPJP\"").
|
|
Where("\"ID_Billing\" = ?", billing.ID_Billing).
|
|
First(&dpjpRow).Error; err != nil {
|
|
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil, nil, nil, nil, nil, nil, 0, err
|
|
}
|
|
// Jika tidak ada DPJP, idDPJP = 0 (normal, boleh tidak ada)
|
|
idDPJP = 0
|
|
} else {
|
|
idDPJP = dpjpRow.ID_DPJP
|
|
}
|
|
|
|
return &billing, tindakanNames, icd9Names, icd10Names, dokterNames, inacbgRINames, inacbgRJNames, idDPJP, nil
|
|
}
|
|
|
|
// GetDokterByNama - Cari dokter berdasarkan nama mereka
|
|
func GetDokterByNama(nama string) (*models.Dokter, error) {
|
|
var dokter models.Dokter
|
|
|
|
if err := database.DB.Where("\"Nama_Dokter\" = ?", nama).First(&dokter).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &dokter, nil
|
|
}
|
|
|
|
func DataFromFE(input models.BillingRequest) (
|
|
*models.BillingPasien,
|
|
*models.Pasien,
|
|
[]models.Billing_Tindakan,
|
|
[]models.Billing_ICD9,
|
|
[]models.Billing_ICD10,
|
|
error,
|
|
) {
|
|
|
|
tx := database.DB.Begin()
|
|
if tx.Error != nil {
|
|
return nil, nil, nil, nil, nil, tx.Error
|
|
}
|
|
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
tx.Rollback()
|
|
}
|
|
}()
|
|
|
|
// ===========================
|
|
// 1. CARI ATAU BUAT PASIEN
|
|
// ===========================
|
|
var pasien models.Pasien
|
|
result := tx.Where("\"Nama_Pasien\" = ?", input.Nama_Pasien).First(&pasien)
|
|
|
|
// Jika pasien sudah ada, update data jika ada perubahan (usia, ruangan, kelas, jenis_kelamin)
|
|
if result.Error == nil {
|
|
updated := false
|
|
if pasien.Usia != input.Usia {
|
|
pasien.Usia = input.Usia
|
|
updated = true
|
|
}
|
|
if pasien.Ruangan != input.Ruangan {
|
|
pasien.Ruangan = input.Ruangan
|
|
updated = true
|
|
}
|
|
if pasien.Kelas != input.Kelas {
|
|
pasien.Kelas = input.Kelas
|
|
updated = true
|
|
}
|
|
if pasien.Jenis_Kelamin != input.Jenis_Kelamin {
|
|
pasien.Jenis_Kelamin = input.Jenis_Kelamin
|
|
updated = true
|
|
}
|
|
if updated {
|
|
if err := tx.Save(&pasien).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal update data pasien: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
pasien = models.Pasien{
|
|
Nama_Pasien: input.Nama_Pasien,
|
|
Jenis_Kelamin: input.Jenis_Kelamin,
|
|
Usia: input.Usia,
|
|
Ruangan: input.Ruangan,
|
|
Kelas: input.Kelas,
|
|
}
|
|
|
|
if err := tx.Create(&pasien).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal membuat pasien baru: %s", err.Error())
|
|
}
|
|
} else {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal mencari pasien: %s", result.Error.Error())
|
|
}
|
|
}
|
|
|
|
if pasien.ID_Pasien == 0 {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil, fmt.Errorf("ID_Pasien tidak valid")
|
|
}
|
|
|
|
// ===========================
|
|
// 2. CARI SEMUA DOKTER
|
|
// ===========================
|
|
var dokterList []models.Dokter
|
|
for _, namaDokter := range input.Nama_Dokter {
|
|
var dokter models.Dokter
|
|
if err := tx.Where("\"Nama_Dokter\" = ?", namaDokter).First(&dokter).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("dokter '%s' tidak ditemukan", namaDokter)
|
|
}
|
|
dokterList = append(dokterList, dokter)
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
// Parse Tanggal_Keluar (frontend sends string). Accept multiple formats.
|
|
var keluarPtr *time.Time
|
|
if input.Tanggal_Keluar != "" && input.Tanggal_Keluar != "null" {
|
|
s := input.Tanggal_Keluar
|
|
// Try several common layouts
|
|
var parsed time.Time
|
|
var err error
|
|
layouts := []string{time.RFC3339, "2006-01-02 15:04:05", "2006-01-02"}
|
|
for _, layout := range layouts {
|
|
parsed, err = time.Parse(layout, s)
|
|
if err == nil {
|
|
t := parsed
|
|
keluarPtr = &t
|
|
break
|
|
}
|
|
}
|
|
if keluarPtr == nil {
|
|
// If parsing failed, return error
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil, fmt.Errorf("invalid tanggal_keluar format: %s", input.Tanggal_Keluar)
|
|
}
|
|
}
|
|
|
|
// ===========================
|
|
// 3. CARI / BUAT BILLING
|
|
// ===========================
|
|
// Catatan:
|
|
// - Kita anggap "billing aktif" = billing yang belum ditutup (Tanggal_Keluar IS NULL) untuk pasien ini.
|
|
// - Jika ada billing aktif, update; jika tidak, buat billing baru.
|
|
var billing models.BillingPasien
|
|
billingResult := tx.
|
|
Where("\"ID_Pasien\" = ? AND \"Tanggal_Keluar\" IS NULL", pasien.ID_Pasien).
|
|
Order("\"ID_Billing\" DESC").
|
|
First(&billing)
|
|
|
|
if billingResult.Error != nil {
|
|
if errors.Is(billingResult.Error, gorm.ErrRecordNotFound) {
|
|
// Belum ada billing aktif → buat billing baru
|
|
billing = models.BillingPasien{
|
|
ID_Pasien: pasien.ID_Pasien,
|
|
Cara_Bayar: input.Cara_Bayar,
|
|
Tanggal_masuk: &now,
|
|
Tanggal_keluar: keluarPtr,
|
|
Total_Tarif_RS: input.Total_Tarif_RS,
|
|
Total_Klaim: input.Total_Klaim_BPJS, // ← Changed: Use input value instead of hardcoded 0
|
|
}
|
|
|
|
// jika frontend mengirim billing_sign, gunakan itu, kalau tidak gunakan default ""
|
|
if input.Billing_sign != "" {
|
|
billing.Billing_sign = input.Billing_sign
|
|
} else {
|
|
billing.Billing_sign = ""
|
|
}
|
|
|
|
if err := tx.Create(&billing).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal membuat billing: %s", err.Error())
|
|
}
|
|
} else {
|
|
// Error lain saat cari billing
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal mencari billing pasien: %s", billingResult.Error.Error())
|
|
}
|
|
} else {
|
|
// Sudah ada billing aktif → update data billing lama, tambahkan tindakan / ICD baru
|
|
billing.Cara_Bayar = input.Cara_Bayar
|
|
if keluarPtr != nil {
|
|
billing.Tanggal_keluar = keluarPtr
|
|
}
|
|
// Tambahkan total tarif dari request baru
|
|
billing.Total_Tarif_RS += input.Total_Tarif_RS
|
|
// Update Total_Tarif_BPJS if:
|
|
// 1. Not yet set (== 0), OR
|
|
// 2. Input value is higher (more accurate baseline from FE)
|
|
// This ensures we always have the correct baseline, not accumulated value from INACBG
|
|
if input.Total_Klaim_BPJS > 0 && (billing.Total_Klaim == 0 || input.Total_Klaim_BPJS > billing.Total_Klaim) {
|
|
billing.Total_Klaim = input.Total_Klaim_BPJS
|
|
log.Printf("[Billing] Updated Total_Tarif_BPJS to %.2f\n", input.Total_Klaim_BPJS)
|
|
}
|
|
|
|
// Log input billing_sign untuk debug
|
|
log.Printf("[Billing Update] Received input.Billing_sign: '%s' (empty=%v)\n", input.Billing_sign, input.Billing_sign == "")
|
|
|
|
// Jika frontend mengirim Billing_sign, gunakan; jika tidak, hitung di backend
|
|
if input.Billing_sign != "" {
|
|
billing.Billing_sign = input.Billing_sign
|
|
log.Printf("[Billing Update] Updated Billing_sign to: %s\n", input.Billing_sign)
|
|
}
|
|
|
|
if err := tx.Save(&billing).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal update billing pasien: %s", err.Error())
|
|
}
|
|
|
|
// Jika frontend mengirim Billing_sign pada update, kirim notifikasi email ke dokter secara async
|
|
|
|
}
|
|
|
|
// ===========================
|
|
// 4. SIMPAN DOKTER KE BILLING_DOKTER DENGAN TANGGAL
|
|
// ===========================
|
|
// Tidak menghapus dokter lama, hanya menambahkan dokter baru dengan tanggal hari ini
|
|
// Ini memungkinkan tracking dokter yang berbeda setiap hari
|
|
tanggalHariIni := time.Now()
|
|
|
|
// Insert semua dokter baru ke billing_dokter dengan tanggal hari ini
|
|
// Cek dulu apakah dokter dengan tanggal yang sama sudah ada (untuk menghindari duplikasi)
|
|
var billingDokterList []models.Billing_Dokter
|
|
for _, dokter := range dokterList {
|
|
// Cek apakah dokter ini sudah ada di billing dengan tanggal yang sama
|
|
var existing models.Billing_Dokter
|
|
result := tx.Where("\"ID_Billing\" = ? AND \"ID_Dokter\" = ? AND DATE(tanggal) = DATE(?)",
|
|
billing.ID_Billing, dokter.ID_Dokter, tanggalHariIni).First(&existing)
|
|
|
|
// Jika belum ada, tambahkan
|
|
if result.Error != nil && errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
billingDokter := models.Billing_Dokter{
|
|
ID_Billing: billing.ID_Billing,
|
|
ID_Dokter: dokter.ID_Dokter,
|
|
Tanggal: &tanggalHariIni,
|
|
}
|
|
billingDokterList = append(billingDokterList, billingDokter)
|
|
}
|
|
// Jika sudah ada, skip (tidak perlu insert lagi)
|
|
}
|
|
|
|
if len(billingDokterList) > 0 {
|
|
if err := tx.Create(&billingDokterList).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal insert billing dokter: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
// ===========================
|
|
// 4.5 SIMPAN DPJP KE BILLING_DPJP
|
|
// ===========================
|
|
// Insert DPJP (Doctor In Charge) ke tabel billing_dpjp jika ID_DPJP disediakan
|
|
if input.ID_DPJP > 0 {
|
|
billingDPJP := models.Billing_DPJP{
|
|
ID_Billing: billing.ID_Billing,
|
|
ID_DPJP: input.ID_DPJP,
|
|
}
|
|
|
|
if err := tx.Create(&billingDPJP).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal insert billing DPJP: %s", err.Error())
|
|
}
|
|
|
|
log.Printf("[Billing DPJP] Inserted billing %d with DPJP %d\n", billing.ID_Billing, input.ID_DPJP)
|
|
}
|
|
|
|
var billingTindakanList []models.Billing_Tindakan
|
|
var billingICD9List []models.Billing_ICD9
|
|
var billingICD10List []models.Billing_ICD10
|
|
|
|
for _, tindakan := range input.Tindakan_RS {
|
|
var tarif models.TarifRS
|
|
|
|
if err := tx.Where("\"Tindakan_RS\" = ?", tindakan).First(&tarif).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("tindakan '%s' tidak ditemukan", tindakan)
|
|
}
|
|
|
|
billTindakan := models.Billing_Tindakan{
|
|
ID_Billing: billing.ID_Billing,
|
|
ID_Tarif_RS: tarif.KodeRS,
|
|
Tanggal_Tindakan: &tanggalHariIni,
|
|
}
|
|
|
|
if err := tx.Create(&billTindakan).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal insert billing tindakan: %s", err.Error())
|
|
}
|
|
|
|
billingTindakanList = append(billingTindakanList, billTindakan)
|
|
}
|
|
|
|
for _, icd := range input.ICD9 {
|
|
var icd9 models.ICD9
|
|
|
|
if err := tx.Where("\"Prosedur\" = ?", icd).First(&icd9).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("ICD9 '%s' tidak ditemukan", icd)
|
|
}
|
|
|
|
billICD9 := models.Billing_ICD9{
|
|
ID_Billing: billing.ID_Billing,
|
|
ID_ICD9: icd9.Kode_ICD9,
|
|
}
|
|
|
|
if err := tx.Create(&billICD9).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal insert billing ICD9: %s", err.Error())
|
|
}
|
|
|
|
billingICD9List = append(billingICD9List, billICD9)
|
|
}
|
|
|
|
for _, icd := range input.ICD10 {
|
|
var icd10 models.ICD10
|
|
|
|
if err := tx.Where("\"Diagnosa\" = ?", icd).First(&icd10).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("ICD10 '%s' tidak ditemukan", icd)
|
|
}
|
|
|
|
billICD10 := models.Billing_ICD10{
|
|
ID_Billing: billing.ID_Billing,
|
|
ID_ICD10: icd10.Kode_ICD10,
|
|
}
|
|
|
|
if err := tx.Create(&billICD10).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, nil, nil, nil, nil,
|
|
fmt.Errorf("gagal insert billing ICD10: %s", err.Error())
|
|
}
|
|
|
|
billingICD10List = append(billingICD10List, billICD10)
|
|
}
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
return nil, nil, nil, nil, nil, err
|
|
}
|
|
if input.Billing_sign != "" && strings.TrimSpace(input.Billing_sign) != "" {
|
|
go func(id int) {
|
|
if err := SendEmailBillingSignToDokter(id); err != nil {
|
|
fmt.Printf("Warning: Gagal mengirim email ke dokter untuk billing ID %d: %v\n", id, err)
|
|
}
|
|
}(billing.ID_Billing)
|
|
}
|
|
|
|
return &billing, &pasien, billingTindakanList, billingICD9List, billingICD10List, nil
|
|
}
|
|
|
|
// GetLastBillingByNama - Ambil billing terakhir pasien (buat dapetin baseline total_klaim pas billing baru dibuat)
|
|
func GetLastBillingByNama(namaPasien string) (*models.BillingPasien, error) {
|
|
// Cari pasien dulu
|
|
var pasien models.Pasien
|
|
if err := database.DB.Where("\"Nama_Pasien\" = ?", namaPasien).First(&pasien).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Cari billing terakhir pasien ini (paling baru berdasarkan ID_Billing)
|
|
var billing models.BillingPasien
|
|
if err := database.DB.
|
|
Where("\"ID_Pasien\" = ?", pasien.ID_Pasien).
|
|
Order("\"ID_Billing\" DESC").
|
|
First(&billing).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &billing, nil
|
|
}
|
|
|
|
// UpdateBillingIdentitas - update data identitas pasien dalam billing
|
|
func UpdateBillingIdentitas(billingId int, namaPasien string, usia int, jeniKelamin string, ruangan string, kelas string, tindakan []string, icd9 []string, icd10 []string) error {
|
|
// Get billing
|
|
var billing models.BillingPasien
|
|
if err := database.DB.Where("\"ID_Billing\" = ?", billingId).First(&billing).Error; err != nil {
|
|
return errors.New("billing tidak ditemukan")
|
|
}
|
|
|
|
// Start transaction
|
|
tx := database.DB.Begin()
|
|
|
|
// Update pasien data
|
|
pasien := models.Pasien{}
|
|
if err := tx.Model(&pasien).
|
|
Where("\"ID_Pasien\" = ?", billing.ID_Pasien).
|
|
Updates(map[string]interface{}{
|
|
"\"Nama_Pasien\"": namaPasien,
|
|
"\"Usia\"": usia,
|
|
"\"Jenis_Kelamin\"": jeniKelamin,
|
|
"\"Ruangan\"": ruangan,
|
|
"\"Kelas\"": kelas,
|
|
}).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal update data pasien: " + err.Error())
|
|
}
|
|
|
|
// Delete existing tindakan
|
|
if err := tx.Where("\"ID_Billing\" = ?", billingId).Delete(&models.Billing_Tindakan{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal delete tindakan: " + err.Error())
|
|
}
|
|
|
|
// Insert new tindakan
|
|
for _, t := range tindakan {
|
|
if t != "" {
|
|
newTindakan := models.Billing_Tindakan{
|
|
ID_Billing: billingId,
|
|
ID_Tarif_RS: t,
|
|
}
|
|
if err := tx.Create(&newTindakan).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal insert tindakan: " + err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete existing ICD9
|
|
if err := tx.Where("\"ID_Billing\" = ?", billingId).Delete(&models.Billing_ICD9{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal delete ICD9: " + err.Error())
|
|
}
|
|
|
|
// Insert new ICD9
|
|
for _, i := range icd9 {
|
|
if i != "" {
|
|
newICD9 := models.Billing_ICD9{
|
|
ID_Billing: billingId,
|
|
ID_ICD9: i,
|
|
}
|
|
if err := tx.Create(&newICD9).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal insert ICD9: " + err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete existing ICD10
|
|
if err := tx.Where("\"ID_Billing\" = ?", billingId).Delete(&models.Billing_ICD10{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal delete ICD10: " + err.Error())
|
|
}
|
|
|
|
// Insert new ICD10
|
|
for _, i := range icd10 {
|
|
if i != "" {
|
|
newICD10 := models.Billing_ICD10{
|
|
ID_Billing: billingId,
|
|
ID_ICD10: i,
|
|
}
|
|
if err := tx.Create(&newICD10).Error; err != nil {
|
|
tx.Rollback()
|
|
return errors.New("gagal insert ICD10: " + err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Commit transaction
|
|
if err := tx.Commit().Error; err != nil {
|
|
return errors.New("gagal commit transaction: " + err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|