9 Commits

Author SHA1 Message Date
Hanan Askarim
82b93583d0 add keterangan untuk http pi instalment 2026-07-14 16:20:35 +07:00
Hanan Askarim
b29eb58db6 update penomoran dari fn fungsi 2026-07-14 15:45:34 +07:00
Hanan Askarim
731b940fb5 fix http pembayaran 2026-07-14 15:06:30 +07:00
Hanan Askarim
73ea318079 add supplier invoice number 2026-07-14 14:43:17 +07:00
Hanan Askarim
d8a65bc5a8 gabungkan fungsi get data dengan create jurnal 2026-07-14 13:25:33 +07:00
Hanan Askarim
e912adeee0 add pengambilan co dari fa_class 2026-07-14 10:28:24 +07:00
Hanan Askarim
be7f3b42be add pembuatan jurnal pi cicilan order asset 2026-07-14 09:47:44 +07:00
Hanan Askarim
048c35473c fix query get cicilan dan insert supplier invoice 2026-07-12 15:15:21 +07:00
Hanan Askarim
562caa467d add generate po contract 2026-07-12 11:40:43 +07:00
14 changed files with 2768 additions and 7042 deletions

View File

@@ -1,113 +0,0 @@
@token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJNX1VzZXJJRCI6IjM4MCIsIk1fVXNlclVzZXJuYW1lIjoicmVnc2J5IiwiTV9Vc2VyR3JvdXBEYXNoYm9hcmQiOiJvbmUtdWlcL3Rlc3RcL3Z1ZXhcL2FjYy1vbmUtanVybmFsXC8iLCJNX1VzZXJEZWZhdWx0VF9TYW1wbGVTdGF0aW9uSUQiOiIwIiwiTV9TdGFmZk5hbWUiOiJTdGFmZiBSZWdpb25hbCIsImlzX2NvdXJpZXIiOiJOIiwidGltZV9hdXRvbG9nb3V0IjoiMTIwIiwiTV9Vc2VyTG9jYXRpb25JRCI6IjM3IiwiTV9Vc2VyTG9jYXRpb25GbGFnIjoiUiIsIlNfUmVnaW9uYWxOYW1lIjoiU3VyYWJheWEgUmF5YSIsIlNfUmVnaW9uYWxJRCI6IjYiLCJNX0JyYW5jaE5hbWUiOiIiLCJNX0JyYW5jaENvZGUiOiIiLCJNX0JyYW5jaElEIjoiMCIsImxvZ2luTGV2ZWwiOiJyZWdpb25hbCIsIk1fQnJhbmNoQ29tcGFueUlEIjoiMSIsIk1fQnJhbmNoQ29tcGFueU5hbWUiOiJQVCBQUkFNSVRBIiwiaXAiOiIxMzkuMTk1LjEyMi4yMzUiLCJhZ2VudCI6Ik1vemlsbGFcLzUuMCAoWDExOyBMaW51eCB4ODZfNjQ7IHJ2OjEzNy4wKSBHZWNrb1wvMjAxMDAxMDEgRmlyZWZveFwvMTM3LjAiLCJ2ZXJzaW9uIjoidjIiLCJsYXN0LWxvZ2luIjoiMjAyNS0wNi0wNCAxMzoyMDowNSIsIk1fU2F0ZWxsaXRlSUQiOjB9.hm6JtstjaQOzb7oDSXQ-oMWuX_jFQZH-HDr3r3OzPac"
@host = accone.aplikasi.web.id/one-api
###
// create inventaris coa mapping
POST https://{{host}}/map/InventarisCoaMapping/createInvCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisGolID": 1,
"CoaInventarisID": 101,
"CoaHutangID": 102,
"CoaPembelianID": 103,
"CoaBebanPenyusutanID": 104,
"CoaAkumulasiPenyusutanID": 105,
"CoaLabaPelepasanID": 106,
"CoaRugiPelepasanID": 107
}
###
// get inventaris coa mapping by ID
POST https://{{host}}/map/InventarisCoaMapping/getInvCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisCoaMappingID": 1
}
###
// edit inventaris coa mapping
POST https://{{host}}/map/InventarisCoaMapping/editInvCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisCoaMappingID": 1,
"M_InventarisGolID": 2,
"CoaInventarisID": 201,
"CoaHutangID": 202,
"CoaPembelianID": 203,
"CoaBebanPenyusutanID": 204,
"CoaAkumulasiPenyusutanID": 205,
"CoaLabaPelepasanID": 206,
"CoaRugiPelepasanID": 207
}
###
// delete inventaris coa mapping
POST https://{{host}}/map/InventarisCoaMapping/deleteInvCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisCoaMappingID": 1
}
###
// create inventaris item coa mapping
POST https://{{host}}/map/InventarisCoaMapping/createInvItemCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_ItemID": 10,
"CoaInventarisID": 201,
"CoaHutangID": 202,
"CoaPembelianID": 203,
"CoaBebanPenyusutanID": 204,
"CoaAkumulasiPenyusutanID": 205,
"CoaLabaPelepasanID": 206,
"CoaRugiPelepasanID": 207
}
###
// get inventaris item coa mapping by ID
POST https://{{host}}/map/InventarisCoaMapping/getInvItemCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisItemCoaMappingID": 1
}
###
// edit inventaris item coa mapping
POST https://{{host}}/map/InventarisCoaMapping/editInvItemCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisItemCoaMappingID": 1,
"M_ItemID": 11,
"CoaInventarisID": 301,
"CoaHutangID": 302,
"CoaPembelianID": 303,
"CoaBebanPenyusutanID": 304,
"CoaAkumulasiPenyusutanID": 305,
"CoaLabaPelepasanID": 306,
"CoaRugiPelepasanID": 307
}
###
// delete inventaris item coa mapping
POST https://{{host}}/map/InventarisCoaMapping/deleteInvItemCoaMapping/
Content-Type: application/json
{
"token": {{token}},
"M_InventarisItemCoaMappingID": 1
}

View File

@@ -1,624 +0,0 @@
<?php
class InventarisCoaMapping extends MY_Controller
{
var $db;
public function index()
{
echo "Inventaris COA Mapping API";
}
public function __construct()
{
parent::__construct();
}
## QUERY ##
public function getListCoa()
{
try {
if (!$this->isLogin) {
throw new Exception('Invalid token');
}
$para = $this->sys_input;
$keyword = "%" . $para['keyword'] . "%";
$sql = "SELECT
coaID,
coaAccountNo,
coaDescription
FROM coa
WHERE coaIsInput = 'Y'
AND (
coaDescription LIKE ?
OR coaAccountNo LIKE ?
)
AND coaIsActive = 'Y'
LIMIT 15";
$que = $this->db->query($sql, [$keyword, $keyword]);
if (!$que) {
throw new Exception('failed to query data inventaris gol', 1);
}
$data = $que->result_array();
$this->sys_ok($data);
} catch (Exception $e) {
$msg = '[Error] ' . $e->getMessage();
$code = $e->getCode();
if ($code == 0) {
$this->sys_error($msg);
} else {
$this->sys_error_db($msg);
}
exit;
}
}
public function getListInventarisGol()
{
try {
if (!$this->isLogin) {
throw new Exception('Invalid token');
}
$sql = "SELECT
M_InventarisGolID,
M_InventarisGolCode,
M_InventarisGolName
FROM m_inventaris_gol gol
WHERE gol.M_InventarisGolIsActive = 'Y'
AND NOT EXISTS (
SELECT 1
FROM m_inventaris_coa_mapping m
WHERE m.M_InventarisCoaMappingM_InventarisGolID = gol.M_InventarisGolID
AND m.M_InventarisCoaMappingIsActive = 'Y'
);";
$que = $this->db->query($sql);
if (!$que) {
throw new Exception('failed to query data inventaris gol', 1);
}
$data = $que->result_array();
$output = [
'records' => $data,
'total' => count($data)
];
$this->sys_ok($output);
} catch (Exception $e) {
$msg = '[Error] ' . $e->getMessage();
$code = $e->getCode();
if ($code == 0) {
$this->sys_error($msg);
} else {
$this->sys_error_db($msg);
}
exit;
}
}
public function getListInventorygolMapping()
{
try {
if (!$this->isLogin) {
throw new Exception('invalid token');
}
$para = $this->sys_input;
$keyword = "%" . $para['keyword'] . "%";
$limit = 10;
$offset = 0;
if ($para['currpage'] > 0) {
$offset = ($para['currpage'] - 1) * $limit;
}
$sql = "SELECT
M_InventarisGolID,
M_InventarisGolCode,
M_InventarisGolName,
M_InventarisCoaMappingID,
M_InventarisCoaMappingCoaInventarisID,
coaInv.coaAccountNo AS CoaInventarisAccountNo,
coaInv.coaDescription AS CoaInventarisDescription,
M_InventarisCoaMappingCoaHutangID,
coaHtg.coaAccountNo AS CoaHutangAccountNo,
coaHtg.coaDescription AS CoaHutangDescription,
M_InventarisCoaMappingCoaBebanPenyusutanID,
coaBbn.coaAccountNo AS CoaBebanPenyusutanAccountNo,
coaBbn.coaDescription AS CoaBebanPenyusutanDescription,
M_InventarisCoaMappingCoaAkumulasiPenyusutanID,
coaAkm.coaAccountNo AS CoaAkumulasiPenyusutanAccountNo,
coaAkm.coaDescription AS CoaAkumulasiPenyusutanDescription,
M_InventarisCoaMappingCoaLabaPelepasanID,
coaLab.coaAccountNo AS CoaLabaPelepasanAccountNo,
coaLab.coaDescription AS CoaLabaPelepasanDescription,
M_InventarisCoaMappingCoaRugiPelepasanID,
coaRug.coaAccountNo AS CoaRugiPelepasanAccountNo,
coaRug.coaDescription AS CoaRugiPelepasanDescription
FROM m_inventaris_gol
JOIN m_inventaris_coa_mapping
ON M_InventarisCoaMappingM_InventarisGolID = M_InventarisGolID
AND M_InventarisCoaMappingIsActive = 'Y'
AND M_InventarisGolIsActive = 'Y'
AND M_InventarisGolName LIKE ?
LEFT JOIN coa AS coaInv
ON M_InventarisCoaMappingCoaInventarisID = coaInv.coaID
LEFT JOIN coa AS coaHtg
ON M_InventarisCoaMappingCoaHutangID = coaHtg.coaID
LEFT JOIN coa AS coaBbn
ON M_InventarisCoaMappingCoaBebanPenyusutanID = coaBbn.coaID
LEFT JOIN coa AS coaAkm
ON M_InventarisCoaMappingCoaAkumulasiPenyusutanID = coaAkm.coaID
LEFT JOIN coa AS coaLab
ON M_InventarisCoaMappingCoaLabaPelepasanID = coaLab.coaID
LEFT JOIN coa AS coaRug
ON M_InventarisCoaMappingCoaRugiPelepasanID = coaRug.coaID
WHERE M_InventarisGolIsActive = 'Y'";
$sql_data = $sql . " ORDER BY M_InventarisGolID LIMIT ? OFFSET ? ";
$que = $this->db->query($sql_data, [
$keyword,
$limit,
$offset
]);
if (!$que) {
throw new Exception('failed to query data mapping coa inventaris golongan', 1);
}
$sql_total = "SELECT COUNT(*) AS total FROM ($sql) AS x";
$que_total = $this->db->query($sql_total, [$keyword]);
if (!$que_total) {
throw new Exception('failed to get total rows data', 1);
}
$this->sys_ok([
"records" => $que->result_array(),
"total" => $que_total->row_array()['total']
]);
} catch (Exception $e) {
$msg = '[Error] ' . $e->getMessage();
$code = $e->getCode();
if ($code == 0) {
$this->sys_error($msg);
} else {
$this->sys_error_db($msg);
}
exit;
}
}
public function getInvCoaMappingDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$para = $this->sys_input;
$sql = "SELECT
M_InventarisCoaMappingID,
M_InventarisCoaMappingM_InventarisGolID,
M_InventarisCoaMappingCoaInventarisID,
M_InventarisCoaMappingCoaHutangID,
M_InventarisCoaMappingCoaPembelianID,
M_InventarisCoaMappingCoaBebanPenyusutanID,
M_InventarisCoaMappingCoaAkumulasiPenyusutanID,
M_InventarisCoaMappingCoaLabaPelepasanID,
M_InventarisCoaMappingCoaRugiPelepasanID,
M_InventarisCoaMappingCreatedUserID,
M_InventarisCoaMappingCreated,
M_InventarisCoaMappingLastUpdated
FROM m_inventaris_coa_mapping
WHERE M_InventarisCoaMappingIsActive = 'Y'
AND M_InventarisCoaMappingID = ?";
$query = $this->db->query($sql, [$para['M_InventarisCoaMappingID']]);
if (!$query) {
$this->sys_error_db("[Error] get data m_inventaris_coa_mapping");
exit;
}
$data = $query->row_array();
$this->sys_ok($data);
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
## MUTATIONS ##
public function createInvCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$user = $this->sys_user;
$sql = "INSERT INTO m_inventaris_coa_mapping (
M_InventarisCoaMappingM_InventarisGolID,
M_InventarisCoaMappingCoaInventarisID,
M_InventarisCoaMappingCoaHutangID,
M_InventarisCoaMappingCoaPembelianID,
M_InventarisCoaMappingCoaBebanPenyusutanID,
M_InventarisCoaMappingCoaAkumulasiPenyusutanID,
M_InventarisCoaMappingCoaLabaPelepasanID,
M_InventarisCoaMappingCoaRugiPelepasanID,
M_InventarisCoaMappingCreatedUserID,
M_InventarisCoaMappingCreated,
M_InventarisCoaMappingLastUpdated
) VALUES (?,?,?,?,?,?,?,?,?,NOW(),NOW())";
$query = $this->db->query($sql, [
$para['M_InventarisGolID'],
$para['CoaInventarisID'],
$para['CoaHutangID'],
$para['CoaPembelianID'],
$para['CoaBebanPenyusutanID'],
$para['CoaAkumulasiPenyusutanID'],
$para['CoaLabaPelepasanID'],
$para['CoaRugiPelepasanID'],
$user['M_UserID']
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert into table m_inventaris_coa_mapping");
exit;
}
$insertID = $this->db->insert_id();
$this->db->trans_commit();
$this->sys_ok($insertID);
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
public function editInvCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$user = $this->sys_user;
$sql = "UPDATE m_inventaris_coa_mapping SET
M_InventarisCoaMappingM_InventarisGolID = ?,
M_InventarisCoaMappingCoaInventarisID = ?,
M_InventarisCoaMappingCoaHutangID = ?,
M_InventarisCoaMappingCoaPembelianID = ?,
M_InventarisCoaMappingCoaBebanPenyusutanID = ?,
M_InventarisCoaMappingCoaAkumulasiPenyusutanID = ?,
M_InventarisCoaMappingCoaLabaPelepasanID = ?,
M_InventarisCoaMappingCoaRugiPelepasanID = ?,
M_InventarisCoaMappingLastUpdated = NOW()
WHERE M_InventarisCoaMappingIsActive = 'Y'
AND M_InventarisCoaMappingID = ?";
$query = $this->db->query($sql, [
$para['M_InventarisGolID'],
$para['CoaInventarisID'],
$para['CoaHutangID'],
$para['CoaPembelianID'],
$para['CoaBebanPenyusutanID'],
$para['CoaAkumulasiPenyusutanID'],
$para['CoaLabaPelepasanID'],
$para['CoaRugiPelepasanID'],
$para['M_InventarisCoaMappingID']
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update table m_inventaris_coa_mapping");
exit;
}
$this->db->trans_commit();
$this->sys_ok("[Success] update data inventaris coa mapping");
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
public function deleteInvCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$sql = "UPDATE m_inventaris_coa_mapping SET
M_InventarisCoaMappingIsActive = 'N',
M_InventarisCoaMappingLastUpdated = NOW()
WHERE M_InventarisCoaMappingIsActive = 'Y'
AND M_InventarisCoaMappingID = ?";
$query = $this->db->query($sql, [$para['M_InventarisCoaMappingID']]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] soft delete data m_inventaris_coa_mapping");
exit;
}
$this->db->trans_commit();
$this->sys_ok("[Success] delete data inventaris coa mapping");
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
## QUERY ITEM ##
public function getListItemInventaris()
{
try {
if (!$this->isLogin) {
throw new Exception('Invalid token');
}
$para = $this->sys_input;
$sql = "SELECT
M_ItemID,
M_ItemCode,
M_ItemDesc,
M_ItemM_InventarisGolID AS itemGolID,
IFNULL(M_InventarisItemCoaMappingID, 0) AS itemCoaMapID,
M_InventarisItemCoaMappingCoaInventarisID,
coaInv.coaAccountNo AS CoaInventarisAccountNo,
coaInv.coaDescription AS CoaInventarisDescription,
M_InventarisItemCoaMappingCoaHutangID,
coaHtg.coaAccountNo AS CoaHutangAccountNo,
coaHtg.coaDescription AS CoaHutangDescription,
M_InventarisItemCoaMappingCoaBebanPenyusutanID,
coaBbn.coaAccountNo AS CoaBebanPenyusutanAccountNo,
coaBbn.coaDescription AS CoaBebanPenyusutanDescription,
M_InventarisItemCoaMappingCoaAkumulasiPenyusutanID,
coaAkm.coaAccountNo AS CoaAkumulasiPenyusutanAccountNo,
coaAkm.coaDescription AS CoaAkumulasiPenyusutanDescription,
M_InventarisItemCoaMappingCoaLabaPelepasanID,
coaLab.coaAccountNo AS CoaLabaPelepasanAccountNo,
coaLab.coaDescription AS CoaLabaPelepasanDescription,
M_InventarisItemCoaMappingCoaRugiPelepasanID,
coaRug.coaAccountNo AS CoaRugiPelepasanAccountNo,
coaRug.coaDescription AS CoaRugiPelepasanDescription
FROM m_item
LEFT JOIN m_inventaris_item_coa_mapping
ON M_ItemID = M_InventarisItemCoaMappingM_ItemID
AND M_InventarisItemCoaMappingIsActive = 'Y'
LEFT JOIN coa AS coaInv
ON M_InventarisItemCoaMappingCoaInventarisID = coaInv.coaID
LEFT JOIN coa AS coaHtg
ON M_InventarisItemCoaMappingCoaHutangID = coaHtg.coaID
LEFT JOIN coa AS coaBbn
ON M_InventarisItemCoaMappingCoaBebanPenyusutanID = coaBbn.coaID
LEFT JOIN coa AS coaAkm
ON M_InventarisItemCoaMappingCoaAkumulasiPenyusutanID = coaAkm.coaID
LEFT JOIN coa AS coaLab
ON M_InventarisItemCoaMappingCoaLabaPelepasanID = coaLab.coaID
LEFT JOIN coa AS coaRug
ON M_InventarisItemCoaMappingCoaRugiPelepasanID = coaRug.coaID
WHERE M_ItemItem_CategoryID = 2
AND M_ItemM_InventarisGolID = ?
AND M_ItemIsActive = 'Y'";
$que = $this->db->query($sql, [
$para['golID']
]);
if (!$que) {
throw new Exception('failed to query data inventaris gol', 1);
}
$data = $que->result_array();
$output = [
'records' => $data,
'total' => count($data)
];
$this->sys_ok($output);
} catch (Exception $e) {
$msg = '[Error] ' . $e->getMessage();
$code = $e->getCode();
if ($code == 0) {
$this->sys_error($msg);
} else {
$this->sys_error_db($msg);
}
exit;
}
}
public function getInvItemCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$para = $this->sys_input;
$sql = "SELECT
M_InventarisItemCoaMappingID,
M_InventarisItemCoaMappingM_ItemID,
M_InventarisItemCoaMappingCoaInventarisID,
M_InventarisItemCoaMappingCoaHutangID,
M_InventarisItemCoaMappingCoaPembelianID,
M_InventarisItemCoaMappingCoaBebanPenyusutanID,
M_InventarisItemCoaMappingCoaAkumulasiPenyusutanID,
M_InventarisItemCoaMappingCoaLabaPelepasanID,
M_InventarisItemCoaMappingCoaRugiPelepasanID,
M_InventarisItemCoaMappingCreatedUserID,
M_InventarisItemCoaMappingCreated,
M_InventarisItemCoaMappingLastUpdated
FROM m_inventaris_item_coa_mapping
WHERE M_InventarisItemCoaMappingIsActive = 'Y'
AND M_InventarisItemCoaMappingID = ?";
$query = $this->db->query($sql, [$para['M_InventarisItemCoaMappingID']]);
if (!$query) {
$this->sys_error_db("[Error] get data m_inventaris_item_coa_mapping");
exit;
}
$data = $query->row_array();
$this->sys_ok($data);
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
## MUTATIONS ITEM ##
public function createInvItemCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$user = $this->sys_user;
$sql = "INSERT INTO m_inventaris_item_coa_mapping (
M_InventarisItemCoaMappingM_ItemID,
M_InventarisItemCoaMappingCoaInventarisID,
M_InventarisItemCoaMappingCoaHutangID,
M_InventarisItemCoaMappingCoaPembelianID,
M_InventarisItemCoaMappingCoaBebanPenyusutanID,
M_InventarisItemCoaMappingCoaAkumulasiPenyusutanID,
M_InventarisItemCoaMappingCoaLabaPelepasanID,
M_InventarisItemCoaMappingCoaRugiPelepasanID,
M_InventarisItemCoaMappingCreatedUserID,
M_InventarisItemCoaMappingCreated,
M_InventarisItemCoaMappingLastUpdated
) VALUES (?,?,?,?,?,?,?,?,?,NOW(),NOW())";
$query = $this->db->query($sql, [
$para['M_ItemID'],
$para['CoaInventarisID'],
$para['CoaHutangID'],
$para['CoaPembelianID'],
$para['CoaBebanPenyusutanID'],
$para['CoaAkumulasiPenyusutanID'],
$para['CoaLabaPelepasanID'],
$para['CoaRugiPelepasanID'],
$user['M_UserID']
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert into table m_inventaris_item_coa_mapping");
exit;
}
$insertID = $this->db->insert_id();
$this->db->trans_commit();
$this->sys_ok("[Success] insert coa item");
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
public function editInvItemCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$user = $this->sys_user;
$sql = "UPDATE m_inventaris_item_coa_mapping SET
M_InventarisItemCoaMappingM_ItemID = ?,
M_InventarisItemCoaMappingCoaInventarisID = ?,
M_InventarisItemCoaMappingCoaHutangID = ?,
M_InventarisItemCoaMappingCoaPembelianID = ?,
M_InventarisItemCoaMappingCoaBebanPenyusutanID = ?,
M_InventarisItemCoaMappingCoaAkumulasiPenyusutanID = ?,
M_InventarisItemCoaMappingCoaLabaPelepasanID = ?,
M_InventarisItemCoaMappingCoaRugiPelepasanID = ?,
M_InventarisItemCoaMappingLastUpdated = NOW()
WHERE M_InventarisItemCoaMappingIsActive = 'Y'
AND M_InventarisItemCoaMappingID = ?";
$query = $this->db->query($sql, [
$para['M_ItemID'],
$para['CoaInventarisID'],
$para['CoaHutangID'],
$para['CoaPembelianID'],
$para['CoaBebanPenyusutanID'],
$para['CoaAkumulasiPenyusutanID'],
$para['CoaLabaPelepasanID'],
$para['CoaRugiPelepasanID'],
$para['M_InventarisItemCoaMappingID']
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update table m_inventaris_item_coa_mapping");
exit;
}
$this->db->trans_commit();
$this->sys_ok("[Success] update data inventaris item coa mapping");
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
public function deleteInvItemCoaMapping()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$para = $this->sys_input;
$sql = "UPDATE m_inventaris_item_coa_mapping SET
M_InventarisItemCoaMappingIsActive = 'N',
M_InventarisItemCoaMappingLastUpdated = NOW()
WHERE M_InventarisItemCoaMappingIsActive = 'Y'
AND M_InventarisItemCoaMappingID = ?";
$query = $this->db->query($sql, [$para['M_InventarisItemCoaMappingID']]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] soft delete data m_inventaris_item_coa_mapping");
exit;
}
$this->db->trans_commit();
$this->sys_ok("[Success] delete data inventaris item coa mapping");
} catch (Exception $exc) {
$msg = $exc->getMessage();
$this->sys_error($msg);
}
}
}

View File

@@ -496,7 +496,6 @@ class Fakturv4 extends MY_Controller
ELSE '' ELSE ''
END as WarehouseName, END as WarehouseName,
ReceiveOrderPoID, ReceiveOrderPoID,
ReceiveOrderPoTypePurchase,
PurchaseOrderItemCategoryID PurchaseOrderItemCategoryID
FROM supplier_invoice FROM supplier_invoice
JOIN supplier_invoice_detail ON SupplierInvoiceID = SupplierInvoiceDetailSupplierInvoiceID JOIN supplier_invoice_detail ON SupplierInvoiceID = SupplierInvoiceDetailSupplierInvoiceID
@@ -589,11 +588,12 @@ class Fakturv4 extends MY_Controller
'P' 'P'
) AS DiscountType, ) AS DiscountType,
SupplierInvoiceReceiveOrderPoID, SupplierInvoiceReceiveOrderPoID,
ReceiveOrderPoNumber, ReceiveOrderPoNumber
ReceiveOrderPoTypePurchase AS typePurchase
FROM supplier_invoice FROM supplier_invoice
JOIN supplier ON SupplierInvoiceSupplierID = SupplierID JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
JOIN receive_order_po ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID JOIN receive_order_po ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
-- JOIN purchase_order ON SupplierInvoicePurchaseOrderID = PurchaseOrderID
-- AND PurchaseOrderIsActive = 'Y'
WHERE SupplierInvoiceIsActive = 'Y' WHERE SupplierInvoiceIsActive = 'Y'
AND SupplierInvoiceID = ?"; AND SupplierInvoiceID = ?";
$que = $this->db->query($sql, $para['SInvoiceID']); $que = $this->db->query($sql, $para['SInvoiceID']);
@@ -601,7 +601,6 @@ class Fakturv4 extends MY_Controller
$this->sys_error_db('[Error] get detail data invoice'); $this->sys_error_db('[Error] get detail data invoice');
exit; exit;
} }
$data = $que->row_array();
$sqldet = "SELECT $sqldet = "SELECT
SupplierInvoiceDetailID, SupplierInvoiceDetailID,
@@ -637,30 +636,7 @@ class Fakturv4 extends MY_Controller
exit; exit;
} }
if (isset($data['typePurchase']) && $data['typePurchase'] == 'aset') { $data = $que->result_array()[0];
$sql_dp = "SELECT
IFNULL(SupplierDownpaymentAmount, 0) AS dp_amount
FROM supplier_invoice
JOIN receive_order_po
ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
JOIN purchase_order_asset_contract
ON PurchaseOrderAssetContractReceiveOrderPoID = ReceiveOrderPoID
AND PurchaseOrderAssetContractIsActive = 'Y'
JOIN supplier_downpayment
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderAssetContractPurchaseOrderID
AND SupplierDownpaymentIsActive = 'Y'
WHERE SupplierInvoiceID = ?";
$que_dp = $this->db->query($sql_dp, [
$para['SInvoiceID']
]);
if (!$que_dp) {
$this->sys_error_db("[Error] get info contract asset");
exit;
}
$dp_amount = $que_dp->row_array()['dp_amount'];
$data['dp_amount'] = $dp_amount;
}
$data['detail'] = $quedet->result_array(); $data['detail'] = $quedet->result_array();
$result = $data; $result = $data;
@@ -1341,8 +1317,7 @@ class Fakturv4 extends MY_Controller
supplier_invoice_detail.*, supplier_invoice_detail.*,
ReceiveOrderPoNumber, ReceiveOrderPoNumber,
ReceiveOrderPoM_BranchCode, ReceiveOrderPoM_BranchCode,
ReceiveOrderPoS_RegionalID, ReceiveOrderPoS_RegionalID
ReceiveOrderPoTypePurchase AS typePurchase
FROM supplier_invoice FROM supplier_invoice
JOIN supplier_invoice_detail ON SupplierInvoiceDetailSupplierInvoiceID = SupplierInvoiceID JOIN supplier_invoice_detail ON SupplierInvoiceDetailSupplierInvoiceID = SupplierInvoiceID
AND SupplierInvoiceDetailIsActive = 'Y' AND SupplierInvoiceDetailIsActive = 'Y'
@@ -1478,6 +1453,7 @@ class Fakturv4 extends MY_Controller
$coapph = $quepph->result_array()[0]; $coapph = $quepph->result_array()[0];
$pphval = doubleval($invoice[0]['SupplierInvoiceTaxAmountPph']); $pphval = doubleval($invoice[0]['SupplierInvoiceTaxAmountPph']);
if ($pphval > 0.00) { if ($pphval > 0.00) {
$insertpph = $this->InsertJurnalTx( $insertpph = $this->InsertJurnalTx(
$jurnalID, $jurnalID,
@@ -1489,22 +1465,22 @@ class Fakturv4 extends MY_Controller
); );
if (!$insertpph['status']) { if (!$insertpph['status']) {
$this->db->trans_rollback(); $this->db->trans_rollback();
$this->sys_error_db($insertpph['msg']); $this->sys_error_db($insertpajak['msg']);
exit; exit;
} }
} }
# insert shipping cost ke jurnal # # insert shipping cost ke jurnal #
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
if ($ship_cost > 0.00) { $queryshipcost = $this->db->query($sqlcoa, ['5320700001']);
$queryshipcost = $this->db->query($sqlcoa, ['5320700001']); if (!$queryshipcost) {
if (!$queryshipcost) { $this->db->trans_rollback();
$this->db->trans_rollback(); $this->sys_error_db("[Error] get coa cost ");
$this->sys_error_db("[Error] get coa cost "); exit;
exit; }
} $coashipcost = $queryshipcost->result_array()[0];
$coashipcost = $queryshipcost->result_array()[0];
if ($ship_cost > 0.00) {
$insertcost = $this->InsertJurnalTx( $insertcost = $this->InsertJurnalTx(
$jurnalID, $jurnalID,
$coashipcost['coaID'], $coashipcost['coaID'],
@@ -1520,63 +1496,6 @@ class Fakturv4 extends MY_Controller
} }
} }
/* Insert jurnal tx for down payment asset */
// ----------------------------------------------------------------------------------------
if (isset($invoice[0]['typePurchase']) && $invoice[0]['typePurchase'] == 'aset') {
$sql_dpasset = "SELECT
PurchaseOrderAssetContractID,
PurchaseOrderAssetContractName,
SupplierDownpaymentAmount,
coaID,
coaDescription
FROM purchase_order_asset_contract
JOIN purchase_order ON PurchaseOrderID = PurchaseOrderAssetContractPurchaseOrderID
JOIN supplier_downpayment
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderID
AND SupplierDownpaymentIsActive = 'Y'
JOIN purchase_order_detail
ON PurchaseOrderID = PurchaseOrderDetailPurchaseOrderID
AND PurchaseOrderDetailIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseOrderDetailItemID
AND M_ItemItem_CategoryID = 3
JOIN fa_class ON Fa_ClassID = M_ItemFa_ClassID
AND Fa_ClassIsActive = 'Y'
JOIN coa ON coaID = Fa_ClassDownPaymentCoaID
AND coaIsActive = 'Y'
WHERE PurchaseOrderAssetContractReceiveOrderPoID = ?
AND PurchaseOrderAssetContractIsActive = 'Y'
LIMIT 1";
$que_dpasset = $this->db->query($sql_dpasset, [
$invoice[0]['SupplierInvoiceReceiveOrderPoID']
]);
if (!$que_dpasset) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] query dp asset not error");
exit;
}
$dpasset_coa = $que_dpasset->row_array();
if (!empty($dpasset_coa)) {
$totalDP = round($dpasset_coa['SupplierDownpaymentAmount'], 2);
if ($totalDP > 0) {
$insert_dp = $this->InsertJurnalTx(
$jurnalID,
$dpasset_coa['coaID'],
$dpasset_coa['coaDescription'],
$user['M_UserID'],
0,
$totalDP
);
if (!$insert_dp['status']) {
$this->db->trans_rollback();
$this->sys_error_db($insert_dp['msg']);
exit;
}
$invoice = $this->CalcProrateDownPaymentAsset($invoice, $totalDP);
}
}
}
// insert jurnal tx hutang per item (kredit) // insert jurnal tx hutang per item (kredit)
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
foreach ($invoice as $key => $inv) { foreach ($invoice as $key => $inv) {
@@ -1684,20 +1603,52 @@ class Fakturv4 extends MY_Controller
$this->sys_error_db($status['msg']); $this->sys_error_db($status['msg']);
exit; exit;
} }
} else if ($item['M_ItemItem_CategoryID'] == '3') { } else if ($item['M_ItemItem_CategoryID'] == '3' && !empty($item['M_ItemFa_ClassID'])) {
$this->InsertJurnalTxAsset($jurnalID, $item['M_ItemID'], $inv, $user['M_UserID']); $sqlsgp = "SELECT * FROM fa_class WHERE Fa_ClassID = ? AND Fa_ClassIsActive = 'Y'";
$quesgp = $this->db->query($sqlsgp, [$item['M_ItemFa_ClassID']]);
if (!$quesgp) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get map_nat_subgroup");
exit;
}
$itemGroup = $quesgp->row_array();
if (empty($itemGroup)) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] fa class item tidak ditemukan / belum dimapping");
exit;
}
$price = (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata']));
// $taxPPH = doubleval($inv['SupplierInvoiceTaxPercentPph']) * $price / 100;
$taxPPN = doubleval($inv['SupplierInvoiceTaxPercentPpn']) * $price / 100;
$kredit = round($price + $taxPPN, 2);
$status = $this->InsertJurnalTx(
$jurnalID,
$itemGroup['Fa_ClassCoaID'],
$itemGroup['Fa_ClassCoaDesc'],
$user['M_UserID'],
0,
$kredit
);
if (!$status) {
$this->sys_error_db($status['msg']);
exit;
}
} else if ($item['M_ItemItem_CategoryID'] == '4') { } else if ($item['M_ItemItem_CategoryID'] == '4') {
$this->InsertJurnalTxJasa($jurnalID, $item['M_ItemID'], $inv, $user['M_UserID']); $this->InsertJurnalTxJasa($jurnalID, $item['M_ItemID'], $inv, $user['M_UserID']);
} }
} }
$sqlinvgr = "INSERT INTO jurnal_addon ( $sqlinvgr = "INSERT INTO jurnal_addon (
jurnalAddOnJurnalID, jurnalAddOnJurnalID,
jurnalAddOnCode, jurnalAddOnCode,
jurnalAddOnValue, jurnalAddOnValue,
jurnalAddOnCreated, jurnalAddOnCreated,
jurnalAddOnCreatedUserID jurnalAddOnCreatedUserID
) VALUES (?,?,?,NOW(),?)"; ) VALUES (?,?,?,NOW(),?)";
$queinvgr = $this->db->query($sqlinvgr, [ $queinvgr = $this->db->query($sqlinvgr, [
$jurnalID, $jurnalID,
'INVGR', 'INVGR',
@@ -1723,13 +1674,13 @@ class Fakturv4 extends MY_Controller
private function InsertJurnalTxJasa($jurnalID, $itemid, $invoice, $userid) private function InsertJurnalTxJasa($jurnalID, $itemid, $invoice, $userid)
{ {
$sql_coa = "SELECT $sql_coa = "SELECT
JasaCoaMapHutangCoaID, JasaCoaMapHutangCoaID,
JasaCoaMapHutangCoaNo, JasaCoaMapHutangCoaNo,
JasaCoaMapHutangCoaDesc JasaCoaMapHutangCoaDesc
FROM jasa_coa_map FROM jasa_coa_map
JOIN coa ON coaID = JasaCoaMapHutangCoaID JOIN coa ON coaID = JasaCoaMapHutangCoaID
AND coaIsActive = 'Y' AND coaIsActive = 'Y'
WHERE JasaCoaMapM_ItemID = ?"; WHERE JasaCoaMapM_ItemID = ?";
$que_coa = $this->db->query($sql_coa, [$itemid]); $que_coa = $this->db->query($sql_coa, [$itemid]);
if (!$que_coa) { if (!$que_coa) {
$this->db->trans_rollback(); $this->db->trans_rollback();
@@ -1766,93 +1717,6 @@ class Fakturv4 extends MY_Controller
} }
} }
private function InsertJurnalTxAsset($jurnalID, $itemid, $invoice, $userid)
{
$sql_coa = "SELECT
Fa_ClassHutangCoaID,
Fa_ClassHutangCoaAccountNo,
Fa_ClassHutangCoaDesc
FROM m_item
JOIN fa_class ON Fa_ClassID = M_ItemFa_ClassID
WHERE M_ItemID = ?";
$que_coa = $this->db->query($sql_coa, $itemid);
if (!$que_coa) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed get coa hutang asset");
exit;
}
$coaasset = $que_coa->row_array();
if ($que_coa->num_rows() <= 0) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] aset debt coa not found");
exit;
}
$invtotal = doubleval($invoice['SupplierInvoiceDetailTotal']);
$disprorata = doubleval($invoice['SupplierInvoiceDetailDiscountPoProrata']);
$price = $invtotal - $disprorata;
$taxPPN = doubleval($invoice['SupplierInvoiceTaxPercentPpn']) * $price / 100;
$kredit = round($price + $taxPPN, 2);
$finalValue = round($kredit - doubleval($invoice['dpReduction']), 2);
$insert = $this->InsertJurnalTx(
$jurnalID,
$coaasset['Fa_ClassHutangCoaID'],
$coaasset['Fa_ClassHutangCoaDesc'],
$userid,
0,
$finalValue
);
if (!$insert) {
$this->db->trans_rollback();
$this->sys_error_db($insert['msg']);
exit;
}
}
private function CalcProrateDownPaymentAsset($items, $dpAmount)
{
$totalKredit = 0;
foreach ($items as $key => $value) {
$invtotal = doubleval($value['SupplierInvoiceDetailTotal']);
$disprorata = doubleval($value['SupplierInvoiceDetailDiscountPoProrata']);
$price = $invtotal - $disprorata;
$taxPPN = doubleval($value['SupplierInvoiceTaxPercentPpn']) * $price / 100;
$kredit = round($price + $taxPPN, 2);
$totalKredit = $totalKredit + $kredit;
$items[$key]['kredit'] = $kredit;
}
if ($totalKredit <= 0) {
foreach ($items as $key => $value) {
$items[$key]['dpReduction'] = 0;
}
return $items;
}
$runningReduction = 0;
end($items);
$lastKey = key($items);
reset($items);
foreach ($items as $key => $value) {
if ($key === $lastKey) {
$reduction = round($dpAmount - $runningReduction, 2);
} else {
$ratio = $value['kredit'] / $totalKredit;
$reduction = round($dpAmount * $ratio, 2);
$runningReduction += $reduction;
}
$items[$key]['dpReduction'] = $reduction;
}
return $items;
}
function InsertJurnalTx($jurnalID, $coaID, $desc, $userID, $debit = 0, $kredit = 0): array function InsertJurnalTx($jurnalID, $coaID, $desc, $userID, $debit = 0, $kredit = 0): array
{ {
try { try {

View File

@@ -1705,38 +1705,22 @@ class ReceiveItemPoInventaris extends MY_Controller
exit; exit;
} }
$sql_invcoa = "SELECT $sql_coa_inv = "SELECT
COALESCE( CoaMapInventarisCoaID,
i.M_InventarisItemCoaMappingID, CoaMapInventarisCoaNo,
g.M_InventarisCoaMappingID CoaMapInventarisCoaDesc
) AS MappingID, FROM coa_map_inventaris
COALESCE( WHERE CoaMapInventarisM_InventarisGolID = ?
i.M_InventarisItemCoaMappingCoaInventarisID, AND CoaMapInventarisIsActive = 'Y'";
g.M_InventarisCoaMappingCoaInventarisID $que_coa_inv = $this->db->query($sql_coa_inv, [$item_cek['M_ItemM_InventarisGolID']]);
) AS CoaInventarisID, if (!$que_coa_inv) {
c.coaDescription AS CoaInventarisDesc
FROM (SELECT 1) AS inventory
LEFT JOIN m_inventaris_item_coa_mapping i
ON i.M_InventarisItemCoaMappingM_ItemID = ?
AND i.M_InventarisItemCoaMappingIsActive = 'Y'
LEFT JOIN m_inventaris_coa_mapping g
ON g.M_InventarisCoaMappingM_InventarisGolID = ?
AND g.M_InventarisCoaMappingIsActive = 'Y'
LEFT JOIN coa c
ON c.coaID = COALESCE(i.M_InventarisItemCoaMappingCoaInventarisID, g.M_InventarisCoaMappingCoaInventarisID)
AND c.coaIsActive = 'Y'";
$que_invcoa = $this->db->query($sql_invcoa, [
$item_cek['M_ItemID'],
$item_cek['M_ItemM_InventarisGolID']
]);
if (!$que_invcoa) {
$this->db->trans_rollback(); $this->db->trans_rollback();
$this->sys_error_db("[Error] failed to get coa biaya item inventaris"); $this->sys_error_db("[Error] failed to get coa biaya item inventaris");
exit; exit;
} }
$iteminv_coa = $que_invcoa->row_array(); $iteminv_coa = $que_coa_inv->row_array();
if (empty($iteminv_coa['CoaInventarisID'])) { if (empty($iteminv_coa['CoaMapInventarisCoaID'])) {
$this->db->trans_rollback(); $this->db->trans_rollback();
$this->sys_error_db("[Error] coa gol inventaris not found"); $this->sys_error_db("[Error] coa gol inventaris not found");
exit; exit;
@@ -1756,8 +1740,8 @@ class ReceiveItemPoInventaris extends MY_Controller
) VALUES (?,?,?,?,?,?)"; ) VALUES (?,?,?,?,?,?)";
$que_tx_jurnal = $this->db->query($sql_tx_jurnal, [ $que_tx_jurnal = $this->db->query($sql_tx_jurnal, [
$jurnal_ID, $jurnal_ID,
$iteminv_coa['CoaInventarisID'], $iteminv_coa['CoaMapInventarisCoaID'],
$iteminv_coa['CoaInventarisDesc'], $iteminv_coa['CoaMapInventarisCoaDesc'],
$debet, $debet,
0, 0,
$user['M_UserID'] $user['M_UserID']
@@ -1770,7 +1754,7 @@ class ReceiveItemPoInventaris extends MY_Controller
} }
$juranl_tx_ID = $this->db->insert_id(); $juranl_tx_ID = $this->db->insert_id();
$each_desc[] = "- Add detail Jurnal debet {$item_cek['M_ItemDesc']} $each_desc[] = "- Add detail Jurnal debet {$item_cek['M_ItemDesc']}
{$iteminv_coa['CoaInventarisDesc']} sejumlah {$this->formatRupiah($debet)}"; {$iteminv_coa['CoaMapInventarisCoaDesc']} sejumlah {$this->formatRupiah($debet)}";
# INSERT JURNAL ADDON # # INSERT JURNAL ADDON #
$sql_addon_jurnal = "INSERT INTO jurnal_addon ( $sql_addon_jurnal = "INSERT INTO jurnal_addon (
@@ -1960,6 +1944,20 @@ class ReceiveItemPoInventaris extends MY_Controller
$this->sys_error_db("[Error] insert update stock"); $this->sys_error_db("[Error] insert update stock");
exit; exit;
} }
// insert stockid barcode barang
// $sql_update_barcode = "UPDATE t_barcode_barang SET
// T_BarcodeBarangStockID = ?
// WHERE T_BarcodeBarangReceiveOrderPoDetailID = ?";
// $qry_update_barcode = $this->db->query($sql_update_barcode, [
// $stock_ID,
// $detail['ReceiveOrderPoDetailID']
// ]);
// if (!$qry_update_barcode) {
// $this->db->trans_rollback();
// $this->sys_error_db("[Error] update barcode stockID", $this->db);
// exit;
// }
} else { } else {
$sql_insert_stock = "INSERT INTO stock ( $sql_insert_stock = "INSERT INTO stock (
StockWarehouseAlmariID, StockWarehouseAlmariID,
@@ -1987,9 +1985,23 @@ class ReceiveItemPoInventaris extends MY_Controller
exit; exit;
} }
$stock_ID = $this->db->insert_id(); $stockID = $this->db->insert_id();
$stock_qty_ori = 0; $stock_qty_ori = 0;
$stock_qty_end = intval($batch['qty']); $stock_qty_end = intval($batch['qty']);
// insert stockid barcode barang
// $sql_update_barcode = "UPDATE t_barcode_barang SET
// T_BarcodeBarangStockID = ?
// WHERE T_BarcodeBarangReceiveOrderPoDetailID = ?";
// $qry_update_barcode = $this->db->query($sql_update_barcode, [
// $stockID,
// $detail['ReceiveOrderPoDetailID']
// ]);
// if (!$qry_update_barcode) {
// $this->db->trans_rollback();
// $this->sys_error_db("[Error] update barcode stockID", $this->db);
// exit;
// }
} }
// insert stock card // insert stock card

View File

@@ -1,55 +1,78 @@
# ============================================================ # ============================================================
# FILE : PurchaseInvoiceInstallment.http # FILE : PurchaseInvoiceInstallment.http
# MODUL : Scheduler — Generate Supplier Installment Cicilan Aset # MODUL : Scheduler — Generate Purchase Invoice Cicilan Aset
# ============================================================ # ============================================================
# #
# DESKRIPSI # DESKRIPSI
# --------- # ---------
# File ini berisi HTTP request untuk menguji endpoint scheduler # File ini berisi kumpulan HTTP request untuk menguji endpoint
# yang secara otomatis membuat baris cicilan ke tabel # scheduler yang secara otomatis membuat Purchase Invoice (PI)
# supplier_installment setiap bulan. # cicilan bulanan berdasarkan kontrak aset aktif.
# #
# CARA PAKAI # CARA PAKAI
# ---------- # ----------
# 1. Gunakan ekstensi "REST Client" di VS Code (humao.rest-client) # 1. Gunakan ekstensi "REST Client" di VS Code (humao.rest-client)
# atau tool sejenis (IntelliJ HTTP Client, Postman, dll). # atau tool sejenis (IntelliJ HTTP Client, Postman, dll).
# 2. Ganti nilai @host sesuai environment. # 2. Ganti nilai @host sesuai environment (local / staging / prod).
# 3. Klik "Send Request" di atas tiap blok ### # 3. Klik "Send Request" di atas tiap blok ### untuk menjalankan
# request tersebut secara individual.
# 4. Jalankan request secara BERURUTAN sesuai urutan yang disarankan
# (lihat keterangan tiap endpoint di bawah).
# #
# ALUR # ALUR PENGGUNAAN YANG DISARANKAN
# ---- # --------------------------------
# [1] GenerateMonthlyInvoices → Jalankan proses generate installment # [1] ListEligibleContracts → Lihat kontrak mana saja yang akan diproses
# [2] GenerateMonthlyInvoices → Jalankan proses generate PI cicilan sekaligus
# [3] InsertSupplierInvoice → (Opsional) Insert manual 1 PI jika diperlukan
# #
# CATATAN # CATATAN
# ------- # -------
# - Default periode: bulan berjalan (tanggal 1 s/d akhir bulan) # - startDate & endDate menentukan periode bulan yang diproses.
# - Aman dijalankan ulang — dedup berdasarkan PO + bulan mencegah # Biasanya diisi dengan tanggal awal dan akhir bulan berjalan.
# duplikasi # - Scheduler ini AMAN dijalankan ulang (idempotent). Kontrak yang
# - Tidak membuat jurnal — jurnal dibuat saat pembayaran cashier # sudah punya PI di bulan yang sama akan dilewati otomatis.
# - Tidak update kontrak — InstallmentPaid diupdate saat pembayaran # - userID pada InsertSupplierInvoice akan diabaikan; sistem
# mengambil userID dari PurchaseOrderAssetContractCreatedUserID.
# ============================================================ # ============================================================
@host = https://accone.aplikasi.web.id/one-api @host = https://accone.aplikasi.web.id/one-api
# ============================================================ # ============================================================
# [1] GENERATE INSTALLMENT BULANAN (MAIN ENDPOINT) # [1] LIST KONTRAK ELIGIBLE
# ============================================================ # ============================================================
# Satu request ini akan: # Gunakan endpoint ini SEBELUM generate untuk melihat preview
# Step 1: Validasi kontrak (aktif, belum lunas, dalam rentang) # kontrak mana saja yang akan dibuatkan PI pada periode ini.
# Step 2: Validasi PO (Approved, Active)
# Step 3: Validasi RO (Confirmed, Active)
# Step 4: Validasi parent invoice (IsInstallment = 'Y')
# Step 5: Cek dedup (belum ada installment bulan ini)
# Step 6: INSERT ke supplier_installment (Status = 'Pending')
# #
# Response: # Response berisi daftar kontrak beserta detail cicilan,
# - totalEligible : jumlah kontrak lolos validasi # status GRNI, dan apakah PI bulan ini sudah ada atau belum.
# - totalInserted : jumlah baris berhasil diinsert
# - created[] : detail tiap installment yang dibuat
# ============================================================ # ============================================================
### [1] Generate installment untuk periode tertentu ### [1] List kontrak cicilan eligible yang belum diproses bulan ini
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/ListEligibleContracts
Content-Type: application/json
{
"startDate": "2026-07-01",
"endDate": "2026-07-31"
}
# ============================================================
# [2] GENERATE PI CICILAN BULANAN (MAIN ENDPOINT)
# ============================================================
# Endpoint utama scheduler. Satu request ini akan:
# 1. Mengambil semua kontrak aset aktif yang eligible.
# 2. Mengecek duplikasi — melewati kontrak yang sudah ada PI-nya.
# 3. Membuat nomor PI via fn_penomoran() berdasarkan user
# pembuat kontrak (PurchaseOrderAssetContractCreatedUserID).
# 4. Insert supplier_invoice + supplier_invoice_detail.
#
# Response berisi:
# - berhasil : daftar PI yang berhasil dibuat (dengan nomorPI, supplierInvoiceID, dll)
# - dilewati : daftar kontrak yang dilewati beserta alasannya
# ============================================================
### [2] Generate PI cicilan untuk semua kontrak pada periode ini
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices
Content-Type: application/json Content-Type: application/json
@@ -58,8 +81,47 @@ Content-Type: application/json
"endDate": "2026-07-31" "endDate": "2026-07-31"
} }
### [1a] Generate installment bulan berjalan (tanpa parameter) # ============================================================
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices # [3] INSERT MANUAL SATU PI (INTERNAL / DEBUG)
# ============================================================
# Endpoint ini dipanggil INTERNAL oleh GenerateMonthlyInvoices
# via cURL. Gunakan hanya untuk debugging atau insert manual
# satu PI tertentu tanpa menjalankan proses batch.
#
# FIELD WAJIB:
# - nomorPI : Nomor PI (format dari fn_penomoran)
# - tanggalPI : Tanggal invoice (YYYY-MM-DD)
# - tanggalJatuhTempo : Tanggal jatuh tempo (YYYY-MM-DD)
# - jumlahCicilan : Nominal cicilan (angka, dalam Rupiah)
# - catatan : Catatan singkat pada header invoice
# - deskripsi : Deskripsi baris detail invoice
# - userID : ID user pembuat (ambil dari kontrak)
# - purchaseOrderAssetContractID : ID kontrak aset
# - purchaseOrderID : ID Purchase Order
# - receiveOrderPoID : ID Receive Order PO (GRNI)
# - supplierID : ID Supplier
# - purchaseOrderSummaryID : ID summary item PO
# - purchaseOrderSummaryItemID : ID item (barang/aset)
# - purchaseOrderSummaryItemUnitID: ID satuan item
# ============================================================
### [3] Insert satu supplier_invoice cicilan secara manual (debug)
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallmentInsert/InsertSupplierInvoice
Content-Type: application/json Content-Type: application/json
{} {
"nomorPI": "PI-2026-07-0001",
"tanggalPI": "2026-07-31",
"tanggalJatuhTempo": "2026-08-14",
"jumlahCicilan": 15000000,
"catatan": "PI Cicilan Otomatis — Kontrak Aset ID 123 periode 2026-07",
"deskripsi": "Cicilan Kontrak Aset — Kendaraan Operasional periode 2026-07",
"userID": 1,
"purchaseOrderAssetContractID": 123,
"purchaseOrderID": 456,
"receiveOrderPoID": 789,
"supplierID": 12,
"purchaseOrderSummaryID": 111,
"purchaseOrderSummaryItemID": 222,
"purchaseOrderSummaryItemUnitID": 333
}

