isLogin) { $this->sys_error("Invalid Token"); exit; } $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; $currentPage = isset($payload["currentPage"]) ? $payload["currentPage"] : 1; $pageSize = isset($payload["pageSize"]) ? $payload["pageSize"] : 10; $offset = ($currentPage - 1) * $pageSize; $startDate = isset($payload["startDate"]) ? $payload["startDate"] : ""; $endDate = isset($payload["endDate"]) ? $payload["endDate"] : ""; $status = isset($payload["status"]) ? $payload["status"] : ""; $search = isset($payload["search"]) ? $payload["search"] : ""; $params = []; $params[] = $startDate; $params[] = $endDate; $params[] = $status; $params[] = $status; $params[] = '%' . $search . '%'; $sql = "SELECT M_UserLocationS_RegionalID as S_RegionalID, IFNULL(M_BranchCode, '') as M_BranchCode, IFNULL(M_BranchName, '') as M_BranchName FROM m_userlocation LEFT JOIN m_branch ON M_BranchID = M_UserLocationM_BranchID WHERE M_UserLocationIsActive = 'Y' AND M_UserLocationM_UserID = ?"; $exec = $this->db->query($sql, [$userId]); if (!$exec) { $this->sys_error_db("select user location", $this->db); exit; } $rows = $exec->result_array(); $prRegional = $rows[0]["S_RegionalID"]; $prBranch = $rows[0]["M_BranchCode"]; $filterBranch = ""; if ($prBranch != "") { $filterBranch = " AND PurchaseRequestM_BranchCode = ?"; $params[] = $prBranch; } $filterRegional = ""; if ($prBranch == "") { $filterRegional = " AND PurchaseRequestS_RegionalID = ?"; $params[] = $prRegional; } $totalCount = 0; $totalPage = 1; $sql = "SELECT COUNT(*) as total FROM purchase_request JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID WHERE PurchaseRequestIsActive = 'Y' AND PurchaseRequestItemCategoryID <> '1' AND ( PurchaseRequestDate BETWEEN ? AND ? ) AND ( PurchaseRequestStatus = ? OR ? = '' ) AND ( PurchaseRequestNumber LIKE ?) $filterBranch $filterRegional"; $exec = $this->db->query($sql, $params); if ($exec) { $totalCount = $exec->result_array()[0]["total"]; $totalPage = ceil($totalCount / $pageSize); } else { $this->sys_error_db("select purchase request", $this->db); exit; } $params[] = $offset; $params[] = $pageSize; $sql = "SELECT DISTINCT PurchaseRequestID as prId, PurchaseRequestNumber as prNumber, PurchaseRequestDate as prDate, PurchaseRequestStatus as prStatus, requestedBy.M_UserUsername as prRequestedBy, IF(PurchaseRequestApprovedBy IS NULL, '', approvedBy.M_UserUsername) as prApprovedBy, PurchaseRequestS_RegionalID as prRegionalId, S_RegionalName as prRegionalName, PurchaseRequestM_BranchCode as prBranchCode, M_BranchName as prBranchName, PurchaseRequestNote as prNote, PurchaseRequestStatus as prStatus, IFNULL(S_RegionalID, '') as S_RegionalID, IFNULL(S_RegionalName, '') as S_RegionalName, IFNULL(M_BranchCode, '') as M_BranchCode, IFNULL(M_BranchName, '') as M_BranchName, item_category.ItemCategoryName as itemCategoryName, item_category.ItemCategoryID as itemCategoryID, IF(ah.AssetHandoverID IS NULL, 0, 1) AS hasHandover, ah.AssetHandoverConfirmedBy as handoverConfirmedBy, ah.AssetHandoverID AS handoverID, ah.AssetHandoverDate AS handoverDate, ah.AssetHandoverToUserID AS handoverToUserID FROM purchase_request JOIN s_regional ON S_RegionalID = PurchaseRequestS_RegionalID JOIN item_category ON item_category.ItemCategoryID = PurchaseRequestItemCategoryID JOIN m_user requestedBy ON requestedBy.M_UserID = PurchaseRequestRequestedBy LEFT JOIN m_user approvedBy ON approvedBy.M_UserID = PurchaseRequestApprovedBy LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode LEFT JOIN asset_handover ah ON ah.AssetHandoverPurchaseRequestID = PurchaseRequestID AND ah.AssetHandoverIsActive = 'Y' WHERE PurchaseRequestIsActive = 'Y' AND PurchaseRequestItemCategoryID <> '1' AND ( PurchaseRequestDate BETWEEN ? AND ? ) AND ( PurchaseRequestStatus = ? OR ? = '' ) AND ( PurchaseRequestNumber LIKE ? ) $filterBranch $filterRegional ORDER BY PurchaseRequestID DESC LIMIT ?, ?"; $exec = $this->db->query($sql, $params); if (!$exec) { $this->sys_error_db("select purchase request", $this->db); exit; } //echo $this->db->last_query(); //exit; $rows = $exec->result_array(); $result = array( "total" => $totalPage, "totalFilter" => $totalCount, "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function searchDetail() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $payload = $this->sys_input; // Menggunakan parameter query $queryCount = "SELECT count(*) as total FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailIsActive = 'Y' AND PurchaseRequestDirectDetailPurchaseRequestDirectID = ?"; $exec = $this->db->query($queryCount, [$payload['PRID']]); $totalCount = 0; if ($exec) { $totalCount = $exec->result_array()[0]["total"]; } else { $this->db->trans_rollback(); $this->sys_error_db("select purchase request detail", $this->db);; exit; } // Menggunakan parameter query $query = "SELECT *, ROW_NUMBER() OVER(ORDER BY PurchaseRequestDirectDetailID) RowNumber , 'N' as isEditingPrice FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailIsActive = 'Y' AND PurchaseRequestDirectDetailPurchaseRequestDirectID = ? ORDER BY PurchaseRequestDirectDetailStatus ASC, PurchaseRequestDirectDetailID ASC"; $exec = $this->db->query($query, [$payload['PRID']]); if ($exec) { $rows = $exec->result_array(); } else { $this->db->trans_rollback(); $this->sys_error_db("select purchase request detail", $this->db); exit; } $result = array( "totalFilter" => $totalCount, "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getBranch() { try { $query = "SELECT DISTINCT M_BranchCode, M_BranchName FROM m_branch WHERE M_BranchIsActive = 'Y' ORDER BY M_BranchName ASC"; $exec = $this->db->query($query, []); if ($exec) { $rows = $exec->result_array(); } else { $this->db->trans_rollback(); $this->sys_error_db("select branch", $this->db); exit; } $result = array( "records" => $rows, "sql" => $this->db->last_query() ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getItemCategory() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $query = "SELECT * FROM item_category WHERE ItemCategoryIsActive = 'Y' AND ItemCategoryID <> '1'"; $exec = $this->db->query($query, []); if ($exec) { $rows = $exec->result_array(); $rst = array( "records" => $rows ); $this->sys_ok($rst); } else { $this->sys_error_db("select item category", $this->db); exit; } } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getRegionalBranchByUser() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $userId = $this->sys_user["M_UserID"]; $query = "SELECT IFNULL(M_BranchID, 0) as M_BranchID, IFNULL(M_BranchCode, '') as M_BranchCode, IFNULL(M_BranchName, '') as M_BranchName FROM m_userlocation LEFT JOIN m_branch ON M_UserLocationM_BranchID = M_BranchID WHERE M_UserLocationM_UserID = ? AND M_UserLocationIsActive = 'Y' LIMIT 1"; $exec = $this->db->query($query, [$userId]); if ($exec) { $rows = $exec->result_array(); } else { $this->sys_error_db("select branch", $this->db); exit; } $rst = array(); $branchId = $rows[0]["M_BranchID"]; $branchCode = $rows[0]["M_BranchCode"]; $branchName = $rows[0]["M_BranchName"]; if (intval($branchId) > 0) { $rst = array( array( "M_BranchCode" => $branchCode, "M_BranchName" => $branchName ) ); } else { $query = "SELECT DISTINCT M_BranchCode, M_BranchName FROM m_branch JOIN m_userlocation ON M_BranchS_RegionalID = M_UserLocationS_RegionalID AND M_UserLocationM_UserID = ? AND M_UserLocationIsActive = 'Y' WHERE M_BranchIsActive = 'Y' ORDER BY M_BranchName ASC"; $exec = $this->db->query($query, [$userId]); if ($exec) { $rst = $exec->result_array(); } else { $this->sys_error_db("select branch regional", $this->db); exit; } } $this->sys_ok($rst); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function deletePurchaseRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); } $this->db->trans_begin(); $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; $prId = isset($payload['PRID']) ? $payload['PRID'] : ""; $prNumber = isset($payload['PRNumber']) ? $payload['PRNumber'] : ""; if ($prId == "" || $prId == null) { $this->sys_error("Invalid PR ID"); exit; } $datas_log = array(); $sql = "SELECT * FROM purchase_request WHERE PurchaseRequestID = ? AND PurchaseRequestIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request select", $this->db); exit; } $header = $query->row_array(); $datas_log['header'] = $header; $sql = "SELECT * FROM purchase_request_detail JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID AND M_ItemIsActive = 'Y' JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID AND ItemUnitIsActive = 'Y' WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail select", $this->db); exit; } $details = $query->result_array(); $datas_log['details'] = $details; $sql = "UPDATE purchase_request SET PurchaseRequestDeleted = NOW(), PurchaseRequestDeletedUserID = ?, PurchaseRequestIsActive = 'N' WHERE PurchaseRequestID = ?"; $deleteParams = [$userId, $prId]; $exec = $this->db->query($sql, $deleteParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("purchase request delete error", $this->db); exit; } $sql = "UPDATE purchase_request_detail SET PurchaseRequestDetailIsActive = 'N', PurchaseRequestDetailDeleted = NOW(), PurchaseRequestDetailDeletedUserID = ? WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $deleteParams = [$userId, $prId]; $exec = $this->db->query($sql, $deleteParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail delete error", $this->db); exit; } $messages = "Purchase Request dengan kode " . $prNumber . " sudah dihapus"; $this->insert_act_log("PRNP", "Delete", $messages, $prId, $this->safeJsonEncode($datas_log), $userId); $this->db->trans_commit(); $result = array("total" => 1, "records" => array("xId" => 0)); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function saveDetail() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); } $this->db->trans_begin(); $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; $PRDTotalPrice = intval($payload['PRDAmountRequest']) * intval($payload['PRDEstimationPrice']); // Gunakan parameter untuk query existensi $query = "SELECT COUNT(*) as exist FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailIsActive = 'Y' AND PurchaseRequestDirectDescription = ? AND PurchaseRequestDirectDetailPurchaseRequestDirectID = ?"; $existParams = [$payload['PRDDescriptionDetail'], $payload['PRID']]; $exist = $this->db->query($query, $existParams); if ($exist) { $row = $exist->row()->exist; } else { $this->sys_error_db("exist error", $this->db); exit; } if ($row == 0) { // Gunakan parameter untuk query insert $sql = "INSERT INTO purchase_request_direct_detail( PurchaseRequestDirectDetailPurchaseRequestDirectID, PurchaseRequestDirectDescription, PurchaseRequestDirectDetailAmountRequest, PurchaseRequestDirectDetailAmount, PurchaseRequestDirectDetailEstimationPrice, PurchaseRequestDirectDetailTotalEstimationPrice, PurchaseRequestDirectDetailTotalRealitationPrice, PurchaseRequestDirectDetailStatus, PurchaseRequestDirectDetailIsActive, PurchaseRequestDirectDetailCreated, PurchaseRequestDirectDetailLastUpdated, PurchaseRequestDirectDetailDeleted, PurchaseRequestDirectDetailCreatedUserID, PurchaseRequestDirectDetailLastUpdatedUserID, PurchaseRequestDirectDetailDeletedUserID ) VALUES (?, ?, ?, NULL, ?, ?, NULL, 'Pending', 'Y', NOW(), NULL, NULL, ?, NULL, NULL)"; $insertParams = [ $payload['PRID'], $payload['PRDDescriptionDetail'], $payload['PRDAmountRequest'], $payload['PRDEstimationPrice'], $PRDTotalPrice, $userId ]; $exec = $this->db->query($sql, $insertParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("request insert error", $this->db); exit; } else { // Gunakan parameter untuk query total harga $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND PurchaseRequestDirectDetailIsActive = 'Y'"; $totalPriceParams = [$payload['PRID']]; $exec = $this->db->query($sqlTotalPrice, $totalPriceParams); $total = 0; if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } else { $total = $exec->result_array()[0]["Total"]; } // Gunakan parameter untuk query update $sql = "UPDATE purchase_request_direct SET PurchaseRequestDirectTotalEstimation = ?, PurchaseRequestLastUpdated = NOW(), PurchaseRequestLastUpdatedUserID = ? WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'"; $updateParams = [$total, $userId, $payload['PRID']]; $exec = $this->db->query($sql, $updateParams); } $this->db->trans_commit(); $result = array("total" => 1, "records" => array("xId" => 0)); $this->sys_ok($result); } else { $errors = array(); if ($row != 0) { array_push($errors, array('msg' => 'Data sudah ada')); } $result = array("total" => -1, "errors" => $errors, "records" => array('status' => 'ERROR')); $this->sys_ok($result); } } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function updateDetail() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); } $this->db->trans_begin(); $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; $PRDTotalPrice = intval($payload["PRDAmountRequest"]) * intval($payload["PRDEstimationPrice"]); // Gunakan parameter untuk query update $sql = "UPDATE purchase_request_direct_detail SET PurchaseRequestDirectDescription = ?, PurchaseRequestDirectDetailAmountRequest = ?, PurchaseRequestDirectDetailEstimationPrice = ?, PurchaseRequestDirectDetailTotalEstimationPrice = ?, PurchaseRequestDirectDetailLastUpdated = NOW(), PurchaseRequestDirectDetailLastUpdatedUserID = ? WHERE PurchaseRequestDirectDetailID = ?"; $updateParams = [ $payload["PRDDescriptionDetail"], $payload["PRDAmountRequest"], $payload["PRDEstimationPrice"], $PRDTotalPrice, $userId, $payload["PRDID"] ]; $exec = $this->db->query($sql, $updateParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("request update error", $this->db); exit; } else { // Gunakan parameter untuk query total harga $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND PurchaseRequestDirectDetailIsActive = 'Y'"; $totalPriceParams = [$payload["PRID"]]; $exec = $this->db->query($sqlTotalPrice, $totalPriceParams); $total = 0; if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } else { $total = $exec->result_array()[0]["Total"]; } // Gunakan parameter untuk query update total $sql = "UPDATE purchase_request_direct SET PurchaseRequestDirectTotalEstimation = ?, PurchaseRequestLastUpdated = NOW(), PurchaseRequestLastUpdatedUserID = ? WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'"; $updateTotalParams = [$total, $userId, $payload["PRID"]]; $exec = $this->db->query($sql, $updateTotalParams); } $this->db->trans_commit(); $result = array("total" => 1, "records" => array("xId" => $payload["PRDID"])); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function deleteDetail() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); } $this->db->trans_begin(); $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; // Gunakan parameter untuk query delete $sql = "UPDATE purchase_request_direct_detail SET PurchaseRequestDirectDetailDeleted = NOW(), PurchaseRequestDirectDetailDeletedUserID = ?, PurchaseRequestDirectDetailIsActive = 'N' WHERE PurchaseRequestDirectDetailID = ?"; $deleteParams = [$userId, $payload["PRDID"]]; $exec = $this->db->query($sql, $deleteParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("request delete error", $this->db); exit; } else { // Gunakan parameter untuk query total harga $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total FROM purchase_request_direct_detail WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND PurchaseRequestDirectDetailIsActive = 'Y'"; $totalPriceParams = [$payload["PRID"]]; $exec = $this->db->query($sqlTotalPrice, $totalPriceParams); $total = 0; if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } else { $total = $exec->result_array()[0]["Total"] ?? 0; } // Gunakan parameter untuk query update total $sql = "UPDATE purchase_request_direct SET PurchaseRequestDirectTotalEstimation = ?, PurchaseRequestLastUpdated = NOW(), PurchaseRequestLastUpdatedUserID = ? WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'"; $updateTotalParams = [$total, $userId, $payload["PRID"]]; $exec = $this->db->query($sql, $updateTotalParams); } $this->db->trans_commit(); $result = array("total" => 1, "records" => array("xId" => 0)); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function orderRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); } $this->db->trans_begin(); $payload = $this->sys_input; $userId = $this->sys_user["M_UserID"]; // Gunakan parameter untuk query update detail $sqlDetail = "UPDATE purchase_request_direct_detail SET PurchaseRequestDirectDetailLastUpdated = NOW(), PurchaseRequestDirectDetailLastUpdatedUserID = ? WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND PurchaseRequestDirectDetailIsActive = 'Y' AND PurchaseRequestDirectDetailStatus = 'Pending'"; $detailParams = [$userId, $payload["PRID"]]; $exec = $this->db->query($sqlDetail, $detailParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } // Gunakan parameter untuk query update status $sql = "UPDATE purchase_request_direct SET PurchaseRequestDirectStatus = 'Pending', PurchaseRequestLastUpdated = NOW(), PurchaseRequestLastUpdatedUserID = ? WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'"; $updateParams = [$userId, $payload["PRID"]]; $exec = $this->db->query($sql, $updateParams); if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } $this->db->trans_commit(); // Gunakan parameter untuk query select $sql = "SELECT *, ROW_NUMBER() OVER(ORDER BY PurchaseRequestDirectNumber) RowNumber FROM purchase_request_direct WHERE PurchaseRequestDirectIsActive = 'Y' AND PurchaseRequestCreatedUserID = ? AND PurchaseRequestDirectID = ?"; $selectParams = [$userId, $payload["PRID"]]; $exec = $this->db->query($sql, $selectParams); $row = []; if (!$exec) { $this->db->trans_rollback(); $this->sys_error_db("order purchase request error", $this->db); exit; } else { $row = $exec->result_array(); } $result = array("total" => 1, "records" => $row); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getDivisionByUser() { try { $userId = $this->sys_user["M_UserID"]; $rows = []; $rows[] = array("DivisionID" => "", "DivisionCode" => "", "DivisionName" => "Semua Divisi"); $query = "SELECT DISTINCT DivisionID, DivisionCode, DivisionName FROM division WHERE DivisionIsActive = 'Y' ORDER BY DivisionName ASC"; $exec = $this->db->query($query); if ($exec) { $rst = $exec->result_array(); foreach ($rst as $key => $row) { $rows[] = array("DivisionID" => $row["DivisionID"], "DivisionCode" => $row["DivisionCode"], "DivisionName" => $row["DivisionName"]); } } else { $this->db->trans_rollback(); $this->sys_error_db("select division", $this->db); exit; } $sql = "SELECT DISTINCT DivisionID, DivisionCode, DivisionName FROM division JOIN m_userdivision ON M_UserDivisionDivisionID = DivisionID AND M_UserDivisionM_UserID = ? WHERE DivisionIsActive = 'Y' ORDER BY M_UserDivisionID DESC LIMIT 1"; $exec = $this->db->query($sql, [$userId]); if ($exec) { $r_selected = $exec->result_array(); if (count($r_selected) > 0) { $row = $r_selected[0]; } else { $row = array("DivisionID" => "", "DivisionCode" => "", "DivisionName" => "Semua Divisi"); } } else { $this->sys_error_db("select division by user", $this->db); exit; } $result = array( "records" => $rows, "selected" => $row ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getItemGroupSubGroup() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $prm = $this->sys_input; $division = isset($prm["division"]) ? $prm["division"] : ""; $rows = []; $rows[] = array("Nat_GroupID" => "", "Nat_GroupCode" => "", "Nat_GroupName" => "Semua Grup", "subGroups" => [ array("Nat_SubGroupID" => "", "Nat_SubGroupCode" => "", "Nat_SubGroupName" => "Semua Sub Grup") ]); $sql = "SELECT DISTINCT Nat_GroupID, Nat_GroupCode, Nat_GroupName, '' as subGroups FROM nat_group JOIN m_item ON M_ItemNat_GroupID = Nat_GroupID AND M_ItemIsActive = 'Y' JOIN m_itemdivision ON M_ItemDivisionM_ItemID = M_ItemID AND M_ItemDivisionIsActive = 'Y' AND (M_ItemDivisionDivisionID = ? OR ? = '') WHERE Nat_GroupIsActive = 'Y' ORDER BY Nat_GroupID ASC"; $query = $this->db->query($sql, [$division, $division]); if (!$query) { $this->sys_error_db("item group list", $this->db); exit; } $rst = $query->result_array(); foreach ($rst as $key => $row) { $row["subGroups"] = array( array("Nat_SubGroupID" => "", "Nat_SubGroupCode" => "", "Nat_SubGroupName" => "Semua Sub Grup") ); if ($row["Nat_GroupID"] != "") { $sqlSubGroup = "SELECT DISTINCT Nat_SubGroupID, Nat_SubGroupCode, Nat_SubGroupName FROM nat_subgroup WHERE Nat_SubGroupIsActive = 'Y' AND Nat_SubGroupNat_GroupID = ? ORDER BY Nat_SubGroupID ASC"; $querySubGroup = $this->db->query($sqlSubGroup, [$row["Nat_GroupID"]]); if (!$querySubGroup) { $this->sys_error_db("item sub group list", $this->db); exit; } $subGroups = $querySubGroup->result_array(); foreach ($subGroups as $keySubGroup => $subGroup) { $row["subGroups"][] = $subGroup; } } $rows[] = $row; } $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getItems() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $user = $this->sys_user; $prm = $this->sys_input; $search = isset($prm["search"]) ? $prm["search"] : ""; $itemCategory = isset($prm["itemCategory"]) ? $prm["itemCategory"] : ""; $division = isset($prm["division"]) ? $prm["division"] : ""; $itemGroup = isset($prm["itemGroup"]) ? $prm["itemGroup"] : ""; $itemSubGroup = isset($prm["itemSubGroup"]) ? $prm["itemSubGroup"] : ""; $unitPurchase = isset($prm["unitPurchase"]) ? $prm["unitPurchase"] : "purchase"; $currentPage = isset($prm["currentPage"]) ? $prm["currentPage"] : 1; $params = []; // Menambahkan parameter untuk unitPurchase $params[] = $unitPurchase; $params[] = $unitPurchase; $filterDivision = ""; if ($division != "") { $filterDivision = "JOIN m_itemdivision ON M_ItemDivisionM_ItemID = M_ItemID AND M_ItemDivisionIsActive = 'Y' AND (M_ItemDivisionDivisionID = ? OR ? = '')"; $params[] = $division; $params[] = $division; } $filterItemGroup = ""; if ($itemGroup != "") { $filterItemGroup = "JOIN nat_group ON M_ItemNat_GroupID = Nat_GroupID AND Nat_GroupIsActive = 'Y' AND (Nat_GroupID = ? OR ? = '')"; $params[] = $itemGroup; $params[] = $itemGroup; } $filterItemSubGroup = ""; if ($itemSubGroup != "") { $filterItemSubGroup = "JOIN nat_subgroup ON M_ItemNat_SubGroupID = Nat_SubGroupID AND Nat_SubGroupIsActive = 'Y' AND (Nat_SubGroupID = ? OR ? = '')"; $params[] = $itemSubGroup; $params[] = $itemSubGroup; } $filterCoaInventaris = ""; if ($itemCategory == "2") { $filterCoaInventaris = "JOIN coa_map_inventaris ON CoaMapInventarisM_InventarisGolID = M_ItemM_InventarisGolID AND CoaMapInventarisIsActive = 'Y'"; } $params[] = $itemCategory; $params[] = $itemCategory; $params[] = '%' . $search . '%'; $limit = 10; $offset = ($currentPage - 1) * $limit; $sql = "SELECT COUNT(*) as total FROM ( SELECT DISTINCT M_ItemID FROM m_item JOIN itemunitmap ON ItemUnitMapM_ItemID = M_ItemID AND ((ItemUnitMapIsPurchase = 'Y' AND ? = 'purchase') OR (ItemUnitMapIsBase = 'Y' AND ? = 'base')) AND ItemUnitMapIsActive = 'Y' JOIN itemunit ON ItemUnitID = ItemUnitMapItemUnitID AND ItemUnitIsActive = 'Y' $filterDivision $filterItemGroup $filterItemSubGroup $filterCoaInventaris WHERE M_ItemIsActive = 'Y' AND ( M_ItemItem_CategoryID = ? OR ? = '' ) AND M_ItemDesc LIKE ? ) as item"; $query = $this->db->query($sql, $params); if (!$query) { $this->sys_error_db("item list", $this->db); exit; } $row = $query->row_array(); $total = ceil($row["total"] / $limit); $params[] = $limit; $params[] = $offset; $sql = "SELECT DISTINCT M_ItemID as itemId, M_ItemCode as itemCode, M_ItemDesc as itemDesc, 0 as qty, 0 as price, ItemUnitID as unitId, ItemUnitCode as unitCode, ItemUnitName as unitName, 0 as detailId, 'draft' as status, 'N' as isEditingPrice, 0 as remaining_stock FROM m_item JOIN itemunitmap ON ItemUnitMapM_ItemID = M_ItemID AND ((ItemUnitMapIsPurchase = 'Y' AND ? = 'purchase') OR (ItemUnitMapIsBase = 'Y' AND ? = 'base')) AND ItemUnitMapIsActive = 'Y' JOIN itemunit ON ItemUnitID = ItemUnitMapItemUnitID AND ItemUnitIsActive = 'Y' $filterDivision $filterItemGroup $filterItemSubGroup $filterCoaInventaris WHERE M_ItemIsActive = 'Y' AND ( M_ItemItem_CategoryID = ? OR ? = '' ) AND M_ItemDesc LIKE ? ORDER BY M_ItemDesc ASC LIMIT ? OFFSET ?"; // Parameter akhir yang digunakan untuk query $searchParam = $params; $query = $this->db->query($sql, $searchParam); if (!$query) { $this->sys_error_db("item list", $this->db); //$this->sys_error($this->db->error()); exit; } //echo $this->db->last_query(); //exit; $rows = $query->result_array(); if (count($rows) > 0) { foreach ($rows as $key => $row) { $rows[$key]["isSelected"] = $row["isSelected"] == "Y" ? true : false; $sql = "SELECT SUM(StockQty) as stockQty FROM stock s JOIN warehouse w ON s.StockWarehouseID = w.WarehouseID WHERE s.StockItemID = ? AND s.StockItemUnitID = ? AND w.WarehouseS_RegionalID = ? AND w.WarehouseIsActive = 'Y' AND (w.WarehouseIsTransit != 'Y' OR w.WarehouseIsTransit IS NULL) AND w.WarehouseM_BranchID = ? AND w.WarehouseIsDefault = 'Y' GROUP BY s.StockItemUnitID"; $qry = $this->db->query($sql, [ $row['itemId'], $row['unitId'], $user['S_RegionalID'], $user['M_BranchID'] ]); if (!$qry) { $this->sys_error_db("Failed get stock", $this->db); exit; } $rowsstock = $qry->row_array(); $rows[$key]["remaining_stock"] = $rowsstock["stockQty"]; } } $result = array( "records" => $rows, "total" => $total ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getUnit() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $prm = $this->sys_input; $search = isset($prm["search"]) ? $prm["search"] : ""; // Menggunakan parameter query untuk pencarian unit $sql = "SELECT ItemUnitID, ItemUnitCode, ItemUnitName, ItemUnitCreated, ItemUnitLastUpdated, ItemUnitIsActive, ItemUnitUserID FROM itemunit WHERE ItemUnitIsActive = 'Y' AND ItemUnitName LIKE ? ORDER BY ItemUnitName ASC"; $searchParam = ['%' . $search . '%']; $query = $this->db->query($sql, $searchParam); if (!$query) { $this->sys_error_db("item unit list", $this->db); exit; } $rows = $query->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getSelectedItem() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $prm = $this->sys_input; $prId = isset($prm["prId"]) ? $prm["prId"] : ""; if ($prId == "") { $this->sys_error("Invalid PR ID"); exit; } $sql = "SELECT PurchaseRequestDetailID as detailId, PurchaseRequestDetailM_ItemID as itemId, M_ItemCode as itemCode, M_ItemDesc as itemDesc, PurchaseRequestDetailItemUnitID as unitId, ItemUnitCode as unitCode, ItemUnitName as unitName, PurchaseRequestDetailQty as qty, PurchaseRequestDetailStatus as status, PurchaseRequestDetailNote as note FROM purchase_request_detail JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID AND M_ItemIsActive = 'Y' JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID AND ItemUnitIsActive = 'Y' WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); if (!$query) { $this->sys_error_db("item list", $this->db); exit; } $rows = $query->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getUnitByItemId() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $prm = $this->sys_input; $itemId = isset($prm["itemId"]) ? $prm["itemId"] : ""; if ($itemId == "") { $this->sys_error("Invalid Item ID"); exit; } $sql = "SELECT DISTINCT ItemUnitID as unitId, ItemUnitCode as unitCode, ItemUnitName as unitName FROM itemunitmap JOIN itemunit ON ItemUnitID = ItemUnitMapItemUnitID AND ItemUnitIsActive = 'Y' WHERE ItemUnitMapM_ItemID = ? AND ItemUnitMapIsActive = 'Y'"; $query = $this->db->query($sql, [$itemId]); if (!$query) { $this->sys_error_db("item unit list", $this->db); exit; } $rows = $query->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function savePurchaseRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $user = $this->sys_user; $userId = $this->sys_user["M_UserID"]; $prm = $this->sys_input; $prDateUse = isset($prm["PRDateUse"]) ? $prm["PRDateUse"] : ""; $prDateUse = date("Y-m-d", strtotime($prDateUse)); if ($prDateUse == "" || $prDateUse == null) { $this->sys_error("Invalid PR Date Use"); exit; } $prRegional = isset($prm["PRRegional"]) ? $prm["PRRegional"] : ""; if ($prRegional == "" || $prRegional == null) { $this->sys_error("Invalid PR Regional"); exit; } if ($user["M_BranchID"] != "0") { $prBranch = isset($prm["PRBranch"]) ? $prm["PRBranch"] : ""; if ($prBranch == "" || $prBranch == null) { $this->sys_error("Invalid PR Branch"); exit; } } else if ($user["M_BranchID"] == "0") { $prBranch = $prm["PRBranch"]; } $prItemCategory = isset($prm["PRItemCategory"]) ? $prm["PRItemCategory"] : ""; if ($prItemCategory == "" || $prItemCategory == null) { $this->sys_error("Invalid PR Item Category"); exit; } $prDescription = isset($prm["PRDescription"]) ? $prm["PRDescription"] : ""; $items = isset($prm["items"]) ? $prm["items"] : []; if (count($items) == 0) { $this->sys_error("PR Items cannot be empty"); exit; } $this->db->trans_begin(); $areaid = $user['M_BranchID']; $areatype = 'B'; if ($user['loginLevel'] == 'regional') { $areaid = $user['S_RegionalID']; $areatype = 'R'; } $sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;"; $quenum = $this->db->query($sqlnum, ['SR', 5, $areatype, $areaid, 'SM', 'Y']); if (!$quenum) { $this->db->trans_rollback(); $this->sys_error_db("[Error] generate number doc", $this->db); exit; } $numpd = $quenum->row_array()['numpd']; $sql = "INSERT INTO purchase_request ( PurchaseRequestNumber, PurchaseRequestDate, PurchaseRequestS_RegionalID, PurchaseRequestM_BranchCode, PurchaseRequestNote, PurchaseRequestItemCategoryID, PurchaseRequestCreated, PurchaseRequestUserID, PurchaseRequestCreatedUserID, PurchaseRequestRequestedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; // VALUES (fn_numbering('PR'), ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $query = $this->db->query($sql, [ $numpd, $prDateUse, $prRegional, $prBranch, $prDescription, $prItemCategory, date("Y-m-d H:i:s"), $userId, $userId, $userId ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request", $this->db); exit; } $prId = $this->db->insert_id(); foreach ($items as $key => $item) { $item["total"] = floatval($item["price"]) * floatval($item["qty"]); $sql = "INSERT INTO purchase_request_detail ( PurchaseRequestDetailPurchaseRequestID, PurchaseRequestDetailM_ItemID, PurchaseRequestDetailItemUnitID, PurchaseRequestDetailQty, PurchaseRequestDetailPrice, PurchaseRequestDetailTotal, PurchaseRequestDetailCreated, PurchaseRequestDetailCreatedUserID, PurchaseRequestDetailUserID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; $query = $this->db->query($sql, [ $prId, $item["itemId"], $item["unitId"], $item["qty"], $item["price"], $item["total"], date("Y-m-d H:i:s"), $userId, $userId ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail", $this->db); exit; } } $sql = "SELECT * FROM purchase_request JOIN m_user ON M_UserID = PurchaseRequestCreatedUserID WHERE PurchaseRequestID = ?"; $query = $this->db->query($sql, [$prId]); $row = $query->row_array(); $sql = "SELECT * FROM purchase_request_detail WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); $rows = $query->result_array(); $data = array( "header" => $row, "details" => $rows ); $message = "Nomor PR: " . $row["PurchaseRequestNumber"] . " berhasil dibuat oleh " . $row["M_UserUsername"]; $this->insert_act_log("PRNP", "NEW", $message, $prId, $this->safeJsonEncode($data), $userId); /** * insert log purchase request detail */ foreach ($rows as $row) { $this->insertPurchaseRequestDetailLog($row, $userId); } $this->db->trans_commit(); $this->sys_ok("Purchase Request created successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function saveAndDoPurchaseRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $user = $this->sys_user; $userId = $this->sys_user["M_UserID"]; $branchId = $user["M_BranchID"]; $regionalId = $user["S_RegionalID"]; $prm = $this->sys_input; $prDateUse = isset($prm["PRDateUse"]) ? $prm["PRDateUse"] : ""; $prDateUse = date("Y-m-d", strtotime($prDateUse)); if ($prDateUse == "" || $prDateUse == null) { $this->sys_error("Invalid PR Date Use"); exit; } $prRegional = isset($prm["PRRegional"]) ? $prm["PRRegional"] : ""; if ($prRegional == "" || $prRegional == null) { $this->sys_error("Invalid PR Regional"); exit; } if ($user["M_BranchID"] != "0") { $prBranch = isset($prm["PRBranch"]) ? $prm["PRBranch"] : ""; if ($prBranch == "" || $prBranch == null) { $this->sys_error("Invalid PR Branch"); exit; } } else if ($user["M_BranchID"] == "0") { $prBranch = $prm["PRBranch"]; } $prItemCategory = isset($prm["PRItemCategory"]) ? $prm["PRItemCategory"] : ""; if ($prItemCategory == "" || $prItemCategory == null) { $this->sys_error("Invalid PR Item Category"); exit; } $prDescription = isset($prm["PRDescription"]) ? $prm["PRDescription"] : ""; $items = isset($prm["items"]) ? $prm["items"] : []; if (count($items) == 0) { $this->sys_error("PR Items cannot be empty"); exit; } $this->db->trans_begin(); $areaid = $user['M_BranchID']; $areatype = 'B'; if ($user['loginLevel'] == 'regional') { $areaid = $user['S_RegionalID']; $areatype = 'R'; } $sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;"; $quenum = $this->db->query($sqlnum, ['SR', 5, $areatype, $areaid, 'SM', 'Y']); if (!$quenum) { $this->db->trans_rollback(); $this->sys_error_db("[Error] generate number doc", $this->db); exit; } $numpd = $quenum->row_array()['numpd']; $sql = "INSERT INTO purchase_request ( PurchaseRequestNumber, PurchaseRequestDate, PurchaseRequestS_RegionalID, PurchaseRequestM_BranchCode, PurchaseRequestNote, PurchaseRequestItemCategoryID, PurchaseRequestStatus, PurchaseRequestCreated, PurchaseRequestUserID, PurchaseRequestCreatedUserID, PurchaseRequestRequestedBy) VALUES (?, ?, ?, ?, ?, ?, 'Pending', ?, ?, ?, ?)"; // VALUES (fn_numbering('PR'), ?, ?, ?, ?, ?, 'Pending', ?, ?, ?, ?)"; $query = $this->db->query($sql, [ $numpd, $prDateUse, $prRegional, $prBranch, $prDescription, $prItemCategory, date("Y-m-d H:i:s"), $userId, $userId, $userId ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request", $this->db); exit; } $prId = $this->db->insert_id(); foreach ($items as $key => $item) { $item["total"] = floatval($item["price"]) * floatval($item["qty"]); $sql = "INSERT INTO purchase_request_detail ( PurchaseRequestDetailPurchaseRequestID, PurchaseRequestDetailM_ItemID, PurchaseRequestDetailItemUnitID, PurchaseRequestDetailQty, PurchaseRequestDetailPrice, PurchaseRequestDetailTotal, PurchaseRequestDetailStatus, PurchaseRequestDetailCreated, PurchaseRequestDetailCreatedUserID, PurchaseRequestDetailUserID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $query = $this->db->query($sql, [ $prId, $item["itemId"], $item["unitId"], $item["qty"], $item["price"], $item["total"], 'Pending', date("Y-m-d H:i:s"), $userId, $userId ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail", $this->db); exit; } } $sql = "SELECT * FROM purchase_request JOIN m_user ON M_UserID = PurchaseRequestCreatedUserID WHERE PurchaseRequestID = ?"; $query = $this->db->query($sql, [$prId]); $row = $query->row_array(); $sql = "SELECT * FROM purchase_request_detail WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); $rows = $query->result_array(); $data = array( "header" => $row, "details" => $rows ); $message = "Nomor PR: " . $row["PurchaseRequestNumber"] . " berhasil dibuat dan diajukan langsung oleh " . $row["M_UserUsername"]; $this->insert_act_log("PRNP", "Pending", $message, $prId, $this->safeJsonEncode($data), $userId); /** * insert log purchase request detail */ foreach ($rows as $row) { $this->insertPurchaseRequestDetailLog($row, $userId); } // notification $this->saveNotification($userId, $prDateUse, $numpd, $prId, $branchId, $regionalId); $this->db->trans_commit(); $this->sys_ok("Purchase Request created and submitted successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } private function insertPurchaseRequestDetailLog(array $data, int $userId) { $sql = "INSERT INTO acc_one_log.purchase_request_detail_log ( PurchaseRequestDetailLogPurchaseRequestDetailID, PurchaseRequestDetailLogPurchaseRequestID, PurchaseRequestDetailLogType, PurchaseRequestDetailLogOldQty, PurchaseRequestDetailLogOldPrice, PurchaseRequestDetailLogCreated, PurchaseRequestDetailLogUserID ) VALUES (?,?,'CREATE',?,?,NOW(),?)"; $params = [ $data['PurchaseRequestDetailID'], $data['PurchaseRequestDetailPurchaseRequestID'], $data['PurchaseRequestDetailQty'] ?? null, $data['PurchaseRequestDetailPrice'] ?? null, $userId ]; if (!$this->db->query($sql, $params)) { $this->sys_error_db("Gagal insert purchase_request_detail_log", $this->db); $this->db->trans_rollback(); exit; } } function insert_act_log($code, $status, $description, $refId, $data, $userId) { $sql = "INSERT INTO user_activity( UserActivityCode, UserActivityStatus, UserActivityDescription, UserActivityRefID, UserActivityData, UserActivityUserID, UserActivityCreated) VALUES (?,?,?,?,?,?,?)"; $query = $this->db->query($sql, [$code, $status, $description, $refId, $data, $userId, date("Y-m-d H:i:s")]); if (!$query) { $this->sys_error_db("user activity", $this->db); exit; } } function getDetailRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $userId = $this->sys_user["M_UserID"]; $prm = $this->sys_input; $requestId = isset($prm["requestId"]) ? $prm["requestId"] : ""; if ($requestId == "" || $requestId == null) { $this->sys_error("Invalid Request ID"); exit; } $sql = "SELECT PurchaseRequestDetailID as detailId, PurchaseRequestDetailM_ItemID as itemId, M_ItemCode as itemCode, M_ItemDesc as itemDesc, PurchaseRequestDetailItemUnitID as unitId, ItemUnitCode as unitCode, ItemUnitName as unitName, PurchaseRequestDetailQty as qty, PurchaseRequestDetailPrice as price, PurchaseRequestDetailTotal as total, PurchaseRequestDetailStatus as status, 'N' as isEditingPrice FROM purchase_request_detail JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID AND M_ItemIsActive = 'Y' JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID AND ItemUnitIsActive = 'Y' WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$requestId]); if (!$query) { $this->sys_error_db("purchase request detail", $this->db); exit; } $rows = $query->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getRiwayatItem() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $para = $this->sys_input; $user = $this->sys_user; $place = $user['M_BranchID']; if ($user['M_BranchID'] == '0') { $place = 'R'; } $page = 0; $limit = 10; if ($para['page'] > 0) { $page = ($para['page'] - 1) * $limit; } $sqlpast = "SELECT PurchaseRequestDetailID, PurchaseRequestDetailM_ItemID, M_ItemDesc, PurchaseRequestDetailItemUnitID, ItemUnitName, PurchaseRequestDetailQty, PurchaseRequestStatus, PurchaseRequestDetailCreated FROM purchase_request_detail JOIN purchase_request ON PurchaseRequestID = PurchaseRequestDetailPurchaseRequestID JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID JOIN m_user ON PurchaseRequestRequestedBy = M_UserID AND M_UserIsActive = 'Y' WHERE PurchaseRequestDetailM_ItemID = ? AND PurchaseRequestDetailIsActive = 'Y' AND (M_UserM_BranchID = ? OR 'R' = ?) ORDER BY PurchaseRequestDetailCreated DESC"; $sqldata = $sqlpast . ' LIMIT ? OFFSET ?'; $quepast = $this->db->query($sqldata, [ $para['itemid'], $place, $place, $limit, $page ]); if (!$quepast) { $this->sys_error_db("[Error] get item history"); exit; } $sqltotal = "SELECT COUNT(*) AS total FROM ($sqlpast) as x "; $quetotal = $this->db->query($sqltotal, [ $para['itemid'], $place, $place, ]); if (!$quetotal) { $this->sys_error_db("[Error] get total item history"); exit; } $result = array( "records" => $quepast->result_array(), "total" => $quetotal->row_array()['total'] ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } private function safeJsonEncode($data) { // Coba encode data ke JSON $jsonData = json_encode($data); // Cek apakah terjadi error saat encode if (json_last_error() !== JSON_ERROR_NONE) { $errorMsg = json_last_error_msg(); error_log("JSON encode error: " . $errorMsg); // Lakukan sanitasi dan perbaikan data $fixedData = $this->fixJsonEncodeIssues($data, $errorMsg); // Coba encode lagi setelah diperbaiki $jsonData = json_encode($fixedData); // Jika masih error, log dan kembalikan objek kosong if (json_last_error() !== JSON_ERROR_NONE) { error_log("Failed to fix JSON encode issues: " . json_last_error_msg()); // Kembalikan objek kosong jika masih gagal return '{}'; } } return $jsonData; } // Fungsi untuk memperbaiki masalah encoding JSON private function fixJsonEncodeIssues($data, $errorMsg) { // Buat salinan data untuk dimodifikasi $fixedData = $data; // Tangani berbagai jenis error if (strpos($errorMsg, 'Malformed UTF-8') !== false) { // Perbaiki masalah karakter UTF-8 $fixedData = $this->fixUTF8Issues($fixedData); } else if (strpos($errorMsg, 'Inf and NaN cannot be JSON encoded') !== false) { // Perbaiki masalah nilai Infinity atau NaN $fixedData = $this->fixInfNanIssues($fixedData); } else { // Konversi semua nilai numerik menjadi string untuk menghindari masalah presisi $fixedData = $this->convertNumericValuesToStrings($fixedData); // Perbaiki masalah referensi recursif $fixedData = $this->fixRecursiveReferences($fixedData); } return $fixedData; } // Perbaiki masalah karakter UTF-8 private function fixUTF8Issues($data) { if (is_string($data)) { return mb_convert_encoding($data, 'UTF-8', 'UTF-8'); } else if (is_array($data)) { foreach ($data as $key => $value) { $data[$key] = $this->fixUTF8Issues($value); } } return $data; } // Perbaiki masalah nilai Infinity atau NaN private function fixInfNanIssues($data) { if (is_array($data)) { foreach ($data as $key => $value) { if (is_float($value) && (is_nan($value) || is_infinite($value))) { $data[$key] = (string)$value; // Konversi ke string } else if (is_array($value)) { $data[$key] = $this->fixInfNanIssues($value); } } } return $data; } // Perbaiki masalah referensi recursif private function fixRecursiveReferences($data, $depth = 0) { // Batasi kedalaman rekursi untuk menghindari infinite loop if ($depth > 50) { return "[MAX_DEPTH_REACHED]"; } if (is_array($data)) { $result = []; foreach ($data as $key => $value) { if (is_array($value)) { $result[$key] = $this->fixRecursiveReferences($value, $depth + 1); } else { $result[$key] = $value; } } return $result; } return $data; } // Cari dan konversi numerik ke string secara rekursif private function convertNumericValuesToStrings($data) { if (is_array($data)) { foreach ($data as $key => $value) { if (is_array($value)) { $data[$key] = $this->convertNumericValuesToStrings($value); } else if (is_numeric($value)) { $data[$key] = (string)$value; } else if (is_bool($value)) { $data[$key] = $value ? "true" : "false"; } } } return $data; } function updatePurchaseRequest() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $messages_log = []; $datas_log = []; $prm = $this->sys_input; $userId = $this->sys_user["M_UserID"]; $user = $this->sys_user; $user_name = $this->sys_user["M_UserUsername"]; $branchId = $user["M_BranchID"]; $regionalId = $user["S_RegionalID"]; $prId = isset($prm["PRID"]) ? $prm["PRID"] : ""; $prNumber = isset($prm["PRNumber"]) ? $prm["PRNumber"] : ""; $prDateUse = isset($prm["PRDateUse"]) ? $prm["PRDateUse"] : ""; $prDateUse = date("Y-m-d", strtotime($prDateUse)); if ($prDateUse == "" || $prDateUse == null) { $this->sys_error("Invalid PR Date Use"); exit; } $prRegional = isset($prm["PRRegional"]) ? $prm["PRRegional"] : ""; if ($prRegional == "" || $prRegional == null) { $this->sys_error("Invalid PR Regional"); exit; } if ($user["M_BranchID"] != "0") { $prBranch = isset($prm["PRBranch"]) ? $prm["PRBranch"] : ""; if ($prBranch == "" || $prBranch == null) { $this->sys_error("Invalid PR Branch"); exit; } } else if ($user["M_BranchID"] == "0") { $prBranch = $prm["PRBranch"]; } $prItemCategory = isset($prm["PRItemCategory"]) ? $prm["PRItemCategory"] : ""; if ($prItemCategory == "" || $prItemCategory == null) { $this->sys_error("Invalid PR Item Category"); exit; } $prDescription = isset($prm["PRDescription"]) ? $prm["PRDescription"] : ""; $items = isset($prm["items"]) ? $prm["items"] : []; if (count($items) == 0) { $this->sys_error("PR Items cannot be empty"); exit; } $this->db->trans_begin(); $status = ''; $statusdetail = ''; $status_log = 'Update'; $prStatus = ''; if ($prm["act"] == "pending") { $status = ", PurchaseRequestStatus = 'Pending'"; $statusdetail = ", PurchaseRequestDetailStatus = 'Pending'"; $status_log = 'Pending'; $prStatus = 'Pending'; } $sql = "SELECT *, changeitemcategory.ItemCategoryName as changeitemcategoryname, olditemcategory.ItemCategoryName as olditemcategoryname FROM purchase_request JOIN item_category changeitemcategory ON changeitemcategory.ItemCategoryID = PurchaseRequestItemCategoryID AND changeitemcategory.ItemCategoryIsActive = 'Y' JOIN item_category olditemcategory ON olditemcategory.ItemCategoryID = ? AND olditemcategory.ItemCategoryIsActive = 'Y' WHERE PurchaseRequestID = ? AND PurchaseRequestIsActive = 'Y'"; $query = $this->db->query($sql, [$prItemCategory, $prId]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request", $this->db); exit; } $row = $query->row_array(); $number = $row["PurchaseRequestNumber"]; $datas_log['header'] = $row; if ($row["PurchaseRequestDate"] != $prDateUse) { $messages_log[] = "Perubahan tanggal PR: " . $row["PurchaseRequestDate"] . " menjadi " . $prDateUse; } if ($row["PurchaseRequestNote"] != $prDescription) { $messages_log[] = "Perubahan keterangan PR: " . $row["PurchaseRequestNote"] . " menjadi " . $prDescription; } if ($row["changeitemcategoryname"] != $row["olditemcategoryname"]) { $messages_log[] = "Perubahan kategori item PR: " . $row["olditemcategoryname"] . " menjadi " . $row["changeitemcategoryname"]; } if ($row["PurchaseRequestStatus"] != $prStatus && $prStatus != '') { $messages_log[] = "Perubahan status PR: " . $row["PurchaseRequestStatus"] . " menjadi " . $prStatus; } $sql = "UPDATE purchase_request SET PurchaseRequestDate = ?, PurchaseRequestS_RegionalID = ?, PurchaseRequestM_BranchCode = ?, PurchaseRequestNote = ?, PurchaseRequestItemCategoryID = ?, PurchaseRequestLastUpdated = ?, PurchaseRequestLastUpdatedUserID = ? $status WHERE PurchaseRequestID = ?"; $params = [ $prDateUse, $prRegional, $prBranch, $prDescription, $prItemCategory, date("Y-m-d H:i:s"), $userId, $prId ]; $query = $this->db->query($sql, $params); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request update", $this->db); exit; } $detail_ids = []; $datas_log['new_details'] = []; $datas_log['updated_details'] = []; $datas_log['deleted_details'] = []; foreach ($items as $key => $item) { $item["total"] = floatval($item["price"]) * floatval($item["qty"]); if ($item["detailId"] == "" || intval($item["detailId"]) == 0) { $sql = "INSERT INTO purchase_request_detail ( PurchaseRequestDetailPurchaseRequestID, PurchaseRequestDetailM_ItemID, PurchaseRequestDetailItemUnitID, PurchaseRequestDetailQty, PurchaseRequestDetailPrice, PurchaseRequestDetailTotal, PurchaseRequestDetailCreated, PurchaseRequestDetailCreatedUserID $statusdetail ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; $query = $this->db->query($sql, [ $prId, $item["itemId"], $item["unitId"], $item["qty"], $item["price"], $item["total"], date("Y-m-d H:i:s"), $userId ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail insert", $this->db); exit; } $prId = $this->db->insert_id(); $detail_ids[] = $prId; $messages_log[] = "Item : " . $item["itemCode"] . " " . $item["itemDesc"] . " " . $item["unitCode"] . " " . $item["unitName"] . " " . $item["qty"] . " " . $item["price"] . " " . $item["total"] . " berhasil ditambahkan"; $datas_log['new_details'][] = $this->convertNumericValuesToStrings($item); } else { $sql = "SELECT * , newitem.M_ItemCode as newitemcode, olditem.M_ItemCode as olditemcode, newitem.M_ItemDesc as newitemdesc, olditem.M_ItemDesc as olditemdesc, newitemunit.ItemUnitCode as newitemunitcode, olditemunit.ItemUnitCode as olditemunitcode, newitemunit.ItemUnitName as newitemunitname, olditemunit.ItemUnitName as olditemunitname FROM purchase_request_detail JOIN m_item newitem ON newitem.M_ItemID = PurchaseRequestDetailM_ItemID AND newitem.M_ItemIsActive = 'Y' JOIN itemunit newitemunit ON newitemunit.ItemUnitID = ? AND newitemunit.ItemUnitIsActive = 'Y' JOIN m_item olditem ON olditem.M_ItemID = ? AND olditem.M_ItemIsActive = 'Y' JOIN itemunit olditemunit ON olditemunit.ItemUnitID = PurchaseRequestDetailItemUnitID AND olditemunit.ItemUnitIsActive = 'Y' WHERE PurchaseRequestDetailID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$item["unitId"], $item["itemId"], $item["detailId"]]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail select", $this->db); exit; } $row = $query->row_array(); if ($row["newitemcode"] != $row["olditemcode"] || $row["newitemdesc"] != $row["olditemdesc"]) { $messages_log[] = "Perubahan item : (" . $row["olditemcode"] . ") " . $row["olditemdesc"] . " menjadi (" . $row["newitemcode"] . ") " . $row["newitemdesc"]; } if ($row["newitemunitcode"] != $row["olditemunitcode"] || $row["newitemunitname"] != $row["olditemunitname"]) { $messages_log[] = "Perubahan satuan : " . $row["olditemunitname"] . " menjadi " . $row["newitemunitname"] . " pada item : (" . $row["newitemcode"] . ") " . $row["newitemdesc"]; } if ($row["PurchaseRequestDetailQty"] != $item["qty"]) { $messages_log[] = "Perubahan kuantitas : " . $row["PurchaseRequestDetailQty"] . " menjadi " . $item["qty"] . " pada item : (" . $row["newitemcode"] . ") " . $row["newitemdesc"]; } if ($row["PurchaseRequestDetailPrice"] != $item["price"]) { $messages_log[] = "Perubahan harga : " . $row["PurchaseRequestDetailPrice"] . " menjadi " . $item["price"] . " pada item : (" . $row["newitemcode"] . ") " . $row["newitemdesc"]; } $sql = "UPDATE purchase_request_detail SET PurchaseRequestDetailM_ItemID = ?, PurchaseRequestDetailItemUnitID = ?, PurchaseRequestDetailQty = ?, PurchaseRequestDetailPrice = ?, PurchaseRequestDetailTotal = ?, PurchaseRequestDetailLastUpdated = ?, PurchaseRequestDetailLastUpdatedUserID = ? $statusdetail WHERE PurchaseRequestDetailID = ?"; $query = $this->db->query($sql, [ $item["itemId"], $item["unitId"], $item["qty"], $item["price"], $item["total"], date("Y-m-d H:i:s"), $userId, $item["detailId"] ]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail update", $this->db); exit; } $detail_ids[] = $item["detailId"]; $datas_log['updated_details'][] = $this->convertNumericValuesToStrings($item); } } $sql = "SELECT * FROM purchase_request_detail WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y' AND PurchaseRequestDetailID NOT IN (" . implode(",", $detail_ids) . ")"; $query = $this->db->query($sql, [$prId]); $deleted_rows = $query->result_array(); foreach ($deleted_rows as $row) { $sql = "UPDATE purchase_request_detail SET PurchaseRequestDetailIsActive = 'N', PurchaseRequestDetailDeleted = ?, PurchaseRequestDetailDeletedUserID = ? WHERE PurchaseRequestDetailID = ?"; $query = $this->db->query($sql, [date("Y-m-d H:i:s"), $userId, $row["PurchaseRequestDetailID"]]); if (!$query) { $this->db->trans_rollback(); $this->sys_error_db("purchase request detail delete", $this->db); exit; } $messages_log[] = "Item: (" . $row["M_ItemCode"] . ") " . $row["M_ItemDesc"] . " | " . $row["ItemUnitName"] . " sebanyak " . $row["PurchaseRequestDetailQty"] . " berhasil dihapus"; $datas_log['deleted_details'][] = $this->convertNumericValuesToStrings($row); } $this->db->trans_commit(); if (count($messages_log) > 0) { $message = "Perubahan PR: " . $prNumber . "\n"; $message .= implode("\n", $messages_log); } else { $message = "PR: " . $prNumber . " tanpa perubahan"; } $datas_log = $this->convertNumericValuesToStrings($datas_log); $this->insert_act_log("PRNP", $status_log, $message, $prId, $this->safeJsonEncode($datas_log), $userId); if ($prm["act"] == "pending") { // notification $this->saveNotification($userId, $prDateUse, $number, $prId, $branchId, $regionalId); } $sql = "SELECT * FROM purchase_request_detail WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; $query = $this->db->query($sql, [$prId]); $rows = $query->result_array(); foreach ($rows as $key => $row) { $this->updatePurchaseRequestDetailLog($row, $userId); } $this->sys_ok("Purchase Request updated successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function confirmHandOver() { try { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; # validasi pr milik user # $pr = "SELECT PurchaseRequestUserID FROM purchase_request WHERE PurchaseRequestID = ?"; $qrypr = $this->db->query($pr, [$prm['purchaseRequestID']]); if (!$qrypr) { $this->sys_error_db("[Error] select pr user", $this->db); exit; } $rowpr = $qrypr->row_array(); if (!$rowpr || $rowpr['PurchaseRequestUserID'] != $user['M_UserID']) { $this->db->trans_rollback(); $this->sys_error("Anda tidak berhak mengkonfirmasi PR ini"); return; } # update confirm hand over # $sql = "UPDATE asset_handover SET AssetHandoverConfirmedAt = NOW(), AssetHandoverConfirmedBy = ?, AssetHandoverLastUpdated = NOW(), AssetHandoverUserID = ? WHERE AssetHandoverPurchaseRequestID = ?"; $qry = $this->db->query($sql, [ $user['M_UserID'], $user['M_UserID'], $prm['purchaseRequestID'] ]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update confirm hand over", $this->db); exit; } # update status purchase request # // $sql_pr = "UPDATE purchase_request // SET PurchaseRequestStatus = 'Closed', // PurchaseRequestLastUpdated = NOW(), // PurchaseRequestLastUpdatedUserID = ? // WHERE PurchaseRequestID = ?"; // $qry_pr = $this->db->query($sql_pr, [$user['M_UserID'], $prm['purchaseRequestID']]); // if (!$qry_pr) { // $this->db->trans_rollback(); // $this->sys_error_db("[Error] update status purchase request", $this->db); // exit; // } // $sql = "SELECT * // FROM purchase_request // JOIN m_user ON M_UserID = PurchaseRequestCreatedUserID // WHERE PurchaseRequestID = ?"; // $query = $this->db->query($sql, [$prm['purchaseRequestID']]); // $row = $query->row_array(); // $sql = "SELECT * FROM purchase_request_detail WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'"; // $query = $this->db->query($sql, [$prm['purchaseRequestID']]); // $rows = $query->result_array(); // $data = array( // "header" => $row, // "details" => $rows // ); // $message = "Nomor PR: " . $row["PurchaseRequestNumber"] . " telah melakukan konfirmasi serah terima oleh " . $row["M_UserUsername"]; // $this->insert_act_log("PRNP", "CONFIRM", $message, $prm['purchaseRequestID'], $this->safeJsonEncode($data), $user['M_UserID']); $this->db->trans_commit(); $this->sys_ok("Konfirmasi serah terima berhasil disimpan"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } private function updatePurchaseRequestDetailLog(array $data, int $userId) { $sql = "UPDATE acc_one_log.purchase_request_detail_log SET PurchaseRequestDetailLogType = 'CREATE', PurchaseRequestDetailLogOldQty = ?, PurchaseRequestDetailLogOldPrice = ?, PurchaseRequestDetailLogCreated = NOW(), PurchaseRequestDetailLogUserID = ? WHERE PurchaseRequestDetailLogPurchaseRequestDetailID = ? AND PurchaseRequestDetailLogPurchaseRequestID = ?"; $params = [ $data['PurchaseRequestDetailQty'] ?? null, $data['PurchaseRequestDetailPrice'] ?? null, $userId, $data['PurchaseRequestDetailID'], $data['PurchaseRequestDetailPurchaseRequestID'], ]; if (!$this->db->query($sql, $params)) { $this->sys_error_db("Gagal update purchase_request_detail_log", $this->db); $this->db->trans_rollback(); exit; } } // notifications function saveNotification($userId, $dateRequest, $number, $refID, $branchId, $regionalId) { try { $this->db->trans_begin(); $xdate = date('d-m-Y'); $sql_user = "SELECT M_UserID, M_UserUsername FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?"; $qry_user = $this->db->query($sql_user, [$userId]); if ($qry_user) { $username = $qry_user->row_array(); } else { $this->sys_error_db("select user error", $this->db); exit; } $description = "Request PR NON PERSEDIAAN pada tanggal " . $xdate . " oleh " . $username['M_UserUsername'] . " dengan nomor " . $number . ""; $sql_menu = "SELECT S_MenuID, S_MenuName, S_MenuUrl, S_MenuLevel FROM s_menu WHERE S_MenuID = 69"; $qry_menu = $this->db->query($sql_menu, []); if ($qry_menu) { $rowurl = $qry_menu->row_array(); } else { $this->sys_error_db("select menu error", $this->db); exit; } $url = $rowurl['S_MenuUrl'] . "?flag=N&status=Pending&startdate=" . $dateRequest . "&search=" . $number; // cari user penerima notifikasi if ($branchId != 0) { // user cabang $sql_receive_user = "SELECT * FROM m_user JOIN m_branch ON M_UserM_BranchID = M_BranchID AND M_BranchIsActive = 'Y' AND M_BranchID = ? WHERE M_UserIsActive = 'Y' AND M_UserM_ApproveLevelID IN (1,2)"; $qry_receive_user = $this->db->query($sql_receive_user, [$branchId]); if ($qry_receive_user) { $rowsuser = $qry_receive_user->result_array(); } else { $this->sys_error_db("select receive user error", $this->db); exit; } } else if ($branchId == 0) { // user regional $sql_receive_user = "SELECT * FROM m_user JOIN s_regional ON M_UserS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y' AND S_RegionalID = ? WHERE M_UserIsActive = 'Y' AND M_UserM_BranchID = 0 AND M_UserM_ApproveLevelID IN (1,2)"; $qry_receive_user = $this->db->query($sql_receive_user, [$regionalId]); if ($qry_receive_user) { $rowsuser = $qry_receive_user->result_array(); } else { $this->sys_error_db("select receive user error", $this->db); exit; } } $sql = "INSERT INTO notification( NotificationRefID, NotificationType, NotificationDescription, NotificationUrl, NotificationUserID, NotificationCreated) VALUES(?,?,?,?,?,NOW())"; $qry = $this->db->query($sql, [ $refID, 'Purchase Request (P)', $description, $url, $userId ]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("insert notification error", $this->db); exit; } $lastid = $this->db->insert_id(); // insert ke detail notification foreach ($rowsuser as $row) { $sql_detail = "INSERT INTO notification_detail( NotificationDetailNotificationID, NotificationDetailM_UserID, NotificationDetailM_ApproveLevelID, NotificationDetailStatus, NotificationDetailCreated, NotificationDetailUserID) VALUES(?,?,?,?,NOW(),?)"; $qry_detail = $this->db->query($sql_detail, [ $lastid, $row['M_UserID'], // user penerima notifikasi $row['M_UserM_ApproveLevelID'], 'unread', $userId ]); if (!$qry_detail) { $this->db->trans_rollback(); $this->sys_error_db("insert notification detail error", $this->db); exit; } } $this->db->trans_commit(); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } }