17 Commits

Author SHA1 Message Date
e1feaa68a8 feature: payment instruction & cashier case cicilan dan downpayment 2026-07-21 15:21:24 +07:00
64f434cd78 feature: po pay downpayment 2026-07-20 13:13:59 +07:00
Hanan Askarim
61e2e4f2ec add keterangan untuk http pi instalment 2026-07-15 10:48:53 +07:00
Hanan Askarim
79fd2864cc update penomoran dari fn fungsi 2026-07-15 10:48:53 +07:00
Hanan Askarim
344c5d42e6 fix http pembayaran 2026-07-15 10:48:53 +07:00
Hanan Askarim
f30c6dbb60 add supplier invoice number 2026-07-15 10:48:53 +07:00
Hanan Askarim
2d072fad16 gabungkan fungsi get data dengan create jurnal 2026-07-15 10:48:53 +07:00
Hanan Askarim
aef86b7acf add pengambilan co dari fa_class 2026-07-15 10:48:53 +07:00
Hanan Askarim
efdf8af569 add pembuatan jurnal pi cicilan order asset 2026-07-15 10:48:53 +07:00
Hanan Askarim
712cbbb80b fix query get cicilan dan insert supplier invoice 2026-07-15 10:48:53 +07:00
Hanan Askarim
977694905c add generate po contract 2026-07-15 10:48:53 +07:00
ee3748066e feature: receive item order asset & insert jurnal faktur asset 2026-07-15 10:43:56 +07:00
709dfdae33 update: api purchase order asset & receive order asset 2026-07-13 09:08:43 +07:00
e62ec1d994 feature: file receiveItemAset & change some query purchaseorderasest 2026-07-10 15:49:00 +07:00
34fb944e6e add: inventaris item coa mapping API 2026-07-10 08:30:36 +07:00
17445d9534 add: inventaris coa mapping API 2026-07-10 08:30:36 +07:00
17423ac0b5 change table asset attachment into contract_asset_attachment 2026-07-10 08:30:12 +07:00
14 changed files with 7019 additions and 2745 deletions

View File

@@ -0,0 +1,113 @@
@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