View File

@@ -3,19 +3,20 @@
/** /**
* PurchaseInvoiceInstallment * PurchaseInvoiceInstallment
* *
* CRON scheduler untuk membuat baris cicilan otomatis ke tabel supplier_installment * Digunakan oleh CRON untuk membuat Purchase Invoice (PI) cicilan aset
* setiap bulan berdasarkan kontrak aset yang aktif dan belum lunas. * secara otomatis setiap bulan berdasarkan kontrak yang aktif.
* *
* Endpoint: * Endpoint utama:
* POST /scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices * POST /scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices
* POST /scheduler/PurchaseInvoiceInstallment/CurlGenerateMonthlyInvoices
*/ */
class PurchaseInvoiceInstallment extends MY_Controller class PurchaseInvoiceInstallment extends MY_Controller
{ {
var $db; var $db;
var $baseUrl = "https://accone.aplikasi.web.id/one-api/";
public function index() public function index()
{ {
echo "Purchase Invoice Installment — Auto Generate Installment Cicilan Aset"; echo "Purchase Invoice Installment — Auto Generate PI Cicilan Aset";
} }
public function __construct() public function __construct()
@@ -24,121 +25,327 @@ class PurchaseInvoiceInstallment extends MY_Controller
} }
/** /**
* GenerateMonthlyInvoices — Step 6 * GenerateMonthlyInvoices
* *
* Creates supplier_installment rows for all eligible contracts this month. * Membuat Purchase Invoice cicilan untuk semua kontrak aset yang aktif
* No journal is created here — that happens at cashier payment time. * dan belum lunas pada bulan yang ditentukan.
* Contract InstallmentPaid is NOT updated here — that happens at payment time.
* *
* Called by CRON daily at 1:00 AM. * Parameter (POST JSON):
* Defaults to current month if no startDate/endDate provided. * - startDate : Tanggal awal periode (format YYYY-MM-DD). Default: awal bulan ini.
* - endDate : Tanggal akhir periode (format YYYY-MM-DD). Default: akhir bulan ini.
* userID diambil otomatis dari token (sys_user["M_UserID"]).
* Jika CRON berjalan tanpa token, fallback ke user ID 0.
*
* Syarat kontrak diproses:
* 1. Kontrak aktif dan berstatus "belum lunas"
* 2. Nilai cicilan > 0
* 3. Jumlah cicilan terbayar < total cicilan
* 4. Tanggal kontrak masuk dalam bulan yang dituju
* 5. RO sudah confirmed
* 6. PO sudah berstatus Approved
*/ */
public function GenerateMonthlyInvoices() public function GenerateMonthlyInvoices()
{ {
try { try {
$para = $this->sys_input; $para = $this->sys_input;
// Ambil userID dari token JWT (sys_user). Fallback ke 0 jika CRON berjalan tanpa token.
$userID = !empty($this->sys_user["M_UserID"]) ? (int) $this->sys_user["M_UserID"] : 0;
$user = $this->getCronUser($userID);
$userID = !empty($this->sys_user["M_UserID"]) $startDate = isset($para["startDate"]) && $para["startDate"] != ""
? (int) $this->sys_user["M_UserID"]
: 0;
$startDate = !empty($para["startDate"])
? $para["startDate"] ? $para["startDate"]
: date("Y-m-01"); : (isset($para["date"]) && $para["date"] != "" ? date("Y-m-01", strtotime($para["date"])) : date("Y-m-01"));
$endDate = isset($para["endDate"]) && $para["endDate"] != ""
$endDate = !empty($para["endDate"])
? $para["endDate"] ? $para["endDate"]
: date("Y-m-t"); : (isset($para["date"]) && $para["date"] != "" ? date("Y-m-t", strtotime($para["date"])) : date("Y-m-t"));
// Validasi format tanggal
if (!$this->isValidDate($startDate) || !$this->isValidDate($endDate)) { if (!$this->isValidDate($startDate) || !$this->isValidDate($endDate)) {
throw new Exception("Format tanggal tidak valid."); throw new Exception("Format tanggal tidak valid. Gunakan format YYYY-MM-DD, contoh: 2025-07-01");
} }
if (strtotime($startDate) > strtotime($endDate)) { if (strtotime($startDate) > strtotime($endDate)) {
throw new Exception("startDate > endDate."); throw new Exception("startDate tidak boleh lebih besar dari endDate");
} }
// ── Steps 15: Get eligible contracts ──────────────────── // Tentukan rentang bulan berdasarkan tanggal acuan
$eligible = $this->getEligibleInstallments($startDate, $endDate); $monthStart = $startDate;
$monthEnd = $endDate;
$dayOfMonth = (int) date("d", strtotime($endDate));
$created = []; // -------------------------------------------------------------------------
$inserted = 0; // Ambil semua kontrak cicilan yang memenuhi syarat pada bulan ini
// -------------------------------------------------------------------------
$sqlKontrak = "SELECT
c.PurchaseOrderAssetContractID,
c.PurchaseOrderAssetContractPurchaseOrderID,
ro.ReceiveOrderPoID AS PurchaseOrderAssetContractReceiveOrderPoID,
c.PurchaseOrderAssetContractName,
c.PurchaseOrderAssetContractStartDate,
c.PurchaseOrderAssetContractEndDate,
c.PurchaseOrderAssetContractInstallmentNumber,
c.PurchaseOrderAssetContractInstallmentPaid,
c.PurchaseOrderAssetContractInstallmentDate,
c.PurchaseOrderAssetContractInstallmentPayAmount,
c.PurchaseOrderAssetContractCreatedUserID,
po.PurchaseOrderID,
po.PurchaseOrderNumber,
po.PurchaseOrderSupplierID,
po.PurchaseOrderPaymentTerm,
po.PurchaseOrderWarehouseType,
po.PurchaseOrderWarehouseID,
ro.ReceiveOrderPoConfirmed,
ps.PurchaseOrderSummaryID,
ps.PurchaseOrderSummaryItemID,
ps.PurchaseOrderSummaryItemUnitID
FROM purchase_order_asset_contract c
$this->db->trans_begin(); -- Pastikan PO sudah Approved dan aktif
JOIN purchase_order po
ON po.PurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID
AND po.PurchaseOrderIsActive = 'Y'
AND po.PurchaseOrderStatus = 'Approved'
foreach ($eligible as $row) { JOIN (
SELECT
rd.ReceiveOrderPoDetailPurchaseOrderID,
MIN(ro0.ReceiveOrderPoID) AS ReceiveOrderPoID,
MAX(ro0.ReceiveOrderPoConfirmed) AS ReceiveOrderPoConfirmed
FROM receive_order_po ro0
JOIN receive_order_po_detail rd
ON rd.ReceiveOrderPoDetailReceiveOrderPoID = ro0.ReceiveOrderPoID
AND rd.ReceiveOrderPoDetailIsActive = 'Y'
WHERE ro0.ReceiveOrderPoIsActive = 'Y'
AND ro0.ReceiveOrderPoConfirmed = 'Y'
GROUP BY rd.ReceiveOrderPoDetailPurchaseOrderID
) ro
ON ro.ReceiveOrderPoDetailPurchaseOrderID = po.PurchaseOrderID
$amount = (float) $row["PurchaseOrderAssetContractInstallmentPayAmount"]; -- Ambil 1 item PO pertama sebagai referensi baris detail PI
$dayOfMonth = (int) ($row["PurchaseOrderAssetContractInstallmentDate"] ?? 1); LEFT JOIN (
$lastDay = (int) date("t", strtotime($endDate)); SELECT ps0.*
$dayOfMonth = min($dayOfMonth, $lastDay); FROM purchase_order_summary ps0
$installDate = date("Y-m", strtotime($endDate)) . "-" . str_pad($dayOfMonth, 2, "0", STR_PAD_LEFT); JOIN (
$dueDate = date("Y-m-d", strtotime($installDate . " +7 days")); SELECT
$createdBy = (int) ($row["PurchaseOrderAssetContractCreatedUserID"] ?? $userID); PurchaseOrderSummaryPurchaseOrderID,
MIN(PurchaseOrderSummaryID) AS PurchaseOrderSummaryID
FROM purchase_order_summary
WHERE PurchaseOrderSummaryIsActive = 'Y'
GROUP BY PurchaseOrderSummaryPurchaseOrderID
) psx
ON psx.PurchaseOrderSummaryID = ps0.PurchaseOrderSummaryID
) ps
ON ps.PurchaseOrderSummaryPurchaseOrderID = po.PurchaseOrderID
// ── Step 6: INSERT supplier_installment ────────────── WHERE c.PurchaseOrderAssetContractIsActive = 'Y'
$sql = "INSERT INTO supplier_installment ( AND c.PurchaseOrderAssetContractStatus = 'belum lunas'
SupplierInstallmentPurchaseOrderID, -- Hanya kontrak yang ada nilai cicilannya
SupplierInstallmentSupplierID, AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0
SupplierInstallmentSupplierInvoiceID, -- Hanya kontrak yang belum selesai seluruh cicilannya
SupplierInstallmentAmount, AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0) < IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0)
SupplierInstallmentDate, -- Kontrak sudah mulai sebelum atau pada akhir bulan ini
SupplierInstallmentDueDate, AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?)
SupplierInstallmentPaymentID, -- Kontrak belum berakhir (atau tidak ada tanggal akhir)
SupplierInstallmentStatus, AND (
SupplierInstallmentIsLunas, c.PurchaseOrderAssetContractEndDate IS NULL
SupplierInstallmentIsActive, OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?)
SupplierInstallmentCreated, )
SupplierInstallmentCreatedUserID -- Tanggal jatuh tempo cicilan sudah melewati atau sama dengan hari ini
) VALUES (?, ?, ?, ?, ?, ?, 0, 'Pending', 'N', 'Y', NOW(), ?)"; AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ?";
$que = $this->db->query($sql, [ $params = [$monthEnd, $monthStart, $dayOfMonth];
$row["PurchaseOrderID"],
$row["PurchaseOrderSupplierID"],
$row["SupplierInvoiceID"],
$amount,
$installDate,
$dueDate,
$createdBy
]);
if (!$que) { $qryKontrak = $this->db->query($sqlKontrak, $params);
$this->db->trans_rollback(); if (!$qryKontrak) {
$this->sys_error_db("Gagal insert supplier_installment."); $this->sys_error_db("Gagal mengambil daftar kontrak cicilan dari database.");
exit;
}
$installmentID = $this->db->insert_id();
$inserted++;
$created[] = [
"installmentID" => $installmentID,
"contractID" => $row["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $row["PurchaseOrderID"],
"parentInvoiceID" => $row["SupplierInvoiceID"],
"parentInvoiceNumber" => $row["SupplierInvoiceNumber"],
"amount" => $amount,
"installDate" => $installDate,
"dueDate" => $dueDate
];
}
if ($this->db->trans_status() === false) {
$this->db->trans_rollback();
$this->sys_error_db("Transaksi gagal.");
exit; exit;
} }
$this->db->trans_commit(); $berhasil = []; // PI yang berhasil dibuat
$dilewati = []; // PI yang dilewati beserta alasannya
// -------------------------------------------------------------------------
// Proses tiap kontrak satu per satu
// -------------------------------------------------------------------------
$kontraks = $qryKontrak->result_array();
foreach ($kontraks as $kontrak) {
// Lewati jika item/satuan PO tidak ditemukan (tidak bisa buat baris detail)
if (empty($kontrak["PurchaseOrderSummaryItemID"]) || empty($kontrak["PurchaseOrderSummaryItemUnitID"])) {
$dilewati[] = [
"kontrakID" => $kontrak["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $kontrak["PurchaseOrderID"],
"alasan" => "Item atau satuan pada Purchase Order tidak ditemukan, tidak bisa membuat baris detail PI."
];
continue;
}
// -------------------------------------------------------
// Cek apakah PI cicilan bulan ini sudah pernah dibuat
// -------------------------------------------------------
$sqlCekDuplikat = "SELECT SupplierInvoiceID, SupplierInvoiceNumber
FROM supplier_invoice
WHERE SupplierInvoiceIsActive = 'Y'
AND SupplierInvoiceDate >= DATE(?)
AND SupplierInvoiceDate <= DATE(?)
AND SupplierInvoiceStatus = 'Draft'
AND (
SupplierInvoiceReceiveOrderPoID = ?
OR EXISTS (
SELECT 1
FROM supplier_invoice_detail sid
WHERE sid.SupplierInvoiceDetailSupplierInvoiceID = SupplierInvoiceID
AND sid.SupplierInvoiceDetailReceiveOrderPoID = ?
AND sid.SupplierInvoiceDetailIsActive = 'Y'
)
)
LIMIT 1";
$qryCekDuplikat = $this->db->query($sqlCekDuplikat, [
$monthStart,
$monthEnd,
$kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
$kontrak["PurchaseOrderAssetContractReceiveOrderPoID"]
]);
if (!$qryCekDuplikat) {
$this->sys_error_db("Gagal memeriksa duplikasi PI cicilan untuk kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ".");
exit;
}
if ($qryCekDuplikat->num_rows() > 0) {
$piExisting = $qryCekDuplikat->row_array();
$dilewati[] = [
"kontrakID" => $kontrak["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $kontrak["PurchaseOrderID"],
"receiveOrderPoID" => $kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
"supplierInvoiceID" => $piExisting["SupplierInvoiceID"],
"nomorInvoice" => $piExisting["SupplierInvoiceNumber"],
"alasan" => "PI cicilan untuk bulan ini sudah dibuat sebelumnya, tidak perlu dibuat ulang."
];
continue;
}
$contractUserID = (int) ($kontrak["PurchaseOrderAssetContractCreatedUserID"] ?? 0);
$contractUser = $this->getCronUser($contractUserID);
// Generate nomor PI otomatis via stored function fn_penomoran
$nomorPI = $this->generateNomorPI($kontrak, $contractUser);
$jumlahCicilan = (float) $kontrak["PurchaseOrderAssetContractInstallmentPayAmount"];
$paymentTerm = isset($kontrak["PurchaseOrderPaymentTerm"]) && $kontrak["PurchaseOrderPaymentTerm"] !== null
? (int) $kontrak["PurchaseOrderPaymentTerm"]
: 0;
$tanggalJatuhTempo = $this->hitungJatuhTempo($endDate, $paymentTerm);
$catatan = "PI Cicilan Otomatis — Kontrak Aset ID " . $kontrak["PurchaseOrderAssetContractID"] . " periode " . date("Y-m", strtotime($startDate));
// -------------------------------------------------------
// INSERT header + detail Purchase Invoice (supplier_invoice & supplier_invoice_detail)
// -------------------------------------------------------
$deskripsi = $kontrak["PurchaseOrderAssetContractName"] != ""
? $kontrak["PurchaseOrderAssetContractName"]
: "Cicilan Kontrak Aset ID " . $kontrak["PurchaseOrderAssetContractID"];
$deskripsi .= " periode " . date("Y-m", strtotime($startDate));
$payloadInsert = [
"nomorPI" => $nomorPI,
"tanggalPI" => $endDate,
"tanggalJatuhTempo" => $tanggalJatuhTempo,
"jumlahCicilan" => $jumlahCicilan,
"catatan" => $catatan,
"deskripsi" => $deskripsi,
"userID" => $contractUserID,
"purchaseOrderAssetContractID" => $kontrak["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $kontrak["PurchaseOrderID"],
"receiveOrderPoID" => $kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
"supplierID" => $kontrak["PurchaseOrderSupplierID"],
"purchaseOrderSummaryID" => $kontrak["PurchaseOrderSummaryID"],
"purchaseOrderSummaryItemID" => $kontrak["PurchaseOrderSummaryItemID"],
"purchaseOrderSummaryItemUnitID" => $kontrak["PurchaseOrderSummaryItemUnitID"]
];
$hasilInsert = $this->curlInsertSupplierInvoice($payloadInsert);
if ($hasilInsert === false) {
$this->sys_error_db("Gagal menyimpan Purchase Invoice cicilan untuk kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ".");
exit;
}
if (!empty($hasilInsert["duplicate"])) {
$dilewati[] = [
"kontrakID" => $kontrak["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $kontrak["PurchaseOrderID"],
"receiveOrderPoID" => $kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
"supplierInvoiceID" => $hasilInsert["supplierInvoiceID"],
"nomorInvoice" => $hasilInsert["supplierInvoiceNumber"],
"alasan" => "PI cicilan untuk bulan ini sudah dibuat sebelumnya, tidak perlu dibuat ulang."
];
continue;
}
$supplierInvoiceID = $hasilInsert["supplierInvoiceID"];
// -------------------------------------------------------
// UPDATE jumlah cicilan terbayar pada kontrak
// -------------------------------------------------------
$this->db->trans_begin();
$cicilanTerbayarBaru = ((int) $kontrak["PurchaseOrderAssetContractInstallmentPaid"]) + 1;
$statusKontrakBaru = $cicilanTerbayarBaru >= (int) $kontrak["PurchaseOrderAssetContractInstallmentNumber"]
? "lunas"
: "belum lunas";
$sqlUpdateKontrak = "UPDATE purchase_order_asset_contract
SET PurchaseOrderAssetContractReceiveOrderPoID = ?,
PurchaseOrderAssetContractInstallmentPaid = ?,
PurchaseOrderAssetContractStatus = ?,
PurchaseOrderAssetContractLastUpdated = NOW()
WHERE PurchaseOrderAssetContractID = ?
AND PurchaseOrderAssetContractIsActive = 'Y'";
$qryUpdateKontrak = $this->db->query($sqlUpdateKontrak, [
$kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
$cicilanTerbayarBaru,
$statusKontrakBaru,
$kontrak["PurchaseOrderAssetContractID"]
]);
if (!$qryUpdateKontrak) {
$this->db->trans_rollback();
$this->sys_error_db("Gagal memperbarui data cicilan terbayar pada kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ".");
exit;
}
// Pastikan tidak ada error di dalam transaksi sebelum commit
if ($this->db->trans_status() === false) {
$this->db->trans_rollback();
$this->sys_error_db("Transaksi database gagal saat memproses kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ". Semua perubahan dibatalkan.");
exit;
}
$this->db->trans_commit();
// Catat PI yang berhasil dibuat
$berhasil[] = [
"kontrakID" => $kontrak["PurchaseOrderAssetContractID"],
"purchaseOrderID" => $kontrak["PurchaseOrderID"],
"supplierInvoiceID" => $supplierInvoiceID,
"nomorInvoice" => $nomorPI,
"jumlahCicilan" => $jumlahCicilan
];
}
// -------------------------------------------------------
// Response sukses — ringkasan hasil proses
// -------------------------------------------------------
$this->sys_ok([ $this->sys_ok([
"startDate" => $startDate, "startDate" => $startDate,
"endDate" => $endDate, "endDate" => $endDate,
"totalEligible" => count($eligible), "periodeAwal" => $monthStart,
"totalInserted" => $inserted, "periodeAkhir" => $monthEnd,
"created" => $created "totalDibuat" => count($berhasil),
"totalDilewati" => count($dilewati),
"daftarDibuat" => $berhasil,
"daftarDilewati" => $dilewati
]); ]);
} catch (Exception $exc) { } catch (Exception $exc) {
if ($this->db->trans_status() === false) { if ($this->db->trans_status() === false) {
$this->db->trans_rollback(); $this->db->trans_rollback();
@@ -147,6 +354,229 @@ class PurchaseInvoiceInstallment extends MY_Controller
} }
} }
/**
* Kirim payload insert supplier_invoice ke controller terpisah via cURL.
*
* @param array $payload
* @return array|false
*/
private function curlInsertSupplierInvoice($payload)
{
$endpoint = rtrim($this->baseUrl, "/") . "/mockup/scheduler/PurchaseInvoiceInstallmentInsert/InsertSupplierInvoice";
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Accept: application/json"
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_CONNECTTIMEOUT => 15,
CURLOPT_TIMEOUT => 120
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$pesanError = curl_error($ch);
curl_close($ch);
$this->sys_error("Gagal menghubungi endpoint insert supplier_invoice. Detail: " . $pesanError);
return false;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
$this->sys_error("Endpoint insert supplier_invoice mengembalikan HTTP " . $httpCode . ".");
return false;
}
$decoded = json_decode($response, true);
if (!is_array($decoded)) {
$this->sys_error("Response insert supplier_invoice tidak valid JSON.");
return false;
}
if (!isset($decoded["status"]) || strtoupper($decoded["status"]) !== "OK") {
$pesan = isset($decoded["message"]) ? $decoded["message"] : "Insert supplier_invoice gagal.";
$this->sys_error($pesan);
return false;
}
return isset($decoded["data"]) && is_array($decoded["data"]) ? $decoded["data"] : $decoded;
}
public function ListEligibleContracts()
{
try {
$para = $this->sys_input;
$startDate = isset($para["startDate"]) && $para["startDate"] != ""
? $para["startDate"]
: (isset($para["date"]) && $para["date"] != "" ? date("Y-m-01", strtotime($para["date"])) : date("Y-m-01"));
$endDate = isset($para["endDate"]) && $para["endDate"] != ""
? $para["endDate"]
: (isset($para["date"]) && $para["date"] != "" ? date("Y-m-t", strtotime($para["date"])) : date("Y-m-t"));
if (!$this->isValidDate($startDate) || !$this->isValidDate($endDate)) {
throw new Exception("Format tanggal tidak valid. Gunakan format YYYY-MM-DD, contoh: 2025-07-01");
}
if (strtotime($startDate) > strtotime($endDate)) {
throw new Exception("startDate tidak boleh lebih besar dari endDate");
}
$monthStart = $startDate;
$monthEnd = $endDate;
$dayOfMonth = (int) date("d", strtotime($endDate));
$sqlKontrak = "SELECT
c.PurchaseOrderAssetContractID,
c.PurchaseOrderAssetContractPurchaseOrderID,
ro.ReceiveOrderPoID AS PurchaseOrderAssetContractReceiveOrderPoID,
c.PurchaseOrderAssetContractName,
c.PurchaseOrderAssetContractStartDate,
c.PurchaseOrderAssetContractEndDate,
c.PurchaseOrderAssetContractInstallmentNumber,
c.PurchaseOrderAssetContractInstallmentPaid,
c.PurchaseOrderAssetContractInstallmentDate,
c.PurchaseOrderAssetContractInstallmentPayAmount,
po.PurchaseOrderID,
po.PurchaseOrderNumber,
po.PurchaseOrderSupplierID,
po.PurchaseOrderPaymentTerm,
po.PurchaseOrderWarehouseType,
po.PurchaseOrderWarehouseID,
ro.ReceiveOrderPoConfirmed,
ps.PurchaseOrderSummaryID,
ps.PurchaseOrderSummaryItemID,
ps.PurchaseOrderSummaryItemUnitID
FROM purchase_order_asset_contract c
JOIN purchase_order po
ON po.PurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID
AND po.PurchaseOrderIsActive = 'Y'
AND po.PurchaseOrderStatus = 'Approved'
JOIN (
SELECT
rd.ReceiveOrderPoDetailPurchaseOrderID,
MIN(ro0.ReceiveOrderPoID) AS ReceiveOrderPoID,
MAX(ro0.ReceiveOrderPoConfirmed) AS ReceiveOrderPoConfirmed
FROM receive_order_po ro0
JOIN receive_order_po_detail rd
ON rd.ReceiveOrderPoDetailReceiveOrderPoID = ro0.ReceiveOrderPoID
AND rd.ReceiveOrderPoDetailIsActive = 'Y'
WHERE ro0.ReceiveOrderPoIsActive = 'Y'
AND ro0.ReceiveOrderPoConfirmed = 'Y'
GROUP BY rd.ReceiveOrderPoDetailPurchaseOrderID
) ro
ON ro.ReceiveOrderPoDetailPurchaseOrderID = po.PurchaseOrderID
LEFT JOIN (
SELECT ps0.*
FROM purchase_order_summary ps0
JOIN (
SELECT
PurchaseOrderSummaryPurchaseOrderID,
MIN(PurchaseOrderSummaryID) AS PurchaseOrderSummaryID
FROM purchase_order_summary
WHERE PurchaseOrderSummaryIsActive = 'Y'
GROUP BY PurchaseOrderSummaryPurchaseOrderID
) psx
ON psx.PurchaseOrderSummaryID = ps0.PurchaseOrderSummaryID
) ps
ON ps.PurchaseOrderSummaryPurchaseOrderID = po.PurchaseOrderID
WHERE c.PurchaseOrderAssetContractIsActive = 'Y'
AND c.PurchaseOrderAssetContractStatus = 'belum lunas'
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0) < IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0)
AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?)
AND (
c.PurchaseOrderAssetContractEndDate IS NULL
OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?)
)
AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ?
ORDER BY c.PurchaseOrderAssetContractID ASC";
$qryKontrak = $this->db->query($sqlKontrak, [$monthEnd, $monthStart, $dayOfMonth]);
if (!$qryKontrak) {
$this->sys_error_db("Gagal mengambil daftar kontrak cicilan eligible.");
exit;
}
$this->sys_ok([
"startDate" => $startDate,
"endDate" => $endDate,
"periodeAwal" => $monthStart,
"periodeAkhir" => $monthEnd,
"total" => $qryKontrak->num_rows(),
"records" => $qryKontrak->result_array()
]);
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
/**
* CurlGenerateMonthlyInvoices
*
* Wrapper untuk memanggil GenerateMonthlyInvoices melalui HTTP request (cURL).
* Cocok digunakan oleh CRON eksternal yang tidak bisa memanggil function PHP langsung.
*
* Parameter (POST JSON):
* - baseUrl : Base URL server tujuan. Default: URL server ini sendiri.
* - startDate : Tanggal awal periode (YYYY-MM-DD). Default: awal bulan ini.
* - endDate : Tanggal akhir periode (YYYY-MM-DD). Default: akhir bulan ini.
* - userID : ID user yang menjalankan. Default: 0.
*/
// =========================================================================
// FUNGSI PRIVATE / HELPER
// =========================================================================
/**
* Generate nomor Purchase Invoice.
*
* @param array $kontrak Data baris kontrak dari query
* @param array $user Data user CRON
* @return string Nomor PI yang dihasilkan
*/
private function generateNomorPI($kontrak, $user)
{
$userID = isset($user["M_UserID"]) ? (int) $user["M_UserID"] : 0;
// Tentukan area ID dan type
$areaid = isset($user["M_BranchID"]) && (int) $user["M_BranchID"] > 0 ? (int) $user["M_BranchID"] : 0;
$areatype = 'B';
if (isset($user["loginLevel"]) && $user["loginLevel"] == 'regional') {
$areaid = isset($user["S_RegionalID"]) && (int) $user["S_RegionalID"] > 0 ? (int) $user["S_RegionalID"] : 0;
$areatype = 'R';
}
// Ambil divisi user
$userDivID = 0;
if ($userID > 0) {
$sqlusrdivisi = "SELECT M_UserDivisionDivisionID FROM m_userdivision
WHERE M_UserDivisionM_UserID = ? AND M_UserDivisionIsActive = 'Y' LIMIT 1";
$queusrdivisi = $this->db->query($sqlusrdivisi, [$userID]);
if ($queusrdivisi && $queusrdivisi->num_rows() > 0) {
$userDivID = (int) $queusrdivisi->row_array()['M_UserDivisionDivisionID'];
}
}
// Jalankan stored function fn_penomoran
$sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;";
$quenum = $this->db->query($sqlnum, ['PI', $userDivID, $areatype, $areaid, 'SM', 'N']);
if ($quenum && $quenum->num_rows() > 0) {
return $quenum->row_array()['numpd'];
}
// Fallback jika stored function gagal
$contractID = isset($kontrak["PurchaseOrderAssetContractID"]) ? (int) $kontrak["PurchaseOrderAssetContractID"] : 0;
return "PI-INS-FALLBACK-" . $contractID . "-" . date("Ymd");
}
/** /**
* Ambil data user berdasarkan userID untuk keperluan CRON. * Ambil data user berdasarkan userID untuk keperluan CRON.
* Jika user tidak ditemukan, kembalikan data default (tanpa branch/regional). * Jika user tidak ditemukan, kembalikan data default (tanpa branch/regional).
@@ -208,95 +638,4 @@ class PurchaseInvoiceInstallment extends MY_Controller
$d = DateTime::createFromFormat("Y-m-d", $tanggal); $d = DateTime::createFromFormat("Y-m-d", $tanggal);
return $d && $d->format("Y-m-d") === $tanggal; return $d && $d->format("Y-m-d") === $tanggal;
} }
/**
* getEligibleInstallments — Steps 15 combined
*
* Returns contracts that:
* Step 1: Are active, not paid off, within date range, due date reached
* Step 2: Have approved & active PO
* Step 3: Have confirmed & active RO
* Step 4: Have a parent supplier_invoice with IsInstallment = 'Y'
* Step 5: Do NOT already have a supplier_installment for this month
*
* @param string $startDate YYYY-MM-DD
* @param string $endDate YYYY-MM-DD
* @return array
*/
private function getEligibleInstallments($startDate, $endDate)
{
$dayOfMonth = (int) date("d", strtotime($endDate));
$sql = "SELECT
c.PurchaseOrderAssetContractID,
c.PurchaseOrderAssetContractInstallmentPayAmount,
c.PurchaseOrderAssetContractInstallmentDate,
c.PurchaseOrderAssetContractCreatedUserID,
po.PurchaseOrderID,
po.PurchaseOrderSupplierID,
si.SupplierInvoiceID,
si.SupplierInvoiceNumber
FROM purchase_order_asset_contract c
-- Step 2: PO must be Approved and Active
JOIN purchase_order po
ON po.PurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID
AND po.PurchaseOrderIsActive = 'Y'
AND po.PurchaseOrderStatus = 'Approved'
-- Step 3: RO must be Confirmed and Active
JOIN (
SELECT
rd.ReceiveOrderPoDetailPurchaseOrderID,
MIN(ro0.ReceiveOrderPoID) AS ReceiveOrderPoID,
MAX(ro0.ReceiveOrderPoConfirmed) AS ReceiveOrderPoConfirmed
FROM receive_order_po ro0
JOIN receive_order_po_detail rd
ON rd.ReceiveOrderPoDetailReceiveOrderPoID = ro0.ReceiveOrderPoID
AND rd.ReceiveOrderPoDetailIsActive = 'Y'
WHERE ro0.ReceiveOrderPoIsActive = 'Y'
AND ro0.ReceiveOrderPoConfirmed = 'Y'
GROUP BY rd.ReceiveOrderPoDetailPurchaseOrderID
) ro ON ro.ReceiveOrderPoDetailPurchaseOrderID = po.PurchaseOrderID
-- Step 4: Parent invoice must exist with IsInstallment = 'Y'
JOIN supplier_invoice si
ON si.SupplierInvoiceReceiveOrderPoID = ro.ReceiveOrderPoID
AND si.SupplierInvoiceIsActive = 'Y'
AND si.SupplierInvoiceIsInstallment = 'Y'
-- Step 1: Contract eligibility
WHERE c.PurchaseOrderAssetContractIsActive = 'Y'
AND c.PurchaseOrderAssetContractStatus = 'belum lunas'
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0)
< IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0)
AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?)
AND (
c.PurchaseOrderAssetContractEndDate IS NULL
OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?)
)
AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ?
-- Step 5: Dedup — no existing supplier_installment this month (any status)
AND NOT EXISTS (
SELECT 1
FROM supplier_installment inst
WHERE inst.SupplierInstallmentIsActive = 'Y'
AND inst.SupplierInstallmentPurchaseOrderID = po.PurchaseOrderID
AND DATE_FORMAT(inst.SupplierInstallmentDate, '%Y-%m') = DATE_FORMAT(?, '%Y-%m')
)
ORDER BY c.PurchaseOrderAssetContractID ASC";
$params = [$endDate, $startDate, $dayOfMonth, $endDate];
$qry = $this->db->query($sql, $params);
if (!$qry) {
$this->sys_error_db("Gagal mengambil daftar installment eligible.");
exit;
}
return $qry->result_array();
}
} }

