Files
be-accone/application/controllers/mockup/purchase/listing/PurchaseRequestListing.php

644 lines
26 KiB
PHP

<?php
class PurchaseRequestListing extends MY_Controller
{
var $db;
public function index()
{
echo "LISTING PURCHASE REQUEST";
}
public function __construct()
{
parent::__construct();
}
public function list_purchaserequest_old19Juni2025()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$para = $this->sys_input;
$startdate = $para["startdate"];
$enddate = $para["enddate"];
$regional = $para["regional"];
$branch = $para['branch'];
$cabang = "";
if ($branch == "ALL" || $branch == "") {
$cabang = "%%";
} else {
$cabang = "%" . $branch . "%";
}
$f_stat = [];
$status = $para["status"];
switch ($status) {
case 'READ':
$f_stat = ["Read", "X"];
break;
case 'NEW':
$f_stat = ["Approved", "X"];
break;
default:
$f_stat = ["Approved", "Read"];
break;
}
$currpage = $para["currpage"];
$page = 0;
$limit = 10;
if ($currpage > 0) {
$page = ($currpage - 1) * $limit;
}
$sqltotal = "SELECT COUNT(DISTINCT PurchaseRequestDetailID) as total
FROM purchase_request
JOIN purchase_request_detail ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID
AND S_RegionalIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemIsActive = 'Y'
LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
AND M_BranchIsActive = 'Y'
LEFT JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID
AND WarehouseIsActive = 'Y'
AND (WarehouseIsTransit != 'Y' OR WarehouseIsTransit IS NULL)
LEFT JOIN stock ON StockItemId = M_ItemID
AND StockWarehouseID = warehouse.WarehouseID
LEFT JOIN purchase_request_flag ON PurchaseRequestFlagPurchaseRequestDetailID = PurchaseRequestDetailID
AND PurchaseRequestFlagIsActive = 'Y'
AND PurchaseRequestFlagIsClosed = 'N'
WHERE PurchaseRequestDetailStatus IN (?,?)
AND PurchaseRequestDate >= DATE(?)
AND PurchaseRequestDate <= DATE(?)
AND PurchaseRequestS_RegionalID = ?
AND (? = '%%' OR
(PurchaseRequestM_BranchCode LIKE ? OR
(PurchaseRequestM_BranchCode IS NULL AND
? = '%%')))
-- GROUP BY PurchaseRequestDetailID
ORDER BY
PurchaseRequestDetailStatus ASC,
PurchaseRequestDetailID DESC,
PurchaseRequestDate DESC,
PurchaseRequestFlagID DESC
";
$qrytot = $this->db->query($sqltotal, [
$f_stat[0],
$f_stat[1],
$startdate,
$enddate,
$regional,
$cabang,
$cabang,
$cabang
]);
$total = $qrytot->result_array()[0]['total'];
$sqldata = "SELECT
COALESCE(PurchaseRequestFlagID, 'new') as PurchaseRequestFlagID,
PurchaseRequestDate, PurchaseRequestNumber,
S_RegionalID, S_RegionalName,
COALESCE(M_BranchCode, '') AS M_BranchCode,
COALESCE(M_BranchName, '') AS M_BranchName,
PurchaseRequestDetailID, M_ItemID,
PurchaseRequestDetailIsCito,
M_ItemDesc, PurchaseRequestDetailQty,
COALESCE(SUM(CASE WHEN warehouse.WarehouseID IS NOT NULL AND stock.StockItemId IS NOT NULL THEN stock.StockQty ELSE 0 END), 0) as StockQty,
COALESCE(warehouse.WarehouseID, '') as StockWarehouseID,
PurchaseRequestDetailStatus,
COALESCE(PurchaseRequestFlagStatus, '') as PurchaseRequestFlagStatus
FROM purchase_request
JOIN purchase_request_detail ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID
AND S_RegionalIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemIsActive = 'Y'
LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
AND M_BranchIsActive = 'Y'
LEFT JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID
AND WarehouseIsActive = 'Y'
AND (WarehouseIsTransit != 'Y' OR WarehouseIsTransit IS NULL)
LEFT JOIN stock ON StockItemId = M_ItemID
AND StockWarehouseID = warehouse.WarehouseID
LEFT JOIN purchase_request_flag ON PurchaseRequestFlagPurchaseRequestDetailID = PurchaseRequestDetailID
AND PurchaseRequestFlagIsActive = 'Y'
AND PurchaseRequestFlagIsClosed = 'N'
WHERE PurchaseRequestDetailStatus IN (?,?)
AND PurchaseRequestDate >= DATE(?)
AND PurchaseRequestDate <= DATE(?)
AND PurchaseRequestS_RegionalID = ?
AND (? = '%%' OR
(PurchaseRequestM_BranchCode LIKE ? OR
(PurchaseRequestM_BranchCode IS NULL AND
? = '%%')))
GROUP BY PurchaseRequestDetailID
ORDER BY PurchaseRequestDetailStatus ASC,
PurchaseRequestDetailID DESC,
PurchaseRequestDate DESC,
PurchaseRequestFlagID DESC
LIMIT ? OFFSET ?";
$qrydata = $this->db->query($sqldata, [
$f_stat[0],
$f_stat[1],
$startdate,
$enddate,
$regional,
$cabang,
$cabang,
$cabang,
$limit,
$page
]);
$data = $qrydata->result_array();
$result = array(
"records" => $data,
"total" => $total
);
$this->sys_ok($result);
} catch (Exception $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
/**
* Refactor 18 Juni 2025 by Mario
* Whats new:
* > Perhitungan stok mempertimbangkan:
* > - Stock hanya diambil dari gudang regional
* > - Stock hanya diambil dari gudang default (untuk handle kasus jakarta ada 2 gudang regional)
* > - Mempertimbangkan unitItem sebelum menjumlahkan kuantitas stok karena ada PR dengan unit berbeda
* > - Menghitung stok dengan subquery daripada join
* > - Memperhatikan StockED untuk ItemCategoryID == 1 (Persediaan), jika ItemID dan ItemUnitID sama maka jumlah semua stok dari Gudang Regional selama StockED >= hari ini
*/
public function list_purchaserequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$para = $this->sys_input;
$startdate = $para["startdate"];
$enddate = $para["enddate"];
$regional = $para["regional"];
$branch = $para['branch'];
$cabang = "";
if ($branch == "ALL" || $branch == "") {
$cabang = "%%";
} else {
$cabang = "%" . $branch . "%";
}
$f_stat = [];
$status = $para["status"];
switch ($status) {
case 'READ':
$f_stat = ["Read", "X"];
break;
case 'NEW':
$f_stat = ["Approved", "X"];
break;
default:
$f_stat = ["Approved", "Read"];
break;
}
$currpage = $para["currpage"];
$page = 0;
$limit = 10;
if ($currpage > 0) {
$page = ($currpage - 1) * $limit;
}
$sqltotal = "SELECT COUNT(DISTINCT PurchaseRequestDetailID) as total
FROM purchase_request_detail
JOIN purchase_request ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID
AND S_RegionalIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemIsActive = 'Y'
LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
AND M_BranchIsActive = 'Y'
LEFT JOIN itemunit unit_req ON unit_req.ItemUnitID = PurchaseRequestDetailItemUnitID
AND unit_req.ItemUnitIsActive = 'Y'
LEFT JOIN purchase_request_flag ON PurchaseRequestFlagPurchaseRequestDetailID = PurchaseRequestDetailID
AND PurchaseRequestFlagIsActive = 'Y'
AND PurchaseRequestFlagIsClosed = 'N'
WHERE PurchaseRequestDetailStatus IN (?,?)
AND PurchaseRequestDate >= DATE(?)
AND PurchaseRequestDate <= DATE(?)
AND PurchaseRequestS_RegionalID = ?
AND (? = '%%' OR
(PurchaseRequestM_BranchCode LIKE ? OR
(PurchaseRequestM_BranchCode IS NULL AND
? = '%%')))";
$qrytot = $this->db->query($sqltotal, [
$f_stat[0],
$f_stat[1],
$startdate,
$enddate,
$regional,
$cabang,
$cabang,
$cabang
]);
$total = $qrytot->result_array()[0]['total'];
$sqldata = "SELECT
COALESCE(PurchaseRequestFlagID, 'new') as PurchaseRequestFlagID,
PurchaseRequestDate, PurchaseRequestNumber,
S_RegionalID, S_RegionalName,
COALESCE(M_BranchCode, '') AS M_BranchCode,
COALESCE(M_BranchName, '') AS M_BranchName,
PurchaseRequestDetailID, M_ItemID,
PurchaseRequestDetailIsCito,
M_ItemDesc, PurchaseRequestDetailQty,
unit_req.ItemUnitName AS UnitRequest,
unit_req.ItemUnitID AS UnitIDRequest,
PurchaseRequestDetailStatus,
COALESCE(PurchaseRequestFlagStatus, '') as PurchaseRequestFlagStatus
FROM purchase_request_detail
JOIN purchase_request ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID
AND S_RegionalIsActive = 'Y'
LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
AND M_BranchIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemIsActive = 'Y'
JOIN itemunit unit_req ON unit_req.ItemUnitID = PurchaseRequestDetailItemUnitID
AND unit_req.ItemUnitIsActive = 'Y'
LEFT JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID
AND WarehouseIsActive = 'Y'
AND (WarehouseIsTransit != 'Y' OR WarehouseIsTransit IS NULL)
AND WarehouseM_BranchID = 0
AND WarehouseIsDefault = 'Y'
LEFT JOIN purchase_request_flag ON PurchaseRequestFlagPurchaseRequestDetailID = PurchaseRequestDetailID
AND PurchaseRequestFlagIsActive = 'Y'
AND PurchaseRequestFlagIsClosed = 'N'
WHERE PurchaseRequestDetailStatus IN (?,?)
AND PurchaseRequestDate >= DATE(?)
AND PurchaseRequestDate <= DATE(?)
AND PurchaseRequestS_RegionalID = ?
AND (? = '%%' OR
(PurchaseRequestM_BranchCode LIKE ? OR
(PurchaseRequestM_BranchCode IS NULL AND
? = '%%')))
ORDER BY PurchaseRequestDetailStatus ASC,
PurchaseRequestDetailID DESC,
PurchaseRequestDate DESC,
PurchaseRequestFlagID DESC
LIMIT ? OFFSET ?";
$qrydata = $this->db->query($sqldata, [
$f_stat[0],
$f_stat[1],
$startdate,
$enddate,
$regional,
$cabang,
$cabang,
$cabang,
$limit,
$page
]);
if (!$qrydata) {
throw new Exception(json_encode($this->db->error()));
}
// TODO: Hapus Last Query jika tidak diperlukan
// $lastQuery = $this->db->last_query();
$data = $qrydata->result_array();
// For each PR Detail, fetch the stock data across all units
foreach ($data as &$row) {
$stockSql = "SELECT
SUM(s.StockQty) as QtyTotal,
u.ItemUnitName,
s.StockItemUnitID
FROM stock s
JOIN warehouse w ON s.StockWarehouseID = w.WarehouseID
JOIN itemunit u ON s.StockItemUnitID = u.ItemUnitID
WHERE s.StockItemId = ?
AND w.WarehouseS_RegionalID = ?
AND w.WarehouseIsActive = 'Y'
AND (w.WarehouseIsTransit != 'Y' OR w.WarehouseIsTransit IS NULL)
AND w.WarehouseM_BranchID = 0
AND w.WarehouseIsDefault = 'Y'
AND (
? != 1
OR (? = 1 AND (s.StockED IS NULL OR s.StockED >= CURDATE()))
)
GROUP BY s.StockItemUnitID, u.ItemUnitName";
$stockQry = $this->db->query($stockSql, [
$row['M_ItemID'],
$row['S_RegionalID'],
$row['PurchaseRequestItemCategoryID'] ?? 0,
$row['PurchaseRequestItemCategoryID'] ?? 0
]);
if (!$stockQry) {
throw new Exception(json_encode($this->db->error()));
}
// Kalau item belum ada di stock, returnnya []
$row['StockQtyArray'] = $stockQry->result_array();
}
$result = array(
"records" => $data,
// "lastQuery" => $lastQuery,
"total" => $total
);
$this->sys_ok($result);
} catch (Exception $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
public function listing_regional()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$prm = $this->sys_input;
$search = "%" . $prm['search'] . "%";
$sql = "SELECT S_RegionalID, S_RegionalName
FROM s_regional WHERE S_RegionalIsActive = 'Y' AND S_RegionalName LIKE ?";
$query = $this->db->query($sql, [$search]);
if (!$query) {
$this->sys_error_db("error get listing regional");
exit;
}
$rows = $query->result_array();
$result = array(
"records" => $rows,
"total" => sizeof($rows)
);
$this->sys_ok($result);
} catch (Exception $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
public function listing_branch()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$prm = $this->sys_input;
$regID = $prm['regionalID'];
$sql = "SELECT
M_BranchCode,
M_BranchName
FROM m_branch
WHERE M_BranchS_RegionalID = ? AND M_BranchIsActive = 'Y'";
$query = $this->db->query($sql, [$regID]);
if (!$query) {
$this->sys_error_db("error get branch based on regional");
exit;
}
$rows = $query->result_array();
$result = array(
"result" => $rows,
"total" => sizeof($rows)
);
$this->sys_ok($result);
} catch (Exception $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
public function insertstatus()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$userid = $this->sys_user["M_UserID"];
$prm = $this->sys_input;
$reqnumber = $prm['reqnumber'];
$reqdetailid = $prm['reqdetailid'];
$regionalid = $prm['regionalid'];
$branchcode = $prm['branchcode'];
$qty = $prm['qty'];
$stock = $prm['stock'];
$status = $prm['status'];
$UnitIDRequest = $prm['UnitIDRequest'];
/* Validasi ItemUnit Request dengan Stock */
$stock = $this->calculateStockByItemUnitReq($stock, $UnitIDRequest);
$sqlin = "INSERT INTO purchase_request_flag (
PurchaseRequestFlagPurchaseRequestDetailID,
PurchaseRequestFlagS_RegionalID,
PurchaseRequestFlagM_BranchCode,
PurchaseRequestFlagQty,
PurchaseRequestFlagQtyRest,
PurchaseRequestFlagStatus,
PurchaseRequestFlagUserID,
PurchaseRequestFlagCreated
) VALUES (?,?,?,?,?,?,?,NOW())";
$query = $this->db->query($sqlin, [
$reqdetailid,
$regionalid,
$branchcode,
$qty,
$qty,
$status,
$userid
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("error insert status request");
exit;
}
$reqflagid = $this->db->insert_id();
$sqlget = "SELECT * FROM purchase_request_flag WHERE PurchaseRequestFlagID = ?";
$queget = $this->db->query($sqlget, [$reqdetailid]);
if (!$queget) {
$this->db->trans_rollback();
$this->sys_error_db("error get latest inserted flag");
exit;
}
$data = $queget->result_array()[0];
$json = json_encode($data);
$sqlog = "INSERT INTO acc_one_log.purchaserequestflag_log (
PurchaseRequestFlagLogPurchaseRequestFlagID,
PurchaseRequestFlagLogStatus,
PurchaseRequestFlagLogQty,
PurchaseRequestFlagLogStock,
PurchaseRequestFlagLogJson,
PurchaseRequestFlagLogUserID,
PurchaseRequestFlagLogCreated
) VALUES (?, ?, ?, ?, ?, ?, NOW())";
$quelog = $this->db->query($sqlog, [$reqflagid, $status, $qty, $stock, $json, $userid]);
if (!$quelog) {
$this->db->trans_rollback();
$this->sys_error_db("error insert log purchase request flag");
exit;
}
$sqlread = "UPDATE purchase_request_detail SET
PurchaseRequestDetailStatus = 'Read'
WHERE PurchaseRequestDetailID = ?";
$queread = $this->db->query($sqlread, [$reqdetailid]);
if (!$queread) {
$this->db->trans_rollback();
$this->sys_error_db("error update status purchase request detail to read");
exit;
}
$sqlpart = "UPDATE purchase_request SET
PurchaseRequestStatus = 'Partial'
WHERE PurchaseRequestRefNumber = ?";
$quepart = $this->db->query($sqlpart, [$reqnumber]);
if (!$quepart) {
$this->db->trans_rollback();
$this->sys_error_db("error update status purchase request to partial");
exit;
}
$this->db->trans_commit();
$this->sys_ok("Success insert status request");
} catch (\Throwable $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
public function changestatus()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$this->db->trans_begin();
$userid = $this->sys_user["M_UserID"];
$prm = $this->sys_input;
$reqnumber = $prm['reqnumber'];
$reqflagid = $prm['requestflagid'];
$reqdetailid = $prm['reqdetailid'];
$regionalid = $prm['regionalid'];
$branchcode = $prm['branchcode'];
$reqqty = $prm['qty'];
$reqstock = $prm['stock'];
$reqstatus = $prm['status'];
$UnitIDRequest = $prm['UnitIDRequest'];
/* Validasi ItemUnit Request dengan Stock */
$stock = $this->calculateStockByItemUnitReq($reqstock, $UnitIDRequest);
$sqlcha = "UPDATE purchase_request_flag SET
PurchaseRequestFlagPurchaseRequestDetailID = ?,
PurchaseRequestFlagS_RegionalID = ?,
PurchaseRequestFlagM_BranchCode = ?,
PurchaseRequestFlagQty = ?,
PurchaseRequestFlagQtyRest = ?,
PurchaseRequestFlagStatus = ?,
PurchaseRequestFlagUserID = ?,
PurchaseRequestFlagLastUpdated = NOW()
WHERE PurchaseRequestFlagID = ?";
$query = $this->db->query($sqlcha, [
$reqdetailid,
$regionalid,
$branchcode,
$reqqty,
$reqqty,
$reqstatus,
$userid,
$reqflagid
]);
if (!$query) {
$this->db->trans_rollback();
$this->sys_error_db("error update status flag requset");
exit;
}
$sqlget = "SELECT * FROM purchase_request_flag WHERE PurchaseRequestFlagID = ?";
$queget = $this->db->query($sqlget, [$reqflagid]);
if (!$queget) {
$this->db->trans_rollback();
$this->sys_error_db("error get data change");
exit;
}
$data = $queget->result_array()[0];
$json = json_encode($data);
$sqlog = "INSERT INTO acc_one_log.purchaserequestflag_log (
PurchaseRequestFlagLogPurchaseRequestFlagID,
PurchaseRequestFlagLogStatus,
PurchaseRequestFlagLogQty,
PurchaseRequestFlagLogStock,
PurchaseRequestFlagLogJson,
PurchaseRequestFlagLogUserID,
PurchaseRequestFlagLogCreated
) VALUES (?, ?, ?, ?, ?, ?, NOW())";
$quelog = $this->db->query($sqlog, [$reqflagid, $reqstatus, $reqqty, $stock, $json, $userid]);
if (!$quelog) {
$this->db->trans_rollback();
$this->sys_error_db("error insert log purchase request flag");
exit;
}
$this->db->trans_commit();
$this->sys_ok("success");
} catch (\Throwable $ex) {
$message = $ex->getMessage();
$this->sys_error($message);
}
}
private function calculateStockByItemUnitReq(array $stock, string $UnitIDRequest): int
{
// Cek $stock empty array atau tidak, jika iya $stok = 0
if (!is_array($stock) || empty($stock)) {
return 0;
}
// Cari object di $stock di mana StockItemUnitID == $UnitIDRequest,
// Jika tidak ada, set $stock = 0
$equivalentStock = array_filter($stock, function ($item) use ($UnitIDRequest) {
return $item['StockItemUnitID'] == $UnitIDRequest;
});
if (empty($equivalentStock)) {
return 0;
}
return array_values($equivalentStock)[0]['QtyTotal'] ?? 0;
}
}