@@ -0,0 +1,624 @@
<?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,6 +496,7 @@ class Fakturv4 extends MY_Controller
ELSE ''
END as WarehouseName,
ReceiveOrderPoID,
ReceiveOrderPoTypePurchase,
PurchaseOrderItemCategoryID
FROM supplier_invoice
JOIN supplier_invoice_detail ON SupplierInvoiceID = SupplierInvoiceDetailSupplierInvoiceID
@@ -588,12 +589,11 @@ class Fakturv4 extends MY_Controller
'P'
) AS DiscountType,
SupplierInvoiceReceiveOrderPoID,
ReceiveOrderPoNumber
ReceiveOrderPoNumber,
ReceiveOrderPoTypePurchase AS typePurchase
FROM supplier_invoice
JOIN supplier ON SupplierInvoiceSupplierID = SupplierID
JOIN receive_order_po ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
-- JOIN purchase_order ON SupplierInvoicePurchaseOrderID = PurchaseOrderID
-- AND PurchaseOrderIsActive = 'Y'
WHERE SupplierInvoiceIsActive = 'Y'
AND SupplierInvoiceID = ?";
$que = $this->db->query($sql, $para['SInvoiceID']);
@@ -601,6 +601,7 @@ class Fakturv4 extends MY_Controller
$this->sys_error_db('[Error] get detail data invoice');
exit;
}
$data = $que->row_array();
$sqldet = "SELECT
SupplierInvoiceDetailID,
@@ -636,7 +637,30 @@ class Fakturv4 extends MY_Controller
exit;
}
$data = $que->result_array()[0];
if (isset($data['typePurchase']) && $data['typePurchase'] == 'aset') {
$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();
$result = $data;
@@ -1317,7 +1341,8 @@ class Fakturv4 extends MY_Controller
supplier_invoice_detail.*,
ReceiveOrderPoNumber,
ReceiveOrderPoM_BranchCode,
ReceiveOrderPoS_RegionalID
ReceiveOrderPoS_RegionalID,
ReceiveOrderPoTypePurchase AS typePurchase
FROM supplier_invoice
JOIN supplier_invoice_detail ON SupplierInvoiceDetailSupplierInvoiceID = SupplierInvoiceID
AND SupplierInvoiceDetailIsActive = 'Y'
@@ -1453,7 +1478,6 @@ class Fakturv4 extends MY_Controller
$coapph = $quepph->result_array()[0];
$pphval = doubleval($invoice[0]['SupplierInvoiceTaxAmountPph']);
if ($pphval > 0.00) {
$insertpph = $this->InsertJurnalTx(
$jurnalID,
@@ -1465,13 +1489,14 @@ class Fakturv4 extends MY_Controller
);
if (!$insertpph['status']) {
$this->db->trans_rollback();
$this->sys_error_db($insertpajak['msg']);
$this->sys_error_db($insertpph['msg']);
exit;
}
}
# insert shipping cost ke jurnal #
// ----------------------------------------------------------------------------------------
if ($ship_cost > 0.00) {
$queryshipcost = $this->db->query($sqlcoa, ['5320700001']);
if (!$queryshipcost) {
$this->db->trans_rollback();
@@ -1480,7 +1505,6 @@ class Fakturv4 extends MY_Controller
}
$coashipcost = $queryshipcost->result_array()[0];
if ($ship_cost > 0.00) {
$insertcost = $this->InsertJurnalTx(
$jurnalID,
$coashipcost['coaID'],
@@ -1496,6 +1520,63 @@ 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)
// ----------------------------------------------------------------------------------------
foreach ($invoice as $key => $inv) {
@@ -1603,40 +1684,8 @@ class Fakturv4 extends MY_Controller
$this->sys_error_db($status['msg']);
exit;
}
} else if ($item['M_ItemItem_CategoryID'] == '3' && !empty($item['M_ItemFa_ClassID'])) {
$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'] == '3') {
$this->InsertJurnalTxAsset($jurnalID, $item['M_ItemID'], $inv, $user['M_UserID']);
} else if ($item['M_ItemItem_CategoryID'] == '4') {
$this->InsertJurnalTxJasa($jurnalID, $item['M_ItemID'], $inv, $user['M_UserID']);
}
@@ -1717,6 +1766,93 @@ 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
{
try {

View File

@@ -66,6 +66,40 @@ class PurchaseOrderAset extends MY_Controller {
}
}
public function getListGudang() {
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$user = $this->sys_user;
$para = $this->sys_input;
$sql = "SELECT
WarehouseID,
WarehouseCode,
WarehouseName
FROM warehouse
WHERE WarehouseIsActive = 'Y'
AND WarehouseS_RegionalID = ?
AND WarehouseM_BranchID = ?
AND WarehouseIsTransit = 'N'";
$que = $this->db->query($sql, [
$user['S_RegionalID'], $para['M_BranchID']
]);
if (!$que) {
$this->sys_error_db("[Error] failed get list gudang");
exit;
}
$data = $que->result_array();
$this->sys_ok($data);
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
public function searchRequestAset() {
try {
if (!$this->isLogin) {
@@ -81,16 +115,13 @@ class PurchaseOrderAset extends MY_Controller {
}
$limit = 10;
$offset = 0;
if ($para['currpage'] > 0) {
$offset = ($para['currpage'] - 1) * $limit;
}
$sql = "SELECT
PurchaseRequestID,
PurchaseRequestNumber,
PurchaseRequestDetailID,
PurchaseRequestFlagID,
M_BranchID,
PurchaseRequestFlagM_BranchCode AS BranchCode,
PurchaseRequestItemCategoryID AS ItemCategoryID,
PurchaseRequestFlagQtyRest - PurchaseRequestFlagQtyProses AS UnprocessFlagQty,
@@ -102,24 +133,26 @@ class PurchaseOrderAset extends MY_Controller {
M_ItemDesc,
ItemUnitID,
ItemUnitName,
SupplierPricePrice as SupplierPrice
SupplierPricePrice as SupplierPrice,
M_UserUsername AS Requestedby
FROM purchase_request
JOIN purchase_request_detail ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID
AND PurchaseRequestDetailIsActive = 'Y'
AND PurchaseRequestM_BranchCode = ?
AND PurchaseRequestItemCategoryID = '3' -- id category item asset
AND PurchaseRequestNumber LIKE ?
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND (PurchaseRequestNumber LIKE ? OR M_ItemDesc LIKE ?)
JOIN purchase_request_flag ON PurchaseRequestFlagPurchaseRequestDetailID = PurchaseRequestDetailID
AND PurchaseRequestFlagStatus = 'PO'
AND PurchaseRequestFlagIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
JOIN m_branch ON M_BranchCode = PurchaseRequestFlagM_BranchCode
AND M_BranchID = ?
AND M_BranchIsActive = 'Y'
JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID
JOIN supplier_price ON SupplierPriceSupplierID = ?
AND SupplierPriceM_ItemID = M_ItemID
AND SupplierPriceItemUnitID = ItemUnitID
AND SupplierPriceIsActive = 'Y'
JOIN m_branch ON M_BranchCode = PurchaseRequestFlagM_BranchCode
AND M_BranchIsActive = 'Y'
JOIN m_user ON M_UserID = PurchaseRequestRequestedBy
WHERE NOT EXISTS (
SELECT 1
FROM purchase_order_detail
@@ -130,10 +163,10 @@ class PurchaseOrderAset extends MY_Controller {
WHERE PurchaseOrderDetailPurchaseRequestDetailID = PurchaseRequestDetailID
)";
$sql_data = $sql . " LIMIT ? OFFSET ? ";
$sql_data = $sql . " LIMIT ? ";
$que_data = $this->db->query($sql_data, [
$para['branchcode'], $keyword, $para['supplierID'],
$limit, $offset
$keyword, $keyword, $para['branchID'], $para['supplierID'],
$limit
]);
if (!$que_data) {
$this->sys_error_db("[Error] get daftar request data");
@@ -143,7 +176,7 @@ class PurchaseOrderAset extends MY_Controller {
$sql_total = "SELECT COUNT(*) AS total FROM ($sql) AS x";
$que_total = $this->db->query($sql_total, [
$para['branchcode'], $keyword, $para['supplierID']
$keyword, $keyword, $para['branchID'], $para['supplierID']
]);
if (!$que_total) {
$this->sys_error_db("[Error] get total request aset");
@@ -188,16 +221,34 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderS_RegionalID,
PurchaseOrderApprovedManagerUserID AS verifiedby,
IFNULL(PurchaseOrderApprovedUserID, 0) AS approvedby,
PurchaseOrderAssetContractID,
PurchaseOrderAssetContractID AS contractID,
PurchaseOrderAssetContractName AS contractName,
PurchaseOrderAssetContractDate AS contractDate,
PurchaseOrderAssetContractStartDate AS contractStart,
PurchaseOrderAssetContractEndDate AS contractEnd,
IFNULL(attach.AttachmentCount, 0) AS AttachmentCount,
SupplierID,
SupplierName
SupplierName,
SupplierDownpaymentID
FROM purchase_order
JOIN supplier ON SupplierID = PurchaseOrderSupplierID
JOIN purchase_order_asset_contract
ON PurchaseOrderAssetContractPurchaseOrderID = PurchaseOrderID
LEFT JOIN supplier_downpayment
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderID
AND SupplierDownpaymentIsActive = 'Y'
LEFT JOIN (
SELECT
ContractAssetAttachmentPurchaseOrderID,
ContractAssetAttachmentPurchaseOrderAssetContractID,
COUNT(*) AS AttachmentCount
FROM contract_asset_attachment
WHERE ContractAssetAttachmentIsActive = 'Y'
GROUP BY
ContractAssetAttachmentPurchaseOrderID,
ContractAssetAttachmentPurchaseOrderAssetContractID
) attach ON attach.ContractAssetAttachmentPurchaseOrderID = PurchaseOrderID
AND attach.ContractAssetAttachmentPurchaseOrderAssetContractID = PurchaseOrderAssetContractID
WHERE PurchaseOrderIsActive = 'Y'
AND PurchaseOrderItemCategoryID = '3'
AND PurchaseOrderS_RegionalID = ?
@@ -255,14 +306,13 @@ class PurchaseOrderAset extends MY_Controller {
$para = $this->sys_input;
$sql = "SELECT
PurchaseOrderAssetAttachmentID AS attach_id,
PurchaseOrderAssetAttachmentName AS img_url,
PurchaseOrderAssetAttachmentCreated AS created
FROM purchase_order_asset_attachment
WHERE PurchaseOrderAssetAttachmentIsActive = 'Y'
AND PurchaseOrderAssetAttachmentContractID = ?
AND PurchaseOrderAssetAttachmentPurchaseOrderID = ?
AND PurchaseOrderAssetAttachmentType = 'order'";
ContractAssetAttachmentID AS attach_id,
ContractAssetAttachmentFileName AS img_url,
ContractAssetAttachmentDate AS created
FROM contract_asset_attachment
WHERE ContractAssetAttachmentIsActive = 'Y'
AND ContractAssetAttachmentPurchaseOrderAssetContractID = ?
AND ContractAssetAttachmentPurchaseOrderID = ?";
$que = $this->db->query($sql, [
$para['contractID'], $para['poID']
]);
@@ -361,7 +411,7 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderGrandTotal AS grandtotal,
CASE
WHEN PurchaseOrderTaxPpnType = 'P' THEN 'percent'
ELSE 'absolute'
ELSE 'nominal'
END AS typepajak,
CASE
WHEN PurchaseOrderTaxPpnType = 'P' THEN PurchaseOrderTaxPercentPpn
@@ -369,7 +419,7 @@ class PurchaseOrderAset extends MY_Controller {
END AS valuepajak,
CASE
WHEN PurchaseOrderDiscountPercent > 0.00 THEN 'percent'
ELSE 'absolute'
ELSE 'nominal'
END AS typediskon,
CASE
WHEN PurchaseOrderDiscountPercent > 0.00 THEN PurchaseOrderDiscountPercent
@@ -379,6 +429,8 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderGrandTotal AS grandtotal,
SupplierID AS supplierID,
SupplierName,
WarehouseID AS gudangID,
WarehouseM_BranchID AS branchID,
PurchaseOrderAssetContractID,
PurchaseOrderAssetContractTAssetAttachmentID AS assetAttachmentID,
PurchaseOrderAssetContractName AS contractName,
@@ -391,11 +443,16 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderAssetContractInstallmentPayAmount AS installmentPayAmount,
PurchaseOrderAssetContractInstallmentDownPaymentType AS installmentDownPaymentType,
PurchaseOrderAssetContractInstallmentDownPayment AS installmentDownPayment,
PurchaseOrderApprovedManagerUserID AS verifiedby
PurchaseOrderApprovedManagerUserID AS verifiedby,
SupplierDownpaymentID
FROM purchase_order
JOIN supplier ON SupplierID = PurchaseOrderSupplierID
JOIN warehouse ON WarehouseID = PurchaseOrderWarehouseID
JOIN purchase_order_asset_contract
ON PurchaseOrderAssetContractPurchaseOrderID = PurchaseOrderID
LEFT JOIN supplier_downpayment
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderID
AND SupplierDownpaymentIsActive = 'Y'
WHERE PurchaseOrderIsActive = 'Y'
AND PurchaseOrderID = ?";
$que_poasset = $this->db->query($sql_poasset, [$para['poID']]);
@@ -428,6 +485,7 @@ class PurchaseOrderAset extends MY_Controller {
}
$subtotal = floatval($datapo['subtotal']);
$downpayment = floatval($datapo['installmentDownPayment']);
$grandtotal = floatval($datapo['grandtotal']);
$valuediskon = floatval($datapo['valuediskon']);
@@ -445,8 +503,11 @@ class PurchaseOrderAset extends MY_Controller {
"subtotal" => $subtotal,
"diskon" => $valuediskon,
"pajak" => $valuepajak,
"downpayment" => $downpayment,
"total_before_downpayment" => $downpayment + $grandtotal,
"total" => $grandtotal
];
/* map summary to purchase order */
$datapo['valuepajak'] = floatval($datapo['valuepajak']);
$datapo['valuediskon'] = floatval($datapo['valuediskon']);
@@ -460,6 +521,28 @@ class PurchaseOrderAset extends MY_Controller {
}
}
public function getUserApproveLevel() {
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$user = $this->sys_user;
$sql = "SELECT M_UserM_ApproveLevelID FROM m_user
WHERE M_UserIsActive = 'Y' AND M_UserID = ? ";
$que = $this->db->query($sql, [$user['M_UserID']]);
if (!$que) {
$this->sys_error_db("[Error] failed get approval level user");
exit;
}
$data = $que->row_array();
$this->sys_ok($data);
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
## MUTATIONS ##
public function createPoAsset() {
try {
@@ -517,6 +600,7 @@ class PurchaseOrderAset extends MY_Controller {
$summary_subtotal = floatval($para['summary']['subtotal']);
$summary_diskon = floatval($para['summary']['diskon']);
$summary_pajak = floatval($para['summary']['pajak']);
$summary_downpayment = floatval($para['summary']['downpayment']);
$summary_total = floatval($para['summary']['total']);
$sql_po = "INSERT INTO purchase_order (
@@ -530,17 +614,20 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderTaxPercentPpn,
PurchaseOrderDiscountPercent,
PurchaseOrderDiscountAmount,
PurchaseOrderWarehouseType,
PurchaseOrderWarehouseID,
PurchaseOrderNote,
PurchaseOrderSubTotal,
PurchaseOrderTaxAmountPpn,
PurchaseOrderGrandTotal,
PurchaseOrderUserID,
PurchaseOrderCreated
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
$que_po = $this->db->query($sql_po, [
$numpd, '3', $para['podate'], $para['reference'], $para['supplierID'],
$user['S_RegionalID'], $taxtype, $taxpercent, $discpercent, $summary_diskon,
$para['catatan'], $summary_subtotal, $summary_pajak, $summary_total, $user['M_UserID']
'single', $para['gudangID'], $para['catatan'], $summary_subtotal,
$summary_pajak, $summary_total, $user['M_UserID']
]);
if (!$que_po) {
$this->db->trans_rollback();
@@ -613,15 +700,16 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderDetailQty,
PurchaseOrderDetailPrice,
PurchaseOrderDetailTotal,
PurchaseOrderDetailWarehouseID,
PurchaseOrderDetailUserID,
PurchaseOrderDetailCreatedUserID,
PurchaseOrderDetailCreated
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
$que_detail = $this->db->query($sql_detail, [
$PurchaseOrderID, $obj['PurchaseSummaryID'], $obj['PurchaseRequestID'],
$obj['PurchaseRequestDetailID'], $obj['PurchaseRequestFlagID'],
$obj['M_ItemID'], $obj['ItemUnitID'], $obj['OriginalQty'], $obj['RequestQty'],
$obj['SupplierPrice'], $total, $user['M_UserID'], $user['M_UserID']
$obj['SupplierPrice'], $total, $para['gudangID'], $user['M_UserID'], $user['M_UserID']
]);
if (!$que_detail) {
$this->db->trans_rollback();
@@ -683,6 +771,33 @@ class PurchaseOrderAset extends MY_Controller {
exit;
}
# INSERT into table supplier_downpayment #
$sql_dp = "INSERT INTO supplier_downpayment (
SupplierDownpaymentPurchasOrderID,
SupplierDownpaymentSupplierID,
SupplierDownpaymentAmount,
SupplierDownpaymentDate,
SupplierDownpaymentDueDate,
SupplierDownpaymentStatus,
SupplierDownpaymentCreatedUserID,
SupplierDownpaymentLastUpdatedUserID
) VALUES (?,?,?,?,?,?,?,?)";
$que_dp = $this->db->query($sql_dp, [
$PurchaseOrderID,
$para['supplierID'],
$summary_downpayment ?: 0.00,
$para['contractStart'],
$para['contractStart'],
'Draft',
$user['M_UserID'],
$user['M_UserID']
]);
if (!$que_dp) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed insert supplier downpayment");
exit;
}
$this->insertLog(
$PurchaseOrderID, 'CREATE', $para, '',
[], $user['M_UserID'], 'create purchase order asset'
@@ -724,6 +839,7 @@ class PurchaseOrderAset extends MY_Controller {
$summary_subtotal = floatval($para['summary']['subtotal']);
$summary_diskon = floatval($para['summary']['diskon']);
$summary_pajak = floatval($para['summary']['pajak']);
$summary_downpayment = floatval($para['summary']['downpayment']);
$summary_total = floatval($para['summary']['total']);
# update po header #
@@ -736,6 +852,8 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderTaxPercentPpn = ?,
PurchaseOrderDiscountPercent = ?,
PurchaseOrderDiscountAmount = ?,
PurchaseOrderWarehouseType = ?,
PurchaseOrderWarehouseID = ?,
PurchaseOrderNote = ?,
PurchaseOrderSubTotal = ?,
PurchaseOrderTaxAmountPpn = ?,
@@ -745,8 +863,8 @@ class PurchaseOrderAset extends MY_Controller {
AND PurchaseOrderIsActive = 'Y'";
$que_po = $this->db->query($sql_po, [
$para['podate'], $para['reference'], $para['supplierID'], $user['S_RegionalID'],
$taxtype, $taxpercent, $discpercent, $summary_diskon, $para['catatan'],
$summary_subtotal, $summary_pajak, $summary_total, $para['PurchaseOrderID']
$taxtype, $taxpercent, $discpercent, $summary_diskon, 'single', $para['gudangID'],
$para['catatan'], $summary_subtotal, $summary_pajak, $summary_total, $para['PurchaseOrderID']
]);
if (!$que_po) {
$this->db->trans_rollback();
@@ -790,6 +908,29 @@ class PurchaseOrderAset extends MY_Controller {
exit;
}
## UPDATE existing downpayment ##
$sql = "UPDATE supplier_downpayment SET
SupplierDownpaymentAmount = ?,
SupplierDownpaymentDate = ?,
SupplierDownpaymentDueDate = ?,
SupplierDownpaymentStatus = ?,
SupplierDownpaymentLastUpdatedUserID = ?
WHERE SupplierDownpaymentID = ?
AND SupplierDownpaymentIsActive = 'Y'";
$que = $this->db->query($sql, [
$summary_downpayment ?: 0.00,
$para['contractStart'],
$para['contractStart'],
'Draft',
$user['M_UserID'],
$para['SupplierDownpaymentID']
]);
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed update supplier downpayment");
exit;
}
# update status old po summary isActive to 'N' #
$sql_active = "UPDATE purchase_order_summary SET
PurchaseOrderSummaryIsActive = 'N'
@@ -875,15 +1016,16 @@ class PurchaseOrderAset extends MY_Controller {
PurchaseOrderDetailQty,
PurchaseOrderDetailPrice,
PurchaseOrderDetailTotal,
PurchaseOrderDetailWarehouseID,
PurchaseOrderDetailUserID,
PurchaseOrderDetailCreatedUserID,
PurchaseOrderDetailCreated
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
$que_detail = $this->db->query($sql_detail, [
$para['PurchaseOrderID'], $obj['PurchaseSummaryID'], $obj['PurchaseRequestID'],
$obj['PurchaseRequestDetailID'], $obj['PurchaseRequestFlagID'],
$obj['M_ItemID'], $obj['ItemUnitID'], $obj['OriginalQty'], $obj['RequestQty'],
$obj['SupplierPrice'], $total, $user['M_UserID'], $user['M_UserID']
$obj['SupplierPrice'], $total, $para['gudangID'], $user['M_UserID'], $user['M_UserID']
]);
if (!$que_detail) {
$this->db->trans_rollback();
@@ -1002,6 +1144,34 @@ class PurchaseOrderAset extends MY_Controller {
exit;
}
$sql_delattac = "UPDATE contract_asset_attachment SET
ContractAssetAttachmentIsActive = 'N'
WHERE ContractAssetAttachmentPurchaseOrderAssetContractID = ?
AND ContractAssetAttachmentPurchaseOrderID = ?";
$que_delattac = $this->db->query($sql_delattac, [
$para['contractID'], $para['poID']
]);
if (!$que_delattac) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed soft delete data attachment");
exit;
}
/* soft delete supplier_downpayment */
$sql_deldp = "UPDATE supplier_downpayment SET
SupplierDownpaymentIsActive = 'N',
SupplierDownpaymentLastUpdatedUserID = ?
WHERE SupplierDownpaymentID = ?
AND SupplierDownpaymentIsActive = 'Y'";
$que_deldp = $this->db->query($sql_deldp, [
$user['M_UserID'], $para['SupplierDownpaymentID']
]);
if (!$que_deldp) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed soft delete supplier downpayment");
exit;
}
/* soft delete purchase order */
$sql_delorder = "UPDATE purchase_order SET
PurchaseOrderIsActive = 'N',
@@ -1028,7 +1198,6 @@ class PurchaseOrderAset extends MY_Controller {
}
}
// upload file
public function uploadAttachment() {
try {
if (!$this->isLogin) {
@@ -1071,19 +1240,34 @@ class PurchaseOrderAset extends MY_Controller {
$upload_data = $this->upload->data();
$filename = $upload_data['file_name'];
$sql_insert = "INSERT INTO purchase_order_asset_attachment (
PurchaseOrderAssetAttachmentContractID,
PurchaseOrderAssetAttachmentPurchaseOrderID,
PurchaseOrderAssetAttachmentName,
PurchaseOrderAssetAttachmentType,
PurchaseOrderAssetAttachmentCreated
$sql_insert = "INSERT INTO contract_asset_attachment (
ContractAssetAttachmentPurchaseOrderAssetContractID,
ContractAssetAttachmentPurchaseOrderID,
ContractAssetAttachmentFileName,
ContractAssetAttachmentDate,
ContractAssetAttachmentCreated
) VALUES (?,?,?,?,NOW())";
$que_insert = $this->db->query($sql_insert, [
$para['contractID'], $para['poID'], $filename, 'order'
$para['contractID'], $para['poID'],
$filename, $para['contractDate']
]);
if (!$que_insert) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed insert attachment table purchase order asset attachment");
$this->sys_error_db("[Error] failed insert attachment table contract asset attachment");
exit;
}
$attachmentID = $this->db->insert_id();
$sql_contract = "UPDATE purchase_order_asset_contract SET
PurchaseOrderAssetContractTAssetAttachmentID = ?
WHERE PurchaseOrderAssetContractID = ?
AND PurchaseOrderAssetContractPurchaseOrderID = ?";
$que_contract = $this->db->query($sql_contract, [
$attachmentID, $para['contractID'], $para['poID']
]);
if (!$que_contract) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] failed update attachmentid into asset contract table");
exit;
}
} else {
@@ -1168,28 +1352,6 @@ class PurchaseOrderAset extends MY_Controller {
}
}
public function getUserApproveLevel() {
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$user = $this->sys_user;
$sql = "SELECT M_UserM_ApproveLevelID FROM m_user
WHERE M_UserIsActive = 'Y' AND M_UserID = ? ";
$que = $this->db->query($sql, [$user['M_UserID']]);
if (!$que) {
$this->sys_error_db("[Error] failed get approval level user");
exit;
}
$data = $que->row_array();
$this->sys_ok($data);
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
private function insertLog($poID, $type, $prm, $dataBefore, $dataAfter, $userID, $desc = '') {
$sql = "INSERT INTO acc_one_log.purchase_order_log (
PurchaseOrderLogPurchaseOrderID,

File diff suppressed because it is too large Load Diff

View File

@@ -1705,22 +1705,38 @@ class ReceiveItemPoInventaris extends MY_Controller
exit;
}
$sql_coa_inv = "SELECT
CoaMapInventarisCoaID,
CoaMapInventarisCoaNo,
CoaMapInventarisCoaDesc
FROM coa_map_inventaris
WHERE CoaMapInventarisM_InventarisGolID = ?
AND CoaMapInventarisIsActive = 'Y'";
$que_coa_inv = $this->db->query($sql_coa_inv, [$item_cek['M_ItemM_InventarisGolID']]);
if (!$que_coa_inv) {
$sql_invcoa = "SELECT
COALESCE(
i.M_InventarisItemCoaMappingID,
g.M_InventarisCoaMappingID
) AS MappingID,
COALESCE(
i.M_InventarisItemCoaMappingCoaInventarisID,
g.M_InventarisCoaMappingCoaInventarisID
) AS CoaInventarisID,
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->sys_error_db("[Error] failed to get coa biaya item inventaris");
exit;
}
$iteminv_coa = $que_coa_inv->row_array();
$iteminv_coa = $que_invcoa->row_array();
if (empty($iteminv_coa['CoaMapInventarisCoaID'])) {
if (empty($iteminv_coa['CoaInventarisID'])) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] coa gol inventaris not found");
exit;
@@ -1740,8 +1756,8 @@ class ReceiveItemPoInventaris extends MY_Controller
) VALUES (?,?,?,?,?,?)";
$que_tx_jurnal = $this->db->query($sql_tx_jurnal, [
$jurnal_ID,
$iteminv_coa['CoaMapInventarisCoaID'],
$iteminv_coa['CoaMapInventarisCoaDesc'],
$iteminv_coa['CoaInventarisID'],
$iteminv_coa['CoaInventarisDesc'],
$debet,
0,
$user['M_UserID']
@@ -1754,7 +1770,7 @@ class ReceiveItemPoInventaris extends MY_Controller
}
$juranl_tx_ID = $this->db->insert_id();
$each_desc[] = "- Add detail Jurnal debet {$item_cek['M_ItemDesc']}
{$iteminv_coa['CoaMapInventarisCoaDesc']} sejumlah {$this->formatRupiah($debet)}";
{$iteminv_coa['CoaInventarisDesc']} sejumlah {$this->formatRupiah($debet)}";
# INSERT JURNAL ADDON #
$sql_addon_jurnal = "INSERT INTO jurnal_addon (
@@ -1944,20 +1960,6 @@ class ReceiveItemPoInventaris extends MY_Controller
$this->sys_error_db("[Error] insert update stock");
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 {
$sql_insert_stock = "INSERT INTO stock (
StockWarehouseAlmariID,
@@ -1985,23 +1987,9 @@ class ReceiveItemPoInventaris extends MY_Controller
exit;
}
$stockID = $this->db->insert_id();
$stock_ID = $this->db->insert_id();
$stock_qty_ori = 0;
$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

View File

@@ -426,7 +426,7 @@ class ReceiveItemPoV2 extends MY_Controller {
AND ReceiveOrderPoIDate BETWEEN DATE(?) AND DATE(?)
AND ReceiveOrderPoS_RegionalID = ?
AND ReceiveOrderPoM_BranchCode LIKE ?
AND ReceiveOrderPoID NOT IN (
AND ReceiveOrderPoID IN (
SELECT DISTINCT ReceiveOrderPoDetailReceiveOrderPoID
FROM receive_order_po_detail
JOIN purchase_order ON ReceiveOrderPoDetailPurchaseOrderID = PurchaseOrderID

View File

@@ -1,78 +1,55 @@
# ============================================================
# FILE : PurchaseInvoiceInstallment.http
# MODUL : Scheduler — Generate Purchase Invoice Cicilan Aset
# MODUL : Scheduler — Generate Supplier Installment Cicilan Aset
# ============================================================
#
# DESKRIPSI
# ---------
# File ini berisi kumpulan HTTP request untuk menguji endpoint
# scheduler yang secara otomatis membuat Purchase Invoice (PI)
# cicilan bulanan berdasarkan kontrak aset aktif.
# File ini berisi HTTP request untuk menguji endpoint scheduler
# yang secara otomatis membuat baris cicilan ke tabel
# supplier_installment setiap bulan.
#
# CARA PAKAI
# ----------
# 1. Gunakan ekstensi "REST Client" di VS Code (humao.rest-client)
# atau tool sejenis (IntelliJ HTTP Client, Postman, dll).
# 2. Ganti nilai @host sesuai environment (local / staging / prod).
# 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).
# 2. Ganti nilai @host sesuai environment.
# 3. Klik "Send Request" di atas tiap blok ###
#
# ALUR PENGGUNAAN YANG DISARANKAN
# --------------------------------
# [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
# ALUR
# ----
# [1] GenerateMonthlyInvoices → Jalankan proses generate installment
#
# CATATAN
# -------
# - startDate & endDate menentukan periode bulan yang diproses.
# Biasanya diisi dengan tanggal awal dan akhir bulan berjalan.
# - Scheduler ini AMAN dijalankan ulang (idempotent). Kontrak yang
# sudah punya PI di bulan yang sama akan dilewati otomatis.
# - userID pada InsertSupplierInvoice akan diabaikan; sistem
# mengambil userID dari PurchaseOrderAssetContractCreatedUserID.
# - Default periode: bulan berjalan (tanggal 1 s/d akhir bulan)
# - Aman dijalankan ulang — dedup berdasarkan PO + bulan mencegah
# duplikasi
# - Tidak membuat jurnal — jurnal dibuat saat pembayaran cashier
# - Tidak update kontrak — InstallmentPaid diupdate saat pembayaran
# ============================================================
@host = https://accone.aplikasi.web.id/one-api
# ============================================================
# [1] LIST KONTRAK ELIGIBLE
# [1] GENERATE INSTALLMENT BULANAN (MAIN ENDPOINT)
# ============================================================
# Gunakan endpoint ini SEBELUM generate untuk melihat preview
# kontrak mana saja yang akan dibuatkan PI pada periode ini.
# Satu request ini akan:
# Step 1: Validasi kontrak (aktif, belum lunas, dalam rentang)
# 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 berisi daftar kontrak beserta detail cicilan,
# status GRNI, dan apakah PI bulan ini sudah ada atau belum.
# Response:
# - totalEligible : jumlah kontrak lolos validasi
# - totalInserted : jumlah baris berhasil diinsert
# - created[] : detail tiap installment yang dibuat
# ============================================================
### [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
### [1] Generate installment untuk periode tertentu
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices
Content-Type: application/json
@@ -81,47 +58,8 @@ Content-Type: application/json
"endDate": "2026-07-31"
}
# ============================================================
# [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
### [1a] Generate installment bulan berjalan (tanpa parameter)
POST {{host}}/mockup/scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices
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,20 +3,19 @@
/**
* PurchaseInvoiceInstallment
*
* Digunakan oleh CRON untuk membuat Purchase Invoice (PI) cicilan aset
* secara otomatis setiap bulan berdasarkan kontrak yang aktif.
* CRON scheduler untuk membuat baris cicilan otomatis ke tabel supplier_installment
* setiap bulan berdasarkan kontrak aset yang aktif dan belum lunas.
*
* Endpoint utama:
* Endpoint:
* POST /scheduler/PurchaseInvoiceInstallment/GenerateMonthlyInvoices
* POST /scheduler/PurchaseInvoiceInstallment/CurlGenerateMonthlyInvoices
*/
class PurchaseInvoiceInstallment extends MY_Controller
{
var $db;
var $baseUrl = "https://accone.aplikasi.web.id/one-api/";
public function index()
{
echo "Purchase Invoice Installment — Auto Generate PI Cicilan Aset";
echo "Purchase Invoice Installment — Auto Generate Installment Cicilan Aset";
}
public function __construct()
@@ -25,327 +24,121 @@ class PurchaseInvoiceInstallment extends MY_Controller
}
/**
* GenerateMonthlyInvoices
* GenerateMonthlyInvoices — Step 6
*
* Membuat Purchase Invoice cicilan untuk semua kontrak aset yang aktif
* dan belum lunas pada bulan yang ditentukan.
* Creates supplier_installment rows for all eligible contracts this month.
* No journal is created here — that happens at cashier payment time.
* Contract InstallmentPaid is NOT updated here — that happens at payment time.
*
* Parameter (POST JSON):
* - 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
* Called by CRON daily at 1:00 AM.
* Defaults to current month if no startDate/endDate provided.
*/
public function GenerateMonthlyInvoices()
{
try {
$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);
$startDate = isset($para["startDate"]) && $para["startDate"] != ""
$userID = !empty($this->sys_user["M_UserID"])
? (int) $this->sys_user["M_UserID"]
: 0;
$startDate = !empty($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"] != ""
: date("Y-m-01");
$endDate = !empty($para["endDate"])
? $para["endDate"]
: (isset($para["date"]) && $para["date"] != "" ? date("Y-m-t", strtotime($para["date"])) : date("Y-m-t"));
// Validasi format tanggal
: 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");
throw new Exception("Format tanggal tidak valid.");
}
if (strtotime($startDate) > strtotime($endDate)) {
throw new Exception("startDate tidak boleh lebih besar dari endDate");
throw new Exception("startDate > endDate.");
}
// Tentukan rentang bulan berdasarkan tanggal acuan
$monthStart = $startDate;
$monthEnd = $endDate;
$dayOfMonth = (int) date("d", strtotime($endDate));
// ── Steps 15: Get eligible contracts ────────────────────
$eligible = $this->getEligibleInstallments($startDate, $endDate);
// -------------------------------------------------------------------------
// 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
$created = [];
$inserted = 0;
-- Pastikan PO sudah Approved dan aktif
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
-- Ambil 1 item PO pertama sebagai referensi baris detail PI
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'
-- Hanya kontrak yang ada nilai cicilannya
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPayAmount, 0) > 0
-- Hanya kontrak yang belum selesai seluruh cicilannya
AND IFNULL(c.PurchaseOrderAssetContractInstallmentPaid, 0) < IFNULL(c.PurchaseOrderAssetContractInstallmentNumber, 0)
-- Kontrak sudah mulai sebelum atau pada akhir bulan ini
AND DATE(c.PurchaseOrderAssetContractStartDate) <= DATE(?)
-- Kontrak belum berakhir (atau tidak ada tanggal akhir)
AND (
c.PurchaseOrderAssetContractEndDate IS NULL
OR DATE(c.PurchaseOrderAssetContractEndDate) >= DATE(?)
)
-- Tanggal jatuh tempo cicilan sudah melewati atau sama dengan hari ini
AND IFNULL(c.PurchaseOrderAssetContractInstallmentDate, 1) <= ?";
$params = [$monthEnd, $monthStart, $dayOfMonth];
$qryKontrak = $this->db->query($sqlKontrak, $params);
if (!$qryKontrak) {
$this->sys_error_db("Gagal mengambil daftar kontrak cicilan dari database.");
exit;
}
$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";
foreach ($eligible as $row) {
$sqlUpdateKontrak = "UPDATE purchase_order_asset_contract
SET PurchaseOrderAssetContractReceiveOrderPoID = ?,
PurchaseOrderAssetContractInstallmentPaid = ?,
PurchaseOrderAssetContractStatus = ?,
PurchaseOrderAssetContractLastUpdated = NOW()
WHERE PurchaseOrderAssetContractID = ?
AND PurchaseOrderAssetContractIsActive = 'Y'";
$amount = (float) $row["PurchaseOrderAssetContractInstallmentPayAmount"];
$dayOfMonth = (int) ($row["PurchaseOrderAssetContractInstallmentDate"] ?? 1);
$lastDay = (int) date("t", strtotime($endDate));
$dayOfMonth = min($dayOfMonth, $lastDay);
$installDate = date("Y-m", strtotime($endDate)) . "-" . str_pad($dayOfMonth, 2, "0", STR_PAD_LEFT);
$dueDate = date("Y-m-d", strtotime($installDate . " +7 days"));
$createdBy = (int) ($row["PurchaseOrderAssetContractCreatedUserID"] ?? $userID);
$qryUpdateKontrak = $this->db->query($sqlUpdateKontrak, [
$kontrak["PurchaseOrderAssetContractReceiveOrderPoID"],
$cicilanTerbayarBaru,
$statusKontrakBaru,
$kontrak["PurchaseOrderAssetContractID"]
// ── Step 6: INSERT supplier_installment ──────────────
$sql = "INSERT INTO supplier_installment (
SupplierInstallmentPurchaseOrderID,
SupplierInstallmentSupplierID,
SupplierInstallmentSupplierInvoiceID,
SupplierInstallmentAmount,
SupplierInstallmentDate,
SupplierInstallmentDueDate,
SupplierInstallmentPaymentID,
SupplierInstallmentStatus,
SupplierInstallmentIsLunas,
SupplierInstallmentIsActive,
SupplierInstallmentCreated,
SupplierInstallmentCreatedUserID
) VALUES (?, ?, ?, ?, ?, ?, 0, 'Pending', 'N', 'Y', NOW(), ?)";
$que = $this->db->query($sql, [
$row["PurchaseOrderID"],
$row["PurchaseOrderSupplierID"],
$row["SupplierInvoiceID"],
$amount,
$installDate,
$dueDate,
$createdBy
]);
if (!$qryUpdateKontrak) {
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("Gagal memperbarui data cicilan terbayar pada kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ".");
$this->sys_error_db("Gagal insert supplier_installment.");
exit;
}
// Pastikan tidak ada error di dalam transaksi sebelum commit
$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 database gagal saat memproses kontrak ID " . $kontrak["PurchaseOrderAssetContractID"] . ". Semua perubahan dibatalkan.");
$this->sys_error_db("Transaksi gagal.");
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([
"startDate" => $startDate,
"endDate" => $endDate,
"periodeAwal" => $monthStart,
"periodeAkhir" => $monthEnd,
"totalDibuat" => count($berhasil),
"totalDilewati" => count($dilewati),
"daftarDibuat" => $berhasil,
"daftarDilewati" => $dilewati
"totalEligible" => count($eligible),
"totalInserted" => $inserted,
"created" => $created
]);
} catch (Exception $exc) {
if ($this->db->trans_status() === false) {
$this->db->trans_rollback();
@@ -354,229 +147,6 @@ 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.
* Jika user tidak ditemukan, kembalikan data default (tanpa branch/regional).
@@ -638,4 +208,95 @@ class PurchaseInvoiceInstallment extends MY_Controller
$d = DateTime::createFromFormat("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,29 +28,92 @@ class Billv2 extends MY_Controller {
$offset = ($params['currentpage'] - 1) * $limit;
}
$sql_base = "SELECT
SupplierPaymentID,
SupplierPaymentDate,
SupplierPaymentNumber,
SupplierPaymentAmount,
SupplierPaymentStatus,
SupplierPaymentIsVerif,
SupplierPaymentIsApproved,
SupplierInvoiceID,
SupplierInvoiceNumber,
SupplierInvoiceDraftPaymentDate,
SupplierCode,
SupplierName
FROM supplier_payment
JOIN supplier_invoice ON SupplierInvoiceID = SupplierPaymentSupplierInvoiceID
// ── UNION base — invoice + downpayment + installment ───
$sql_base = "
SELECT
sp.SupplierPaymentID,
sp.SupplierPaymentDate,
sp.SupplierPaymentNumber,
sp.SupplierPaymentAmount,
sp.SupplierPaymentStatus,
sp.SupplierPaymentIsVerif,
sp.SupplierPaymentIsApproved,
sp.SupplierPaymentIsActive,
si.SupplierInvoiceID,
si.SupplierInvoiceNumber,
si.SupplierInvoiceDraftPaymentDate,
sup.SupplierCode,
sup.SupplierName,
'INVOICE' AS type
FROM supplier_payment sp
JOIN supplier_invoice si
ON si.SupplierInvoiceID = sp.SupplierPaymentSupplierInvoiceID
JOIN supplier sup
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')
JOIN supplier ON SupplierID = SupplierInvoiceSupplierID
WHERE SupplierPaymentIsActive = 'Y'
ORDER BY SupplierPaymentID DESC";
ORDER BY SupplierPaymentID DESC
LIMIT ? OFFSET ?";
$sql_data = $sql_base . " LIMIT ? OFFSET ? ";
$que_data = $this->db->query($sql_data, [
$keyword, $params['startdate'], $params['enddate'],
$params['status'], $params['status'], $limit, $offset
@@ -59,7 +122,13 @@ class Billv2 extends MY_Controller {
throw new Exception("[Error] failed get data supplier payment", 2);
}
$sql_total = "SELECT COUNT(*) AS total FROM ($sql_base) AS x";
// ── COUNT — wrap UNION in outer filter ──────────────────
$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, [
$keyword, $params['startdate'], $params['enddate'],
$params['status'], $params['status']
@@ -74,7 +143,6 @@ class Billv2 extends MY_Controller {
];
$this->sys_ok($output);
exit;
} catch (Exception $exc) {
$message = $exc->getMessage();
$code = $exc->getCode();
@@ -96,28 +164,40 @@ class Billv2 extends MY_Controller {
$para = $this->sys_input;
$sql = "SELECT
SupplierInvoiceID,
SupplierInvoiceRefNumber,
SupplierInvoiceDeliveryOrderNumber,
SupplierInvoiceSupplierInvoiceNumber,
SupplierInvoiceSupplierInvoiceDate,
SupplierInvoiceSubTotal,
SupplierInvoiceTaxPercentPph,
SupplierInvoiceTaxPercentPpn,
SupplierInvoiceTaxAmountPpn,
SupplierInvoiceDiscountAmount,
SupplierInvoiceDiscountPercent,
SupplierInvoiceShippingCost,
SupplierInvoiceGrandTotal,
SupplierInvoiceAdjustmentAmount,
SupplierInvoiceAdjustmentNote,
SupplierInvoiceNote,
IF (SupplierInvoiceDiscountAmount > 0, 'R', 'P') AS DiscountType
// ── Detect payment type ──────────────────────────────────
$sql_type = "SELECT
SupplierPaymentSupplierInvoiceID,
SupplierPaymentSupplierDownpaymentID,
SupplierPaymentSupplierInstallmentID
FROM supplier_payment
JOIN supplier_invoice ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID
AND SupplierPaymentID = ?
AND SupplierPaymentIsActive = 'Y'";
WHERE SupplierPaymentID = ? AND SupplierPaymentIsActive = 'Y'";
$que_type = $this->db->query($sql_type, [$para['paymentID']]);
if (!$que_type) {
throw new Exception("[Error] failed get payment header", 2);
}
$payment = $que_type->row_array();
if (!$payment) {
throw new Exception("[Error] payment not found", 2);
}
// ── INVOICE branch ──────────────────────────────────────
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);
@@ -125,33 +205,21 @@ class Billv2 extends MY_Controller {
$data = $que->row_array();
$sql_detail = "SELECT
SupplierInvoiceDetailID,
SupplierInvoiceDetailSupplierInvoiceID,
SupplierInvoiceDetailPurchaseOrderID,
SupplierInvoiceDetailPurchaseOrderSummaryID,
SupplierInvoiceDetailReceiveOrderPoID,
SupplierInvoiceDetailReceiveOrderPoDetailID,
SupplierInvoiceDetailItemID,
SupplierInvoiceDetailItemUnitID,
SupplierInvoiceDetailDescription,
M_ItemDesc,
SupplierInvoiceDetailQty,
SupplierInvoiceDetailPrice,
SupplierInvoiceDetailDiscountPercent,
SupplierInvoiceDetailDiscountDiscountRupiah,
SupplierInvoiceDetailDiscountDiscountType,
SupplierInvoiceDetailDiscountAmount,
(SupplierInvoiceDetailPrice - SupplierInvoiceDetailDiscountAmount) AS DiscountedPrice,
SupplierInvoiceDetailDiscountPoProrata,
SupplierInvoiceDetailTotal,
M_ItemCode,
M_ItemDesc
SupplierInvoiceDetailTotal
FROM supplier_payment_detail
JOIN supplier_invoice_detail ON SupplierInvoiceDetailIsActive = 'Y'
JOIN supplier_invoice_detail
ON SupplierInvoiceDetailIsActive = 'Y'
AND SupplierPaymentDetailSupplierPaymentID = ?
AND SupplierInvoiceDetailSupplierInvoiceID = ?
JOIN m_item ON M_ItemID = SupplierInvoiceDetailItemID
AND M_ItemIsActive = 'Y'
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']
]);
@@ -159,8 +227,107 @@ class Billv2 extends MY_Controller {
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);
} catch (Exception $exc) {
$message = $exc->getMessage();

View File

@@ -12,7 +12,8 @@ class Bill extends MY_Controller
$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,
SupplierPaymentDetailSupplierInvoiceDetailID as detail_id,
@@ -35,15 +36,18 @@ class Bill extends MY_Controller
CONCAT('Verified by : ',b.M_UserUsername, ' ',DATE_FORMAT(SupplierPaymentVerifDate,'%d-%m-%Y %H:%i')) as d_verif
FROM supplier_payment
JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID AND SupplierPaymentDetailIsActive = '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
SupplierPaymentSupplierInvoiceID = {$orderid}
AND
SupplierPaymentIsActive = '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 SupplierPaymentSupplierInvoiceID = {$orderid}
AND SupplierPaymentIsActive = 'Y'
GROUP BY SupplierPaymentID";
$query = $this->db_onedev->query($sql);
if ($query) {
@@ -54,14 +58,149 @@ class Bill extends MY_Controller
}
}
return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev);
exit;
}
}
public function add_tagihans($orderid){
$sql = "SELECT SupplierInvoiceID as tagihan_id,
public function add_notes_downpayment($orderid)
{
$sql = "SELECT SupplierPaymentSupplierDownpaymentID AS note_order_id,
SupplierPaymentID AS note_id,
SupplierDownpaymentID AS detail_id,
SupplierPaymentDate AS note_date,
SupplierPaymentNumber AS note_number,
GROUP_CONCAT(DISTINCT coaDescription separator ' , ') AS paymenttypes_name,
SUM(SupplierDownpaymentAmount) AS note_amount,
n.M_UserUsername AS note_user,
SupplierDownpaymentIsActive 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_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,
@@ -73,25 +212,43 @@ class Bill extends MY_Controller
jurnalTxID SupplierInvoiceDetailID,
PurchaseOrderID SupplierInvoiceDetailPurchaseOrderID
FROM supplier_invoice
JOIN purchase_order ON SupplierInvoicePurchaseOrderID = PurchaseOrderID
JOIN jurnal_addon ON jurnalAddOnValue = SupplierInvoiceNumber
JOIN jurnal_tx ON jurnalTxJurnalID = jurnalAddOnJurnalID AND jurnalTxCredit <> 0 AND jurnalTxCoaID <> 563
LEFT JOIN supplier_payment ON SupplierPaymentSupplierInvoiceID = SupplierInvoiceID AND SupplierInvoiceIsActive = 'Y'
LEFT JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID AND SupplierPaymentDetailSupplierInvoiceDetailID = jurnalTxID AND SupplierPaymentDetailIsActive = 'Y'
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, [$orderid]);
$query = $this->db_onedev->query($sql, array_merge($excludeIds, [$orderid]));
if ($query) {
$rows = $query->result_array();
return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev);
exit;
}
}
public function add_tests($orderid){
$sql = " SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
public function add_tests($orderid)
{
$sql = "SELECT
SupplierPaymentSupplierInvoiceID as note_order_id,
SupplierPaymentID as note_id,
SupplierPaymentDate as note_date,
SupplierPaymentNumber as note_number,
@@ -103,13 +260,17 @@ class Bill extends MY_Controller
SupplierInvoiceDetailTotal,
SupplierPaymentDetailAmount
FROM supplier_payment
JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
LEFT JOIN supplier_invoice_detail ON SupplierPaymentDetailSupplierInvoiceDetailID = SupplierInvoiceDetailID
LEFT JOIN purchase_order ON SupplierInvoiceDetailPurchaseOrderID = PurchaseOrderID
JOIN coa ON SupplierPaymentCoaID = coaID
LEFT JOIN m_user ON SupplierPaymentDetailUserID = M_UserID
WHERE
SupplierPaymentID = {$orderid}
JOIN supplier_payment_detail
ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
LEFT JOIN supplier_invoice_detail
ON SupplierPaymentDetailSupplierInvoiceDetailID = SupplierInvoiceDetailID
LEFT JOIN purchase_order
ON SupplierInvoiceDetailPurchaseOrderID = PurchaseOrderID
JOIN coa
ON SupplierPaymentCoaID = coaID
LEFT JOIN m_user
ON SupplierPaymentDetailUserID = M_UserID
WHERE SupplierPaymentID = {$orderid}
GROUP BY SupplierPaymentDetailID";
$query = $this->db_onedev->query($sql);
if ($query) {
@@ -117,19 +278,19 @@ class Bill extends MY_Controller
if ($rows) {
}
return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev);
exit;
}
}
public function search()
public function search_old()
{
//# cek token valid
if (! $this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$supplier = $prm["supplier"];
$search = $prm["search"];
@@ -139,32 +300,42 @@ class Bill extends MY_Controller
$regionalid = $this->sys_user['S_RegionalID'];
$number_limit = 10;
$number_offset = ($prm['current_page'] - 1) * $number_limit ;
$number_offset = ((int)$prm['current_page'] - 1) * $number_limit;
$where = "SupplierInvoiceIsActive = 'Y'
AND SupplierPaymentIsApproved = 'Y'
AND SupplierPaymentIsVerif = 'Y'
AND SupplierPaymentIsConfirm = '{$status}'
AND (SupplierInvoiceNumber LIKE '%{$search}%' OR SupplierInvoiceSupplierInvoiceNumber LIKE '%{$search}%')
AND SupplierName LIKE '%{$supplier}%'
AND ReceiveOrderPoS_RegionalID = {$regionalid}
AND SupplierInvoiceDraftPaymentDate BETWEEN '{$startdate}' AND '{$enddate}'";
// ── WHERE ────────────────────────────────────────────────
$where = " si.SupplierInvoiceIsActive = 'Y'
AND sp.SupplierPaymentIsApproved = 'Y'
AND sp.SupplierPaymentIsVerif = 'Y'
AND sp.SupplierPaymentIsConfirm = ?
AND (si.SupplierInvoiceNumber LIKE ?
OR si.SupplierInvoiceSupplierInvoiceNumber LIKE ?)
AND sup.SupplierName LIKE ?
AND rop.ReceiveOrderPoS_RegionalID = ?
AND si.SupplierInvoiceDraftPaymentDate BETWEEN ? AND ? ";
$where_params = [
$status,
'%' . $search . '%',
'%' . $search . '%',
'%' . $supplier . '%',
$regionalid,
$startdate,
$enddate,
];
// ── COUNT ────────────────────────────────────────────────
$sql_count = "
SELECT count(*) as total
FROM supplier_invoice si
JOIN jurnal_addon ja ON ja.jurnalAddOnValue = si.SupplierInvoiceNumber
JOIN receive_order_po rop ON rop.ReceiveOrderPoID = si.SupplierInvoiceReceiveOrderPoID
LEFT JOIN supplier_payment sp
ON sp.SupplierPaymentSupplierInvoiceID = si.SupplierInvoiceID
AND sp.SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier sup ON sup.SupplierID = si.SupplierInvoiceSupplierID
WHERE $where";
$sql = " SELECT count(*) as total
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
$where
";
// echo $sql;
$query = $this->db_onedev->query($sql, $sql_param);
$query = $this->db_onedev->query($sql_count, $where_params);
$tot_count = 0;
$tot_page = 0;
@@ -176,80 +347,457 @@ class Bill extends MY_Controller
exit;
}
// ── DATA — only columns the frontend actually reads ──────
$sql_data = "
SELECT
si.SupplierInvoiceID,
si.SupplierInvoiceNumber,
si.SupplierInvoiceDraftPaymentDate,
si.SupplierInvoiceIsLunas AS flaglunas,
si.SupplierInvoiceSupplierInvoiceNumber,
DATE_FORMAT(
IFNULL(si.SupplierInvoiceSupplierInvoiceDate,''),'%d-%m-%Y'
) AS tanggalinvoice,
sup.SupplierName,
sp.SupplierPaymentID,
sp.SupplierPaymentIsConfirm,
IFNULL(sp.SupplierPaymentCashierNumber,'') AS SupplierPaymentCashierNumber,
DATE_FORMAT(
si.SupplierInvoiceDraftPaymentDate,'%d-%m-%Y'
) AS tanggalbayar,
0 AS totalbill,
0 AS paid,
0 AS unpaid,
'' AS SupplierPaymentNumber,
0 AS SupplierPaymentAmount,
'' AS SupplierPaymentDate,
'' AS notes,
'' AS tagihans,
0 AS xrounding,
'' AS chex
FROM supplier_invoice si
JOIN jurnal_addon ja ON ja.jurnalAddOnValue = si.SupplierInvoiceNumber
JOIN receive_order_po rop ON rop.ReceiveOrderPoID = si.SupplierInvoiceReceiveOrderPoID
LEFT JOIN supplier_payment sp
ON sp.SupplierPaymentSupplierInvoiceID = si.SupplierInvoiceID
AND sp.SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier sup ON sup.SupplierID = si.SupplierInvoiceSupplierID
WHERE $where
GROUP BY si.SupplierInvoiceID
ORDER BY si.SupplierInvoiceID ASC
LIMIT ? OFFSET ?";
$sql = "SELECT supplier_invoice.*,
SupplierName,
'' M_MouName,
0 as totalbill,
0 as paid,
0 as unpaid,
SupplierInvoiceIsLunas as flaglunas,
'' as SupplierPaymentNumber,
0 as SupplierPaymentAmount,
'' as SupplierPaymentDate,
'' as SupplierInvoiceIssueRefNumber,
'' as notes,
'' as tagihans,
'N' as isbillterpusat,
DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d-%m-%Y') as tanggalbayar,
DATE_FORMAT(SupplierInvoiceDraftPaymentDate,'%d%m%Y') as tanggalbayartext,
IF(SupplierPaymentID IS NULL,'N','Y') as status_invoice,
SupplierPaymentID,
SupplierPaymentIsConfirm,
DATE_FORMAT(IFNULL(SupplierInvoiceSupplierInvoiceDate,''),'%d-%m-%Y') as tanggalinvoice,
0 xrounding,
'' chex,
IFNULL(SupplierPaymentCashierNumber,'') SupplierPaymentCashierNumber
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
$where
GROUP BY SupplierInvoiceID
ORDER BY SupplierInvoiceID ASC
limit $number_limit offset $number_offset";
//echo $sql;
$query = $this->db_onedev->query($sql, $sql_param);
$data_params = array_merge($where_params, [$number_limit, $number_offset]);
$query = $this->db_onedev->query($sql_data, $data_params);
$rows = $query->result_array();
// ── ENRICH ───────────────────────────────────────────────
if ($rows) {
foreach ($rows as $k => $v) {
$rows[$k]['chex'] = false;
$s_payment = $this->db_onedev->query("SELECT GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
GROUP_CONCAT(DATE_FORMAT(SupplierPaymentDate,'%d-%m-%Y') SEPARATOR ', ') as SupplierPaymentDate
FROM supplier_payment
WHERE SupplierPaymentIsActive = 'Y' AND SupplierPaymentSupplierInvoiceID = {$v['SupplierInvoiceID']}")->row();
$inv_id = $v['SupplierInvoiceID'];
$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 = {$v['SupplierInvoiceID']}
GROUP BY SupplierInvoiceID")->row();
$amount = $s_payment->SupplierPaymentAmount ? $s_payment->SupplierPaymentAmount : "0.00";
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
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 si
JOIN jurnal_addon ja ON ja.jurnalAddOnValue = si.SupplierInvoiceNumber
JOIN jurnal_tx jt
ON jt.jurnalTxJurnalID = ja.jurnalAddOnJurnalID
AND jt.jurnalTxCredit <> 0
AND jt.jurnalTxCoaID <> 563
WHERE si.SupplierInvoiceID = ?
GROUP BY si.SupplierInvoiceID",
[$inv_id]
)->row();
$amount = $s_payment->SupplierPaymentAmount
? $s_payment->SupplierPaymentAmount
: "0.00";
$unpaid = (float)$s_jurnal->totalbill - (float)$amount;
$rows[$k]['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]['totalbill'] = $s_jurnal->totalbill
? $s_jurnal->totalbill
: "0.00";
$rows[$k]['unpaid'] = number_format($unpaid, 2, '.', '');
$rows[$k]['notes'] = $this->add_notes($v['SupplierInvoiceID']);
$rows[$k]['tagihans'] = $this->add_tagihans($v['SupplierInvoiceID']);
$rows[$k]['notes'] = $this->add_notes($inv_id);
$rows[$k]['tagihans'] = $this->add_tagihans($inv_id);
}
}
$result = array("total" => $tot_page, "records" => $rows, "sql"=> $this->db_onedev->last_query());
$result = array("total" => $tot_page, "records" => $rows);
$this->sys_ok($result);
exit;
}
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 branch WHERE ─────────────────────────────────
$inv_where = " si.SupplierInvoiceIsActive = 'Y'
AND rop.ReceiveOrderPoS_RegionalID = ? ";
$inv_params = [$regionalid];
// ── DOWNPAYMENT branch WHERE ─────────────────────────────
$dp_where = " dp.SupplierDownpaymentIsActive = 'Y'
AND po.PurchaseOrderS_RegionalID = ? ";
$dp_params = [$regionalid];
// ── INSTALLMENT branch WHERE ────────────────────────────
$inst_where = " inst.SupplierInstallmentIsActive = 'Y'
AND rop.ReceiveOrderPoS_RegionalID = ? ";
$inst_params = [$regionalid];
// ── UNION base ───────────────────────────────────────────
$sql_base = "
SELECT
si.SupplierInvoiceID,
0 AS DownpaymentID,
0 AS InstallmentID,
0 AS parent_invoice_id,
si.SupplierInvoiceNumber,
si.SupplierInvoiceDraftPaymentDate,
si.SupplierInvoiceDraftPaymentDate AS filter_date,
si.SupplierInvoiceIsLunas AS flaglunas,
si.SupplierInvoiceSupplierInvoiceNumber,
DATE_FORMAT(
IFNULL(si.SupplierInvoiceSupplierInvoiceDate,''),'%d-%m-%Y'
) AS tanggalinvoice,
sup.SupplierName,
sp.SupplierPaymentID,
sp.SupplierPaymentIsConfirm,
sp.SupplierPaymentIsApproved,
sp.SupplierPaymentIsVerif,
sp.SupplierPaymentIsActive,
IFNULL(sp.SupplierPaymentCashierNumber,'') AS SupplierPaymentCashierNumber,
DATE_FORMAT(
si.SupplierInvoiceDraftPaymentDate,'%d-%m-%Y'
) AS tanggalbayar,
0 AS totalbill,
0 AS paid,
0 AS unpaid,
'' AS SupplierPaymentNumber,
0 AS SupplierPaymentAmount,
'' AS SupplierPaymentDate,
'' AS notes,
'' AS tagihans,
0 AS xrounding,
'' AS chex,
'INVOICE' AS type
FROM supplier_invoice si
JOIN jurnal_addon ja ON ja.jurnalAddOnValue = si.SupplierInvoiceNumber
JOIN receive_order_po rop ON rop.ReceiveOrderPoID = si.SupplierInvoiceReceiveOrderPoID
LEFT JOIN supplier_payment sp
ON sp.SupplierPaymentSupplierInvoiceID = si.SupplierInvoiceID
AND sp.SupplierPaymentIsActive = 'Y'
LEFT JOIN supplier sup ON sup.SupplierID = si.SupplierInvoiceSupplierID
WHERE $inv_where
GROUP BY si.SupplierInvoiceID
UNION ALL
SELECT
0 AS SupplierInvoiceID,
dp.SupplierDownpaymentID AS DownpaymentID,
0 AS InstallmentID,
0 AS parent_invoice_id,
CONCAT('DP-', po.PurchaseOrderNumber) AS SupplierInvoiceNumber,
dp.SupplierDownpaymentDueDate AS SupplierInvoiceDraftPaymentDate,
dp.SupplierDownpaymentDueDate AS filter_date,
dp.SupplierDownpaymentIsLunas AS flaglunas,
'' AS SupplierInvoiceSupplierInvoiceNumber,
DATE_FORMAT(dp.SupplierDownpaymentDate,'%d-%m-%Y') AS tanggalinvoice,
dp_sup.SupplierName AS SupplierName,
sp.SupplierPaymentID,
sp.SupplierPaymentIsConfirm,
sp.SupplierPaymentIsApproved,
sp.SupplierPaymentIsVerif,
sp.SupplierPaymentIsActive,
IFNULL(sp.SupplierPaymentCashierNumber,'') AS SupplierPaymentCashierNumber,
DATE_FORMAT(
dp.SupplierDownpaymentDueDate,'%d-%m-%Y'
) AS tanggalbayar,
dp.SupplierDownpaymentAmount AS totalbill,
CASE WHEN dp.SupplierDownpaymentStatus = 'Paid'
THEN dp.SupplierDownpaymentAmount
ELSE 0 END AS paid,
CASE WHEN dp.SupplierDownpaymentStatus = 'Paid'
THEN 0
ELSE dp.SupplierDownpaymentAmount END AS unpaid,
'' AS SupplierPaymentNumber,
0 AS SupplierPaymentAmount,
'' AS SupplierPaymentDate,
'' AS notes,
'' AS tagihans,
0 AS xrounding,
'' AS chex,
'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 $dp_where
UNION ALL
SELECT
0 AS SupplierInvoiceID,
0 AS DownpaymentID,
inst.SupplierInstallmentID AS InstallmentID,
si_inst.SupplierInvoiceID AS parent_invoice_id,
CONCAT('INST-', si_inst.SupplierInvoiceNumber) AS SupplierInvoiceNumber,
inst.SupplierInstallmentDueDate AS SupplierInvoiceDraftPaymentDate,
inst.SupplierInstallmentDueDate AS filter_date,
inst.SupplierInstallmentIsLunas AS flaglunas,
si_inst.SupplierInvoiceSupplierInvoiceNumber AS SupplierInvoiceSupplierInvoiceNumber,
DATE_FORMAT(
IFNULL(si_inst.SupplierInvoiceSupplierInvoiceDate,''),'%d-%m-%Y'
) AS tanggalinvoice,
inst_sup.SupplierName AS SupplierName,
IFNULL(sp.SupplierPaymentID,0) AS SupplierPaymentID,
IFNULL(sp.SupplierPaymentIsConfirm,'N') AS SupplierPaymentIsConfirm,
IFNULL(sp.SupplierPaymentIsApproved,'N') AS SupplierPaymentIsApproved,
IFNULL(sp.SupplierPaymentIsVerif,'N') AS SupplierPaymentIsVerif,
IFNULL(sp.SupplierPaymentIsActive,'Y') AS SupplierPaymentIsActive,
IFNULL(sp.SupplierPaymentCashierNumber,'') AS SupplierPaymentCashierNumber,
DATE_FORMAT(
inst.SupplierInstallmentDueDate,'%d-%m-%Y'
) AS tanggalbayar,
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,
'' AS SupplierPaymentNumber,
0 AS SupplierPaymentAmount,
'' AS SupplierPaymentDate,
'' AS notes,
'' AS tagihans,
0 AS xrounding,
'' AS chex,
'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_inst
ON si_inst.SupplierInvoiceID = inst.SupplierInstallmentSupplierInvoiceID
JOIN receive_order_po rop
ON rop.ReceiveOrderPoID = si_inst.SupplierInvoiceReceiveOrderPoID
JOIN supplier inst_sup
ON inst_sup.SupplierID = inst.SupplierInstallmentSupplierID
WHERE $inst_where";
// ── Outer common filters ─────────────────────────────────
$outer_where = " SupplierPaymentIsActive = 'Y'
AND SupplierPaymentIsApproved = 'Y'
AND SupplierPaymentIsVerif = 'Y'
AND SupplierPaymentIsConfirm = ?
AND (SupplierInvoiceNumber LIKE ? OR SupplierInvoiceSupplierInvoiceNumber LIKE ?)
AND SupplierName LIKE ?
AND filter_date BETWEEN ? AND ? ";
$outer_params = [
$status,
'%' . $search . '%',
'%' . $search . '%',
'%' . $supplier . '%',
$startdate,
$enddate,
];
// ── COUNT ────────────────────────────────────────────────
$sql_count = "
SELECT COUNT(*) AS total
FROM ($sql_base) AS combined
WHERE $outer_where";
$count_params = array_merge($inv_params, $dp_params, $inst_params, $outer_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("supplier payment count", $this->db_onedev);
exit;
}
// ── DATA ─────────────────────────────────────────────────
$sql_data = "
SELECT * FROM ($sql_base) AS combined
WHERE $outer_where
ORDER BY SupplierInvoiceID ASC
LIMIT ? OFFSET ?";
$data_params = array_merge($inv_params, $dp_params, $inst_params, $outer_params, [$number_limit, $number_offset]);
$query = $this->db_onedev->query($sql_data, $data_params);
$rows = $query->result_array();
// ── ENRICH ───────────────────────────────────────────────
if ($rows) {
foreach ($rows as $k => $v) {
// ── Downpayment branch ──────────────────────────
if ($v['type'] === 'DP') {
$rows[$k]['chex'] = false;
$dp_id = $v['DownpaymentID'];
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
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]['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'] = [];
continue;
}
// ── Installment branch ─────────────────────────
if ($v['type'] === 'INSTALLMENT') {
$rows[$k]['chex'] = false;
$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,
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]['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);
continue;
}
// ── Invoice branch ──────────────────────────────
$rows[$k]['chex'] = false;
$inv_id = $v['SupplierInvoiceID'];
$s_payment = $this->db_onedev->query("
SELECT
GROUP_CONCAT(SupplierPaymentNumber SEPARATOR ', ') as SupplierPaymentNumber,
SUM(IFNULL(SupplierPaymentAmount,0)) as SupplierPaymentAmount,
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 si
JOIN jurnal_addon ja ON ja.jurnalAddOnValue = si.SupplierInvoiceNumber
JOIN jurnal_tx jt
ON jt.jurnalTxJurnalID = ja.jurnalAddOnJurnalID
AND jt.jurnalTxCredit <> 0
AND jt.jurnalTxCoaID <> 563
WHERE si.SupplierInvoiceID = ?
GROUP BY si.SupplierInvoiceID",
[$inv_id]
)->row();
$amount = $s_payment->SupplierPaymentAmount
? $s_payment->SupplierPaymentAmount
: "0.00";
$unpaid = (float)$s_jurnal->totalbill - (float)$amount;
$rows[$k]['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;
}
}

View File

@@ -3,9 +3,10 @@
class PaymentV2 extends MY_Controller
{
var $db;
public function index()
{
echo "API";
echo 'API';
}
public function __construct()
@@ -17,8 +18,8 @@ class PaymentV2 extends MY_Controller
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
$this->sys_error('invalid token');
exit();
}
$this->db->trans_begin();
@@ -26,15 +27,15 @@ class PaymentV2 extends MY_Controller
$param = $this->sys_input;
$users = $this->sys_user;
# Generate number supplier payment #
$sql_gennumber = "SELECT `fn_numbering`(?) as numberx";
// Generate number supplier payment #
$sql_gennumber = 'SELECT `fn_numbering`(?) as numberx';
$paygroupnum = $this->db->query($sql_gennumber, ['PC'])->row()->numberx;
$paynumber = $this->db->query($sql_gennumber, ['PN'])->row()->numberx;
if ($paygroupnum == '' || $paynumber == '') {
$this->db->trans_rollback();
$this->sys_error_db("[Error] generate number supplier payment");
exit;
$this->sys_error_db('[Error] generate number supplier payment');
exit();
}
$rounding = 0;
@@ -43,7 +44,7 @@ class PaymentV2 extends MY_Controller
$rounding = round($sisa, 2);
}
# UPDATE header supplier payment #
// UPDATE header supplier payment #
$sql_updateheader = "UPDATE supplier_payment SET
SupplierPaymentIsConfirm = 'Y',
SupplierPaymentConfirmUserID = ?,
@@ -61,67 +62,259 @@ class PaymentV2 extends MY_Controller
$rounding,
$param['keterangan'],
$param['paymenttype'],
$param['orderid']
$param['orderid'],
]);
if (!$que_updateheader) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update supplier payment header");
exit;
$this->sys_error_db('[Error] update supplier payment header');
exit();
}
# UPDATE status lunas supplier invoice #
// UPDATE status lunas supplier invoice #
switch ($param['type']) {
case 'DP':
$sql_updatedp = "UPDATE supplier_downpayment
SET SupplierDownpaymentIsLunas = 'Y'
WHERE SupplierDownpaymentID = ?";
$que_updatedp = $this->db->query($sql_updatedp, [
abs($param['DownpaymentID']),
]);
if (!$que_updatedp) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] update status lunas downpayment');
exit();
}
break;
case 'INSTALLMENT':
$sql_updinstlment = "UPDATE supplier_installment
SET SupplierInstallmentIsLunas = 'Y'
WHERE SupplierInstallmentID = ?";
$que_updinstlment = $this->db->query($sql_updinstlment, [
$param['InstallmentID'],
]);
if (!$que_updinstlment) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] update status lunas installment');
exit();
}
$sql_updKontrak = "UPDATE purchase_order_asset_contract c
JOIN supplier_installment inst
ON inst.SupplierInstallmentPurchaseOrderID = c.PurchaseOrderAssetContractPurchaseOrderID
SET
c.PurchaseOrderAssetContractInstallmentPaid = c.PurchaseOrderAssetContractInstallmentPaid + 1,
c.PurchaseOrderAssetContractStatus = IF(
c.PurchaseOrderAssetContractInstallmentPaid + 1 >= c.PurchaseOrderAssetContractInstallmentNumber,
'lunas',
'belum lunas'
),
c.PurchaseOrderAssetContractLastUpdated = NOW()
WHERE inst.SupplierInstallmentID = ?
AND inst.SupplierInstallmentIsActive = 'Y'
AND c.PurchaseOrderAssetContractIsActive = 'Y'";
$que_updKontrak = $this->db->query($sql_updKontrak, [
$param['InstallmentID'],
]);
if (!$que_updKontrak) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] update kontrak cicilan');
exit();
}
break;
default:
$sql_suppinvoice = "UPDATE supplier_invoice
SET SupplierInvoiceIsLunas = 'Y'
WHERE SupplierInvoiceID = ?";
$que_suppinvoice = $this->db->query($sql_suppinvoice, [$param['SupplierInvoiceID']]);
$que_suppinvoice = $this->db->query($sql_suppinvoice, [
$param['SupplierInvoiceID'],
]);
if (!$que_suppinvoice) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update status lunas invoice");
exit;
$this->sys_error_db('[Error] update status lunas invoice');
exit();
}
break;
}
# GET Latest data supplier payment #
$sql_suppayment = "SELECT * FROM supplier_payment WHERE SupplierPaymentID = ?";
// GET Latest data supplier payment for logging #
$sql_suppayment = 'SELECT * FROM supplier_payment WHERE SupplierPaymentID = ?';
$que_suppayment = $this->db->query($sql_suppayment, [$param['orderid']]);
if (!$que_suppayment) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data latest supplier payment");
exit;
$this->sys_error_db('[Error] get data latest supplier payment');
exit();
}
$suppayment_header = $que_suppayment->row_array();
$suppayment_detail = [];
$sql_suppaymentdetail = "SELECT * FROM supplier_payment_detail
WHERE SupplierPaymentDetailSupplierPaymentID = ?";
switch ($param['type']) {
case 'DP':
$sql_suppaymentdetail = "SELECT supplier_downpayment.*
FROM supplier_payment
JOIN supplier_downpayment
ON SupplierPaymentSupplierDownpaymentID = SupplierDownpaymentID
AND SupplierDownpaymentIsActive = 'Y'
WHERE SupplierPaymentID = ?";
$que_suppaymentdetail = $this->db->query($sql_suppaymentdetail, [$param['orderid']]);
if (!$que_suppaymentdetail) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data latest supplier payment detail");
exit;
$this->sys_error_db('[Error] get data latest supplier downpayment');
exit();
}
$suppayment_detail = $que_suppaymentdetail->result_array();
break;
case 'INSTALLMENT':
$sql_suppaymentdetail = "SELECT
supplier_installment.*,
PurchaseOrderAssetContractInstallmentNumber AS qtyPay,
PurchaseOrderAssetContractInstallmentPaid AS qtyPaid
FROM supplier_payment
JOIN supplier_installment
ON SupplierInstallmentID = SupplierPaymentSupplierInstallmentID
AND SupplierInstallmentIsActive = 'Y'
JOIN purchase_order_asset_contract
ON PurchaseOrderAssetContractPurchaseOrderID = SupplierInstallmentPurchaseOrderID
AND PurchaseOrderAssetContractIsActive = 'Y'
WHERE SupplierPaymentID = ?";
$que_suppaymentdetail = $this->db->query($sql_suppaymentdetail, [$param['orderid']]);
if (!$que_suppaymentdetail) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] get data latest supplier installment');
exit();
}
$suppayment_detail = $que_suppaymentdetail->result_array();
break;
default:
$sql_suppaymentdetail = 'SELECT * FROM supplier_payment_detail
WHERE SupplierPaymentDetailSupplierPaymentID = ?';
$que_suppaymentdetail = $this->db->query($sql_suppaymentdetail, [$param['orderid']]);
if (!$que_suppaymentdetail) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] get data latest supplier payment detail');
exit();
}
$suppayment_detail = $que_suppaymentdetail->result_array();
break;
}
$data_log = [
"header" => $suppayment_header,
"detail" => $suppayment_detail
'header' => $suppayment_header,
'detail' => $suppayment_detail,
];
# LOG activity confirm payment #
// LOG activity confirm payment #
$messg = "Pembayaran Faktur No: {$suppayment_header['SupplierPaymentNumber']}";
$messg .= " telah dikonfirmasi oleh {$users['M_UserUsername']} dengan nomor";
$messg .= " pembayaran kasir: {$suppayment_header['SupplierPaymentCashierNumber']}";
$this->insert_activity_log(
"PF",
"CONFIRM",
$messg,
$param['orderid'],
$data_log,
$users['M_UserID']
);
$this->insert_activity_log('PF', 'CONFIRM', $messg, $param['orderid'], $data_log, $users['M_UserID']);
# INSERT JURNAL #
// INSERT JURNAL #
$detail_transac = [];
# GET data hutang #
switch ($param['type']) {
case 'DP':
$sql_coaDP = "SELECT
coaID,
coaDescription,
SupplierDownpaymentAmount,
M_ItemID,
SupplierPaymentNumber,
M_ItemID
FROM supplier_payment
JOIN supplier_downpayment
ON SupplierDownpaymentID = SupplierPaymentSupplierDownpaymentID
AND SupplierDownpaymentIsActive = 'Y'
JOIN purchase_order_detail
ON SupplierDownpaymentPurchasOrderID = PurchaseOrderDetailPurchaseOrderID
AND PurchaseOrderDetailIsActive = 'Y'
JOIN m_item
ON M_ItemID = PurchaseOrderDetailItemID
AND M_ItemIsActive = 'Y'
JOIN fa_class
ON Fa_ClassID = M_ItemFa_ClassID
AND M_ItemIsActive = 'Y'
JOIN coa
ON coaID = Fa_ClassDownPaymentCoaID
AND coaIsActive = 'Y'
WHERE SupplierPaymentID = ?";
$que_coaDP = $this->db->query($sql_coaDP, [
$param['orderid'],
]);
if (!$que_coaDP) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] get data hutang item dp');
exit();
}
$data_dp = $que_coaDP->result_array();
if (empty($data_dp)) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] no COA found for uang muka item');
exit();
}
foreach ($data_dp as $key => $dp) {
$detail_transac[] = [
'coaID' => $dp['coaID'],
'coaDescription' => $dp['coaDescription'],
'debit' => $dp['SupplierDownpaymentAmount'],
'credit' => 0,
'addoncode' => 'DP-JFA',
'addonvalue' => $dp['SupplierPaymentNumber'],
'addonitemid' => $dp['M_ItemID'],
];
}
break;
case 'INSTALLMENT':
$sql_datahutang = "SELECT
coaID,
coaDescription,
SupplierInstallmentAmount,
M_ItemID,
SupplierPaymentNumber,
M_ItemID
FROM supplier_payment
JOIN supplier_installment
ON SupplierInstallmentID = SupplierPaymentSupplierInstallmentID
AND SupplierInstallmentIsActive = 'Y'
JOIN purchase_order_detail
ON SupplierInstallmentPurchaseOrderID = PurchaseOrderDetailPurchaseOrderID
AND PurchaseOrderDetailIsActive = 'Y'
JOIN m_item
ON M_ItemID = PurchaseOrderDetailItemID
AND M_ItemIsActive = 'Y'
JOIN fa_class
ON Fa_ClassID = M_ItemFa_ClassID
AND M_ItemIsActive = 'Y'
JOIN coa
ON coaID = Fa_ClassHutangCoaID
AND coaIsActive = 'Y'
WHERE SupplierPaymentID = ?";
$que_datahutang = $this->db->query($sql_datahutang, [
$param['orderid'],
]);
if (!$que_datahutang) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] get data hutang item cicilan');
exit();
}
$data_cicil = $que_datahutang->result_array();
if (empty($data_cicil)) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] no COA found for installment item');
exit();
}
foreach ($data_cicil as $key => $cicil) {
$detail_transac[] = [
'coaID' => $cicil['coaID'],
'coaDescription' => $cicil['coaDescription'],
'debit' => $cicil['SupplierInstallmentAmount'],
'credit' => 0,
'addoncode' => 'INST-JFA',
'addonvalue' => $cicil['SupplierPaymentNumber'],
'addonitemid' => $cicil['M_ItemID'],
];
}
break;
default:
// GET data hutang #
$sql_datahutang = "SELECT
SupplierPaymentNumber AS addonvalue,
SupplierPaymentDetailID,
@@ -130,32 +323,43 @@ class PaymentV2 extends MY_Controller
SupplierPaymentDetailAmount,
SupplierInvoiceDetailItemID
FROM supplier_payment
JOIN supplier_payment_detail ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
JOIN supplier_invoice_detail ON SupplierInvoiceDetailSupplierInvoiceID = SupplierPaymentSupplierInvoiceID
JOIN supplier_payment_detail
ON SupplierPaymentDetailSupplierPaymentID = SupplierPaymentID
JOIN supplier_invoice_detail
ON SupplierInvoiceDetailSupplierInvoiceID = SupplierPaymentSupplierInvoiceID
AND SupplierInvoiceDetailIsActive = 'Y'
JOIN jurnal_tx ON SupplierPaymentDetailSupplierInvoiceDetailID = jurnalTxID
JOIN jurnal_tx
ON SupplierPaymentDetailSupplierInvoiceDetailID = jurnalTxID
AND jurnalTxIsActive = 'Y'
WHERE SupplierPaymentID = ?
AND SupplierPaymentDetailIsActive = 'Y'";
$que_datahutang = $this->db->query($sql_datahutang, [$param['orderid']]);
if (!$que_datahutang) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data hutang item");
exit;
$this->sys_error_db('[Error] get data hutang item');
exit();
}
$data_hutang = $que_datahutang->result_array();
if (empty($data_hutang)) {
$this->db->trans_rollback();
$this->sys_error_db('[Error] no COA found for hutang item');
exit();
}
foreach ($data_hutang as $key => $debt) {
$detail_transac[] = [
"coaID" => $debt['coaID'],
"coaDescription" => $debt['coaDescription'],
"debit" => $debt['SupplierPaymentDetailAmount'],
"credit" => 0,
"addoncode" => "JFA",
"addonvalue" => $debt['addonvalue'],
"addonitemid" => $debt['SupplierInvoiceDetailItemID']
'coaID' => $debt['coaID'],
'coaDescription' => $debt['coaDescription'],
'debit' => $debt['SupplierPaymentDetailAmount'],
'credit' => 0,
'addoncode' => 'JFA',
'addonvalue' => $debt['addonvalue'],
'addonitemid' => $debt['SupplierInvoiceDetailItemID'],
];
}
break;
}
# GET data bayar #
// GET data bayar #
$sql_databayar = "SELECT
CONCAT('Jurnal Payment Invoice Nomor : ',
SupplierPaymentNumber, DATE_FORMAT(now(),
@@ -179,68 +383,86 @@ class PaymentV2 extends MY_Controller
$que_databayar = $this->db->query($sql_databayar, [$param['orderid']]);
if (!$que_databayar) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data bayar");
exit;
$this->sys_error_db('[Error] get data bayar');
exit();
}
$data_bayar = $que_databayar->row_array();
$detail_transac[] = [
"coaID" => $data_bayar['coaID'],
"coaDescription" => $data_bayar['coaDescription'],
"debit" => 0,
"credit" => abs($data_bayar['bayar']),
"addoncode" => "PAYINVSG",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $data_bayar['coaID'],
'coaDescription' => $data_bayar['coaDescription'],
'debit' => 0,
'credit' => abs($data_bayar['bayar']),
'addoncode' => 'PAYINVSG',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
# rugi / untung dari rounding #
// rugi / untung dari rounding #
$sql_lossprofit = "SELECT coaID, coaDescription
FROM coa WHERE coaAccountNo = ? AND coaIsActive = 'Y'";
$data_round = doubleval($data_bayar['rounding']);
if ($data_round > 0) {
# loss #
// loss #
$que_lossprofit = $this->db->query($sql_lossprofit, ['6120402001']);
if (!$que_lossprofit) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data coa loss sisa kas");
exit;
$this->sys_error_db('[Error] get data coa loss sisa kas');
exit();
}
$loss_coa = $que_lossprofit->row_array();
$detail_transac[] = [
"coaID" => $loss_coa['coaID'],
"coaDescription" => $loss_coa['coaDescription'],
"debit" => abs($data_round),
"credit" => 0,
"addoncode" => "PAYINVSG",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $loss_coa['coaID'],
'coaDescription' => $loss_coa['coaDescription'],
'debit' => abs($data_round),
'credit' => 0,
'addoncode' => 'PAYINVSG',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
} elseif ($data_round < 0) {
# profit #
// profit #
$que_lossprofit = $this->db->query($sql_lossprofit, ['6110500001']);
if (!$que_lossprofit) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data coa profit sisa kas");
exit;
$this->sys_error_db('[Error] get data coa profit sisa kas');
exit();
}
$profit_coa = $que_lossprofit->row_array();
$detail_transac[] = [
"coaID" => $profit_coa['coaID'],
"coaDescription" => $profit_coa['coaDescription'],
"debit" => 0,
"credit" => abs($data_round),
"addoncode" => "PAYINVSG",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $profit_coa['coaID'],
'coaDescription' => $profit_coa['coaDescription'],
'debit' => 0,
'credit' => abs($data_round),
'addoncode' => 'PAYINVSG',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
}
// "PI Cicilan Aset - {$invoiceNumber}";
$description = '';
// "Jurnal cicilan ke-{$cicilanKe} dari {$totalCicilan} | {$namaKontrak} | PO: {$nomorPO} | Periode {$periode}";
switch ($param['type']) {
case 'DP':
$data_bayar['jurnaltitle'] .= " | Pembayaran Uang Muka Aset - {$param['dpkode']}";
break;
case 'INSTALLMENT':
$cicil = $suppayment_detail[0];
$data_bayar['jurnaltitle'] .= " | Pembayaran Cicilan Aset - {$param['installmentkode']}";
$data_bayar['jurnaldesc'] .= " | Jurnal cicilan ke-{$cicil['qtyPaid']} dari {$cicil['qtyPay']}";
break;
default:
// code
break;
}
$this->insertJurnal($users, $data_bayar, $detail_transac);
$this->db->trans_commit();
$this->sys_ok("success update v2 test");
$this->sys_ok('success update v2 test');
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
@@ -251,22 +473,22 @@ class PaymentV2 extends MY_Controller
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
$this->sys_error('Invalid Token');
exit();
}
$this->db->trans_begin();
$param = $this->sys_input;
$users = $this->sys_user;
# Generate number supplier payment #
$sql_gennumber = "SELECT `fn_numbering`(?) as numberx";
// Generate number supplier payment #
$sql_gennumber = 'SELECT `fn_numbering`(?) as numberx';
$paygroupnum = $this->db->query($sql_gennumber, ['PC'])->row()->numberx;
if ($paygroupnum == '') {
$this->db->trans_rollback();
$this->sys_error_db("[Error] generate number group supplier payment");
exit;
$this->sys_error_db('[Error] generate number group supplier payment');
exit();
}
$rounding = 0;
@@ -275,27 +497,26 @@ class PaymentV2 extends MY_Controller
$rounding = round($sisa, 2);
}
$lastIndex = count($param['details']) - 1;
# LOOP details invoice payment #
// LOOP details invoice payment #
foreach ($param['details'] as $idx => $obj) {
$paynumber = $this->db->query($sql_gennumber, ['PN'])->row()->numberx;
if ($paynumber == '') {
$this->db->trans_rollback();
$this->sys_error_db("[Error] generate number kasir supplier payment");
exit;
$this->sys_error_db('[Error] generate number kasir supplier payment');
exit();
}
$SupplierPaymentID = $obj['SupplierPaymentID'];
$SupplierInvoiceID = $obj['SupplierInvoiceID'];
# CEK index invoice terakhir #
// CEK index invoice terakhir #
$roundvalue = 0;
if ($idx == $lastIndex) {
$roundvalue = $rounding;
}
# UPDATE header supplier payment #
// UPDATE header supplier payment #
$sql_updateheader = "UPDATE supplier_payment SET
SupplierPaymentIsConfirm = 'Y',
SupplierPaymentConfirmUserID = ?,
@@ -313,67 +534,60 @@ class PaymentV2 extends MY_Controller
$roundvalue,
$param['keterangan'],
$param['paymenttype'],
$SupplierPaymentID
$SupplierPaymentID,
]);
if (!$que_updateheader) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update supplier payment header");
exit;
$this->sys_error_db('[Error] update supplier payment header');
exit();
}
# UPDATE status lunas supplier invoice #
// UPDATE status lunas supplier invoice #
$sql_suppinvoice = "UPDATE supplier_invoice
SET SupplierInvoiceIsLunas = 'Y'
WHERE SupplierInvoiceID = ?";
$que_suppinvoice = $this->db->query($sql_suppinvoice, [$SupplierInvoiceID]);
if (!$que_suppinvoice) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update status lunas invoice");
exit;
$this->sys_error_db('[Error] update status lunas invoice');
exit();
}
# GET Latest data supplier payment #
$sql_suppayment = "SELECT * FROM supplier_payment WHERE SupplierPaymentID = ?";
// GET Latest data supplier payment #
$sql_suppayment = 'SELECT * FROM supplier_payment WHERE SupplierPaymentID = ?';
$que_suppayment = $this->db->query($sql_suppayment, [$SupplierPaymentID]);
if (!$que_suppayment) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data latest supplier payment");
exit;
$this->sys_error_db('[Error] get data latest supplier payment');
exit();
}
$suppayment_header = $que_suppayment->row_array();
$sql_suppaymentdetail = "SELECT * FROM supplier_payment_detail
WHERE SupplierPaymentDetailSupplierPaymentID = ?";
$sql_suppaymentdetail = 'SELECT * FROM supplier_payment_detail
WHERE SupplierPaymentDetailSupplierPaymentID = ?';
$que_suppaymentdetail = $this->db->query($sql_suppaymentdetail, [$SupplierPaymentID]);
if (!$que_suppaymentdetail) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data latest supplier payment detail");
exit;
$this->sys_error_db('[Error] get data latest supplier payment detail');
exit();
}
$suppayment_detail = $que_suppaymentdetail->result_array();
$data_log = [
"header" => $suppayment_header,
"detail" => $suppayment_detail
'header' => $suppayment_header,
'detail' => $suppayment_detail,
];
# LOG activity confirm payment #
// LOG activity confirm payment #
$messg = "Pembayaran Faktur No: {$suppayment_header['SupplierPaymentNumber']}";
$messg .= " telah dikonfirmasi oleh {$users['M_UserUsername']} dengan nomor";
$messg .= " pembayaran kasir: {$suppayment_header['SupplierPaymentCashierNumber']}";
$this->insert_activity_log(
"PF",
"CONFIRM",
$messg,
$SupplierPaymentID,
$data_log,
$users['M_UserID']
);
$this->insert_activity_log('PF', 'CONFIRM', $messg, $SupplierPaymentID, $data_log, $users['M_UserID']);
## INSERT jurnal ##
// # INSERT jurnal ##
$detail_transac = [];
# GET data hutang #
// GET data hutang #
$sql_datahutang = "SELECT
SupplierPaymentNumber AS addonvalue,
SupplierPaymentDetailID,
@@ -391,23 +605,23 @@ class PaymentV2 extends MY_Controller
$que_datahutang = $this->db->query($sql_datahutang, [$SupplierPaymentID]);
if (!$que_datahutang) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data hutang item");
exit;
$this->sys_error_db('[Error] get data hutang item');
exit();
}
$data_hutang = $que_datahutang->result_array();
foreach ($data_hutang as $key => $debt) {
$detail_transac[] = [
"coaID" => $debt['coaID'],
"coaDescription" => $debt['coaDescription'],
"debit" => $debt['SupplierPaymentDetailAmount'],
"credit" => 0,
"addoncode" => "JFA",
"addonvalue" => $debt['addonvalue'],
"addonitemid" => $debt['SupplierInvoiceDetailItemID']
'coaID' => $debt['coaID'],
'coaDescription' => $debt['coaDescription'],
'debit' => $debt['SupplierPaymentDetailAmount'],
'credit' => 0,
'addoncode' => 'JFA',
'addonvalue' => $debt['addonvalue'],
'addonitemid' => $debt['SupplierInvoiceDetailItemID'],
];
}
# GET data bayar #
// GET data bayar #
$sql_databayar = "SELECT
CONCAT('Jurnal Payment Invoice Nomor : ',
SupplierPaymentNumber, DATE_FORMAT(now(),
@@ -431,61 +645,61 @@ class PaymentV2 extends MY_Controller
$que_databayar = $this->db->query($sql_databayar, [$SupplierPaymentID]);
if (!$que_databayar) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data bayar");
exit;
$this->sys_error_db('[Error] get data bayar');
exit();
}
$data_bayar = $que_databayar->row_array();
$detail_transac[] = [
"coaID" => $data_bayar['coaID'],
"coaDescription" => $data_bayar['coaDescription'],
"debit" => 0,
"credit" => abs($data_bayar['bayar']),
"addoncode" => "PAYINVGR",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $data_bayar['coaID'],
'coaDescription' => $data_bayar['coaDescription'],
'debit' => 0,
'credit' => abs($data_bayar['bayar']),
'addoncode' => 'PAYINVGR',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
# rugi / untung dari rounding #
// rugi / untung dari rounding #
$sql_lossprofit = "SELECT coaID, coaDescription
FROM coa WHERE coaAccountNo = ? AND coaIsActive = 'Y'";
$data_round = doubleval($data_bayar['rounding']);
if ($data_round > 0) {
# loss #
// loss #
$que_lossprofit = $this->db->query($sql_lossprofit, ['6120402001']);
if (!$que_lossprofit) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data coa loss sisa kas");
exit;
$this->sys_error_db('[Error] get data coa loss sisa kas');
exit();
}
$loss_coa = $que_lossprofit->row_array();
$detail_transac[] = [
"coaID" => $loss_coa['coaID'],
"coaDescription" => $loss_coa['coaDescription'],
"debit" => abs($data_round),
"credit" => 0,
"addoncode" => "PAYINVGR",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $loss_coa['coaID'],
'coaDescription' => $loss_coa['coaDescription'],
'debit' => abs($data_round),
'credit' => 0,
'addoncode' => 'PAYINVGR',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
} elseif ($data_round < 0) {
# profit #
// profit #
$que_lossprofit = $this->db->query($sql_lossprofit, ['6110500001']);
if (!$que_lossprofit) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get data coa profit sisa kas");
exit;
$this->sys_error_db('[Error] get data coa profit sisa kas');
exit();
}
$profit_coa = $que_lossprofit->row_array();
$detail_transac[] = [
"coaID" => $profit_coa['coaID'],
"coaDescription" => $profit_coa['coaDescription'],
"debit" => 0,
"credit" => abs($data_round),
"addoncode" => "PAYINVGR",
"addonvalue" => $data_bayar['addonvalue'],
"addonitemid" => 0
'coaID' => $profit_coa['coaID'],
'coaDescription' => $profit_coa['coaDescription'],
'debit' => 0,
'credit' => abs($data_round),
'addoncode' => 'PAYINVGR',
'addonvalue' => $data_bayar['addonvalue'],
'addonitemid' => 0,
];
}
@@ -493,7 +707,7 @@ class PaymentV2 extends MY_Controller
}
$this->db->trans_commit();
$this->sys_ok("[Success] success multi payment invoice");
$this->sys_ok('[Success] success multi payment invoice');
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
@@ -502,49 +716,49 @@ class PaymentV2 extends MY_Controller
private function insertJurnal($users, $databayar, $detailtrx)
{
# GET periode jurnal #
// GET periode jurnal #
$sql_periode = "SELECT periodeID FROM periode
WHERE DATE(NOW()) BETWEEN periodeStartDate AND periodeEndDate
AND periodeIsActive = 'Y' AND periodeIsClosed = 'N'";
$que_periode = $this->db->query($sql_periode, []);
if (!$que_periode) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] find periode id");
exit;
$this->sys_error_db('[Error] find periode id');
exit();
}
if ($que_periode->num_rows() === 0) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] Waktu periode tidak ditemukan");
exit;
$this->sys_error_db('[Error] Waktu periode tidak ditemukan');
exit();
}
$JurnalPeriode = $que_periode->row_array()['periodeID'];
# GENERATE nomor jurnal #
// GENERATE nomor jurnal #
$sql_jurnalno = "SELECT `fn_numbering`('J') AS jnumber";
$que_jurnalno = $this->db->query($sql_jurnalno, []);
if (!$que_jurnalno) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] generate jurnal number");
exit;
$this->sys_error_db('[Error] generate jurnal number');
exit();
}
$JurnalNumber = $que_jurnalno->row_array()['jnumber'];
$JurnalTitle = $databayar['jurnaltitle'];
$JurnalDescp = $databayar['jurnaldesc'];
# GET jurnal type #
// GET jurnal type #
$sql_jurnaltype = "SELECT JurnalTypeID FROM jurnal_type
WHERE JurnalTypeCode = 'PAYMENTINV' AND JurnalTypeIsActive = 'Y'";
$que_jurnaltype = $this->db->query($sql_jurnaltype, []);
if (!$que_jurnaltype) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get jurnal type");
exit;
$this->sys_error_db('[Error] get jurnal type');
exit();
}
$JurnalType = $que_jurnaltype->row_array()['JurnalTypeID'];
# INSERT jurnal header #
$sql_insheader = "INSERT INTO jurnal (
// INSERT jurnal header #
$sql_insheader = 'INSERT INTO jurnal (
jurnalM_BranchCompanyID,
JurnalS_RegionalID,
jurnalM_BranchCode,
@@ -555,7 +769,7 @@ class PaymentV2 extends MY_Controller
jurnalDate,
jurnalJurnalTypeID,
jurnalM_UserID
) VALUES (?,?,?,?,?,?,?,NOW(),?,?)";
) VALUES (?,?,?,?,?,?,?,NOW(),?,?)';
$que_inserjurnal = $this->db->query($sql_insheader, [
$users['M_BranchCompanyID'],
$users['S_RegionalID'],
@@ -565,42 +779,42 @@ class PaymentV2 extends MY_Controller
$JurnalTitle,
$JurnalDescp,
$JurnalType,
$users['M_UserID']
$users['M_UserID'],
]);
if (!$que_inserjurnal) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert jurnal header");
exit;
$this->sys_error_db('[Error] insert jurnal header');
exit();
}
$JurnalID = $this->db->insert_id();
# INSERT jurnal tx #
// INSERT jurnal tx #
foreach ($detailtrx as $key => $trax) {
$sql_trax = "INSERT INTO jurnal_tx (
$sql_trax = 'INSERT INTO jurnal_tx (
jurnalTxJurnalID,
jurnalTxCoaID,
jurnalTxDescription,
jurnalTxDebit,
jurnalTxCredit,
jurnalTxM_UserID
) VALUES (?,?,?,?,?,?)";
) VALUES (?,?,?,?,?,?)';
$que_trax = $this->db->query($sql_trax, [
$JurnalID,
$trax['coaID'],
$trax['coaDescription'],
$trax['debit'],
$trax['credit'],
$users['M_UserID']
$users['M_UserID'],
]);
if (!$que_trax) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert jurnal tx");
exit;
$this->sys_error_db('[Error] insert jurnal tx');
exit();
}
$JurnalTxID = $this->db->insert_id();
# INSERT jurnal addon #
$sql_addon = "INSERT INTO jurnal_addon (
// INSERT jurnal addon #
$sql_addon = 'INSERT INTO jurnal_addon (
jurnalAddOnJurnalID,
jurnalAddOnJurnalTxID,
jurnalAddOnCode,
@@ -608,19 +822,19 @@ class PaymentV2 extends MY_Controller
jurnalAddOnM_ItemID,
jurnalAddOnCreated,
jurnalAddOnCreatedUserID
) VALUES (?,?,?,?,?,NOW(),?)";
) VALUES (?,?,?,?,?,NOW(),?)';
$que_addon = $this->db->query($sql_addon, [
$JurnalID,
$JurnalTxID,
$trax['addoncode'],
$trax['addonvalue'],
$trax['addonitemid'],
$users['M_UserID']
$users['M_UserID'],
]);
if (!$que_addon) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert jurnal addon");
exit;
$this->sys_error_db('[Error] insert jurnal addon');
exit();
}
}
}
@@ -630,11 +844,11 @@ class PaymentV2 extends MY_Controller
$json = json_encode($data);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->db->trans_rollback();
$this->sys_error("[Error] encode data into json for log activity");
exit;
$this->sys_error('[Error] encode data into json for log activity');
exit();
}
$sql = "INSERT INTO user_activity(
$sql = 'INSERT INTO user_activity(
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
@@ -642,19 +856,19 @@ class PaymentV2 extends MY_Controller
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES (?,?,?,?,?,?,NOW())";
) VALUES (?,?,?,?,?,?,NOW())';
$que = $this->db->query($sql, [
$actcode,
$status,
$desc,
$refID,
$json,
$userID
$userID,
]);
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert into table log activity");
exit;
$this->sys_error_db('[Error] insert into table log activity');
exit();
}
}
}

