Compare commits
3
Commits
142ac841ff
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec2f340e13 | ||
|
|
a6af3d5f3f | ||
|
|
cc6abb00ac |
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
# Database Configuration
|
# Database Configuration
|
||||||
DB_HOST=host.docker.internal
|
DB_HOST=db
|
||||||
|
# DB_HOST=host.docker.internal
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_USER=postgres
|
DB_USER=postgres
|
||||||
DB_PASSWORD=gakbikinkembung25
|
DB_PASSWORD=gakbikinkembung25
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ type BillingRequest struct {
|
|||||||
Ruangan string `json:"ruangan" binding:"required"`
|
Ruangan string `json:"ruangan" binding:"required"`
|
||||||
Kelas string `json:"kelas" binding:"required"`
|
Kelas string `json:"kelas" binding:"required"`
|
||||||
Tindakan_RS []string `json:"tindakan_rs" binding:"required"`
|
Tindakan_RS []string `json:"tindakan_rs" binding:"required"`
|
||||||
|
Tanggal_Masuk string `json:"tanggal_masuk"` // ← Added: Tanggal masuk dari frontend (format: YYYY-MM-DD)
|
||||||
Tanggal_Keluar string `json:"tanggal_keluar"`
|
Tanggal_Keluar string `json:"tanggal_keluar"`
|
||||||
Billing_sign string `json:"billing_sign"`
|
Billing_sign string `json:"billing_sign"`
|
||||||
ICD9 []string `json:"icd9"`
|
ICD9 []string `json:"icd9"`
|
||||||
|
|||||||
@@ -68,10 +68,10 @@ func SendEmailToMultiple(to []string, subject, body string) error {
|
|||||||
smtpPort := os.Getenv("SMTP_PORT")
|
smtpPort := os.Getenv("SMTP_PORT")
|
||||||
|
|
||||||
if from == "" {
|
if from == "" {
|
||||||
from = "asikmahdi@gmail.com"
|
from = "careit565@gmail.com"
|
||||||
}
|
}
|
||||||
if password == "" {
|
if password == "" {
|
||||||
password = "njom rhxb prrj tuoj"
|
password = "gkhz bjax uamw xydf"
|
||||||
}
|
}
|
||||||
if smtpHost == "" {
|
if smtpHost == "" {
|
||||||
smtpHost = "smtp.gmail.com"
|
smtpHost = "smtp.gmail.com"
|
||||||
|
|||||||
@@ -314,6 +314,30 @@ func DataFromFE(input models.BillingRequest) (
|
|||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
|
// Parse Tanggal_Masuk - accept multiple formats
|
||||||
|
var masukPtr *time.Time
|
||||||
|
if input.Tanggal_Masuk != "" && input.Tanggal_Masuk != "null" {
|
||||||
|
s := input.Tanggal_Masuk
|
||||||
|
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
|
||||||
|
masukPtr = &t
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if masukPtr == nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, nil, nil, nil, nil, fmt.Errorf("invalid tanggal_masuk format: %s", input.Tanggal_Masuk)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Jika tidak ada input, default ke hari ini
|
||||||
|
masukPtr = &now
|
||||||
|
}
|
||||||
|
|
||||||
// Parse Tanggal_Keluar (frontend sends string). Accept multiple formats.
|
// Parse Tanggal_Keluar (frontend sends string). Accept multiple formats.
|
||||||
var keluarPtr *time.Time
|
var keluarPtr *time.Time
|
||||||
if input.Tanggal_Keluar != "" && input.Tanggal_Keluar != "null" {
|
if input.Tanggal_Keluar != "" && input.Tanggal_Keluar != "null" {
|
||||||
@@ -355,7 +379,7 @@ func DataFromFE(input models.BillingRequest) (
|
|||||||
billing = models.BillingPasien{
|
billing = models.BillingPasien{
|
||||||
ID_Pasien: pasien.ID_Pasien,
|
ID_Pasien: pasien.ID_Pasien,
|
||||||
Cara_Bayar: input.Cara_Bayar,
|
Cara_Bayar: input.Cara_Bayar,
|
||||||
Tanggal_masuk: &now,
|
Tanggal_masuk: masukPtr,
|
||||||
Tanggal_keluar: keluarPtr,
|
Tanggal_keluar: keluarPtr,
|
||||||
Total_Tarif_RS: input.Total_Tarif_RS,
|
Total_Tarif_RS: input.Total_Tarif_RS,
|
||||||
Total_Klaim: input.Total_Klaim_BPJS, // ← Changed: Use input value instead of hardcoded 0
|
Total_Klaim: input.Total_Klaim_BPJS, // ← Changed: Use input value instead of hardcoded 0
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ func GetRiwayatPasienAll(db *gorm.DB) ([]models.Riwayat_Pasien_all, error) {
|
|||||||
if err := db.Table("\"billing_tindakan\"").
|
if err := db.Table("\"billing_tindakan\"").
|
||||||
Where("\"ID_Billing\" IN ?", billingIDs).
|
Where("\"ID_Billing\" IN ?", billingIDs).
|
||||||
Select("\"ID_Billing\", \"ID_Tarif_RS\" as \"Kode\"").
|
Select("\"ID_Billing\", \"ID_Tarif_RS\" as \"Kode\"").
|
||||||
|
Order("\"ID_Billing\" ASC, \"tanggal_tindakan\" ASC").
|
||||||
Scan(&tindakanRows).Error; err != nil {
|
Scan(&tindakanRows).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -54,7 +55,7 @@ func GetRiwayatPasienAll(db *gorm.DB) ([]models.Riwayat_Pasien_all, error) {
|
|||||||
tindakanMap[t.ID_Billing] = append(tindakanMap[t.ID_Billing], t.Kode)
|
tindakanMap[t.ID_Billing] = append(tindakanMap[t.ID_Billing], t.Kode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ambil tanggal tindakan dari tabel billing_tindakan
|
// Ambil tanggal tindakan dari tabel billing_tindakan (ambil yang pertama aja per billing supaya konsisten)
|
||||||
tindakanDateMap := make(map[int]*time.Time)
|
tindakanDateMap := make(map[int]*time.Time)
|
||||||
var tindakanDateRows []struct {
|
var tindakanDateRows []struct {
|
||||||
ID_Billing int
|
ID_Billing int
|
||||||
@@ -64,12 +65,13 @@ func GetRiwayatPasienAll(db *gorm.DB) ([]models.Riwayat_Pasien_all, error) {
|
|||||||
if err := db.Table("\"billing_tindakan\"").
|
if err := db.Table("\"billing_tindakan\"").
|
||||||
Where("\"ID_Billing\" IN ?", billingIDs).
|
Where("\"ID_Billing\" IN ?", billingIDs).
|
||||||
Select("\"ID_Billing\", \"tanggal_tindakan\"").
|
Select("\"ID_Billing\", \"tanggal_tindakan\"").
|
||||||
|
Order("\"ID_Billing\" ASC, \"tanggal_tindakan\" ASC").
|
||||||
Scan(&tindakanDateRows).Error; err != nil {
|
Scan(&tindakanDateRows).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range tindakanDateRows {
|
for _, t := range tindakanDateRows {
|
||||||
if t.Tanggal_Tindakan != nil {
|
if t.Tanggal_Tindakan != nil && tindakanDateMap[t.ID_Billing] == nil {
|
||||||
tindakanDateMap[t.ID_Billing] = t.Tanggal_Tindakan
|
tindakanDateMap[t.ID_Billing] = t.Tanggal_Tindakan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,6 +264,7 @@ func GetAllRiwayatpasien(db *gorm.DB) ([]models.Request_Admin_Inacbg, error) {
|
|||||||
if err := db.Table("\"billing_tindakan\"").
|
if err := db.Table("\"billing_tindakan\"").
|
||||||
Where("\"ID_Billing\" IN ?", billingIDs).
|
Where("\"ID_Billing\" IN ?", billingIDs).
|
||||||
Select("\"ID_Billing\", \"ID_Tarif_RS\" as \"Kode\"").
|
Select("\"ID_Billing\", \"ID_Tarif_RS\" as \"Kode\"").
|
||||||
|
Order("\"ID_Billing\" ASC, \"tanggal_tindakan\" ASC").
|
||||||
Scan(&tindakanRows).Error; err != nil {
|
Scan(&tindakanRows).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[.ShellClassInfo]
|
||||||
|
IconResource=C:\Users\rengginang\Desktop\CAREIT_V4\frontendcareit_v4\public\assets\LOGO_CAREIT.ico,0
|
||||||
|
[ViewState]
|
||||||
|
Mode=
|
||||||
|
Vid=
|
||||||
|
FolderType=Generic
|
||||||
Generated
+5
-5
@@ -23,8 +23,8 @@
|
|||||||
"@capacitor/cli": "^8.0.0",
|
"@capacitor/cli": "^8.0.0",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vercel/speed-insights": "^1.3.1",
|
"@vercel/speed-insights": "^1.3.1",
|
||||||
"babel-plugin-react-compiler": "1.0.0",
|
"babel-plugin-react-compiler": "1.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
@@ -2611,9 +2611,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.2.7",
|
"version": "19.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
||||||
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -40,8 +40,8 @@
|
|||||||
"@capacitor/cli": "^8.0.0",
|
"@capacitor/cli": "^8.0.0",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vercel/speed-insights": "^1.3.1",
|
"@vercel/speed-insights": "^1.3.1",
|
||||||
"babel-plugin-react-compiler": "1.0.0",
|
"babel-plugin-react-compiler": "1.0.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
|||||||
@@ -441,6 +441,13 @@ const INACBG_Admin_Ruangan = ({
|
|||||||
const totalKlaim = data.total_klaim || 0;
|
const totalKlaim = data.total_klaim || 0;
|
||||||
setTotalKlaimOriginal(totalKlaim);
|
setTotalKlaimOriginal(totalKlaim);
|
||||||
console.log(`💰 Set totalKlaimOriginal: ${totalKlaim}`);
|
console.log(`💰 Set totalKlaimOriginal: ${totalKlaim}`);
|
||||||
|
|
||||||
|
// Seed liveBillingSign dari nilai tersimpan di DB, supaya display awal sesuai dengan BE
|
||||||
|
// Akan di-overwrite otomatis oleh useEffect saat user mengubah kode INACBG
|
||||||
|
if (data.billing_sign) {
|
||||||
|
setLiveBillingSign(data.billing_sign);
|
||||||
|
console.log(`🎨 Seeded liveBillingSign from DB: ${data.billing_sign}`);
|
||||||
|
}
|
||||||
// DONT set totalKlaimBPJS here - biarkan useEffect calculate yang set nilai dengan benar
|
// DONT set totalKlaimBPJS here - biarkan useEffect calculate yang set nilai dengan benar
|
||||||
// Jadi jangan: setTotalKlaimBPJS(totalKlaim);
|
// Jadi jangan: setTotalKlaimBPJS(totalKlaim);
|
||||||
|
|
||||||
@@ -777,15 +784,15 @@ const INACBG_Admin_Ruangan = ({
|
|||||||
const percentage = (totalTarifRS / totalKlaimBPJS) * 100;
|
const percentage = (totalTarifRS / totalKlaimBPJS) * 100;
|
||||||
console.log(`📊 Percentage: ${percentage.toFixed(2)}% `);
|
console.log(`📊 Percentage: ${percentage.toFixed(2)}% `);
|
||||||
|
|
||||||
if (percentage <= 25) {
|
if (percentage <= 70) {
|
||||||
console.log("✅ Returning: Hijau (<=25%)");
|
console.log("✅ Returning: Hijau (<=70%)");
|
||||||
return "Hijau"; // Tarif RS <=25% dari Klaim BPJS Efektif = AMAN
|
return "Hijau"; // Tarif RS <=70% dari Klaim BPJS Efektif = AMAN
|
||||||
} else if (percentage <= 50) {
|
} else if (percentage > 70 && percentage <= 99) {
|
||||||
console.log("✅ Returning: Kuning (26-50%)");
|
console.log("✅ Returning: Kuning (71-99%)");
|
||||||
return "Kuning"; // 26%-50% = PERLU PERHATIAN
|
return "Kuning"; // 71%-99% = PERLU PERHATIAN
|
||||||
} else {
|
} else {
|
||||||
console.log("✅ Returning: Merah (>50%)");
|
console.log("✅ Returning: Merah (>99%)");
|
||||||
return "Merah"; // >50% = WASPADA
|
return "Merah"; // >99% = WASPADA
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1581,9 +1588,9 @@ rounded - lg text - left transition - all
|
|||||||
} `}
|
} `}
|
||||||
>
|
>
|
||||||
{liveBillingSign === "" && "Belum bisa dihitung (isi data klaim & tarif dulu)"}
|
{liveBillingSign === "" && "Belum bisa dihitung (isi data klaim & tarif dulu)"}
|
||||||
{liveBillingSign === "Hijau" && "Hijau - AMAN (<= 25%)"}
|
{liveBillingSign === "Hijau" && "Hijau - AMAN (<= 70%)"}
|
||||||
{liveBillingSign === "Kuning" && "Kuning - PERHATIAN (26% - 50%)"}
|
{liveBillingSign === "Kuning" && "Kuning - PERHATIAN (71% - 99%)"}
|
||||||
{liveBillingSign === "Merah" && "Merah - WASPADA (> 50%)"}
|
{liveBillingSign === "Merah" && "Merah - WASPADA (>= 100%)"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load diff
@@ -188,7 +188,8 @@ const RiwayatBillingPasien = ({ onLogout, userRole, onEdit, selectedRuangan }: R
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Hitung warning sign secara dinamis berdasarkan current tarif RS vs existing klaim
|
// Hitung warning sign secara dinamis berdasarkan current tarif RS vs existing klaim
|
||||||
// This ensures warning updates even if INACBG hasn't been input yet
|
// Threshold harus konsisten dengan calculateBillingSign di billing-pasien & INACBG_Admin_Ruangan:
|
||||||
|
// <=70% = Hijau, 71-99% = Kuning, >=100% = Merah
|
||||||
const calculateDynamicWarningSign = (totalTarifRS: number | undefined, totalKlaim: number | undefined): string => {
|
const calculateDynamicWarningSign = (totalTarifRS: number | undefined, totalKlaim: number | undefined): string => {
|
||||||
if (!totalTarifRS || !totalKlaim || totalTarifRS <= 0 || totalKlaim <= 0) {
|
if (!totalTarifRS || !totalKlaim || totalTarifRS <= 0 || totalKlaim <= 0) {
|
||||||
return ""; // No data to calculate
|
return ""; // No data to calculate
|
||||||
@@ -196,9 +197,9 @@ const RiwayatBillingPasien = ({ onLogout, userRole, onEdit, selectedRuangan }: R
|
|||||||
|
|
||||||
const percentage = (totalTarifRS / totalKlaim) * 100;
|
const percentage = (totalTarifRS / totalKlaim) * 100;
|
||||||
|
|
||||||
if (percentage <= 25) {
|
if (percentage <= 70) {
|
||||||
return "Hijau"; // Safe
|
return "Hijau"; // Safe
|
||||||
} else if (percentage <= 50) {
|
} else if (percentage <= 99) {
|
||||||
return "Kuning"; // Warning
|
return "Kuning"; // Warning
|
||||||
} else {
|
} else {
|
||||||
return "Merah"; // Alert
|
return "Merah"; // Alert
|
||||||
|
|||||||
Reference in New Issue
Block a user