add pengambilan co dari fa_class

This commit is contained in:
Hanan Askarim
2026-07-14 10:28:24 +07:00
committed by sasadib
parent efdf8af569
commit aef86b7acf

View File

@@ -3,23 +3,103 @@
/** /**
* JurnalPiCicilanOrderAset * JurnalPiCicilanOrderAset
* *
* Endpoint scheduler untuk membuat jurnal PI cicilan order aset. * Controller scheduler untuk membuat jurnal akuntansi atas Purchase Invoice (PI)
* Controller ini dibuat agar bisa dipanggil via cURL dari proses generator. * cicilan order aset secara otomatis.
*
* Alur bisnis proses:
* 1. Validasi parameter input (tanggal, branchCode, title, description, details)
* 2. Insert header jurnal ke tabel `jurnal`
* - Nomor jurnal di-generate via fn_numbering('J')
* - Tipe jurnal: PAYMENT
* - Berisi: title, description, tanggal, regionalID, kode cabang, branchCompanyID
* 3. Insert baris transaksi ke tabel `jurnal_tx` (untuk setiap baris cicilan)
* - Referensi ke jurnalID header
* - COA (Chart of Account) dan deskripsinya:
* * Sisi hutang cicilan → nilai DEBIT
* * Sisi pembayaran cicilan → nilai KREDIT
* 4. Insert data tambahan ke tabel `jurnal_addon` (jika ada addonValue atau mItemID)
* - Referensi ke jurnalID dan jurnalTxID
* - Berisi: addonCode (default: "PICICIL"), addonValue, mItemID
*
* Endpoint:
* POST /mockup/scheduler/JurnalPiCicilanOrderAset/CreateJournal
* POST /mockup/scheduler/JurnalPiCicilanOrderAset/CreatePiInstallmentJournal
* GET /mockup/scheduler/JurnalPiCicilanOrderAset/ListEligiblePurchaseOrderAssetContracts
*/ */
class JurnalPiCicilanOrderAset extends MY_Controller class JurnalPiCicilanOrderAset extends MY_Controller
{ {
var $db; var $db;
/**
* Endpoint default — menampilkan nama controller sebagai penanda aktif.
*/
public function index() public function index()
{ {
echo "Jurnal PI Cicilan Order Aset"; echo "Jurnal PI Cicilan Order Aset";
} }
/**
* Konstruktor — inisialisasi parent controller.
*/
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
} }
/**
* CreateJournal — Membuat jurnal PI cicilan order aset.
*
* Proses bisnis:
* 1. Validasi semua parameter wajib: date, branchCode, title, description, details
* 2. Ambil periodeID dari tanggal transaksi (tabel periode)
* 3. Ambil regionalID dari branchCode (tabel m_branch)
* 4. Ambil branchCompanyID dari branchCode (tabel m_branch_companydetail)
* 5. Ambil jurnalTypeID dari kode tipe jurnal (default: "PAYMENT")
* 6. Generate nomor jurnal otomatis via fn_numbering('J')
* 7. Validasi balance: total debit harus sama dengan total credit
* 8. INSERT header jurnal ke tabel `jurnal`:
* - jurnalNo : nomor jurnal hasil generate
* - jurnalJurnalTypeID: tipe PAYMENT
* - jurnalTitle : judul jurnal
* - jurnalDescription: keterangan jurnal
* - jurnalDate : tanggal transaksi
* - JurnalS_RegionalID: ID regional cabang
* - jurnalM_BranchCode: kode cabang
* 9. Untuk setiap baris detail, INSERT ke `jurnal_tx`:
* - jurnalTxJurnalID : referensi ke header jurnal
* - jurnalTxCoaID : COA yang digunakan (hutang cicilan / kas/bank)
* - jurnalTxDescription: keterangan baris (nama cicilan/aset)
* - jurnalTxDebit : nilai hutang (sisi debit)
* - jurnalTxCredit : nilai bayar (sisi kredit)
* 10. Jika ada addonValue atau mItemID, INSERT ke `jurnal_addon`:
* - jurnalAddOnJurnalID : referensi ke header jurnal
* - jurnalAddOnJurnalTxID: referensi ke baris jurnal_tx
* - jurnalAddOnCode : kode addon (default: "PICICIL")
* - jurnalAddOnValue : nilai tambahan (misal: nomor PI/kontrak)
* - jurnalAddOnM_ItemID : ID item aset yang terkait
*
* Parameter (POST JSON):
* - date : Tanggal jurnal (YYYY-MM-DD). Default: hari ini.
* - branchCode : Kode cabang. WAJIB.
* - title : Judul jurnal. WAJIB.
* - description : Keterangan jurnal. WAJIB.
* - details : Array baris transaksi. WAJIB, minimal 1 baris.
* - coaID : ID Chart of Account. WAJIB per baris.
* - description : Keterangan baris.
* - debit : Nilai debit (hutang cicilan).
* - credit : Nilai kredit (pembayaran cicilan).
* - addonValue : (opsional) Nilai addon, misal nomor PI.
* - mItemID : (opsional) ID item aset.
* - addonCode : (opsional) Kode addon. Default: "PICICIL".
* - periodeID : (opsional) ID periode. Default: diambil dari tanggal.
* - regionalID : (opsional) ID regional. Default: diambil dari branchCode.
* - branchCompanyID: (opsional) ID branch company. Default: diambil dari branchCode.
* - jurnalTypeID : (opsional) ID tipe jurnal. Default: diambil dari jurnalTypeCode.
* - jurnalTypeCode: (opsional) Kode tipe jurnal. Default: "PAYMENT".
* - userID : ID user yang membuat jurnal.
*
* @return JSON { jurnalID, jurnalNo, detailCount, addonCount }
*/
public function CreateJournal() public function CreateJournal()
{ {
try { try {
@@ -78,21 +158,22 @@ class JurnalPiCicilanOrderAset extends MY_Controller
throw new Exception("jurnalTypeID / jurnalTypeCode tidak valid."); throw new Exception("jurnalTypeID / jurnalTypeCode tidak valid.");
} }
$userID = isset($para["userID"]) ? (int) $para["userID"] : 0; $userID = isset($para["userID"]) ? (int) $para["userID"] : 0;
$jurnalNo = $this->generateJournalNumber(); $jurnalNo = $this->generateJournalNumber();
if ($jurnalNo === false || $jurnalNo == "") { if ($jurnalNo === false || $jurnalNo == "") {
throw new Exception("Gagal generate nomor jurnal."); throw new Exception("Gagal generate nomor jurnal.");
} }
$totalDebit = 0; // Validasi balance: total debit harus sama dengan total credit
$totalDebit = 0;
$totalCredit = 0; $totalCredit = 0;
foreach ($details as $idx => $detail) { foreach ($details as $idx => $detail) {
$debit = isset($detail["debit"]) ? (float) $detail["debit"] : 0; $debit = isset($detail["debit"]) ? (float) $detail["debit"] : 0;
$credit = isset($detail["credit"]) ? (float) $detail["credit"] : 0; $credit = isset($detail["credit"]) ? (float) $detail["credit"] : 0;
if ($debit < 0 || $credit < 0) { if ($debit < 0 || $credit < 0) {
throw new Exception("Nilai debit/credit tidak boleh negatif pada detail ke-" . ($idx + 1)); throw new Exception("Nilai debit/credit tidak boleh negatif pada detail ke-" . ($idx + 1));
} }
$totalDebit += $debit; $totalDebit += $debit;
$totalCredit += $credit; $totalCredit += $credit;
} }
@@ -102,6 +183,9 @@ class JurnalPiCicilanOrderAset extends MY_Controller
$this->db->trans_begin(); $this->db->trans_begin();
// -----------------------------------------------------------------
// INSERT header jurnal ke tabel `jurnal`
// -----------------------------------------------------------------
$sqlHeader = "INSERT INTO jurnal ( $sqlHeader = "INSERT INTO jurnal (
jurnalM_BranchCompanyID, jurnalM_BranchCompanyID,
JurnalS_RegionalID, JurnalS_RegionalID,
@@ -134,14 +218,17 @@ class JurnalPiCicilanOrderAset extends MY_Controller
exit; exit;
} }
$jurnalID = $this->db->insert_id(); $jurnalID = $this->db->insert_id();
$createdAddonCount = 0; $createdAddonCount = 0;
// -----------------------------------------------------------------
// INSERT baris transaksi ke tabel `jurnal_tx` (per baris cicilan)
// -----------------------------------------------------------------
foreach ($details as $idx => $detail) { foreach ($details as $idx => $detail) {
$coaID = isset($detail["coaID"]) ? (int) $detail["coaID"] : 0; $coaID = isset($detail["coaID"]) ? (int) $detail["coaID"] : 0;
$descriptionTx = isset($detail["description"]) ? trim($detail["description"]) : ""; $descriptionTx = isset($detail["description"]) ? trim($detail["description"]) : "";
$debit = isset($detail["debit"]) ? (float) $detail["debit"] : 0; $debit = isset($detail["debit"]) ? (float) $detail["debit"] : 0;
$credit = isset($detail["credit"]) ? (float) $detail["credit"] : 0; $credit = isset($detail["credit"]) ? (float) $detail["credit"] : 0;
if ($coaID <= 0) { if ($coaID <= 0) {
$this->db->trans_rollback(); $this->db->trans_rollback();
@@ -149,6 +236,8 @@ class JurnalPiCicilanOrderAset extends MY_Controller
exit; exit;
} }
// Sisi debit = hutang cicilan (COA hutang)
// Sisi kredit = pembayaran cicilan (COA kas/bank)
$sqlTx = "INSERT INTO jurnal_tx ( $sqlTx = "INSERT INTO jurnal_tx (
jurnalTxJurnalID, jurnalTxJurnalID,
jurnalTxCoaID, jurnalTxCoaID,
@@ -175,9 +264,13 @@ class JurnalPiCicilanOrderAset extends MY_Controller
$jurnalTxID = $this->db->insert_id(); $jurnalTxID = $this->db->insert_id();
$addonValue = isset($detail["addonValue"]) ? trim($detail["addonValue"]) : ""; // -----------------------------------------------------------------
$mItemID = isset($detail["mItemID"]) ? (int) $detail["mItemID"] : 0; // INSERT data tambahan ke tabel `jurnal_addon` (jika ada)
$addonCode = isset($detail["addonCode"]) && $detail["addonCode"] != "" ? trim($detail["addonCode"]) : "PICICIL"; // Diisi jika ada addonValue (misal nomor PI) atau mItemID (ID aset)
// -----------------------------------------------------------------
$addonValue = isset($detail["addonValue"]) ? trim($detail["addonValue"]) : "";
$mItemID = isset($detail["mItemID"]) ? (int) $detail["mItemID"] : 0;
$addonCode = isset($detail["addonCode"]) && $detail["addonCode"] != "" ? trim($detail["addonCode"]) : "PICICIL";
if ($addonValue != "" || $mItemID > 0) { if ($addonValue != "" || $mItemID > 0) {
$sqlAddon = "INSERT INTO jurnal_addon ( $sqlAddon = "INSERT INTO jurnal_addon (
@@ -216,21 +309,50 @@ class JurnalPiCicilanOrderAset extends MY_Controller
$this->db->trans_commit(); $this->db->trans_commit();
$this->sys_ok([ $this->sys_ok([
"jurnalID" => $jurnalID, "jurnalID" => $jurnalID,
"jurnalNo" => $jurnalNo, "jurnalNo" => $jurnalNo,
"detailCount" => count($details), "detailCount" => count($details),
"addonCount" => $createdAddonCount "addonCount" => $createdAddonCount
]); ]);
} catch (Exception $exc) { } catch (Exception $exc) {
$this->sys_error($exc->getMessage()); $this->sys_error($exc->getMessage());
} }
} }
/**
* CreatePiInstallmentJournal — Alias dari CreateJournal.
*
* Endpoint alternatif dengan nama yang lebih spesifik untuk konteks
* pembuatan jurnal PI cicilan order aset. Memanggil CreateJournal secara langsung.
*
* @see CreateJournal()
*/
public function CreatePiInstallmentJournal() public function CreatePiInstallmentJournal()
{ {
$this->CreateJournal(); $this->CreateJournal();
} }
/**
* ListEligiblePurchaseOrderAssetContracts — Menampilkan daftar kontrak aset
* yang memenuhi syarat untuk dibuatkan jurnal PI cicilan pada periode tertentu.
*
* Syarat kontrak eligible:
* - Kontrak aktif dan berstatus "belum lunas"
* - Nilai cicilan > 0
* - Jumlah cicilan terbayar < total cicilan
* - Tanggal kontrak masuk dalam rentang startDateendDate
* - PO sudah berstatus Approved
* - Barang sudah diterima (receive_order_po sudah confirmed)
*
* Endpoint ini digunakan untuk preview/verifikasi sebelum proses generate jurnal
* dijalankan secara massal oleh CRON.
*
* Parameter (GET/POST):
* - startDate : Awal periode (YYYY-MM-DD). Default: tanggal 1 bulan ini.
* - endDate : Akhir periode (YYYY-MM-DD). Default: tanggal akhir bulan ini.
*
* @return JSON { startDate, endDate, total, records[] }
*/
public function ListEligiblePurchaseOrderAssetContracts() public function ListEligiblePurchaseOrderAssetContracts()
{ {
try { try {
@@ -255,15 +377,27 @@ class JurnalPiCicilanOrderAset extends MY_Controller
$this->sys_ok([ $this->sys_ok([
"startDate" => $startDate, "startDate" => $startDate,
"endDate" => $endDate, "endDate" => $endDate,
"total" => count($records), "total" => count($records),
"records" => $records "records" => $records
]); ]);
} catch (Exception $exc) { } catch (Exception $exc) {
$this->sys_error($exc->getMessage()); $this->sys_error($exc->getMessage());
} }
} }
// =========================================================================
// FUNGSI PRIVATE / HELPER
// =========================================================================
/**
* generateJournalNumber — Generate nomor jurnal otomatis.
*
* Memanggil stored function MySQL fn_numbering('J') untuk mendapatkan
* nomor jurnal berikutnya sesuai urutan penomoran yang berlaku.
*
* @return string|false Nomor jurnal (misal: "J/2025/07/0001"), atau false jika gagal.
*/
private function generateJournalNumber() private function generateJournalNumber()
{ {
$qry = $this->db->query("SELECT fn_numbering('J') AS JNumber"); $qry = $this->db->query("SELECT fn_numbering('J') AS JNumber");
@@ -273,6 +407,15 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return $qry->row_array()["JNumber"]; return $qry->row_array()["JNumber"];
} }
/**
* getPeriodeIDByDate — Ambil ID periode akuntansi berdasarkan tanggal transaksi.
*
* Periode diambil dari tabel `periode` yang aktif dan mencakup tanggal yang diberikan.
* Digunakan untuk mengisi field jurnalperiodeID pada header jurnal.
*
* @param string $date Tanggal transaksi (format YYYY-MM-DD)
* @return int periodeID yang sesuai, atau 0 jika tidak ditemukan
*/
private function getPeriodeIDByDate($date) private function getPeriodeIDByDate($date)
{ {
$sql = "SELECT periodeID $sql = "SELECT periodeID
@@ -287,6 +430,15 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return (int) $qry->row_array()["periodeID"]; return (int) $qry->row_array()["periodeID"];
} }
/**
* getBranchCompanyIDByBranchCode — Ambil ID branch company berdasarkan kode cabang.
*
* Data diambil dari tabel `m_branch_companydetail` yang aktif.
* Digunakan untuk mengisi field jurnalM_BranchCompanyID pada header jurnal.
*
* @param string $branchCode Kode cabang (misal: "JKT-01")
* @return int branchCompanyID yang sesuai, atau 0 jika tidak ditemukan
*/
private function getBranchCompanyIDByBranchCode($branchCode) private function getBranchCompanyIDByBranchCode($branchCode)
{ {
$sql = "SELECT M_BranchCompanyDetailM_BranchCompanyID AS branchCompanyID $sql = "SELECT M_BranchCompanyDetailM_BranchCompanyID AS branchCompanyID
@@ -301,6 +453,15 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return (int) $qry->row_array()["branchCompanyID"]; return (int) $qry->row_array()["branchCompanyID"];
} }
/**
* getRegionalIDByBranchCode — Ambil ID regional berdasarkan kode cabang.
*
* Data diambil dari tabel `m_branch` yang aktif.
* Digunakan untuk mengisi field JurnalS_RegionalID pada header jurnal.
*
* @param string $branchCode Kode cabang (misal: "JKT-01")
* @return int regionalID yang sesuai, atau 0 jika tidak ditemukan
*/
private function getRegionalIDByBranchCode($branchCode) private function getRegionalIDByBranchCode($branchCode)
{ {
$sql = "SELECT M_BranchS_RegionalID AS regionalID $sql = "SELECT M_BranchS_RegionalID AS regionalID
@@ -315,6 +476,15 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return (int) $qry->row_array()["regionalID"]; return (int) $qry->row_array()["regionalID"];
} }
/**
* getJurnalTypeID — Ambil ID tipe jurnal berdasarkan kode tipe.
*
* Data diambil dari tabel `jurnal_type` yang aktif.
* Untuk PI cicilan order aset, kode yang digunakan adalah "PAYMENT".
*
* @param string $jurnalTypeCode Kode tipe jurnal (misal: "PAYMENT")
* @return int JurnalTypeID yang sesuai, atau 0 jika tidak ditemukan
*/
private function getJurnalTypeID($jurnalTypeCode) private function getJurnalTypeID($jurnalTypeCode)
{ {
$sql = "SELECT JurnalTypeID $sql = "SELECT JurnalTypeID
@@ -329,6 +499,28 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return (int) $qry->row_array()["JurnalTypeID"]; return (int) $qry->row_array()["JurnalTypeID"];
} }
/**
* getEligiblePurchaseOrderAssetContracts — Ambil kontrak aset yang layak dibuatkan jurnal.
*
* Query ini mengambil semua kontrak dari `purchase_order_asset_contract` yang memenuhi
* syarat berikut:
* - Kontrak aktif, status "belum lunas", nilai cicilan > 0
* - Cicilan terbayar masih kurang dari total cicilan
* - Tanggal kontrak masuk dalam rentang periode yang diberikan
* - Tanggal jatuh tempo cicilan sudah lewat atau sama dengan hari ini
* - PO sudah Approved dan aktif
* - Barang sudah diterima dan receive order sudah confirmed
*
* Data yang dikembalikan mencakup:
* - Detail kontrak (ID, nama, tanggal, nilai cicilan)
* - Data PO (nomor PO, supplier, payment term, warehouse)
* - Data cabang (kode cabang, nama, regionalID, branchCompanyID)
* - Data item PO pertama (sebagai referensi baris jurnal)
*
* @param string $startDate Awal periode filter (YYYY-MM-DD)
* @param string $endDate Akhir periode filter (YYYY-MM-DD)
* @return array Array of row kontrak yang eligible
*/
private function getEligiblePurchaseOrderAssetContracts($startDate, $endDate) private function getEligiblePurchaseOrderAssetContracts($startDate, $endDate)
{ {
$sql = "SELECT $sql = "SELECT
@@ -355,6 +547,15 @@ class JurnalPiCicilanOrderAset extends MY_Controller
wh.WarehouseM_BranchID AS WarehouseM_BranchID, wh.WarehouseM_BranchID AS WarehouseM_BranchID,
ro.ReceiveOrderPoID, ro.ReceiveOrderPoID,
ro.ReceiveOrderPoConfirmed, ro.ReceiveOrderPoConfirmed,
mi.M_ItemID AS ItemID,
mi.M_ItemCode AS ItemCode,
mi.M_ItemDesc AS ItemDesc,
mi.M_ItemFa_ClassID,
fc.Fa_ClassID AS ItemFaClassID,
fc.Fa_ClassName AS ItemFaClassName,
fc.Fa_ClassCoaID AS ItemCoaID,
fc.Fa_ClassCoaAccountNo AS ItemCoaAccountNo,
fc.Fa_ClassCoaDesc AS ItemCoaDesc,
m_branch.M_BranchCode, m_branch.M_BranchCode,
m_branch.M_BranchName, m_branch.M_BranchName,
m_branch.M_BranchS_RegionalID, m_branch.M_BranchS_RegionalID,
@@ -363,12 +564,18 @@ class JurnalPiCicilanOrderAset extends MY_Controller
ps.PurchaseOrderSummaryItemID, ps.PurchaseOrderSummaryItemID,
ps.PurchaseOrderSummaryItemUnitID ps.PurchaseOrderSummaryItemUnitID
FROM purchase_order_asset_contract c FROM purchase_order_asset_contract c
-- Pastikan PO sudah Approved dan aktif
JOIN purchase_order po JOIN purchase_order po
ON po.PurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID ON po.PurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID
AND po.PurchaseOrderIsActive = 'Y' AND po.PurchaseOrderIsActive = 'Y'
AND po.PurchaseOrderStatus = 'Approved' AND po.PurchaseOrderStatus = 'Approved'
-- Data warehouse/gudang tujuan PO
LEFT JOIN warehouse wh LEFT JOIN warehouse wh
ON wh.WarehouseID = po.PurchaseOrderWarehouseID ON wh.WarehouseID = po.PurchaseOrderWarehouseID
-- Pastikan barang sudah diterima (receive order confirmed)
JOIN ( JOIN (
SELECT SELECT
rd.ReceiveOrderPoDetailPurchaseOrderID, rd.ReceiveOrderPoDetailPurchaseOrderID,
@@ -383,12 +590,18 @@ class JurnalPiCicilanOrderAset extends MY_Controller
GROUP BY rd.ReceiveOrderPoDetailPurchaseOrderID GROUP BY rd.ReceiveOrderPoDetailPurchaseOrderID
) ro ) ro
ON ro.ReceiveOrderPoDetailPurchaseOrderID = po.PurchaseOrderID ON ro.ReceiveOrderPoDetailPurchaseOrderID = po.PurchaseOrderID
-- Data cabang dari warehouse
LEFT JOIN m_branch LEFT JOIN m_branch
ON m_branch.M_BranchID = wh.WarehouseM_BranchID ON m_branch.M_BranchID = wh.WarehouseM_BranchID
AND m_branch.M_BranchIsActive = 'Y' AND m_branch.M_BranchIsActive = 'Y'
-- Data branch company untuk header jurnal
LEFT JOIN m_branch_companydetail LEFT JOIN m_branch_companydetail
ON m_branch_companydetail.M_BranchCompanyDetailM_BranchCode = m_branch.M_BranchCode ON m_branch_companydetail.M_BranchCompanyDetailM_BranchCode = m_branch.M_BranchCode
AND m_branch_companydetail.M_BranchCompanyDetailIsActive = 'Y' AND m_branch_companydetail.M_BranchCompanyDetailIsActive = 'Y'
-- Ambil 1 item PO pertama sebagai referensi baris jurnal
LEFT JOIN ( LEFT JOIN (
SELECT ps0.* SELECT ps0.*
FROM purchase_order_summary ps0 FROM purchase_order_summary ps0
@@ -403,15 +616,29 @@ class JurnalPiCicilanOrderAset extends MY_Controller
ON psx.PurchaseOrderSummaryID = ps0.PurchaseOrderSummaryID ON psx.PurchaseOrderSummaryID = ps0.PurchaseOrderSummaryID
) ps ) ps
ON ps.PurchaseOrderSummaryPurchaseOrderID = po.PurchaseOrderID ON ps.PurchaseOrderSummaryPurchaseOrderID = po.PurchaseOrderID
-- COA jurnal diambil dari item -> fa_class
LEFT JOIN m_item mi
ON mi.M_ItemID = ps.PurchaseOrderSummaryItemID
AND mi.M_ItemIsActive = 'Y'
LEFT JOIN fa_class fc
ON fc.Fa_ClassID = mi.M_ItemFa_ClassID
AND fc.Fa_ClassIsActive = 'Y'
WHERE c.PurchaseOrderAssetContractIsActive = 'Y' WHERE c.PurchaseOrderAssetContractIsActive = 'Y'
AND c.PurchaseOrderAssetContractStatus = 'belum lunas' AND c.PurchaseOrderAssetContractStatus = 'belum lunas'
-- Hanya kontrak yang ada nilai cicilannya
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0 AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0
-- Hanya kontrak yang belum selesai seluruh cicilannya
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0) < IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0) AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0) < IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0)
-- Kontrak sudah mulai sebelum atau pada akhir periode
AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?) AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?)
-- Kontrak belum berakhir (atau tidak ada tanggal akhir)
AND ( AND (
c.PurchaseOrderAssetContractEndDate IS NULL c.PurchaseOrderAssetContractEndDate IS NULL
OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?) OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?)
) )
-- Tanggal jatuh tempo cicilan sudah tiba
AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ? AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ?
ORDER BY c.PurchaseOrderAssetContractID ASC"; ORDER BY c.PurchaseOrderAssetContractID ASC";
@@ -424,6 +651,12 @@ class JurnalPiCicilanOrderAset extends MY_Controller
return $qry->result_array(); return $qry->result_array();
} }
/**
* isValidDate — Validasi format tanggal YYYY-MM-DD.
*
* @param string $tanggal String tanggal yang akan divalidasi
* @return bool true jika format valid, false jika tidak
*/
private function isValidDate($tanggal) private function isValidDate($tanggal)
{ {
$d = DateTime::createFromFormat("Y-m-d", $tanggal); $d = DateTime::createFromFormat("Y-m-d", $tanggal);