View File

@@ -6,13 +6,15 @@ class Bill extends MY_Controller
{
echo "Bill API";
}
public function __construct()
{
parent::__construct();
$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,
SupplierPaymentDetailSupplierInvoiceDetailID as detail_id,
@@ -54,14 +56,144 @@ class Bill extends MY_Controller
}
}
return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev);
exit;
}
}
public function add_tagihans($orderid){
$sql = "SELECT SupplierInvoiceID as tagihan_id,
public function add_notes_downpayment($orderid)
{
$sql = "SELECT SupplierPaymentSupplierDownpaymentID AS note_order_id,
SupplierPaymentID AS note_id,
SupplierDownpaymentID AS detail_id,
SupplierPaymentDate AS note_date,
SupplierPaymentNumber AS note_number,
GROUP_CONCAT(DISTINCT coaDescription separator ' , ') AS paymenttypes_name,
SUM(SupplierDownpaymentAmount) AS note_amount,
n.M_UserUsername AS note_user,
SupplierDownpaymentIsActive 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_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,
@@ -72,30 +204,42 @@ class Bill extends MY_Controller
'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
JOIN jurnal_tx ON jurnalTxJurnalID = jurnalAddOnJurnalID AND jurnalTxCredit <> 0 AND jurnalTxCoaID <> 563
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 = {$orderid}
GROUP BY jurnalTxID
";
$query = $this->db_onedev->query($sql);
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 notes", $this->db_onedev);
$this->sys_error_db("get tagihans", $this->db_onedev);
exit;
}
}
public function add_tests($orderid){
public function add_tests($orderid)
{
$sql = " SELECT SupplierPaymentSupplierInvoiceID as note_order_id,
SupplierPaymentID as note_id,
SupplierPaymentDate as note_date,
@@ -122,19 +266,20 @@ class Bill extends MY_Controller
if ($rows) {
}
return $rows;
} else {
$this->sys_error_db("get notes", $this->db_onedev);
exit;
}
}
public function search()
public function search_old()
{
//# cek token valid
if (! $this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$supplier = $prm["supplier"];
$search = $prm["search"];
@@ -243,7 +388,6 @@ class Bill extends MY_Controller
$rows[$k]['notes'] = $this->add_notes($v['SupplierInvoiceID']);
$rows[$k]['tagihans'] = $this->add_tagihans($v['SupplierInvoiceID']);
}
}
@@ -253,5 +397,392 @@ class Bill extends MY_Controller
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