View File

@@ -28,92 +28,29 @@ class Billv2 extends MY_Controller {
$offset = ($params['currentpage'] - 1) * $limit; $offset = ($params['currentpage'] - 1) * $limit;
} }
// ── UNION base — invoice + downpayment + installment ─── $sql_base = "SELECT
$sql_base = " SupplierPaymentID,
SELECT SupplierPaymentDate,
sp.SupplierPaymentID, SupplierPaymentNumber,
sp.SupplierPaymentDate, SupplierPaymentAmount,
sp.SupplierPaymentNumber, SupplierPaymentStatus,
sp.SupplierPaymentAmount, SupplierPaymentIsVerif,
sp.SupplierPaymentStatus, SupplierPaymentIsApproved,
sp.SupplierPaymentIsVerif, SupplierInvoiceID,
sp.SupplierPaymentIsApproved, SupplierInvoiceNumber,
sp.SupplierPaymentIsActive, SupplierInvoiceDraftPaymentDate,
si.SupplierInvoiceID, SupplierCode,
si.SupplierInvoiceNumber, SupplierName
si.SupplierInvoiceDraftPaymentDate, FROM supplier_payment
sup.SupplierCode, JOIN supplier_invoice ON SupplierInvoiceID = SupplierPaymentSupplierInvoiceID
sup.SupplierName, AND SupplierPaymentNumber LIKE ?
'INVOICE' AS type AND (SupplierPaymentDate BETWEEN DATE(?) AND DATE(?))
FROM supplier_payment sp AND (SupplierPaymentStatus = ? OR ? = 'All')
JOIN supplier_invoice si JOIN supplier ON SupplierID = SupplierInvoiceSupplierID
ON si.SupplierInvoiceID = sp.SupplierPaymentSupplierInvoiceID WHERE SupplierPaymentIsActive = 'Y'
JOIN supplier sup ORDER BY SupplierPaymentID DESC";
ON sup.SupplierID = si.SupplierInvoiceSupplierID
WHERE sp.SupplierPaymentSupplierInvoiceID > 0
UNION ALL
SELECT
sp.SupplierPaymentID,
sp.SupplierPaymentDate,
sp.SupplierPaymentNumber,
sp.SupplierPaymentAmount,
sp.SupplierPaymentStatus,
sp.SupplierPaymentIsVerif,
sp.SupplierPaymentIsApproved,
sp.SupplierPaymentIsActive,
dp.SupplierDownpaymentID * -1 AS SupplierInvoiceID,
CONCAT('DP-', po.PurchaseOrderNumber) AS SupplierInvoiceNumber,
dp.SupplierDownpaymentDueDate AS SupplierInvoiceDraftPaymentDate,
dp_sup.SupplierCode AS SupplierCode,
dp_sup.SupplierName AS SupplierName,
'DP' AS type
FROM supplier_payment sp
JOIN supplier_downpayment dp
ON dp.SupplierDownpaymentID = sp.SupplierPaymentSupplierDownpaymentID
JOIN supplier dp_sup
ON dp_sup.SupplierID = dp.SupplierDownpaymentSupplierID
JOIN purchase_order po
ON po.PurchaseOrderID = dp.SupplierDownpaymentPurchasOrderID
WHERE sp.SupplierPaymentSupplierDownpaymentID IS NOT NULL
UNION ALL
SELECT
sp.SupplierPaymentID,
sp.SupplierPaymentDate,
sp.SupplierPaymentNumber,
sp.SupplierPaymentAmount,
sp.SupplierPaymentStatus,
sp.SupplierPaymentIsVerif,
sp.SupplierPaymentIsApproved,
sp.SupplierPaymentIsActive,
0 AS SupplierInvoiceID,
CONCAT('INST-', si_inst.SupplierInvoiceNumber) AS SupplierInvoiceNumber,
inst.SupplierInstallmentDueDate AS SupplierInvoiceDraftPaymentDate,
inst_sup.SupplierCode AS SupplierCode,
inst_sup.SupplierName AS SupplierName,
'INSTALLMENT' AS type
FROM supplier_payment sp
JOIN supplier_installment inst
ON inst.SupplierInstallmentID = sp.SupplierPaymentSupplierInstallmentID
JOIN supplier_invoice si_inst
ON si_inst.SupplierInvoiceID = inst.SupplierInstallmentSupplierInvoiceID
JOIN supplier inst_sup
ON inst_sup.SupplierID = inst.SupplierInstallmentSupplierID
WHERE sp.SupplierPaymentSupplierInstallmentID IS NOT NULL";
// ── Outer: common filters + ordering + pagination ───────
$sql_data = "
SELECT * FROM ($sql_base) AS combined
WHERE SupplierPaymentIsActive = 'Y'
AND SupplierPaymentNumber LIKE ?
AND (SupplierPaymentDate BETWEEN DATE(?) AND DATE(?))
AND (SupplierPaymentStatus = ? OR ? = 'All')
ORDER BY SupplierPaymentID DESC
LIMIT ? OFFSET ?";
$sql_data = $sql_base . " LIMIT ? OFFSET ? ";
$que_data = $this->db->query($sql_data, [ $que_data = $this->db->query($sql_data, [
$keyword, $params['startdate'], $params['enddate'], $keyword, $params['startdate'], $params['enddate'],
$params['status'], $params['status'], $limit, $offset $params['status'], $params['status'], $limit, $offset
@@ -122,13 +59,7 @@ class Billv2 extends MY_Controller {
throw new Exception("[Error] failed get data supplier payment", 2); throw new Exception("[Error] failed get data supplier payment", 2);
} }
// ── COUNT — wrap UNION in outer filter ────────────────── $sql_total = "SELECT COUNT(*) AS total FROM ($sql_base) AS x";
$sql_total = "SELECT COUNT(*) AS total FROM ($sql_base) AS combined
WHERE SupplierPaymentIsActive = 'Y'
AND SupplierPaymentNumber LIKE ?
AND (SupplierPaymentDate BETWEEN DATE(?) AND DATE(?))
AND (SupplierPaymentStatus = ? OR ? = 'All')";
$que_total = $this->db->query($sql_total, [ $que_total = $this->db->query($sql_total, [
$keyword, $params['startdate'], $params['enddate'], $keyword, $params['startdate'], $params['enddate'],
$params['status'], $params['status'] $params['status'], $params['status']
@@ -139,10 +70,11 @@ class Billv2 extends MY_Controller {
$output = [ $output = [
"records" => $que_data->result_array(), "records" => $que_data->result_array(),
"total" => $que_total->row_array()['total'] "total" =>$que_total->row_array()['total']
]; ];
$this->sys_ok($output); $this->sys_ok($output);
exit;
} catch (Exception $exc) { } catch (Exception $exc) {
$message = $exc->getMessage(); $message = $exc->getMessage();
$code = $exc->getCode(); $code = $exc->getCode();
@@ -164,169 +96,70 @@ class Billv2 extends MY_Controller {
$para = $this->sys_input; $para = $this->sys_input;
// ── Detect payment type ────────────────────────────────── $sql = "SELECT
$sql_type = "SELECT SupplierInvoiceID,
SupplierPaymentSupplierInvoiceID, SupplierInvoiceRefNumber,
SupplierPaymentSupplierDownpaymentID, SupplierInvoiceDeliveryOrderNumber,
SupplierPaymentSupplierInstallmentID SupplierInvoiceSupplierInvoiceNumber,
FROM supplier_payment SupplierInvoiceSupplierInvoiceDate,
WHERE SupplierPaymentID = ? AND SupplierPaymentIsActive = 'Y'"; SupplierInvoiceSubTotal,
SupplierInvoiceTaxPercentPph,
$que_type = $this->db->query($sql_type, [$para['paymentID']]); SupplierInvoiceTaxPercentPpn,
if (!$que_type) { SupplierInvoiceTaxAmountPpn,
throw new Exception("[Error] failed get payment header", 2); SupplierInvoiceDiscountAmount,
SupplierInvoiceDiscountPercent,
SupplierInvoiceShippingCost,
SupplierInvoiceGrandTotal,
SupplierInvoiceAdjustmentAmount,
SupplierInvoiceAdjustmentNote,
SupplierInvoiceNote,
IF (SupplierInvoiceDiscountAmount > 0, 'R', 'P') AS DiscountType
FROM supplier_payment
JOIN supplier_invoice ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID
AND SupplierPaymentID = ?
AND SupplierPaymentIsActive = 'Y'";
$que = $this->db->query($sql, [$para['paymentID']]);
if (!$que) {
throw new Exception("[Error] failed get row data", 2);
} }
$payment = $que_type->row_array(); $data = $que->row_array();
if (!$payment) {
throw new Exception("[Error] payment not found", 2); $sql_detail = "SELECT
SupplierInvoiceDetailID,
SupplierInvoiceDetailSupplierInvoiceID,
SupplierInvoiceDetailPurchaseOrderID,
SupplierInvoiceDetailPurchaseOrderSummaryID,
SupplierInvoiceDetailReceiveOrderPoID,
SupplierInvoiceDetailReceiveOrderPoDetailID,
SupplierInvoiceDetailItemID,
SupplierInvoiceDetailItemUnitID,
SupplierInvoiceDetailDescription,
SupplierInvoiceDetailQty,
SupplierInvoiceDetailPrice,
SupplierInvoiceDetailDiscountPercent,
SupplierInvoiceDetailDiscountDiscountRupiah,
SupplierInvoiceDetailDiscountDiscountType,
SupplierInvoiceDetailDiscountAmount,
(SupplierInvoiceDetailPrice - SupplierInvoiceDetailDiscountAmount) AS DiscountedPrice,
SupplierInvoiceDetailDiscountPoProrata,
SupplierInvoiceDetailTotal,
M_ItemCode,
M_ItemDesc
FROM supplier_payment_detail
JOIN supplier_invoice_detail ON SupplierInvoiceDetailIsActive = 'Y'
AND SupplierPaymentDetailSupplierPaymentID = ?
AND SupplierInvoiceDetailSupplierInvoiceID = ?
JOIN m_item ON M_ItemID = SupplierInvoiceDetailItemID
AND M_ItemIsActive = 'Y'
GROUP BY SupplierInvoiceDetailID";
$que_detail = $this->db->query($sql_detail, [
$para['paymentID'], $data['SupplierInvoiceID']
]);
if (!$que_detail) {
throw new Exception("[Error] failed to get item payments", 2);
} }
// ── INVOICE branch ────────────────────────────────────── $data['detail'] = $que_detail->result_array();
if ($payment['SupplierPaymentSupplierInvoiceID'] > 0) {
$sql = "SELECT
si.SupplierInvoiceSubTotal,
si.SupplierInvoiceShippingCost,
si.SupplierInvoiceDiscountPercent,
si.SupplierInvoiceDiscountAmount,
si.SupplierInvoiceTaxPercentPpn,
si.SupplierInvoiceTaxAmountPpn,
si.SupplierInvoiceGrandTotal,
si.SupplierInvoiceID,
'INVOICE' AS type
FROM supplier_payment sp
JOIN supplier_invoice si
ON si.SupplierInvoiceID = sp.SupplierPaymentSupplierInvoiceID
WHERE sp.SupplierPaymentID = ? AND sp.SupplierPaymentIsActive = 'Y'";
$que = $this->db->query($sql, [$para['paymentID']]);
if (!$que) {
throw new Exception("[Error] failed get row data", 2);
}
$data = $que->row_array();
$sql_detail = "SELECT
M_ItemDesc,
SupplierInvoiceDetailQty,
SupplierInvoiceDetailPrice,
SupplierInvoiceDetailDiscountAmount,
(SupplierInvoiceDetailPrice - SupplierInvoiceDetailDiscountAmount) AS DiscountedPrice,
SupplierInvoiceDetailTotal
FROM supplier_payment_detail
JOIN supplier_invoice_detail
ON SupplierInvoiceDetailIsActive = 'Y'
AND SupplierPaymentDetailSupplierPaymentID = ?
AND SupplierInvoiceDetailSupplierInvoiceID = ?
JOIN m_item
ON M_ItemID = SupplierInvoiceDetailItemID AND M_ItemIsActive = 'Y'
GROUP BY SupplierInvoiceDetailID";
$que_detail = $this->db->query($sql_detail, [
$para['paymentID'], $data['SupplierInvoiceID']
]);
if (!$que_detail) {
throw new Exception("[Error] failed to get item payments", 2);
}
unset($data['SupplierInvoiceID']);
$data['detail'] = $que_detail->result_array();
// ── DOWNPAYMENT branch ──────────────────────────────────
} elseif ($payment['SupplierPaymentSupplierDownpaymentID'] > 0) {
$sql = "SELECT
dp.SupplierDownpaymentPurchasOrderID,
dp.SupplierDownpaymentAmount AS SupplierInvoiceSubTotal,
0 AS SupplierInvoiceShippingCost,
0 AS SupplierInvoiceDiscountPercent,
0 AS SupplierInvoiceDiscountAmount,
0 AS SupplierInvoiceTaxPercentPpn,
0 AS SupplierInvoiceTaxAmountPpn,
dp.SupplierDownpaymentAmount AS SupplierInvoiceGrandTotal,
'DP' AS type
FROM supplier_payment sp
JOIN supplier_downpayment dp
ON dp.SupplierDownpaymentID = sp.SupplierPaymentSupplierDownpaymentID
WHERE sp.SupplierPaymentID = ? AND sp.SupplierPaymentIsActive = 'Y'";
$que = $this->db->query($sql, [$para['paymentID']]);
if (!$que) {
throw new Exception("[Error] failed get DP row data", 2);
}
$data = $que->row_array();
$sql_detail = "SELECT
CONCAT('DP-', M_ItemDesc) AS M_ItemDesc,
PurchaseOrderDetailQty AS SupplierInvoiceDetailQty,
PurchaseOrderDetailPrice AS SupplierInvoiceDetailPrice,
PurchaseOrderSummaryDiscountAmount AS SupplierInvoiceDetailDiscountAmount,
(PurchaseOrderDetailPrice - PurchaseOrderSummaryDiscountAmount) AS DiscountedPrice,
PurchaseOrderSummaryTotal AS SupplierInvoiceDetailTotal
FROM supplier_downpayment
JOIN purchase_order
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderID
JOIN purchase_order_detail
ON PurchaseOrderDetailPurchaseOrderID = PurchaseOrderID
AND PurchaseOrderDetailIsActive = 'Y'
JOIN purchase_order_summary
ON PurchaseOrderSummaryID = PurchaseOrderDetailPurchaseSummaryID
AND PurchaseOrderSummaryIsActive = 'Y'
JOIN m_item
ON M_ItemID = PurchaseOrderDetailItemID
WHERE SupplierDownpaymentPurchasOrderID = ?";
$que_detail = $this->db->query($sql_detail, [
$data['SupplierDownpaymentPurchasOrderID']
]);
if (!$que_detail) {
throw new Exception('failed to get dp detail', 2);
}
$data['detail'] = $que_detail->result_array();
} else {
$sql = "SELECT
inst.SupplierInstallmentAmount AS SupplierInvoiceSubTotal,
0 AS SupplierInvoiceShippingCost,
0 AS SupplierInvoiceDiscountPercent,
0 AS SupplierInvoiceDiscountAmount,
0 AS SupplierInvoiceTaxPercentPpn,
0 AS SupplierInvoiceTaxAmountPpn,
inst.SupplierInstallmentAmount AS SupplierInvoiceGrandTotal,
si.SupplierInvoiceID,
'INSTALLMENT' AS type
FROM supplier_payment sp
JOIN supplier_installment inst
ON inst.SupplierInstallmentID = sp.SupplierPaymentSupplierInstallmentID
JOIN supplier_invoice si
ON si.SupplierInvoiceID = inst.SupplierInstallmentSupplierInvoiceID
WHERE sp.SupplierPaymentID = ? AND sp.SupplierPaymentIsActive = 'Y'";
$que = $this->db->query($sql, [$para['paymentID']]);
if (!$que) {
throw new Exception("[Error] failed get Installment row data", 2);
}
$data = $que->row_array();
$sql_detail = "SELECT
M_ItemDesc,
SupplierInvoiceDetailQty,
SupplierInvoiceDetailPrice,
SupplierInvoiceDetailDiscountAmount,
(SupplierInvoiceDetailPrice - SupplierInvoiceDetailDiscountAmount) AS DiscountedPrice,
SupplierInvoiceDetailTotal
FROM supplier_invoice_detail
JOIN m_item
ON M_ItemID = SupplierInvoiceDetailItemID AND M_ItemIsActive = 'Y'
WHERE SupplierInvoiceDetailSupplierInvoiceID = ?
AND SupplierInvoiceDetailIsActive = 'Y'
GROUP BY SupplierInvoiceDetailID";
$que_detail = $this->db->query($sql_detail, [$data['SupplierInvoiceID']]);
if (!$que_detail) {
throw new Exception("[Error] failed to get installment item payments", 2);
}
unset($data['SupplierInvoiceID']);
$data['detail'] = $que_detail->result_array();
}
$this->sys_ok($data); $this->sys_ok($data);
} catch (Exception $exc) { } catch (Exception $exc) {
@@ -381,12 +214,12 @@ class Billv2 extends MY_Controller {
$user = $this->sys_user; $user = $this->sys_user;
if ($para['userlevel'] == '1') { if ($para['userlevel'] == '1') {
$sql = "UPDATE supplier_payment SET $sql = "UPDATE supplier_payment SET
SupplierPaymentIsVerif = 'Y', SupplierPaymentIsVerif = 'Y',
SupplierPaymentStatus = 'Verified', SupplierPaymentStatus = 'Verified',
SupplierPaymentVerifUserID = ?, SupplierPaymentVerifUserID = ?,
SupplierPaymentVerifDate = NOW() SupplierPaymentVerifDate = NOW()
WHERE SupplierPaymentID = ? WHERE SupplierPaymentID = ?
AND SupplierPaymentIsActive = 'Y'"; AND SupplierPaymentIsActive = 'Y'";
$query = $this->db->query($sql, [ $query = $this->db->query($sql, [
$user['M_UserID'], $para['paymentID'] $user['M_UserID'], $para['paymentID']
@@ -398,12 +231,12 @@ class Billv2 extends MY_Controller {
} }
if ($para['userlevel'] == '2') { if ($para['userlevel'] == '2') {
$sql = "UPDATE supplier_payment SET $sql = "UPDATE supplier_payment SET
SupplierPaymentIsApproved = 'Y', SupplierPaymentIsApproved = 'Y',
SupplierPaymentStatus = 'Approved', SupplierPaymentStatus = 'Approved',
SupplierPaymentApprovedUserID = ?, SupplierPaymentApprovedUserID = ?,
SupplierPaymentApprovedDate = NOW() SupplierPaymentApprovedDate = NOW()
WHERE SupplierPaymentID = ? WHERE SupplierPaymentID = ?
AND SupplierPaymentIsActive = 'Y'"; AND SupplierPaymentIsActive = 'Y'";
$query = $this->db->query($sql, [ $query = $this->db->query($sql, [
$user['M_UserID'], $para['paymentID'] $user['M_UserID'], $para['paymentID']
@@ -428,4 +261,4 @@ class Billv2 extends MY_Controller {
exit; exit;
} }
} }
} }

View File

@@ -1,22 +1,20 @@
<?php <?php
class Bill extends MY_Controller class Bill extends MY_Controller
{ {
var $db_onedev; var $db_onedev;
public function index() public function index()
{ {
echo "Bill API"; echo "Bill API";
} }
public function __construct()
public function __construct() {
{ parent::__construct();
parent::__construct(); $this->db_onedev = $this->load->database("onedev", true);
$this->db_onedev = $this->load->database("onedev", true); }
}
public function add_notes($orderid){
public function add_notes($orderid) $sql = " SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
{ SupplierPaymentID as note_id,
$sql = "SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
SupplierPaymentID as note_id,
SupplierPaymentDetailSupplierInvoiceDetailID as detail_id, SupplierPaymentDetailSupplierInvoiceDetailID as detail_id,
SupplierPaymentDate as note_date, SupplierPaymentDate as note_date,
SupplierPaymentNumber as note_number, SupplierPaymentNumber as note_number,
@@ -43,205 +41,63 @@ class Bill extends MY_Controller
LEFT JOIN m_user a ON SupplierPaymentApprovedUserID = a.M_UserID LEFT JOIN m_user a ON SupplierPaymentApprovedUserID = a.M_UserID
LEFT JOIN m_user b ON SupplierPaymentVerifUserID = b.M_UserID LEFT JOIN m_user b ON SupplierPaymentVerifUserID = b.M_UserID
WHERE WHERE
SupplierPaymentSupplierInvoiceID = {$orderid} SupplierPaymentSupplierInvoiceID = {$orderid}
AND AND
SupplierPaymentIsActive = 'Y' SupplierPaymentIsActive = 'Y'
GROUP BY SupplierPaymentID"; GROUP BY SupplierPaymentID";
$query = $this->db_onedev->query($sql); $query = $this->db_onedev->query($sql);
if ($query) { if ($query) {
$rows = $query->result_array(); $rows = $query->result_array();
if ($rows) { if($rows){
foreach ($rows as $k => $v) { foreach($rows as $k => $v){
$rows[$k]['tests'] = $this->add_tests($v['note_id']); $rows[$k]['tests'] = $this->add_tests($v['note_id']);
} }
} }
return $rows; return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev); } else {
exit; $this->sys_error_db("get notes", $this->db_onedev);
} exit;
} }
}
public function add_tagihans($orderid){
$sql = "SELECT SupplierInvoiceID as tagihan_id,
PurchaseOrderNumber as tagihan_number,
jurnalTxDescription as pasien,
jurnalTxCredit as tagihan_total,
IF(SupplierPaymentDetailID IS NULL , jurnalTxCredit, jurnalTxCredit - SUM(SupplierPaymentDetailAmount)) as tagihan_tagihan,
0 as tagihan_bayar,
DATE_FORMAT(SupplierInvoiceDueDate,'%d-%m-%Y') as tagihan_duedate,
SupplierInvoiceIsActive as tagihan_active,
'N' as show_detail,
jurnalTxID SupplierInvoiceDetailID,
PurchaseOrderID SupplierInvoiceDetailPurchaseOrderID
public function add_notes_downpayment($orderid) FROM supplier_invoice
{ JOIN receive_order_po ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
$sql = "SELECT SupplierPaymentSupplierDownpaymentID AS note_order_id, JOIN receive_order_po_detail ON ReceiveOrderPoDetailReceiveOrderPoID = ReceiveOrderPoID
SupplierPaymentID AS note_id, JOIN purchase_order ON ReceiveOrderPoDetailPurchaseOrderID = PurchaseOrderID
SupplierDownpaymentID AS detail_id, JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
SupplierPaymentDate AS note_date, JOIN jurnal_tx ON jurnalTxJurnalID = jurnalAddOnJurnalID AND jurnalTxCredit <> 0 AND jurnalTxCoaID <> 563
SupplierPaymentNumber AS note_number, LEFT JOIN supplier_payment ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID AND SupplierInvoiceIsActive = 'Y'
GROUP_CONCAT(DISTINCT coaDescription separator ' , ') AS paymenttypes_name, LEFT JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID AND SupplierPaymentDetailSupplierInvoiceDetailID = jurnalTxID AND SupplierPaymentDetailIsActive = 'Y'
SUM(SupplierDownpaymentAmount) AS note_amount, WHERE
n.M_UserUsername AS note_user, SupplierInvoiceID = {$orderid}
SupplierDownpaymentIsActive AS note_active, GROUP BY jurnalTxID
'N' AS show_detail, ";
SupplierPaymentNote AS keterangan, $query = $this->db_onedev->query($sql);
SupplierPaymentCoaID, if ($query) {
coaID, $rows = $query->result_array();
coaDescription, return $rows;
SupplierPaymentIsConfirm,
CONCAT( } else {
'Confirmed by : ',c.M_UserUsername, ' ', $this->sys_error_db("get notes", $this->db_onedev);
DATE_FORMAT(SupplierPaymentConfirmDate, '%d-%m-%Y %H:%i') exit;
) AS d_confirm, }
SupplierPaymentIsApproved, }
CONCAT( public function add_tests($orderid){
'Approved by : ',a.M_UserUsername, ' ', $sql = " SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
DATE_FORMAT(SupplierPaymentApprovedDate,'%d-%m-%Y %H:%i') SupplierPaymentID as note_id,
) AS d_approved,
CONCAT(
'Verified by : ',b.M_UserUsername, ' ',
DATE_FORMAT(SupplierPaymentVerifDate,'%d-%m-%Y %H:%i')
) AS d_verif
FROM supplier_payment
JOIN supplier_downpayment
ON SupplierDownpaymentID = SupplierPaymentSupplierDownpaymentID
AND SupplierDownpaymentIsActive = 'Y'
LEFT JOIN coa ON SupplierPaymentCoaID = coaID
LEFT JOIN m_user n ON SupplierPaymentUserID = n.M_UserID
LEFT JOIN m_user c ON SupplierPaymentConfirmUserID = c.M_UserID
LEFT JOIN m_user a ON SupplierPaymentApprovedUserID = a.M_UserID
LEFT JOIN m_user b ON SupplierPaymentVerifUserID = b.M_UserID
WHERE SupplierPaymentSupplierDownpaymentID = {$orderid}
AND SupplierPaymentIsActive = 'Y'
GROUP BY SupplierPaymentID";
$query = $this->db_onedev->query($sql);
if ($query) {
$rows = $query->result_array();
return $rows ?: [];
} else {
$this->sys_error_db("get DP notes", $this->db_onedev);
exit;
}
}
public function add_notes_installment($orderid)
{
$sql = "SELECT SupplierPaymentSupplierInstallmentID as note_order_id,
SupplierPaymentID as note_id,
SupplierInstallmentID as detail_id,
SupplierPaymentDate as note_date,
SupplierPaymentNumber as note_number,
GROUP_CONCAT(DISTINCT coaDescription separator ' , ') as paymenttypes_name,
SUM(SupplierInstallmentAmount) as note_amount,
n.M_UserUsername as note_user,
SupplierInstallmentIsActive as note_active,
'N' as show_detail,
SupplierPaymentNote as keterangan,
SupplierPaymentCoaID,
coaID,
coaDescription,
SupplierPaymentIsConfirm,
CONCAT(
'Confirmed by : ',c.M_UserUsername, ' ',
DATE_FORMAT(SupplierPaymentConfirmDate,'%d-%m-%Y %H:%i')
) AS d_confirm,
SupplierPaymentIsApproved,
CONCAT(
'Approved by : ',a.M_UserUsername, ' ',
DATE_FORMAT(SupplierPaymentApprovedDate,'%d-%m-%Y %H:%i')
) AS d_approved,
CONCAT(
'Verified by : ',b.M_UserUsername, ' ',
DATE_FORMAT(SupplierPaymentVerifDate,'%d-%m-%Y %H:%i')
) AS d_verif
FROM supplier_payment
JOIN supplier_installment
ON SupplierInstallmentID = SupplierPaymentSupplierInstallmentID
AND SupplierInstallmentIsActive = 'Y'
LEFT JOIN coa ON SupplierPaymentCoaID = coaID
LEFT JOIN m_user n ON SupplierPaymentUserID = n.M_UserID
LEFT JOIN m_user c ON SupplierPaymentConfirmUserID = c.M_UserID
LEFT JOIN m_user a ON SupplierPaymentApprovedUserID = a.M_UserID
LEFT JOIN m_user b ON SupplierPaymentVerifUserID = b.M_UserID
WHERE SupplierPaymentSupplierInstallmentID = {$orderid}
AND SupplierPaymentIsActive = 'Y'
GROUP BY SupplierPaymentID";
$query = $this->db_onedev->query($sql);
if ($query) {
$rows = $query->result_array();
return $rows ?: [];
} else {
$this->sys_error_db("get Installment notes", $this->db_onedev);
exit;
}
}
public function add_tagihans($orderid)
{
$sql_dp = "SELECT
Fa_ClassDownPaymentCoaID
FROM supplier_invoice_detail
JOIN m_item
ON M_ItemID = SupplierInvoiceDetailItemID
AND SupplierInvoiceDetailSupplierInvoiceID = ?
AND SupplierInvoiceDetailIsActive = 'Y'
AND SupplierInvoiceDetailIsVerified = 'Y'
JOIN fa_class
ON Fa_ClassID = M_ItemFa_ClassID
AND Fa_ClassIsActive = 'Y'";
$que_dp = $this->db_onedev->query($sql_dp, [$orderid]);
if (!$que_dp) {
$this->sys_error_db("failed to get coa id dp tagihans", $this->db_onedev);
exit;
}
$dataDP = $que_dp->result_array();
$excludeIds = array_column($dataDP, 'Fa_ClassDownPaymentCoaID');
$excludeIds[] = 563; // always excluded
$excludeIds = array_unique($excludeIds);
$excludeIds = array_values($excludeIds); // re-index
$notInPlaceholders = implode(',', array_fill(0, count($excludeIds), '?'));
$sql = "SELECT
SupplierInvoiceID as tagihan_id,
PurchaseOrderNumber as tagihan_number,
jurnalTxDescription as pasien,
jurnalTxCredit as tagihan_total,
IF(SupplierPaymentDetailID IS NULL , jurnalTxCredit, jurnalTxCredit - SUM(SupplierPaymentDetailAmount)) as tagihan_tagihan,
0 as tagihan_bayar,
DATE_FORMAT(SupplierInvoiceDueDate,'%d-%m-%Y') as tagihan_duedate,
SupplierInvoiceIsActive as tagihan_active,
'N' as show_detail,
jurnalTxID SupplierInvoiceDetailID,
PurchaseOrderID SupplierInvoiceDetailPurchaseOrderID
FROM supplier_invoice
JOIN receive_order_po
ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
JOIN receive_order_po_detail
ON ReceiveOrderPoDetailReceiveOrderPoID = ReceiveOrderPoID
JOIN purchase_order
ON ReceiveOrderPoDetailPurchaseOrderID = PurchaseOrderID
JOIN jurnal_addon
ON jurnalAddOnValue = SupplierInvoiceNumber
AND jurnalAddOnIsActive = 'Y'
JOIN jurnal_tx
ON jurnalTxJurnalID = jurnalAddOnJurnalID
AND jurnalTxIsActive = 'Y'
AND jurnalTxCredit <> 0
AND jurnalTxCoaID NOT IN ($notInPlaceholders)
LEFT JOIN supplier_payment
ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID
AND SupplierInvoiceIsActive = 'Y'
LEFT JOIN supplier_payment_detail
ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
AND SupplierPaymentDetailSupplierInvoiceDetailID = jurnalTxID
AND SupplierPaymentDetailIsActive = 'Y'
WHERE SupplierInvoiceID = ?
GROUP BY jurnalTxID";
$query = $this->db_onedev->query($sql, array_merge($excludeIds, [$orderid]));
if ($query) {
$rows = $query->result_array();
return $rows;
} else {
$this->sys_error_db("get tagihans", $this->db_onedev);
exit;
}
}
public function add_tests($orderid)
{
$sql = " SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
SupplierPaymentID as note_id,
SupplierPaymentDate as note_date, SupplierPaymentDate as note_date,
SupplierPaymentNumber as note_number, SupplierPaymentNumber as note_number,
GROUP_CONCAT(coaDescription separator ' , ') as paymenttypes_name, GROUP_CONCAT(coaDescription separator ' , ') as paymenttypes_name,
@@ -252,537 +108,150 @@ class Bill extends MY_Controller
SupplierInvoiceDetailTotal, SupplierInvoiceDetailTotal,
SupplierPaymentDetailAmount SupplierPaymentDetailAmount
FROM supplier_payment FROM supplier_payment
JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
LEFT JOIN supplier_invoice_detail ON SupplierPaymentDetailSupplierInvoiceDetailID = SupplierInvoiceDetailID LEFT JOIN supplier_invoice_detail ON SupplierPaymentDetailSupplierInvoiceDetailID = SupplierInvoiceDetailID
LEFT JOIN purchase_order ON SupplierInvoiceDetailPurchaseOrderID = PurchaseOrderID LEFT JOIN purchase_order ON SupplierInvoiceDetailPurchaseOrderID = PurchaseOrderID
LEFT JOIN coa ON SupplierPaymentCoaID = coaID LEFT JOIN coa ON SupplierPaymentCoaID = coaID
LEFT JOIN m_user ON SupplierPaymentDetailUserID = M_UserID LEFT JOIN m_user ON SupplierPaymentDetailUserID = M_UserID
WHERE WHERE
SupplierPaymentID = {$orderid} SupplierPaymentID = {$orderid}
GROUP BY SupplierPaymentDetailID"; GROUP BY SupplierPaymentDetailID";
$query = $this->db_onedev->query($sql); $query = $this->db_onedev->query($sql);
if ($query) { if ($query) {
$rows = $query->result_array(); $rows = $query->result_array();
if ($rows) { if($rows){
} }
return $rows; return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev); } else {
exit; $this->sys_error_db("get notes", $this->db_onedev);
} exit;
} }
}
public function search_old() public function search()
{ {
//# cek token valid //# cek token valid
if (! $this->isLogin) { if (! $this->isLogin) {
$this->sys_error("Invalid Token"); $this->sys_error("Invalid Token");
exit; exit;
} }
$prm = $this->sys_input;
$prm = $this->sys_input; $supplier = $prm["supplier"];
$supplier = $prm["supplier"]; $search = $prm["search"];
$search = $prm["search"]; $status = $prm["status"];
$status = $prm["status"]; $startdate = $prm["startdate"];
$startdate = $prm["startdate"]; $enddate = $prm["enddate"];
$enddate = $prm["enddate"]; $regionalid = $this->sys_user['S_RegionalID'];
$regionalid = $this->sys_user['S_RegionalID'];
$number_limit = 10;
$number_limit = 10; $number_offset = ($prm['current_page'] - 1) * $number_limit ;
$number_offset = ($prm['current_page'] - 1) * $number_limit;
$where = "SupplierInvoiceIsActive = 'Y'
$where = "SupplierInvoiceIsActive = 'Y' AND SupplierInvoiceStatus = 'Approved'
AND SupplierInvoiceStatus = 'Approved' AND SupplierInvoiceGrandTotal > 0
AND SupplierInvoiceGrandTotal > 0 AND IF(SupplierPaymentID IS NULL,'N','Y') = '{$status}'
AND IF(SupplierPaymentID IS NULL,'N','Y') = '{$status}' AND (SupplierInvoiceNumber LIKE '%{$search}%' AND SupplierName LIKE '%{$supplier}%')
AND (SupplierInvoiceNumber LIKE '%{$search}%' AND SupplierName LIKE '%{$supplier}%') AND ReceiveOrderPoS_RegionalID = {$regionalid}
AND ReceiveOrderPoS_RegionalID = {$regionalid} AND SupplierInvoiceDraftPaymentDate BETWEEN '{$startdate}' AND '{$enddate}'";
AND SupplierInvoiceDraftPaymentDate BETWEEN '{$startdate}' AND '{$enddate}'";
$sql = " SELECT count(*) as total
$sql = " SELECT count(*) as total FROM supplier_invoice
FROM supplier_invoice JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber LEFT JOIN supplier_payment ON SupplierInvoiceID = SupplierPaymentSupplierInvoiceID AND SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier_payment ON SupplierInvoiceID = SupplierPaymentSupplierInvoiceID AND SupplierPaymentIsActive = 'Y' LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID
JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID WHERE
WHERE $where
$where ";
"; // echo $sql;
// echo $sql; $query = $this->db_onedev->query($sql, $sql_param);
$query = $this->db_onedev->query($sql, $sql_param);
$tot_count = 0;
$tot_count = 0; $tot_page = 0;
$tot_page = 0; if ($query) {
if ($query) { $tot_count = $query->result_array()[0]["total"];
$tot_count = $query->result_array()[0]["total"]; $tot_page = ceil($tot_count/$number_limit);
$tot_page = ceil($tot_count / $number_limit); } else {
} else { $this->sys_error_db("supplier_invoice count", $this->db_onedev);
$this->sys_error_db("supplier_invoice count", $this->db_onedev); exit;
exit; }
}
$sql = "SELECT supplier_invoice.*,
$sql = "SELECT supplier_invoice.*, SupplierName,
SupplierName, '' M_MouName,
'' M_MouName, 0 as totalbill,
0 as totalbill, 0 as paid,
0 as paid, 0 as unpaid,
0 as unpaid, SupplierInvoiceIsLunas as flaglunas,
SupplierInvoiceIsLunas as flaglunas, 0 as SupplierPaymentID,
0 as SupplierPaymentID, '' as SupplierPaymentNumber,
'' as SupplierPaymentNumber, 0 as SupplierPaymentAmount,
0 as SupplierPaymentAmount, '' as SupplierPaymentDate,
'' as SupplierPaymentDate, '' as SupplierInvoiceIssueRefNumber,
'' as SupplierInvoiceIssueRefNumber, '' as notes,
'' as notes, '' as tagihans,
'' as tagihans, 'N' as isbillterpusat,
'N' as isbillterpusat, DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d-%m-%Y') as tanggalbayar,
DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d-%m-%Y') as tanggalbayar, DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d%m%Y') as tanggalbayartext,
DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d%m%Y') as tanggalbayartext, IF(SupplierPaymentID IS NULL,'N','Y') as status_invoice,
IF(SupplierPaymentID IS NULL,'N','Y') as status_invoice, IFNULL(SupplierPaymentIsApproved,'N') as SupplierPaymentIsApproved,
IFNULL(SupplierPaymentIsApproved,'N') as SupplierPaymentIsApproved, IFNULL(SupplierPaymentIsVerif,'N') as SupplierPaymentIsVerif,
IFNULL(SupplierPaymentIsVerif,'N') as SupplierPaymentIsVerif, IFNULL(SupplierPaymentCashierNumber,'') SupplierPaymentCashierNumber
IFNULL(SupplierPaymentCashierNumber,'') SupplierPaymentCashierNumber
FROM supplier_invoice
FROM supplier_invoice LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID
JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID LEFT JOIN supplier_payment ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID AND SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier_payment ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID AND SupplierPaymentIsActive = 'Y' WHERE
WHERE $where
$where GROUP BY SupplierInvoiceID
GROUP BY SupplierInvoiceID ORDER BY SupplierInvoiceID ASC
ORDER BY SupplierInvoiceID ASC limit $number_limit offset $number_offset";
limit $number_limit offset $number_offset"; //echo $sql;
//echo $sql; $query = $this->db_onedev->query($sql, $sql_param);
$query = $this->db_onedev->query($sql, $sql_param); $rows = $query->result_array();
$rows = $query->result_array(); if($rows){
if ($rows) { foreach($rows as $k => $v){
foreach ($rows as $k => $v) { $s_payment = $this->db_onedev->query("SELECT GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
$s_payment = $this->db_onedev->query("SELECT GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber, SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount, IFNULL(SupplierPaymentID,0) SupplierPaymentID,
IFNULL(SupplierPaymentID,0) SupplierPaymentID, GROUP_CONCAT(DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y') SEPARATOR ', ') as SupplierPaymentDate
GROUP_CONCAT(DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y') SEPARATOR ', ') as SupplierPaymentDate FROM supplier_payment
FROM supplier_payment WHERE SupplierPaymentIsActive = 'Y' AND SupplierPaymentSupplierInvoiceID = {$v['SupplierInvoiceID']}")->row();
WHERE SupplierPaymentIsActive = 'Y' AND SupplierPaymentSupplierInvoiceID = {$v['SupplierInvoiceID']}")->row();
$s_jurnal = $this->db_onedev->query("SELECT SUM(jurnalTxCredit) totalbill
$s_jurnal = $this->db_onedev->query("SELECT SUM(jurnalTxCredit) totalbill FROM supplier_invoice
FROM supplier_invoice JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber JOIN jurnal_tx ON jurnalTxJurnalID = jurnalAddOnJurnalID AND jurnalTxCredit <> 0 AND jurnalTxCoaID <> 563
JOIN jurnal_tx ON jurnalTxJurnalID = jurnalAddOnJurnalID AND jurnalTxCredit <> 0 AND jurnalTxCoaID <> 563 WHERE SupplierInvoiceID = {$v['SupplierInvoiceID']}
WHERE SupplierInvoiceID = {$v['SupplierInvoiceID']} GROUP BY SupplierInvoiceID")->row();
GROUP BY SupplierInvoiceID")->row(); $amount = $s_payment->SupplierPaymentAmount ? $s_payment->SupplierPaymentAmount : "0.00";
$amount = $s_payment->SupplierPaymentAmount ? $s_payment->SupplierPaymentAmount : "0.00"; $unpaid = (float)$s_jurnal->totalbill - (float)$amount;
$unpaid = (float)$s_jurnal->totalbill - (float)$amount; $rows[$k]['SupplierPaymentID'] = $s_payment->SupplierPaymentID ? $s_payment->SupplierPaymentID : '0';
$rows[$k]['SupplierPaymentID'] = $s_payment->SupplierPaymentID ? $s_payment->SupplierPaymentID : '0'; $rows[$k]['SupplierPaymentNumber'] = $s_payment->SupplierPaymentNumber ? $s_payment->SupplierPaymentNumber : '';
$rows[$k]['SupplierPaymentNumber'] = $s_payment->SupplierPaymentNumber ? $s_payment->SupplierPaymentNumber : ''; $rows[$k]['SupplierPaymentAmount'] = $amount;
$rows[$k]['SupplierPaymentAmount'] = $amount; $rows[$k]['SupplierPaymentDate'] = $s_payment->SupplierPaymentDate;
$rows[$k]['SupplierPaymentDate'] = $s_payment->SupplierPaymentDate; $rows[$k]['paid'] = $amount;
$rows[$k]['paid'] = $amount; $rows[$k]['totalbill'] = $s_jurnal->totalbill ? $s_jurnal->totalbill : "0.00";
$rows[$k]['totalbill'] = $s_jurnal->totalbill ? $s_jurnal->totalbill : "0.00"; $rows[$k]['unpaid'] = number_format($unpaid, 2, '.', '');
$rows[$k]['unpaid'] = number_format($unpaid, 2, '.', '');
$rows[$k]['notes'] = $this->add_notes($v['SupplierInvoiceID']);
$rows[$k]['notes'] = $this->add_notes($v['SupplierInvoiceID']); $rows[$k]['tagihans'] = $this->add_tagihans($v['SupplierInvoiceID']);
$rows[$k]['tagihans'] = $this->add_tagihans($v['SupplierInvoiceID']);
} }
} }
$result = array("total" => $tot_page, "records" => $rows, "sql" => $this->db_onedev->last_query()); $result = array("total" => $tot_page, "records" => $rows, "sql"=> $this->db_onedev->last_query());
$this->sys_ok($result); $this->sys_ok($result);
exit; exit;
} }
/**
* search — unified invoice + downpayment list:
* - Only columns the frontend actually reads (no wildcard, no dead aliases)
* - UNION ALL merges supplier_invoice and supplier_downpayment
* - DP rows enriched via SupplierPaymentSupplierDownpaymentID FK
* - All queries use PDO parameterised placeholders
*/
public function search()
{
if (! $this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$supplier = $prm["supplier"];
$search = $prm["search"];
$status = $prm["status"];
$startdate = $prm["startdate"];
$enddate = $prm["enddate"];
$regionalid = $this->sys_user['S_RegionalID'];
$number_limit = 10;
$number_offset = ((int)$prm['current_page'] - 1) * $number_limit;
// ── INVOICE WHERE ──────────────────────────────────────────
$inv_where = " SupplierInvoiceIsActive = 'Y'
AND SupplierInvoiceStatus = 'Approved'
AND SupplierInvoiceGrandTotal > 0
AND SupplierInvoiceIsInstallment = 'N'
AND IF(SupplierPaymentID IS NULL,'N','Y') = ?
AND SupplierInvoiceNumber LIKE ?
AND SupplierName LIKE ?
AND ReceiveOrderPoS_RegionalID = ?
AND SupplierInvoiceDraftPaymentDate BETWEEN ? AND ? ";
$inv_params = [
$status,
'%' . $search . '%',
'%' . $supplier . '%',
$regionalid,
$startdate,
$enddate,
];
// ── DOWNPAYMENT WHERE ──────────────────────────────────────
$dp_where = " SupplierDownpaymentIsActive = 'Y'
AND IF(SupplierDownpaymentStatus = 'Paid','Y','N') = ?
AND PurchaseOrderNumber LIKE ?
AND SupplierName LIKE ?
AND PurchaseOrderS_RegionalID = ?
AND SupplierDownpaymentDueDate BETWEEN ? AND ? ";
$dp_params = [
$status,
'%' . $search . '%',
'%' . $supplier . '%',
$regionalid,
$startdate,
$enddate,
];
// ── INSTALLMENT WHERE ───────────────────────────────────
$inst_where = " inst.SupplierInstallmentIsActive = 'Y'
AND IF(sp.SupplierPaymentID IS NULL,'N','Y') = ?
AND CONCAT('INST-', si.SupplierInvoiceNumber) LIKE ?
AND sup.SupplierName LIKE ?
AND rop.ReceiveOrderPoS_RegionalID = ?
AND inst.SupplierInstallmentDueDate BETWEEN ? AND ? ";
$inst_params = [
$status,
'%' . $search . '%',
'%' . $supplier . '%',
$regionalid,
$startdate,
$enddate,
];
// ── COUNT query — UNION of all three sources ────────────
$sql_count = "SELECT SUM(cnt) as total FROM (
SELECT count(*) as cnt
FROM supplier_invoice
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
LEFT JOIN supplier_payment
ON SupplierInvoiceID = SupplierPaymentSupplierInvoiceID
AND SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID
WHERE $inv_where
UNION ALL
SELECT count(*) as cnt
FROM supplier_downpayment
JOIN purchase_order ON PurchaseOrderID = SupplierDownpaymentPurchasOrderID
JOIN supplier ON SupplierID = SupplierDownpaymentSupplierID
WHERE $dp_where
UNION ALL
SELECT count(*) as cnt
FROM supplier_installment inst
LEFT JOIN supplier_payment sp
ON sp.SupplierPaymentSupplierInstallmentID = inst.SupplierInstallmentID
AND sp.SupplierPaymentIsActive = 'Y'
JOIN supplier_invoice si
ON si.SupplierInvoiceID = inst.SupplierInstallmentSupplierInvoiceID
JOIN receive_order_po rop
ON rop.ReceiveOrderPoID = si.SupplierInvoiceReceiveOrderPoID
JOIN supplier sup
ON sup.SupplierID = inst.SupplierInstallmentSupplierID
WHERE $inst_where
) AS combined";
$count_params = array_merge($inv_params, $dp_params, $inst_params);
$query = $this->db_onedev->query($sql_count, $count_params);
$tot_count = 0;
$tot_page = 0;
if ($query) {
$tot_count = $query->result_array()[0]["total"];
$tot_page = ceil($tot_count / $number_limit);
} else {
$this->sys_error_db("payment instructions count", $this->db_onedev);
exit;
}
// ── DATA query — UNION with identical columns ──────────────
$sql_data = "
SELECT * FROM (
SELECT
SupplierInvoiceID,
0 as DownpaymentID,
0 as InstallmentID,
SupplierInvoiceNumber,
SupplierInvoiceDraftPaymentDate,
SupplierInvoiceIsLunas as flaglunas,
SupplierName,
DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d-%m-%Y') as tanggalbayar,
IFNULL(SupplierPaymentIsApproved,'N') as SupplierPaymentIsApproved,
IFNULL(SupplierPaymentCashierNumber,'') as SupplierPaymentCashierNumber,
0 as totalbill,
0 as paid,
0 as unpaid,
0 as SupplierPaymentID,
'' as SupplierPaymentNumber,
0 as SupplierPaymentAmount,
'' as SupplierPaymentDate,
'' as notes,
'' as tagihans,
0 as parent_invoice_id,
'INVOICE' as type
FROM supplier_invoice
LEFT JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN receive_order_po ON SupplierInvoiceReceiveOrderPoID = ReceiveOrderPoID
LEFT JOIN supplier_payment
ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID
AND SupplierPaymentIsActive = 'Y'
WHERE $inv_where
GROUP BY SupplierInvoiceID
UNION ALL
SELECT
0 as SupplierInvoiceID,
SupplierDownpaymentID as DownpaymentID,
0 as InstallmentID,
CONCAT('DP-', PurchaseOrderNumber) as SupplierInvoiceNumber,
SupplierDownpaymentDueDate as SupplierInvoiceDraftPaymentDate,
SupplierDownpaymentIsLunas as flaglunas,
SupplierName,
DATE_FORMAT(SupplierDownpaymentDueDate,'%d-%m-%Y') as tanggalbayar,
IFNULL(SupplierPaymentIsApproved,'N') as SupplierPaymentIsApproved,
IFNULL(SupplierPaymentCashierNumber,'') as SupplierPaymentCashierNumber,
SupplierDownpaymentAmount as totalbill,
CASE WHEN SupplierDownpaymentStatus = 'Paid'
THEN SupplierDownpaymentAmount
ELSE 0 END as paid,
CASE WHEN SupplierDownpaymentStatus = 'Paid'
THEN 0
ELSE SupplierDownpaymentAmount END as unpaid,
0 as SupplierPaymentID,
'' as SupplierPaymentNumber,
0 as SupplierPaymentAmount,
'' as SupplierPaymentDate,
'' as notes,
'' as tagihans,
0 as parent_invoice_id,
'DP' as type
FROM supplier_downpayment
JOIN purchase_order ON PurchaseOrderID = SupplierDownpaymentPurchasOrderID
JOIN supplier ON SupplierID = SupplierDownpaymentSupplierID
LEFT JOIN supplier_payment
ON SupplierPaymentSupplierDownpaymentID = SupplierDownpaymentID
AND SupplierPaymentIsActive = 'Y'
WHERE $dp_where
UNION ALL
SELECT
0 as SupplierInvoiceID,
0 as DownpaymentID,
inst.SupplierInstallmentID as InstallmentID,
CONCAT('INST-', si.SupplierInvoiceNumber) as SupplierInvoiceNumber,
inst.SupplierInstallmentDueDate as SupplierInvoiceDraftPaymentDate,
inst.SupplierInstallmentIsLunas as flaglunas,
sup.SupplierName,
DATE_FORMAT(inst.SupplierInstallmentDueDate,'%d-%m-%Y') as tanggalbayar,
IFNULL(sp.SupplierPaymentIsApproved,'N') as SupplierPaymentIsApproved,
IFNULL(sp.SupplierPaymentCashierNumber,'') as SupplierPaymentCashierNumber,
inst.SupplierInstallmentAmount as totalbill,
CASE WHEN inst.SupplierInstallmentStatus = 'Paid'
THEN inst.SupplierInstallmentAmount
ELSE 0 END as paid,
CASE WHEN inst.SupplierInstallmentStatus = 'Paid'
THEN 0
ELSE inst.SupplierInstallmentAmount END as unpaid,
0 as SupplierPaymentID,
'' as SupplierPaymentNumber,
0 as SupplierPaymentAmount,
'' as SupplierPaymentDate,
'' as notes,
'' as tagihans,
si.SupplierInvoiceID as parent_invoice_id,
'INSTALLMENT' as type
FROM supplier_installment inst
LEFT JOIN supplier_payment sp
ON sp.SupplierPaymentSupplierInstallmentID = inst.SupplierInstallmentID
AND sp.SupplierPaymentIsActive = 'Y'
JOIN supplier_invoice si
ON si.SupplierInvoiceID = inst.SupplierInstallmentSupplierInvoiceID
JOIN receive_order_po rop
ON rop.ReceiveOrderPoID = si.SupplierInvoiceReceiveOrderPoID
JOIN supplier sup
ON sup.SupplierID = inst.SupplierInstallmentSupplierID
WHERE $inst_where
) AS combined
ORDER BY SupplierInvoiceID ASC
LIMIT ? OFFSET ?";
$data_params = array_merge($inv_params, $dp_params, $inst_params, [$number_limit, $number_offset]);
$query = $this->db_onedev->query($sql_data, $data_params);
if (!$query) {
$this->sys_error_db("payment instructions data", $this->db_onedev);
exit;
}
$rows = $query->result_array();
// ── ENRICH — per-row sub-queries ───────────────────────────
if ($rows) {
foreach ($rows as $k => $v) {
// ── Downpayment branch ──────────────────────────
if ($v['type'] === 'DP') {
$dp_id = $v['DownpaymentID'];
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
IFNULL(SupplierPaymentID,0) as SupplierPaymentID,
GROUP_CONCAT(
DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y')
SEPARATOR ', '
) as SupplierPaymentDate
FROM supplier_payment
WHERE SupplierPaymentIsActive = 'Y'
AND SupplierPaymentSupplierDownpaymentID = ?",
[$dp_id]
)->row();
$amount = $s_payment->SupplierPaymentAmount
? $s_payment->SupplierPaymentAmount
: "0.00";
$rows[$k]['SupplierPaymentID'] = $s_payment->SupplierPaymentID
? $s_payment->SupplierPaymentID
: '0';
$rows[$k]['SupplierPaymentNumber'] = $s_payment->SupplierPaymentNumber
? $s_payment->SupplierPaymentNumber
: '';
$rows[$k]['SupplierPaymentAmount'] = $amount;
$rows[$k]['SupplierPaymentDate'] = $s_payment->SupplierPaymentDate;
$rows[$k]['paid'] = $amount;
$rows[$k]['notes'] = $this->add_notes_downpayment($dp_id);
$rows[$k]['tagihans'] = [];
// totalbill, unpaid already correct from UNION CASE
continue;
}
// ── Installment branch ─────────────────────────
if ($v['type'] === 'INSTALLMENT') {
$inst_id = $v['InstallmentID'];
$parent_invoice_id = $v['parent_invoice_id'];
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
IFNULL(SupplierPaymentID,0) as SupplierPaymentID,
GROUP_CONCAT(
DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y')
SEPARATOR ', '
) as SupplierPaymentDate
FROM supplier_payment
WHERE SupplierPaymentIsActive = 'Y'
AND SupplierPaymentSupplierInstallmentID = ?",
[$inst_id]
)->row();
$amount = $s_payment->SupplierPaymentAmount
? $s_payment->SupplierPaymentAmount
: "0.00";
$rows[$k]['SupplierPaymentID'] = $s_payment->SupplierPaymentID
? $s_payment->SupplierPaymentID
: '0';
$rows[$k]['SupplierPaymentNumber'] = $s_payment->SupplierPaymentNumber
? $s_payment->SupplierPaymentNumber
: '';
$rows[$k]['SupplierPaymentAmount'] = $amount;
$rows[$k]['SupplierPaymentDate'] = $s_payment->SupplierPaymentDate;
$rows[$k]['paid'] = $amount;
$rows[$k]['notes'] = $this->add_notes_installment($inst_id);
$rows[$k]['tagihans'] = $this->add_tagihans($parent_invoice_id);
// totalbill, unpaid already correct from UNION CASE
continue;
}
// ── Invoice branch ───────────────────────────────
$inv_id = $v['SupplierInvoiceID'];
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
IFNULL(SupplierPaymentID,0) as SupplierPaymentID,
GROUP_CONCAT(
DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y')
SEPARATOR ', '
) as SupplierPaymentDate
FROM supplier_payment
WHERE SupplierPaymentIsActive = 'Y'
AND SupplierPaymentSupplierInvoiceID = ?",
[$inv_id]
)->row();
$s_jurnal = $this->db_onedev->query("
SELECT SUM(jurnalTxCredit) totalbill
FROM supplier_invoice
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN jurnal_tx
ON jurnalTxJurnalID = jurnalAddOnJurnalID
AND jurnalTxCredit <> 0
AND jurnalTxCoaID <> 563
WHERE SupplierInvoiceID = ?
GROUP BY SupplierInvoiceID",
[$inv_id]
)->row();
$amount = $s_payment->SupplierPaymentAmount
? $s_payment->SupplierPaymentAmount
: "0.00";
$unpaid = (float)$s_jurnal->totalbill - (float)$amount;
$rows[$k]['SupplierPaymentID'] = $s_payment->SupplierPaymentID
? $s_payment->SupplierPaymentID
: '0';
$rows[$k]['SupplierPaymentNumber'] = $s_payment->SupplierPaymentNumber
? $s_payment->SupplierPaymentNumber
: '';
$rows[$k]['SupplierPaymentAmount'] = $amount;
$rows[$k]['SupplierPaymentDate'] = $s_payment->SupplierPaymentDate;
$rows[$k]['paid'] = $amount;
$rows[$k]['totalbill'] = $s_jurnal->totalbill
? $s_jurnal->totalbill
: "0.00";
$rows[$k]['unpaid'] = number_format($unpaid, 2, '.', '');
$rows[$k]['notes'] = $this->add_notes($inv_id);
$rows[$k]['tagihans'] = $this->add_tagihans($inv_id);
}
}
$result = array("total" => $tot_page, "records" => $rows);
$this->sys_ok($result);
exit;
}
} }

File diff suppressed because it is too large Load Diff