From 695e82ee40c0640eac3fa608597f557defb73cea Mon Sep 17 00:00:00 2001 From: Basoro Date: Sun, 24 May 2026 10:07:40 +0800 Subject: [PATCH 01/10] fix: set manufacture and expiration dates to nullable in device schema --- mlite_db.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlite_db.sql b/mlite_db.sql index e7f23dc10..722ab5f63 100644 --- a/mlite_db.sql +++ b/mlite_db.sql @@ -1651,8 +1651,8 @@ CREATE TABLE `mlite_bpjs_emr_device` ( `kode_produk` VARCHAR(100) DEFAULT NULL, `keterangan` TEXT DEFAULT NULL, `manufacturer` VARCHAR(255) DEFAULT NULL, - 'manufacture_date' DATE NOT NULL, - 'expiration_date' DATE NOT NULL, + 'manufacture_date' DATE DEFAULT NULL, + 'expiration_date' DATE DEFAULT NULL, `model` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uq_device_id` (`device_id`), From 58542fafc06e52ab89f6e3d45b6a04218cb7de48 Mon Sep 17 00:00:00 2001 From: Basoro Date: Sun, 24 May 2026 22:55:46 +0800 Subject: [PATCH 02/10] Update --- config.php | 2 +- mlite_db.sql | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.php b/config.php index 27cfbc4e3..b0ada2a5b 100644 --- a/config.php +++ b/config.php @@ -102,7 +102,7 @@ function env(string $key, $default = null) ])); // Developer mode -define('DEV_MODE', env('DEVMODE') ?: 'true'); +define('DEV_MODE', true); define('JWT_SECRET', 'mlite_secret_key_change_me'); diff --git a/mlite_db.sql b/mlite_db.sql index 722ab5f63..6ec8f383b 100644 --- a/mlite_db.sql +++ b/mlite_db.sql @@ -2060,7 +2060,7 @@ CREATE TABLE `mlite_esignatures` ( PRIMARY KEY (`id`), KEY `ref_idx` (`ref_type`,`ref_id`), KEY `hash_idx` (`signature_hash`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; CREATE TABLE `mlite_geolocation_presensi` ( @@ -2798,7 +2798,7 @@ CREATE TABLE `mlite_sertisign_webhook` ( PRIMARY KEY (`id`), KEY `transaction_idx` (`transaction_id`), KEY `status_idx` (`status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; CREATE TABLE `mlite_mapping_snomed_icd` ( From dc7d15f5c61cb3d54ffe6e5a67bd0528caf0df2c Mon Sep 17 00:00:00 2001 From: Basoro Date: Tue, 26 May 2026 08:23:50 +0800 Subject: [PATCH 03/10] refactor: replace repeated   with str_repeat update three instances across both inpatient and outpatient kasir plugin admin files to use str_repeat for non-breaking space indentation instead of hardcoded HTML   sequences, improving maintainability and compatibility --- plugins/kasir_rawat_inap/Admin.php | 2 +- plugins/kasir_rawat_jalan/Admin.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/kasir_rawat_inap/Admin.php b/plugins/kasir_rawat_inap/Admin.php index e3db0565b..0ee90b0c8 100644 --- a/plugins/kasir_rawat_inap/Admin.php +++ b/plugins/kasir_rawat_inap/Admin.php @@ -1041,7 +1041,7 @@ public function anyRincian() // Prepare ingredient row (hide prices) $row['nomor'] = ''; - $row['nama_brng'] = "     - " . $row['nama_brng']; + $row['nama_brng'] = str_repeat("\u{00A0}", 4) . ' - ' . $row['nama_brng']; $row['total'] = 0; $row['embalase'] = 0; $row['tuslah'] = 0; diff --git a/plugins/kasir_rawat_jalan/Admin.php b/plugins/kasir_rawat_jalan/Admin.php index 6380e8a4d..425dca836 100644 --- a/plugins/kasir_rawat_jalan/Admin.php +++ b/plugins/kasir_rawat_jalan/Admin.php @@ -822,7 +822,7 @@ public function anyRincian() // Prepare ingredient row (hide prices) $row['nomor'] = ''; - $row['nama_brng'] = "     - " . $row['nama_brng']; + $row['nama_brng'] = str_repeat("\u{00A0}", 4) . ' - ' . $row['nama_brng']; $row['total'] = 0; $row['embalase'] = 0; $row['tuslah'] = 0; @@ -2006,7 +2006,7 @@ public function anyFaktur() if ($row) { $total_racikan += $row['total']; - $row['nama_brng'] = "     - " . $row['nama_brng']; + $row['nama_brng'] = str_repeat("\u{00A0}", 4) . ' - ' . $row['nama_brng']; $row['total'] = 0; $row['jml'] = 0; $row['biaya_obat'] = 0; From 6bf9dcd3fcc7ee27c76c0d0edcb20b693778d913 Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 10:14:01 +0800 Subject: [PATCH 04/10] feat(keuangan): add filters and improve general ledger - Add year filter for rekening tahun annual account management page - Rework buku besar general ledger report: add conditional akun column, saldo normal column, opening/closing balance rows, summary statistics, and toggle to show final balances - Fix buku besar print view to pass all required parameters and include summary data - Simplify periode display logic for general ledger print view - Improve cash flow statement calculation and allocation logic - Update balance sheet calculations to use annual opening balances from rekeningtahun table - Add new akun kegiatan dummy data and improved dummy data handling --- plugins/keuangan/Admin.php | 634 ++++++++++++++---- plugins/keuangan/view/admin/buku.besar.html | 63 +- .../keuangan/view/admin/buku.besar.print.html | 39 +- .../keuangan/view/admin/rekening.tahun.html | 10 + 4 files changed, 596 insertions(+), 150 deletions(-) diff --git a/plugins/keuangan/Admin.php b/plugins/keuangan/Admin.php index dfb97bfef..0a25333ef 100644 --- a/plugins/keuangan/Admin.php +++ b/plugins/keuangan/Admin.php @@ -96,12 +96,16 @@ public function getRekeningTahun() $this->core->addJS(url([ADMIN, 'keuangan', 'akunrekeningjs']), 'footer'); $this->_addHeaderFiles(); $curr_year = date('Y'); + $year = isset($_GET['tahun']) ? (int) $_GET['tahun'] : (int) $curr_year; + if ($year < 2000 || $year > ((int) date('Y') + 5)) { + $year = (int) $curr_year; + } $akunrekening = $this->db('mlite_rekening')->toArray(); $rekeningtahun = $this->db('mlite_rekeningtahun') ->join('mlite_rekening', 'mlite_rekening.kd_rek=mlite_rekeningtahun.kd_rek') - ->where('thn', $curr_year) + ->where('thn', $year) ->toArray(); - return $this->draw('rekening.tahun.html', ['akunrekening' => $akunrekening, 'rekeningtahun' => $rekeningtahun]); + return $this->draw('rekening.tahun.html', ['akunrekening' => $akunrekening, 'rekeningtahun' => $rekeningtahun, 'tahun_filter' => $year]); } public function postSaveRekeningTahun() @@ -215,8 +219,10 @@ public function getBukuBesar() } $kd_rek = isset($_GET['kd_rek']) ? $_GET['kd_rek'] : ''; + $showSaldoAkhir = !empty($_GET['show_saldo_akhir']); + $showSaldoAkhirInt = $showSaldoAkhir ? 1 : 0; - $sql = "SELECT mlite_detailjurnal.no_jurnal, tgl_jurnal, keterangan, debet, kredit, mlite_rekening.balance FROM mlite_detailjurnal JOIN mlite_jurnal ON mlite_detailjurnal.no_jurnal = mlite_jurnal.no_jurnal JOIN mlite_rekening ON mlite_detailjurnal.kd_rek = mlite_rekening.kd_rek WHERE (mlite_jurnal.tgl_jurnal BETWEEN ? AND ?)"; + $sql = "SELECT mlite_detailjurnal.no_jurnal, tgl_jurnal, keterangan, debet, kredit, mlite_detailjurnal.kd_rek, mlite_rekening.nm_rek, mlite_rekening.balance FROM mlite_detailjurnal JOIN mlite_jurnal ON mlite_detailjurnal.no_jurnal = mlite_jurnal.no_jurnal JOIN mlite_rekening ON mlite_detailjurnal.kd_rek = mlite_rekening.kd_rek WHERE (mlite_jurnal.tgl_jurnal BETWEEN ? AND ?)"; $params = [$tgl_awal, $tgl_akhir]; if(!empty($kd_rek)) { @@ -224,21 +230,256 @@ public function getBukuBesar() $params[] = $kd_rek; } - $sql .= " ORDER BY mlite_detailjurnal.no_jurnal ASC"; + if (!empty($kd_rek)) { + $sql .= " ORDER BY mlite_jurnal.tgl_jurnal ASC, mlite_detailjurnal.no_jurnal ASC"; + } else { + $sql .= " ORDER BY mlite_detailjurnal.kd_rek ASC, mlite_jurnal.tgl_jurnal ASC, mlite_detailjurnal.no_jurnal ASC"; + } $query = $this->db()->pdo()->prepare($sql); $query->execute($params); - $bukubesar = $query->fetchAll(\PDO::FETCH_ASSOC); - $saldo = 0; - foreach ($bukubesar as $key => $row) { - $debet = (float)$row['debet']; - $kredit = (float)$row['kredit']; - if ($row['balance'] === 'D') { - $saldo += ($debet - $kredit); + $rows = $query->fetchAll(\PDO::FETCH_ASSOC); + $bukubesar = []; + $summary = [ + 'rekening_count' => 0, + 'total_debet' => 0, + 'total_kredit' => 0, + 'saldo_akhir_d' => 0, + 'saldo_akhir_k' => 0, + 'saldo_akhir_net' => 0, + 'saldo_akhir_side' => '', + 'saldo_akhir_amount' => 0, + 'saldo_akhir_net_side' => '', + 'saldo_akhir_net_amount' => 0, + ]; + + if (!empty($kd_rek)) { + $saldo = 0; + $tahun = (int) date('Y', strtotime($tgl_awal)); + $saldoAwalRow = $this->db('mlite_rekeningtahun')->where('thn', $tahun)->where('kd_rek', $kd_rek)->oneArray(); + $saldoAwal = (float) ($saldoAwalRow['saldo_awal'] ?? 0); + + $rekeningRow = $this->db('mlite_rekening')->where('kd_rek', $kd_rek)->oneArray(); + $nmRek = (string) ($rekeningRow['nm_rek'] ?? ''); + $balance = (string) ($rekeningRow['balance'] ?? 'D'); + + $awalTahun = $tahun . '-01-01'; + $sqlMutasi = " + SELECT COALESCE(SUM( + CASE + WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) + ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + END + ), 0) AS mutasi + FROM mlite_detailjurnal jd + JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal + JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek + WHERE jd.kd_rek = ? + AND j.tgl_jurnal >= ? + AND j.tgl_jurnal < ? + "; + $stMutasi = $this->db()->pdo()->prepare($sqlMutasi); + $stMutasi->execute([$kd_rek, $awalTahun, $tgl_awal]); + $mutasi = (float) (($stMutasi->fetch()['mutasi'] ?? 0)); + + $saldo = $saldoAwal + $mutasi; + $saldoAbs = abs($saldo); + $saldoSisi = $saldo >= 0 ? $balance : ($balance === 'D' ? 'K' : 'D'); + $summary['rekening_count'] = 1; + $bukubesar[] = [ + 'no_jurnal' => '', + 'tgl_jurnal' => $tgl_awal, + 'kd_rek' => $kd_rek, + 'nm_rek' => $nmRek, + 'keterangan' => 'Saldo awal', + 'debet' => 0, + 'kredit' => 0, + 'balance' => $balance, + 'saldo' => $saldo, + 'saldo_normal' => $saldoAbs, + 'saldo_sisi' => $saldoSisi, + 'row_type' => 'saldo_awal', + ]; + foreach ($rows as $row) { + $debet = (float) ($row['debet'] ?? 0); + $kredit = (float) ($row['kredit'] ?? 0); + if (($row['balance'] ?? '') === 'D') { + $saldo += ($debet - $kredit); + } else { + $saldo += ($kredit - $debet); + } + $row['saldo'] = $saldo; + $rowBalance = (string) ($row['balance'] ?? $balance); + $row['saldo_normal'] = abs((float) $saldo); + $row['saldo_sisi'] = $saldo >= 0 ? $rowBalance : ($rowBalance === 'D' ? 'K' : 'D'); + $row['row_type'] = 'mutasi'; + $summary['total_debet'] += $debet; + $summary['total_kredit'] += $kredit; + $bukubesar[] = $row; + } + + $saldoAbs = abs((float) $saldo); + $saldoSisi = $saldo >= 0 ? $balance : ($balance === 'D' ? 'K' : 'D'); + if ($showSaldoAkhir) { + $bukubesar[] = [ + 'no_jurnal' => '', + 'tgl_jurnal' => $tgl_akhir, + 'kd_rek' => $kd_rek, + 'nm_rek' => $nmRek, + 'keterangan' => 'Saldo akhir', + 'debet' => 0, + 'kredit' => 0, + 'balance' => $balance, + 'saldo' => $saldo, + 'saldo_normal' => $saldoAbs, + 'saldo_sisi' => $saldoSisi, + 'row_type' => 'saldo_akhir', + ]; + } + + if ($saldoSisi === 'D') { + $summary['saldo_akhir_d'] = $saldoAbs; + $summary['saldo_akhir_net'] = $saldoAbs; } else { - $saldo += ($kredit - $debet); + $summary['saldo_akhir_k'] = $saldoAbs; + $summary['saldo_akhir_net'] = -$saldoAbs; + } + $summary['saldo_akhir_side'] = $saldoSisi; + $summary['saldo_akhir_amount'] = $saldoAbs; + $summary['saldo_akhir_net_side'] = $saldoSisi; + $summary['saldo_akhir_net_amount'] = $saldoAbs; + } else { + $tahun = (int) date('Y', strtotime($tgl_awal)); + $awalTahun = $tahun . '-01-01'; + + $saldoAwalRows = $this->db('mlite_rekeningtahun')->where('thn', $tahun)->toArray(); + $saldoAwalMap = []; + foreach ($saldoAwalRows as $r) { + $saldoAwalMap[(string) $r['kd_rek']] = (float) ($r['saldo_awal'] ?? 0); + } + + $sqlMutasiAll = " + SELECT jd.kd_rek, COALESCE(SUM( + CASE + WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) + ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + END + ), 0) AS mutasi + FROM mlite_detailjurnal jd + JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal + JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek + WHERE j.tgl_jurnal >= ? + AND j.tgl_jurnal < ? + GROUP BY jd.kd_rek + "; + $stMutasiAll = $this->db()->pdo()->prepare($sqlMutasiAll); + $stMutasiAll->execute([$awalTahun, $tgl_awal]); + $mutasiMap = []; + foreach ($stMutasiAll->fetchAll(\PDO::FETCH_ASSOC) as $m) { + $mutasiMap[(string) $m['kd_rek']] = (float) ($m['mutasi'] ?? 0); + } + + $rowsByKd = []; + $kdSet = []; + foreach ($rows as $row) { + $k = (string) ($row['kd_rek'] ?? ''); + if ($k === '') { + continue; + } + $rowsByKd[$k][] = $row; + $kdSet[$k] = true; + } + foreach (array_keys($saldoAwalMap) as $k) { + $kdSet[$k] = true; } - $bukubesar[$key]['saldo'] = $saldo; + $kds = array_keys($kdSet); + sort($kds); + + $saldoPerKd = []; + foreach ($kds as $k) { + $saldoPerKd[$k] = (float) ($saldoAwalMap[$k] ?? 0) + (float) ($mutasiMap[$k] ?? 0); + } + + foreach ($kds as $k) { + $hasRows = !empty($rowsByKd[$k]); + $hasSaldoAwal = abs((float) ($saldoAwalMap[$k] ?? 0)) > 0.000001; + if (!$hasRows && !$hasSaldoAwal) { + continue; + } + + $rekeningRow = $this->db('mlite_rekening')->where('kd_rek', $k)->oneArray(); + $nmRek = (string) ($rekeningRow['nm_rek'] ?? ''); + $balance = (string) ($rekeningRow['balance'] ?? 'D'); + + $summary['rekening_count']++; + $saldoAbs = abs((float) $saldoPerKd[$k]); + $saldoSisi = $saldoPerKd[$k] >= 0 ? $balance : ($balance === 'D' ? 'K' : 'D'); + $bukubesar[] = [ + 'no_jurnal' => '', + 'tgl_jurnal' => $tgl_awal, + 'kd_rek' => $k, + 'nm_rek' => $nmRek, + 'keterangan' => 'Saldo awal', + 'debet' => 0, + 'kredit' => 0, + 'balance' => $balance, + 'saldo' => $saldoPerKd[$k], + 'saldo_normal' => $saldoAbs, + 'saldo_sisi' => $saldoSisi, + 'row_type' => 'saldo_awal', + ]; + + foreach (($rowsByKd[$k] ?? []) as $row) { + $debet = (float) ($row['debet'] ?? 0); + $kredit = (float) ($row['kredit'] ?? 0); + if (($row['balance'] ?? '') === 'D') { + $saldoPerKd[$k] += ($debet - $kredit); + } else { + $saldoPerKd[$k] += ($kredit - $debet); + } + $row['saldo'] = $saldoPerKd[$k]; + $rowBalance = (string) ($row['balance'] ?? $balance); + $row['saldo_normal'] = abs((float) $saldoPerKd[$k]); + $row['saldo_sisi'] = $saldoPerKd[$k] >= 0 ? $rowBalance : ($rowBalance === 'D' ? 'K' : 'D'); + $row['row_type'] = 'mutasi'; + $summary['total_debet'] += $debet; + $summary['total_kredit'] += $kredit; + $bukubesar[] = $row; + } + + $saldoAkhirAbs = abs((float) $saldoPerKd[$k]); + $saldoAkhirSisi = $saldoPerKd[$k] >= 0 ? $balance : ($balance === 'D' ? 'K' : 'D'); + if ($showSaldoAkhir) { + $bukubesar[] = [ + 'no_jurnal' => '', + 'tgl_jurnal' => $tgl_akhir, + 'kd_rek' => $k, + 'nm_rek' => $nmRek, + 'keterangan' => 'Saldo akhir', + 'debet' => 0, + 'kredit' => 0, + 'balance' => $balance, + 'saldo' => $saldoPerKd[$k], + 'saldo_normal' => $saldoAkhirAbs, + 'saldo_sisi' => $saldoAkhirSisi, + 'row_type' => 'saldo_akhir', + ]; + } + + if ($saldoAkhirSisi === 'D') { + $summary['saldo_akhir_d'] += $saldoAkhirAbs; + $summary['saldo_akhir_net'] += $saldoAkhirAbs; + } else { + $summary['saldo_akhir_k'] += $saldoAkhirAbs; + $summary['saldo_akhir_net'] -= $saldoAkhirAbs; + } + } + + $net = (float) $summary['saldo_akhir_net']; + $netAbs = abs($net); + $netSisi = $net >= 0 ? 'D' : 'K'; + $summary['saldo_akhir_net_side'] = $netSisi; + $summary['saldo_akhir_net_amount'] = $netAbs; } $akunrekening = $this->db('mlite_rekening')->toArray(); @@ -246,7 +487,10 @@ public function getBukuBesar() if(isset($_GET['action']) && $_GET['action'] == 'print') { echo $this->draw('buku.besar.print.html', [ 'bukubesar' => $bukubesar, - 'action' => url([ADMIN,'keuangan','bukubesar']) + 'action' => url([ADMIN,'keuangan','bukubesar']), + 'kd_rek_filter' => $kd_rek, + 'show_saldo_akhir' => $showSaldoAkhirInt, + 'summary' => $summary, ]); exit(); } else { @@ -254,8 +498,10 @@ public function getBukuBesar() 'bukubesar' => $bukubesar, 'akunrekening' => $akunrekening, 'kd_rek_filter' => $kd_rek, + 'show_saldo_akhir' => $showSaldoAkhirInt, 'tgl_awal' => htmlspecialchars($tgl_awal, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), 'tgl_akhir' => htmlspecialchars($tgl_akhir, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), + 'summary' => $summary, ]); } } @@ -287,23 +533,30 @@ public function getCashFlow() array("tipe" => "M", "arus_kas" => "Kegiatan Pendanaan"), ); + $cashAccounts = ['1101', '1102', '1103', '1104', '1105']; + $cashPlaceholders = implode(',', array_fill(0, count($cashAccounts), '?')); + // Hitung saldo awal kas dari akun kas (1101-1105) sebelum periode $query_saldo_awal = " SELECT COALESCE(SUM( CASE - WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) - ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + WHEN j.tgl_jurnal < ? THEN + CASE + WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) + ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + END + ELSE 0 END ), 0) as saldo_kas FROM mlite_rekening r LEFT JOIN mlite_detailjurnal jd ON r.kd_rek = jd.kd_rek - LEFT JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal AND j.tgl_jurnal < ? - WHERE r.kd_rek IN ('1101', '1102', '1103', '1104', '1105') + LEFT JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal + WHERE r.kd_rek IN ($cashPlaceholders) AND r.tipe = 'N' "; $stmt_saldo = $this->db()->pdo()->prepare($query_saldo_awal); - $stmt_saldo->execute([$tgl_awal]); + $stmt_saldo->execute(array_merge([$tgl_awal], $cashAccounts)); $result_saldo = $stmt_saldo->fetch(); $saldo_awal_kas = $result_saldo['saldo_kas'] ?? 0; @@ -311,85 +564,136 @@ public function getCashFlow() $total_debet = 0; $total_saldo_kredit = 0; $total_saldo_debet = 0; - $n = 1; + $sqlJurnal = " + SELECT + j.no_jurnal, + j.tgl_jurnal, + jd.kd_rek, + r.nm_rek, + r.tipe, + r.balance, + jd.debet, + jd.kredit + FROM mlite_jurnal j + JOIN mlite_detailjurnal jd ON jd.no_jurnal = j.no_jurnal + JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek + WHERE j.tgl_jurnal >= ? AND j.tgl_jurnal <= ? + AND j.no_jurnal IN ( + SELECT DISTINCT no_jurnal FROM mlite_detailjurnal WHERE kd_rek IN ($cashPlaceholders) + ) + ORDER BY j.tgl_jurnal ASC, j.no_jurnal ASC + "; + $stmtJurnal = $this->db()->pdo()->prepare($sqlJurnal); + $stmtJurnal->execute(array_merge([$tgl_awal, $tgl_akhir], $cashAccounts)); + $detail = $stmtJurnal->fetchAll(\PDO::FETCH_ASSOC); + + $byJurnal = []; + foreach ($detail as $r) { + $no = (string) ($r['no_jurnal'] ?? ''); + if ($no === '') { + continue; + } + $byJurnal[$no][] = $r; + } + + $agg = [ + 'R' => ['masuk' => [], 'keluar' => []], + 'N' => ['masuk' => [], 'keluar' => []], + 'M' => ['masuk' => [], 'keluar' => []], + ]; + + foreach ($byJurnal as $noJurnal => $lines) { + $cashDelta = 0.0; + foreach ($lines as $ln) { + $kd = (string) ($ln['kd_rek'] ?? ''); + if (in_array($kd, $cashAccounts, true)) { + $cashDelta += (float) ($ln['debet'] ?? 0) - (float) ($ln['kredit'] ?? 0); + } + } + if (abs($cashDelta) < 0.000001) { + continue; + } + + $isIn = $cashDelta > 0; + $weights = []; + $totalWeight = 0.0; + foreach ($lines as $ln) { + $kd = (string) ($ln['kd_rek'] ?? ''); + if ($kd === '' || in_array($kd, $cashAccounts, true)) { + continue; + } + $debet = (float) ($ln['debet'] ?? 0); + $kredit = (float) ($ln['kredit'] ?? 0); + $w = $isIn ? max($kredit - $debet, 0) : max($debet - $kredit, 0); + if ($w <= 0) { + continue; + } + $weights[] = [$ln, $w]; + $totalWeight += $w; + } + + if ($totalWeight <= 0) { + continue; + } + + foreach ($weights as $item) { + [$ln, $w] = $item; + $tipe = (string) ($ln['tipe'] ?? ''); + if (!isset($agg[$tipe])) { + continue; + } + $kd = (string) ($ln['kd_rek'] ?? ''); + $nm = (string) ($ln['nm_rek'] ?? ''); + $amount = abs($cashDelta) * ($w / $totalWeight); + + $bucket = $isIn ? 'masuk' : 'keluar'; + if (!isset($agg[$tipe][$bucket][$kd])) { + $agg[$tipe][$bucket][$kd] = [ + 'kd_rek' => $kd, + 'nm_rek' => $nm, + 'kredit_all' => 0, + 'debet_all' => 0, + 'saldo_awal' => 0, + ]; + } + + if ($isIn) { + $agg[$tipe][$bucket][$kd]['kredit_all'] += $amount; + } else { + $agg[$tipe][$bucket][$kd]['debet_all'] += $amount; + } + } + } + + $n = 1; foreach ($rows_aruskas as $row) { + $tipe = (string) ($row['tipe'] ?? ''); $row['nomor'] = $n++; $row['total_masuk'] = 0; $row['total_keluar'] = 0; $row['total_saldo_awal_masuk'] = 0; $row['total_saldo_awal_keluar'] = 0; - // Arus kas masuk (transaksi yang menambah kas) dalam periode - $query_masuk = " - SELECT - jd.kd_rek, - r.nm_rek, - r.tipe, - r.balance, - SUM(CASE - WHEN jd.kd_rek IN ('1101', '1102', '1103', '1104', '1105') THEN jd.debet - ELSE jd.kredit - END) as total_masuk - FROM mlite_detailjurnal jd - JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek - JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal - WHERE r.tipe = ? - AND j.tgl_jurnal >= ? AND j.tgl_jurnal <= ? - AND ((jd.kd_rek IN ('1101', '1102', '1103', '1104', '1105') AND jd.debet > 0) - OR (jd.kd_rek NOT IN ('1101', '1102', '1103', '1104', '1105') AND jd.kredit > 0)) - GROUP BY jd.kd_rek, r.nm_rek, r.tipe, r.balance - HAVING total_masuk > 0 - "; - - $stmt_masuk = $this->db()->pdo()->prepare($query_masuk); - $stmt_masuk->execute([$row['tipe'], $tgl_awal, $tgl_akhir]); - $rows_masuk = $stmt_masuk->fetchAll(); - - $row['jurnal_masuk'] = []; - foreach ($rows_masuk as $row_masuk) { - $row_masuk['kredit_all'] = $row_masuk['total_masuk']; - $row_masuk['saldo_awal'] = 0; - $row['total_masuk'] += $row_masuk['total_masuk']; - $row['jurnal_masuk'][] = $row_masuk; - $total_kredit += $row_masuk['total_masuk']; + $row['jurnal_masuk'] = array_values($agg[$tipe]['masuk'] ?? []); + usort($row['jurnal_masuk'], function ($a, $b) { + return strcmp((string) ($a['kd_rek'] ?? ''), (string) ($b['kd_rek'] ?? '')); + }); + foreach ($row['jurnal_masuk'] as $m) { + $row['total_masuk'] += (float) ($m['kredit_all'] ?? 0); } - // Arus kas keluar (transaksi yang mengurangi kas) dalam periode - $query_keluar = " - SELECT - jd.kd_rek, - r.nm_rek, - r.tipe, - r.balance, - SUM(CASE - WHEN jd.kd_rek IN ('1101', '1102', '1103', '1104', '1105') THEN jd.kredit - ELSE jd.debet - END) as total_keluar - FROM mlite_detailjurnal jd - JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek - JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal - WHERE r.tipe = ? - AND j.tgl_jurnal >= ? AND j.tgl_jurnal <= ? - AND ((jd.kd_rek IN ('1101', '1102', '1103', '1104', '1105') AND jd.kredit > 0) - OR (jd.kd_rek NOT IN ('1101', '1102', '1103', '1104', '1105') AND jd.debet > 0)) - GROUP BY jd.kd_rek, r.nm_rek, r.tipe, r.balance - HAVING total_keluar > 0 - "; - - $stmt_keluar = $this->db()->pdo()->prepare($query_keluar); - $stmt_keluar->execute([$row['tipe'], $tgl_awal, $tgl_akhir]); - $rows_keluar = $stmt_keluar->fetchAll(); - - $row['jurnal_keluar'] = []; - foreach ($rows_keluar as $row_keluar) { - $row_keluar['debet_all'] = $row_keluar['total_keluar']; - $row_keluar['saldo_awal'] = 0; - $row['total_keluar'] += $row_keluar['total_keluar']; - $row['jurnal_keluar'][] = $row_keluar; - $total_debet += $row_keluar['total_keluar']; + $row['jurnal_keluar'] = array_values($agg[$tipe]['keluar'] ?? []); + usort($row['jurnal_keluar'], function ($a, $b) { + return strcmp((string) ($a['kd_rek'] ?? ''), (string) ($b['kd_rek'] ?? '')); + }); + foreach ($row['jurnal_keluar'] as $k) { + $row['total_keluar'] += (float) ($k['debet_all'] ?? 0); } + $total_kredit += $row['total_masuk']; + $total_debet += $row['total_keluar']; + $aruskas[] = $row; } @@ -446,57 +750,69 @@ public function getNeraca() $total_hutang_jangka_panjang = 0; $total_modal = 0; - // Query untuk mendapatkan saldo awal rekening (sebelum periode) - $query_saldo_awal = " - SELECT - r.kd_rek, - r.nm_rek, - r.balance as saldo_normal, - COALESCE(SUM(jd.debet), 0) as total_debet_awal, - COALESCE(SUM(jd.kredit), 0) as total_kredit_awal, - CASE - WHEN r.balance = 'D' THEN COALESCE(SUM(jd.debet), 0) - COALESCE(SUM(jd.kredit), 0) - ELSE COALESCE(SUM(jd.kredit), 0) - COALESCE(SUM(jd.debet), 0) - END as saldo_awal - FROM mlite_rekening r - LEFT JOIN mlite_detailjurnal jd ON r.kd_rek = jd.kd_rek - LEFT JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal AND j.tgl_jurnal < ? - WHERE r.tipe IN ('N', 'M') - GROUP BY r.kd_rek, r.nm_rek, r.balance + $tahun = (int) date('Y', strtotime($tgl_awal)); + $awalTahun = $tahun . '-01-01'; + + $saldo_awal_tahun = []; + $sqlSaldoAwalTahun = " + SELECT rt.kd_rek, rt.saldo_awal + FROM mlite_rekeningtahun rt + JOIN mlite_rekening r ON r.kd_rek = rt.kd_rek + WHERE rt.thn = ? + AND r.tipe IN ('N', 'M') "; - - $stmt_awal = $this->db()->pdo()->prepare($query_saldo_awal); - $stmt_awal->execute([$tgl_awal]); - $saldo_awal_data = []; - foreach($stmt_awal->fetchAll() as $row) { - $saldo_awal_data[$row['kd_rek']] = $row['saldo_awal']; + $stSaldoAwalTahun = $this->db()->pdo()->prepare($sqlSaldoAwalTahun); + $stSaldoAwalTahun->execute([$tahun]); + foreach ($stSaldoAwalTahun->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $saldo_awal_tahun[(string) $row['kd_rek']] = (float) ($row['saldo_awal'] ?? 0); } - // Query untuk mendapatkan mutasi dalam periode - $query_mutasi = " - SELECT - r.kd_rek, - r.nm_rek, - r.balance as saldo_normal, - COALESCE(SUM(jd.debet), 0) as total_debet_periode, - COALESCE(SUM(jd.kredit), 0) as total_kredit_periode, - CASE - WHEN r.balance = 'D' THEN COALESCE(SUM(jd.debet), 0) - COALESCE(SUM(jd.kredit), 0) - ELSE COALESCE(SUM(jd.kredit), 0) - COALESCE(SUM(jd.debet), 0) - END as mutasi_periode - FROM mlite_rekening r - LEFT JOIN mlite_detailjurnal jd ON r.kd_rek = jd.kd_rek - LEFT JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal - WHERE r.tipe IN ('N', 'M') - AND j.tgl_jurnal >= ? AND j.tgl_jurnal <= ? - GROUP BY r.kd_rek, r.nm_rek, r.balance + $sqlMutasi = " + SELECT + jd.kd_rek, + COALESCE(SUM( + CASE + WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) + ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + END + ), 0) AS mutasi + FROM mlite_detailjurnal jd + JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal + JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek + WHERE r.tipe IN ('N', 'M') + AND j.tgl_jurnal >= ? + AND j.tgl_jurnal < ? + GROUP BY jd.kd_rek "; - - $stmt_mutasi = $this->db()->pdo()->prepare($query_mutasi); - $stmt_mutasi->execute([$tgl_awal, $tgl_akhir]); - $mutasi_data = []; - foreach($stmt_mutasi->fetchAll() as $row) { - $mutasi_data[$row['kd_rek']] = $row['mutasi_periode']; + $stMutasiBefore = $this->db()->pdo()->prepare($sqlMutasi); + $stMutasiBefore->execute([$awalTahun, $tgl_awal]); + $mutasi_before = []; + foreach ($stMutasiBefore->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $mutasi_before[(string) $row['kd_rek']] = (float) ($row['mutasi'] ?? 0); + } + + $sqlMutasiPeriode = " + SELECT + jd.kd_rek, + COALESCE(SUM( + CASE + WHEN r.balance = 'D' THEN COALESCE(jd.debet, 0) - COALESCE(jd.kredit, 0) + ELSE COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0) + END + ), 0) AS mutasi + FROM mlite_detailjurnal jd + JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal + JOIN mlite_rekening r ON r.kd_rek = jd.kd_rek + WHERE r.tipe IN ('N', 'M') + AND j.tgl_jurnal >= ? + AND j.tgl_jurnal <= ? + GROUP BY jd.kd_rek + "; + $stMutasiPeriode = $this->db()->pdo()->prepare($sqlMutasiPeriode); + $stMutasiPeriode->execute([$tgl_awal, $tgl_akhir]); + $mutasi_periode = []; + foreach ($stMutasiPeriode->fetchAll(\PDO::FETCH_ASSOC) as $row) { + $mutasi_periode[(string) $row['kd_rek']] = (float) ($row['mutasi'] ?? 0); } // Ambil semua rekening aktif @@ -506,8 +822,9 @@ public function getNeraca() $result = $stmt_rekening->fetchAll(); foreach($result as $rek) { // Hitung saldo akhir = saldo awal + mutasi periode - $saldo_awal = isset($saldo_awal_data[$rek['kd_rek']]) ? $saldo_awal_data[$rek['kd_rek']] : 0; - $mutasi = isset($mutasi_data[$rek['kd_rek']]) ? $mutasi_data[$rek['kd_rek']] : 0; + $kdRek = (string) ($rek['kd_rek'] ?? ''); + $saldo_awal = (float) ($saldo_awal_tahun[$kdRek] ?? 0) + (float) ($mutasi_before[$kdRek] ?? 0); + $mutasi = (float) ($mutasi_periode[$kdRek] ?? 0); $saldo_akhir = $saldo_awal + $mutasi; // Skip akun dengan saldo 0 @@ -579,7 +896,7 @@ public function getNeraca() // Hitung laba rugi periode berjalan untuk penyesuaian modal $query_labarugi = " SELECT - COALESCE(SUM(CASE WHEN r.balance = 'K' THEN jd.kredit - jd.debet ELSE jd.debet - jd.kredit END), 0) as laba_rugi + COALESCE(SUM(COALESCE(jd.kredit, 0) - COALESCE(jd.debet, 0)), 0) as laba_rugi FROM mlite_rekening r LEFT JOIN mlite_detailjurnal jd ON r.kd_rek = jd.kd_rek LEFT JOIN mlite_jurnal j ON j.no_jurnal = jd.no_jurnal @@ -594,6 +911,15 @@ public function getNeraca() // Tambahkan laba rugi ke total modal $total_modal += $laba_rugi; + if (abs((float) $laba_rugi) >= 0.01) { + $modal[] = [ + 'kd_rek' => '', + 'nm_rek' => 'Laba/Rugi Periode', + 'saldo' => (float) $laba_rugi, + 'saldo_awal' => 0, + 'mutasi' => (float) $laba_rugi + ]; + } // Hitung total aktiva dan pasiva $total_aktiva = $total_aktiva_lancar + $total_aktiva_tetap; @@ -662,6 +988,17 @@ public function postSaveSettings() public function postInsertDummyKeuangan() { + $akunKegiatan = [ + ['kegiatan' => 'Penerimaan Pasien Rawat Jalan', 'kd_rek' => '4101'], + ['kegiatan' => 'Penerimaan Pasien Rawat Inap', 'kd_rek' => '4102'], + ['kegiatan' => 'Penerimaan Penjualan Obat & BHP', 'kd_rek' => '4103'], + ['kegiatan' => 'Penerimaan Laboratorium', 'kd_rek' => '4104'], + ['kegiatan' => 'Penerimaan Radiologi', 'kd_rek' => '4105'], + ['kegiatan' => 'Pembayaran Gaji Karyawan', 'kd_rek' => '5101'], + ['kegiatan' => 'Pembelian Obat & BHP', 'kd_rek' => '5201'], + ['kegiatan' => 'Pembayaran Biaya Operasional', 'kd_rek' => '5301'], + ]; + $rekeningtahun = [ ['thn' => 2025, 'kd_rek' => '1101', 'saldo_awal' => 50000000], ['thn' => 2025, 'kd_rek' => '1201', 'saldo_awal' => 200000000], @@ -768,6 +1105,9 @@ public function postInsertDummyKeuangan() foreach ($rekeningtahun as $item) { $requiredRekening[$item['kd_rek']] = true; } + foreach ($akunKegiatan as $item) { + $requiredRekening[$item['kd_rek']] = true; + } foreach ($detailjurnal as $item) { $requiredRekening[$item['kd_rek']] = true; } @@ -802,11 +1142,31 @@ public function postInsertDummyKeuangan() } $insertedRekeningTahun = 0; + $updatedRekeningTahun = 0; foreach ($rekeningtahun as $item) { $exists = $this->db('mlite_rekeningtahun')->where('thn', $item['thn'])->where('kd_rek', $item['kd_rek'])->oneArray(); if (empty($exists)) { $this->db('mlite_rekeningtahun')->save($item); $insertedRekeningTahun++; + } else { + $current = (float) ($exists['saldo_awal'] ?? 0); + $next = (float) ($item['saldo_awal'] ?? 0); + if (abs($current - $next) >= 0.01) { + $this->db('mlite_rekeningtahun') + ->where('thn', $item['thn']) + ->where('kd_rek', $item['kd_rek']) + ->save(['saldo_awal' => $item['saldo_awal']]); + $updatedRekeningTahun++; + } + } + } + + $insertedAkunKegiatan = 0; + foreach ($akunKegiatan as $item) { + $exists = $this->db('mlite_akun_kegiatan')->where('kegiatan', $item['kegiatan'])->oneArray(); + if (empty($exists)) { + $this->db('mlite_akun_kegiatan')->save($item); + $insertedAkunKegiatan++; } } @@ -835,7 +1195,7 @@ public function postInsertDummyKeuangan() } $this->db()->pdo()->commit(); - $this->notify('success', 'Data dummy keuangan diproses. Insert baru: rekening tahun '.$insertedRekeningTahun.', jurnal '.$insertedJurnal.', detail jurnal '.$insertedDetail.'.'); + $this->notify('success', 'Data dummy keuangan diproses. Rekening tahun: insert '.$insertedRekeningTahun.', update '.$updatedRekeningTahun.'. Akun kegiatan: insert '.$insertedAkunKegiatan.'. Jurnal: insert '.$insertedJurnal.'. Detail jurnal: insert '.$insertedDetail.'.'); } catch (\Exception $e) { $this->db()->pdo()->rollBack(); $this->notify('failure', 'Insert data dummy keuangan gagal: '.$e->getMessage()); diff --git a/plugins/keuangan/view/admin/buku.besar.html b/plugins/keuangan/view/admin/buku.besar.html index 41b41e9df..e2368b480 100644 --- a/plugins/keuangan/view/admin/buku.besar.html +++ b/plugins/keuangan/view/admin/buku.besar.html @@ -8,11 +8,7 @@
- {if: isset($_GET['tgl_awal']) && isset($_GET['tgl_akhir'])} - Print - {else} - Print - {/if} + Print
@@ -35,6 +31,12 @@ {/loop} +
  • + +
  • @@ -51,32 +53,75 @@

    Kelola Buku Besar

    No. Jurnal Tanggal + {if: empty($kd_rek_filter)} + Akun + {/if} Keterangan Debet Kredit Saldo + Saldo Normal {if: $bukubesar} {loop: $bukubesar} + {if: isset($value.row_type) && $value.row_type == 'saldo_akhir'} + + {else} + {if: isset($value.row_type) && $value.row_type == 'saldo_awal'} + + {else} + {/if} + {/if} {?=isset_or($value.no_jurnal)?} {?=isset_or($value.tgl_jurnal)?} - {?=isset_or($value.keterangan)?} + {if: empty($kd_rek_filter)} + {?=isset_or($value.kd_rek)?} - {?=isset_or($value.nm_rek)?} + {/if} + + {if: isset($value.row_type) && ($value.row_type == 'saldo_awal' || $value.row_type == 'saldo_akhir')} + {?=isset_or($value.keterangan)?} + {else} + {?=isset_or($value.keterangan)?} + {/if} + {?= number_format($value.debet,2,',','.')?} {?= number_format($value.kredit,2,',','.')?} {?= number_format($value.saldo,2,',','.')?} + {?=isset_or($value.saldo_sisi)?} {?= number_format((float) isset_or($value.saldo_normal),2,',','.')?} {/loop} {else} - Belum ada data buku besar. + {if: empty($kd_rek_filter)} + Belum ada data buku besar. + {else} + Belum ada data buku besar. + {/if} {/if}
  • + {if: isset($summary)} +
    +
    Ringkasan Buku Besar
    +
    Jumlah rekening: {?= (int) isset_or($summary.rekening_count)?}
    +
    Total debet: {?= number_format((float) isset_or($summary.total_debet),2,',','.')?}
    +
    Total kredit: {?= number_format((float) isset_or($summary.total_kredit),2,',','.')?}
    + {if: $show_saldo_akhir == 1} + {if: empty($kd_rek_filter)} +
    Total saldo akhir (D): {?= number_format((float) isset_or($summary.saldo_akhir_d),2,',','.')?}
    +
    Total saldo akhir (K): {?= number_format((float) isset_or($summary.saldo_akhir_k),2,',','.')?}
    +
    Saldo akhir (net): {?=isset_or($summary.saldo_akhir_net_side)?} {?= number_format((float) isset_or($summary.saldo_akhir_net_amount),2,',','.')?}
    + {else} +
    Saldo akhir: {?=isset_or($summary.saldo_akhir_side)?} {?= number_format((float) isset_or($summary.saldo_akhir_amount),2,',','.')?}
    + {/if} + {/if} +
    + {/if}
    @@ -87,5 +132,9 @@

    Kelola Buku Besar

    format: 'YYYY-MM-DD', locale: 'id' }); + + $(document).on('click', '.dropdown-menu', function (e) { + e.stopPropagation(); + }); }); diff --git a/plugins/keuangan/view/admin/buku.besar.print.html b/plugins/keuangan/view/admin/buku.besar.print.html index 338eb9925..da1586eac 100644 --- a/plugins/keuangan/view/admin/buku.besar.print.html +++ b/plugins/keuangan/view/admin/buku.besar.print.html @@ -43,11 +43,7 @@

    {?=isset_or($settings.nama_instansi)?}


    Laporan Buku Besar
    - {if: isset($_GET['tgl_awal']) && isset($_GET['tgl_akhir'])} - Periode {?=date('d-m-Y', strtotime($_GET['tgl_awal']))?} s/d {?=date('d-m-Y', strtotime($_GET['tgl_akhir']))?} - {else} - Periode {?=date('d-m-Y')?} s/d {?=date('d-m-Y')?} - {/if} + Periode {?=date('d-m-Y', strtotime($_GET['tgl_awal'] ?? date('Y-m-d')))?} s/d {?=date('d-m-Y', strtotime($_GET['tgl_akhir'] ?? date('Y-m-d')))?}

    @@ -56,10 +52,14 @@

    {?=isset_or($settings.nama_instansi)?}

    No. Jurnal Tanggal + {if: empty($kd_rek_filter)} + Akun + {/if} Keterangan Debet Kredit Saldo + Saldo Normal @@ -67,15 +67,42 @@

    {?=isset_or($settings.nama_instansi)?}

    {?=isset_or($value.no_jurnal)?} {?=isset_or($value.tgl_jurnal)?} - {?=isset_or($value.keterangan)?} + {if: empty($kd_rek_filter)} + {?=isset_or($value.kd_rek)?} - {?=isset_or($value.nm_rek)?} + {/if} + + {if: isset($value.row_type) && ($value.row_type == 'saldo_awal' || $value.row_type == 'saldo_akhir')} + {?=isset_or($value.keterangan)?} + {else} + {?=isset_or($value.keterangan)?} + {/if} + {?= number_format($value.debet,2,',','.')?} {?= number_format($value.kredit,2,',','.')?} {?= number_format($value.saldo,2,',','.')?} + {?=isset_or($value.saldo_sisi)?} {?= number_format((float) isset_or($value.saldo_normal),2,',','.')?} {/loop}
    + {if: isset($summary)} +
    +
    Ringkasan Buku Besar
    +
    Jumlah rekening: {?= (int) isset_or($summary.rekening_count)?}
    +
    Total debet: {?= number_format((float) isset_or($summary.total_debet),2,',','.')?}
    +
    Total kredit: {?= number_format((float) isset_or($summary.total_kredit),2,',','.')?}
    + {if: $show_saldo_akhir == 1} + {if: empty($kd_rek_filter)} +
    Total saldo akhir (D): {?= number_format((float) isset_or($summary.saldo_akhir_d),2,',','.')?}
    +
    Total saldo akhir (K): {?= number_format((float) isset_or($summary.saldo_akhir_k),2,',','.')?}
    +
    Saldo akhir (net): {?=isset_or($summary.saldo_akhir_net_side)?} {?= number_format((float) isset_or($summary.saldo_akhir_net_amount),2,',','.')?}
    + {else} +
    Saldo akhir: {?=isset_or($summary.saldo_akhir_side)?} {?= number_format((float) isset_or($summary.saldo_akhir_amount),2,',','.')?}
    + {/if} + {/if} +
    + {/if} diff --git a/plugins/keuangan/view/admin/rekening.tahun.html b/plugins/keuangan/view/admin/rekening.tahun.html index 2ca9daa37..97ab1e2c1 100644 --- a/plugins/keuangan/view/admin/rekening.tahun.html +++ b/plugins/keuangan/view/admin/rekening.tahun.html @@ -32,6 +32,16 @@

    Input Saldo Awal

    +
    +
    + + + + + + +
    +
    From 748a38bbd6946671f1b097c2de56df34d8b47579 Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 10:20:41 +0800 Subject: [PATCH 05/10] fix(bpjs-emr): make device date columns nullable update the database upgrade script to set manufacture_date and expiration_date columns for mlite_bpjs_emr_device as nullable with default null, and fix SQL syntax by using backticks instead of single quotes for column names --- systems/upgrade.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/systems/upgrade.php b/systems/upgrade.php index f8ae963be..ed165346d 100644 --- a/systems/upgrade.php +++ b/systems/upgrade.php @@ -1874,8 +1874,8 @@ function rrmdir($dir) `keterangan` TEXT DEFAULT NULL, `manufacturer` TEXT DEFAULT NULL, `model` TEXT DEFAULT NULL, - 'manufacture_date' TEXT NOT NULL, - 'expiration_date' TEXT NOT NULL + `manufacture_date` TEXT DEFAULT NULL, + `expiration_date` TEXT DEFAULT NULL );"); $this->core->db()->pdo()->exec("CREATE INDEX IF NOT EXISTS `idx_bpjs_emr_device_nama_alkes` ON `mlite_bpjs_emr_device` (`nama_alkes`);"); $this->core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `mlite_bpjs_emr_logs` ( @@ -1950,8 +1950,8 @@ function rrmdir($dir) try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur_ranap` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_operasi` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` TEXT NOT NULL;"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` TEXT NOT NULL;"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` TEXT DEFAULT NULL;"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` TEXT DEFAULT NULL;"); } catch (\Exception $e) {} } else { // Kapabilitas MySQL sejak 6.2.0 $this->core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `mlite_mini_pacs_study` ( @@ -2121,8 +2121,8 @@ function rrmdir($dir) `keterangan` text DEFAULT NULL, `manufacturer` varchar(255) DEFAULT NULL, `model` varchar(255) DEFAULT NULL, - 'manufacture_date' DATE NOT NULL, - 'expiration_date' DATE NOT NULL, + `manufacture_date` DATE DEFAULT NULL, + `expiration_date` DATE DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uq_device_id` (`device_id`), KEY `idx_nama_alkes` (`nama_alkes`) @@ -2148,8 +2148,8 @@ function rrmdir($dir) try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur_ranap` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_operasi` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` DATE NOT NULL"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` DATE NOT NULL"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` DATE DEFAULT NULL"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` DATE DEFAULT NULL"); } catch (\Exception $e) {} $this->core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `mlite_bpjs_emr_uuid_condition` ( `kd_penyakit` varchar(15) NOT NULL, `uuid` varchar(200) DEFAULT NULL @@ -2219,16 +2219,16 @@ function rrmdir($dir) try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur_ranap` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_operasi` ADD COLUMN `master_device_id` INTEGER DEFAULT NULL;"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` TEXT NOT NULL;"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` TEXT NOT NULL;"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` TEXT DEFAULT NULL;"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` TEXT DEFAULT NULL;"); } catch (\Exception $e) {} } else { try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_lab` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_radiologi` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_prosedur_ranap` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_mapping_operasi` ADD COLUMN `master_device_id` int DEFAULT NULL"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` DATE NOT NULL"); } catch (\Exception $e) {} - try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` DATE NOT NULL"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `manufacture_date` DATE DEFAULT NULL"); } catch (\Exception $e) {} + try { $this->core->db()->pdo()->exec("ALTER TABLE `mlite_bpjs_emr_device` ADD COLUMN `expiration_date` DATE DEFAULT NULL"); } catch (\Exception $e) {} } $return = '6.3.1'; break; From ac15b1300eed4d3384a05d32d8b2d8d1718aefcf Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 10:21:53 +0800 Subject: [PATCH 06/10] Update --- systems/upgrade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/systems/upgrade.php b/systems/upgrade.php index ed165346d..e3a31e3e1 100644 --- a/systems/upgrade.php +++ b/systems/upgrade.php @@ -2172,7 +2172,7 @@ function rrmdir($dir) PRIMARY KEY (`id`), KEY `ref_idx` (`ref_type`,`ref_id`), KEY `hash_idx` (`signature_hash`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;"); + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"); $this->core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `mlite_sertisign_webhook` ( `id` int NOT NULL AUTO_INCREMENT, `transaction_id` varchar(100) NOT NULL, @@ -2183,7 +2183,7 @@ function rrmdir($dir) PRIMARY KEY (`id`), KEY `transaction_idx` (`transaction_id`), KEY `status_idx` (`status`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;"); + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;"); $this->core->db()->pdo()->exec("CREATE TABLE IF NOT EXISTS `mlite_mapping_snomed_icd` ( `id` int NOT NULL AUTO_INCREMENT, `no_rawat` varchar(20) NOT NULL, From 717c99b0f472afa8d88ac7f596f28a4f84a35a1a Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 20:09:59 +0800 Subject: [PATCH 07/10] Update --- plugins/keuangan/README.md | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/plugins/keuangan/README.md b/plugins/keuangan/README.md index c24e88caa..23035c5c9 100644 --- a/plugins/keuangan/README.md +++ b/plugins/keuangan/README.md @@ -66,6 +66,87 @@ Admin mengelola master data dan konfigurasi: - Atur akun default modul keuangan (mis. akun kredit layanan). - Simpan perubahan konfigurasi. +## Simulasi Penggunaan Tanpa Data Dummy (Tahun 2026) + +Bagian ini contoh alur pengisian jika Anda memulai dari nol (tanpa “Data Dummy Keuangan”) untuk tahun 2026. + +### A. Pengaturan Akun Rekening + +Buat minimal beberapa akun berikut: + +- **1101 Kas Umum** (Aktiva; tipe: N; saldo normal/balance: D) +- **1201 Bank** (opsional) (Aktiva; tipe: N; balance: D) +- **3101 Modal Disetor** (Modal; tipe: N; balance: K) +- **4101 Pendapatan Jasa** (Pendapatan; tipe: R; balance: K) +- **5101 Biaya Operasional** (Beban; tipe: R; balance: D) +- **2101 Hutang Usaha** (opsional) (Hutang; tipe: N; balance: K) + +Catatan: +- Tipe **N** = akun Neraca (Aktiva/Hutang/Modal). +- Tipe **R** = akun Laba-Rugi (Pendapatan/Beban). + +### B. Pengaturan Rekening Tahun (Saldo Awal 2026) + +Menu: **Keuangan → Rekening Tahun** → pilih tahun **2026**. + +Contoh saldo awal yang seimbang: +- 1101 Kas Umum = 10.000.000 +- 3101 Modal Disetor = 10.000.000 + +Jika saldo awal tidak seimbang, laporan Neraca akan menampilkan peringatan selisih. + +### C. Pengaturan Kegiatan (Pengaturan Rekening / Input Kegiatan) + +Menu: **Keuangan → Pengaturan Rekening**. + +Tujuan kegiatan adalah pengelompokan aktivitas (umumnya untuk pelaporan arus kas/kegiatan). + +Contoh set minimal: +- Penerimaan Jasa → mapping rekening **4101** +- Biaya Operasional → mapping rekening **5101** +- Pembelian Kredit (opsional) → mapping rekening **2101** atau rekening beban terkait + +### D. Contoh Pengisian Jurnal (Dana Masuk & Dana Keluar) + +Menu: **Keuangan → Posting Jurnal** (atau input jurnal sesuai alur di instalasi Anda). + +Pastikan setiap jurnal memiliki minimal 2 baris dan **Total Debet = Total Kredit**. + +#### 1) Dana Masuk (Penerimaan Jasa Tunai) + +- Tanggal: 2026-01-05 +- Keterangan: Penerimaan jasa tunai +- Detail: + - Debet 1101 Kas Umum = 2.000.000 + - Kredit 4101 Pendapatan Jasa = 2.000.000 + +#### 2) Dana Keluar (Biaya Operasional Dibayar Tunai) + +- Tanggal: 2026-01-06 +- Keterangan: Bayar listrik/ATK +- Detail: + - Debet 5101 Biaya Operasional = 500.000 + - Kredit 1101 Kas Umum = 500.000 + +#### 3) Dana Keluar (Pembelian Kredit / Timbul Hutang) (Opsional) + +- Tanggal: 2026-01-10 +- Keterangan: Pembelian perlengkapan secara kredit +- Detail: + - Debet 5101 Biaya Operasional = 1.200.000 + - Kredit 2101 Hutang Usaha = 1.200.000 + +### E. Cara Validasi Output Laporan + +- **Buku Besar**: + - Pilih 1101 untuk melihat saldo kas (saldo awal + mutasi). + - Pilih 4101 untuk melihat total pendapatan. + - Pilih 5101 untuk melihat total biaya. +- **Neraca Keuangan** (periode 01-01-2026 s/d tanggal akhir): + - Aktiva harus sama dengan Pasiva + Modal (laba/rugi periode muncul sebagai penyesuaian modal). +- **Cash Flow**: + - Jurnal “Dana Masuk” muncul di arus masuk, jurnal “Dana Keluar” muncul di arus keluar. + ## Catatan - Gunakan data akun dan jurnal yang valid agar laporan Cash Flow dan Neraca akurat. From 0b7514cab2bf741b8922ee2889b9092bd69b9aee Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 20:21:10 +0800 Subject: [PATCH 08/10] Update --- plugins/surat/Admin.php | 15 +++++++++++---- plugins/surat/view/admin/sakit.manage.html | 3 ++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/surat/Admin.php b/plugins/surat/Admin.php index 943a5b6c2..026738909 100644 --- a/plugins/surat/Admin.php +++ b/plugins/surat/Admin.php @@ -78,7 +78,9 @@ public function anyRujukan($page = 1) $this->assign['searchURL'] = url([ADMIN, 'surat', 'rujukan']); $this->assign['addURL'] = url([ADMIN, 'surat', 'rujukanadd']); $this->assign['phrase'] = $phrase; - return $this->draw('rujukan.manage.html', ['rujukan' => htmlspecialchars_array($this->assign)]); + $assign = htmlspecialchars_array($this->assign); + $assign['pagination'] = $this->assign['pagination']; + return $this->draw('rujukan.manage.html', ['rujukan' => $assign]); } public function getRujukanAdd() @@ -220,6 +222,7 @@ public function anySakit($page = 1) if (count($rows)) { foreach ($rows as $row) { $row = htmlspecialchars_array($row); + $row['printURL'] = url([ADMIN, 'surat', 'suratsakit', convertNorawat($row['no_rawat'])]); $row['editURL'] = url([ADMIN, 'surat', 'sakitedit', $row['id']]); $row['deleteURL'] = url([ADMIN, 'surat', 'sakithapus', $row['id']]); $this->assign['list'][] = $row; @@ -229,7 +232,9 @@ public function anySakit($page = 1) $this->assign['searchURL'] = url([ADMIN, 'surat', 'sakit']); $this->assign['addURL'] = url([ADMIN, 'surat', 'sakitadd']); $this->assign['phrase'] = $phrase; - return $this->draw('sakit.manage.html', ['sakit' => htmlspecialchars_array($this->assign)]); + $assign = htmlspecialchars_array($this->assign); + $assign['pagination'] = $this->assign['pagination']; + return $this->draw('sakit.manage.html', ['sakit' => $assign]); } public function getSakitAdd() @@ -378,7 +383,9 @@ public function anySehat($page = 1) $this->assign['searchURL'] = url([ADMIN, 'surat', 'sehat']); $this->assign['addURL'] = url([ADMIN, 'surat', 'sehatadd']); $this->assign['phrase'] = $phrase; - return $this->draw('sehat.manage.html', ['sehat' => htmlspecialchars_array($this->assign)]); + $assign = htmlspecialchars_array($this->assign); + $assign['pagination'] = $this->assign['pagination']; + return $this->draw('sehat.manage.html', ['sehat' => $assign]); } public function getSehatAdd() @@ -526,4 +533,4 @@ private function _addHeaderFiles() $this->core->addJS(url('assets/jscripts/jquery.dataTables.min.js')); $this->core->addJS(url('assets/jscripts/dataTables.bootstrap.min.js')); } -} \ No newline at end of file +} diff --git a/plugins/surat/view/admin/sakit.manage.html b/plugins/surat/view/admin/sakit.manage.html index d1561f20a..7b047d7ad 100644 --- a/plugins/surat/view/admin/sakit.manage.html +++ b/plugins/surat/view/admin/sakit.manage.html @@ -45,6 +45,7 @@

    Jumlah: {?=count($sakit.totalReco

    @@ -62,4 +63,4 @@

    Jumlah: {?=count($sakit.totalReco - \ No newline at end of file + From 6ad388c895f5ece4165653db180de3b402b164cd Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 20:28:47 +0800 Subject: [PATCH 09/10] feat(surat): add print buttons and fix print styling Add print URL generation for health and referral certificates in the backend admin controller, add print action buttons to their respective management tables, fix trailing newlines in template files, and update print styling in the sick certificate view to hide the e-signature button alongside save and print buttons when printing. --- plugins/surat/Admin.php | 2 ++ plugins/surat/view/admin/rujukan.manage.html | 3 ++- plugins/surat/view/admin/sehat.manage.html | 3 ++- plugins/surat/view/admin/surat.sakit.html | 4 ++-- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/surat/Admin.php b/plugins/surat/Admin.php index 026738909..58a502591 100644 --- a/plugins/surat/Admin.php +++ b/plugins/surat/Admin.php @@ -69,6 +69,7 @@ public function anyRujukan($page = 1) if (count($rows)) { foreach ($rows as $row) { $row = htmlspecialchars_array($row); + $row['printURL'] = url([ADMIN, 'surat', 'suratrujukan', convertNorawat($row['no_rawat'])]); $row['editURL'] = url([ADMIN, 'surat', 'rujukanedit', $row['id']]); $row['deleteURL'] = url([ADMIN, 'surat', 'rujukanhapus', $row['id']]); $this->assign['list'][] = $row; @@ -374,6 +375,7 @@ public function anySehat($page = 1) if (count($rows)) { foreach ($rows as $row) { $row = htmlspecialchars_array($row); + $row['printURL'] = url([ADMIN, 'surat', 'suratsehat', convertNorawat($row['no_rawat'])]); $row['editURL'] = url([ADMIN, 'surat', 'sehatedit', $row['id']]); $row['deleteURL'] = url([ADMIN, 'surat', 'sehathapus', $row['id']]); $this->assign['list'][] = $row; diff --git a/plugins/surat/view/admin/rujukan.manage.html b/plugins/surat/view/admin/rujukan.manage.html index c3e2a6463..9aa64b10d 100644 --- a/plugins/surat/view/admin/rujukan.manage.html +++ b/plugins/surat/view/admin/rujukan.manage.html @@ -45,6 +45,7 @@

    Jumlah: {?=count($rujukan.totalRe

    @@ -62,4 +63,4 @@

    Jumlah: {?=count($rujukan.totalRe - \ No newline at end of file + diff --git a/plugins/surat/view/admin/sehat.manage.html b/plugins/surat/view/admin/sehat.manage.html index 4ca3a9ffe..828863094 100644 --- a/plugins/surat/view/admin/sehat.manage.html +++ b/plugins/surat/view/admin/sehat.manage.html @@ -45,6 +45,7 @@

    Jumlah: {?=count($sehat.totalReco

    @@ -62,4 +63,4 @@

    Jumlah: {?=count($sehat.totalReco - \ No newline at end of file + diff --git a/plugins/surat/view/admin/surat.sakit.html b/plugins/surat/view/admin/surat.sakit.html index bb97a3f79..56609de38 100644 --- a/plugins/surat/view/admin/surat.sakit.html +++ b/plugins/surat/view/admin/surat.sakit.html @@ -13,7 +13,7 @@ font-family: georgia; } @media print { - #saveButton, #printPageButton { + #saveButton, #printPageButton, #signButton { display: none; } textarea { @@ -173,4 +173,4 @@

    ▣ Simpan - + From e0b7f5e26292d61b88b776c62e9306556edb12b5 Mon Sep 17 00:00:00 2001 From: Basoro Date: Wed, 27 May 2026 20:49:10 +0800 Subject: [PATCH 10/10] feat(kasir_rawat_jalan): add shift recap report and enhance print outputs Add new menu entry for shift recap report Add new shift recap report page with date range filtering Implement CSV export for shift report data Update existing cashier report to include institution branding header when printing Pass site settings to all report templates for dynamic header content Refactor print JavaScript function to reuse the institution header template --- plugins/kasir_rawat_jalan/Admin.php | 31 +++- .../kasir_rawat_jalan/view/admin/report.html | 34 +++- .../view/admin/shift.report.html | 157 ++++++++++++++++++ 3 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 plugins/kasir_rawat_jalan/view/admin/shift.report.html diff --git a/plugins/kasir_rawat_jalan/Admin.php b/plugins/kasir_rawat_jalan/Admin.php index 425dca836..1568ec36f 100644 --- a/plugins/kasir_rawat_jalan/Admin.php +++ b/plugins/kasir_rawat_jalan/Admin.php @@ -17,6 +17,7 @@ public function navigation() 'Kelola' => 'manage', 'Kasir' => 'shift', 'Laporan' => 'report', + 'Rekap Shift' => 'shiftreport', ]; } @@ -2298,7 +2299,7 @@ public function anyReport() $detailStmt->execute([$awal, $akhir]); $details = $detailStmt->fetchAll(); - return $this->draw('report.html', ['awal' => $awal, 'akhir' => $akhir, 'rows' => $rows, 'details' => $details]); + return $this->draw('report.html', ['awal' => $awal, 'akhir' => $akhir, 'rows' => $rows, 'details' => $details, 'settings' => $this->settings('settings')]); } public function anyReportExport() @@ -2317,4 +2318,32 @@ public function anyReportExport() exit(); } + public function anyShiftReport() + { + $this->_addHeaderFiles(); + $awal = isset($_GET['awal']) ? $_GET['awal'] : date('Y-m-d').' 00:00:00'; + $akhir = isset($_GET['akhir']) ? $_GET['akhir'] : date('Y-m-d').' 23:59:59'; + $pdo = $this->db()->pdo(); + $stmt = $pdo->prepare("SELECT s.id_shift, s.user_id, COALESCE(p.nama, u.fullname) AS nama_kasir, s.waktu_buka, s.waktu_tutup, IFNULL(s.kas_awal,0) kas_awal, IFNULL(s.total_transaksi,0) total_transaksi, IFNULL(s.kas_akhir,0) kas_akhir, IFNULL(s.selisih,0) selisih, s.keterangan FROM mlite_kasir_shift s LEFT JOIN mlite_users u ON u.id=s.user_id LEFT JOIN pegawai p ON p.nik=u.username WHERE (s.waktu_buka BETWEEN ? AND ?) OR (s.waktu_tutup BETWEEN ? AND ?) OR (s.waktu_buka <= ? AND (s.waktu_tutup IS NULL OR s.waktu_tutup >= ?)) ORDER BY s.waktu_buka ASC, s.id_shift ASC"); + $stmt->execute([$awal, $akhir, $awal, $akhir, $awal, $akhir]); + $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC); + return $this->draw('shift.report.html', ['awal' => $awal, 'akhir' => $akhir, 'rows' => $rows, 'settings' => $this->settings('settings')]); + } + + public function anyShiftReportExport() + { + $awal = isset($_GET['awal']) ? $_GET['awal'] : date('Y-m-d').' 00:00:00'; + $akhir = isset($_GET['akhir']) ? $_GET['akhir'] : date('Y-m-d').' 23:59:59'; + header('Content-Type: text/csv'); + header('Content-Disposition: attachment; filename="rekap_shift_kasir.csv"'); + $pdo = $this->db()->pdo(); + $stmt = $pdo->prepare("SELECT s.id_shift, s.user_id, COALESCE(p.nama, u.fullname) AS nama_kasir, s.waktu_buka, s.waktu_tutup, IFNULL(s.kas_awal,0) kas_awal, IFNULL(s.total_transaksi,0) total_transaksi, IFNULL(s.kas_akhir,0) kas_akhir, IFNULL(s.selisih,0) selisih, s.keterangan FROM mlite_kasir_shift s LEFT JOIN mlite_users u ON u.id=s.user_id LEFT JOIN pegawai p ON p.nik=u.username WHERE (s.waktu_buka BETWEEN ? AND ?) OR (s.waktu_tutup BETWEEN ? AND ?) OR (s.waktu_buka <= ? AND (s.waktu_tutup IS NULL OR s.waktu_tutup >= ?)) ORDER BY s.waktu_buka ASC, s.id_shift ASC"); + $stmt->execute([$awal, $akhir, $awal, $akhir, $awal, $akhir]); + echo "id_shift,user_id,nama_kasir,waktu_buka,waktu_tutup,kas_awal,total_transaksi,kas_akhir,selisih,keterangan\n"; + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + echo ($row['id_shift'] ?? '').",".($row['user_id'] ?? '').",\"".str_replace('\"', '\"\"', (string)($row['nama_kasir'] ?? ''))."\",".($row['waktu_buka'] ?? '').",".($row['waktu_tutup'] ?? '').",".($row['kas_awal'] ?? 0).",".($row['total_transaksi'] ?? 0).",".($row['kas_akhir'] ?? 0).",".($row['selisih'] ?? 0).",\"".str_replace('\"', '\"\"', (string)($row['keterangan'] ?? ''))."\"\n"; + } + exit(); + } + } diff --git a/plugins/kasir_rawat_jalan/view/admin/report.html b/plugins/kasir_rawat_jalan/view/admin/report.html index 52e8f3800..5b2e7d7fe 100644 --- a/plugins/kasir_rawat_jalan/view/admin/report.html +++ b/plugins/kasir_rawat_jalan/view/admin/report.html @@ -26,6 +26,37 @@

    Laporan Kasir


    +

    {?=isset_or($value.lama_angka)?} {?=isset_or($value.lama_huruf)?} {?=isset_or($value.dokter)?} + Cetak Edit Hapus {?=isset_or($value.diagnosa)?} {?=isset_or($value.dokter)?} + Cetak Edit Hapus {?=isset_or($value.keperluan)?} {?=isset_or($value.dokter)?} + Cetak Edit Hapus
    + + + + + + + + + + + + +
    + + +

    + {?=isset_or($settings.nama_instansi)?}
    + Alamat: {?=isset_or($settings.alamat)?} - {?=isset_or($settings.kota)?} - {?=isset_or($settings.propinsi)?}
    + Telepon: {?=isset_or($settings.nomor_telepon)?} - Email: {?=isset_or($settings.email)?} +

    +
    +
    +
    +
    LAPORAN KASIR RAWAT JALAN
    +
    Periode {?=isset_or($awal)?} s/d {?=isset_or($akhir)?}
    +
    +
    +
    @@ -91,8 +122,9 @@

    Laporan Kasir

    function printContent(el){ var restore = document.body.innerHTML; + var kop = document.getElementById('kop_print') ? document.getElementById('kop_print').innerHTML : ''; var content = document.getElementById(el).innerHTML; - document.body.innerHTML = content; + document.body.innerHTML = kop + content; window.print(); document.body.innerHTML = restore; } diff --git a/plugins/kasir_rawat_jalan/view/admin/shift.report.html b/plugins/kasir_rawat_jalan/view/admin/shift.report.html new file mode 100644 index 000000000..d37b6b09b --- /dev/null +++ b/plugins/kasir_rawat_jalan/view/admin/shift.report.html @@ -0,0 +1,157 @@ +
    +
    +

    Rekap Shift Kasir

    +
    +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    + + Export CSV + +
    +
    +
    + +
    +
    + + + + + + + + + + + + +
    + + +

    + {?=isset_or($settings.nama_instansi)?}
    + Alamat: {?=isset_or($settings.alamat)?} - {?=isset_or($settings.kota)?} - {?=isset_or($settings.propinsi)?}
    + Telepon: {?=isset_or($settings.nomor_telepon)?} - Email: {?=isset_or($settings.email)?} +

    +
    +
    +
    +
    REKAP SHIFT KASIR RAWAT JALAN
    +
    Periode {?=isset_or($awal)?} s/d {?=isset_or($akhir)?}
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ID ShiftID KasirNama KasirWaktu BukaWaktu TutupStatusKas AwalTotal TransaksiKas AkhirSelisihKeterangan
    Total
    +
    + + + +