Files
be-accone/application/controllers/mockup/itemout/Itemoutv3.php

3045 lines
117 KiB
PHP

<?php
class Itemoutv3 extends MY_Controller
{
var $db;
public function index()
{
echo "Item Out/Requester API";
}
public function __construct()
{
parent::__construct();
}
// jika jumlah item out sebagian maka status request item out menjadi partial
// jika jumlah item out komplit maka status request item out menjadi completed
public function saveRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$date = isset($prm["date"]) ? $prm["date"] : "";
if ($date == "" || $date == null) {
$this->sys_error("Invalid Date Use");
exit;
}
$warehouseID = isset($prm["warehouseID"]) ? $prm["warehouseID"] : "";
if ($warehouseID == "" || $warehouseID == null) {
$this->sys_error("Warehouse masih kosong");
exit;
}
$note = "";
if (isset($prm["note"])) {
$note = trim($prm["note"]);
}
$divisionID = isset($prm["divisionID"]) ? $prm["divisionID"] : "";
if ($divisionID == "" || $divisionID == null) {
$this->sys_error("Division masih kosong");
exit;
}
$items = isset($prm["items"]) ? $prm["items"] : [];
if (count($items) == 0) {
$this->sys_error("Items cannot be empty");
exit;
}
$sqlnum = "SELECT `fn_numbering`('IO') as IOnumber";
$qrynum = $this->db->query($sqlnum, []);
$IOnumber = $qrynum->row()->IOnumber;
$sqlIO = "INSERT INTO t_item_out (
T_ItemOutDate,
T_ItemOutNumber,
T_ItemOutWarehouseID,
T_ItemOutNote,
T_ItemOutDivisionID,
T_ItemOutStatus,
T_ItemOutIsActive,
T_ItemOutUserID,
T_ItemOutCreated,
T_ItemOutLastUpdated) VALUES(?,?,?,?,?,'Draft','Y',?,NOW(),NOW())";
$qryIO = $this->db->query($sqlIO, [
$date,
$IOnumber,
$warehouseID,
$note,
$divisionID,
$userId
]);
if (!$qryIO) {
$this->db->trans_rollback();
$this->sys_error_db("Failed to insert data table item out", $this->db);
}
$ioId = $this->db->insert_id();
// Kelompokkan item berdasarkan rioID
$grouped = [];
foreach ($items as $item) {
$grouped[$item['rioID']][] = $item;
}
foreach ($grouped as $rioID => $itemGroup) {
$statusHeader = 'Completed';
foreach ($itemGroup as $item) {
$receiveQty = intval($item['rioDReceiveQty']);
// encode json list batch number
$jsonBatchNo = "[]";
if (isset($item['ItemRequest']) && is_array($item['ItemRequest'])) {
$batches = $item['ItemRequest'];
if (sizeof($batches) > 0) {
$jsonResult = json_encode($batches);
if ($jsonResult === false) {
throw new Exception("[Error] Failed to encode json batch number");
} else {
$jsonBatchNo = $jsonResult;
}
}
}
// transaksi insert item out detail
$sql = "INSERT INTO t_item_out_detail(
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailRequestItemOutID,
T_ItemOutDetailRequestItemOutDetailID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailItemBatchNo,
T_ItemOutDetailQty,
T_ItemOutDetailCreated,
T_ItemOutDetailUserID) VALUES(?, ?, ?, ?, ?, ?, ?, NOW(), ?)";
$qry = $this->db->query($sql, [
$ioId,
$item["rioID"],
$item["rioDID"],
$item["itemID"],
$item["unitID"],
$jsonBatchNo,
$receiveQty,
$userId
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("failed to insert data table item out detail", $this->db);
exit;
}
$isPartial = intval($receiveQty) < intval($item['rioDQty']);
$detailStatus = $isPartial ? 'Partial' : 'Completed';
if ($isPartial) {
$statusHeader = 'Partial'; // Jika ada satu saja partial, status header ikut partial
}
// Update request item out detail
$sqlDetail = "UPDATE request_item_out_detail SET
RequestItemOutDetailStatus = ?,
RequestItemOutDetailLastUpdated = NOW(),
RequestItemOutDetailUserID = ?
WHERE RequestItemOutDetailID = ?";
$queryDetail = $this->db->query($sqlDetail, [
$detailStatus,
$userId,
$item['rioDID']
]);
if (!$queryDetail) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update detail RIO", $this->db);
exit;
}
}
$sqlHeader = "UPDATE request_item_out SET
RequestItemOutStatus = ?,
RequestItemOutUserID = ?,
RequestItemOutLastUpdated = NOW()
WHERE RequestItemOutID = ?";
$queryHeader = $this->db->query($sqlHeader, [
$statusHeader,
$userId,
$rioID
]);
if (!$queryHeader) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update header RIO", $this->db);
exit;
}
$userdesc = "Transaksi item out dengan kode " . $IOnumber . " telah di buat";
$this->insertUserActivityIo($ioId, $userId, "DRAFT", $userdesc);
// Insert user activity (log)
$this->insertUserActivityRio($rioID, $userId, $statusHeader);
}
// transaksi pengurangan stockqty
foreach ($items as $key => $item) {
// array stock request per batch
foreach ($item["ItemRequest"] as $k => $v) {
// update stock
$stockupd = "UPDATE stock
SET StockQty = StockQty - ?
WHERE StockID = ?
AND StockWarehouseID = ?";
$stockupd = $this->db->query($stockupd, [
intval($v["QtyReq"]),
$v["StockID"],
$v["WarehouseID"]
]);
if (!$stockupd) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update stock qty item out", $this->db);
exit;
}
$receiveQty = intval($v['QtyReq']);
$currentQty = intval($v['StockQty']);
$remainingQty = max(0, $currentQty - $receiveQty);
// insert stockcard
$sqlcard = "INSERT INTO stockcard (
StockCardWarehouseID,
StockCardDatetime,
StockCardItemID,
StockCardItemUnitID,
StockCardBatchNo,
StockCardED,
StockCardReffID,
StockCardStatus,
StockCardBefore,
StockCardIn,
StockCardOut,
StockCardAfter,
StockCardUserID
) VALUES (?, NOW(), ?, ?, ?, ?, ?, 'IO', ?, 0, ?, ?, ?)";
$qrycard = $this->db->query($sqlcard, array(
$v["WarehouseID"],
$v["StockItemID"],
$v["StockItemUnitID"],
$v["StockBatchNo"],
$v["StockED"],
$v["StockID"],
$currentQty,
$receiveQty,
$remainingQty,
$userId
));
if (!$qrycard) {
$this->db->trans_rollback();
$this->sys_error_db("Error insert stock card", $this->db);
exit;
}
// insert into stocklog
$sqllog = "INSERT INTO stocklog (
StockLogWarehouseID,
StockLogDateTime,
StockLogItemID,
StockLogItemUnitID,
StockLogStockNumber,
StockLogBatchNo,
StockLogED,
StockLogReffID,
StockLogStatus,
StockLogQty,
StockLogUserID
) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?)";
$qrylog = $this->db->query($sqllog, [
$v["WarehouseID"],
$v["StockItemID"],
$v["StockItemUnitID"],
$v["StockStockNumber"],
$v["StockBatchNo"],
$v["StockED"],
$v["StockID"],
'IO',
$receiveQty,
$userId,
]);
if (!$qrylog) {
$this->db->trans_rollback();
$this->sys_error_db("Error insert stocklog", $this->db);
exit;
}
}
}
$this->db->trans_commit();
$result = array(
"total" => 1,
"affected_rows" => $this->db->affected_rows()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getItemOuts()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$ioID = isset($prm["ioID"]) ? $prm["ioID"] : "";
if ($ioID == "" || $ioID == null) {
$this->sys_error("Invalid item out ID");
exit;
}
$sql = "SELECT
T_ItemOutDetailID,
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailRequestItemOutID,
T_ItemOutDetailRequestItemOutDetailID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailItemBatchNo,
T_ItemOutDetailQty,
T_ItemOutID,
T_ItemOutDate,
T_ItemOutNumber,
T_ItemOutNote,
RequestItemOutDetailID,
RequestItemOutDetailReceiveQty,
RequestItemOutDetailQty,
IFNULL(RequestItemOutDetailQty, 0) - IFNULL(T_ItemOutDetailQty, 0) as remainingRequestQty,
M_ItemID,
M_ItemDesc,
ItemUnitID,
ItemUnitCode,
ItemUnitName,
CASE
WHEN WarehouseType = 'B' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', M_BranchName)
WHEN WarehouseType = 'R' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', S_RegionalName)
ELSE ''
END WarehouseName,
WarehouseID,
StockID,
StockWarehouseID,
StockWarehouseAlmariID,
StockWarehouseRackID,
StockStockNumber,
StockItemID,
StockItemUnitID,
StockItemPrice,
StockBatchNo,
StockED,
StockLastUpdated,
StockUserID,
SUM(stock.StockQty) AS StockQty
FROM t_item_out_detail
JOIN t_item_out ON T_ItemOutDetailT_ItemOutID = T_ItemOutID
AND T_ItemOutIsActive = 'Y'
JOIN warehouse ON T_ItemOutWarehouseID = WarehouseID
JOIN request_item_out_detail ON T_ItemOutDetailRequestItemOutDetailID = RequestItemOutDetailID
AND RequestItemOutDetailIsActive = 'Y'
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN itemunit ON T_ItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN stock ON StockItemID = T_ItemOutDetailM_ItemID
AND StockItemUnitID = T_ItemOutDetailItemUnitID
AND StockWarehouseID = T_ItemOutWarehouseID
JOIN s_regional ON WarehouseS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y'
LEFT JOIN m_branch ON WarehouseM_BranchID = M_BranchID AND M_BranchIsActive = 'Y'
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
GROUP BY T_ItemOutDetailID
ORDER BY T_ItemOutDetailID DESC";
$qry = $this->db->query($sql, [$ioID]);
if (!$qry) {
$this->sys_error_db("ERROR, get detail item out data", $this->db);
exit;
}
$rows = $qry->result_array();
foreach ($rows as $key => $value) {
$jsonStr = $value['T_ItemOutDetailItemBatchNo'];
$batches = [];
if (!empty($jsonStr)) {
$decode = json_decode($jsonStr);
if ($decode !== null && json_last_error() === JSON_ERROR_NONE) {
$batches = $decode;
} else {
$this->sys_error_db("[Error] decode json for batches number");
exit;
}
}
$rows[$key]['ItemRequest'] = $batches;
unset($rows[$key]['T_ItemOutDetailItemBatchNo']);
}
$result = array(
"records" => $rows
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function confirmIO()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$ioID = isset($prm["ioID"]) ? $prm["ioID"] : "";
if ($ioID == "" || $ioID == null) {
$this->sys_error("Item out ID not found");
exit;
}
$sql_update = "UPDATE t_item_out SET
T_ItemOutIsConfirmDate = NOW(),
T_ItemOutIsConfirm = 'Y',
T_ItemOutUserID = ?,
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qry_update = $this->db->query($sql_update, [$userId, $ioID]);
if (!$qry_update) {
$this->db->trans_rollback();
$this->sys_error_db("Gagal konfirmasi", $this->db);
exit;
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$ioID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di konfirmasi";
$this->insertUserActivityIo($ioID, $userId, "CONFIRM", $userdesc);
$this->db->trans_commit();
$result = array(
"total" => 1,
"affected_rows" => $this->db->affected_rows()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function approveIO()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$ioID = isset($prm["ioID"]) ? $prm["ioID"] : "";
if ($ioID == "" || $ioID == null) {
$this->sys_error("Item out ID not found");
exit;
}
$sqlApp = "UPDATE t_item_out SET
T_ItemOutApproveDate = NOW(),
T_ItemOutApproveID = ?
WHERE T_ItemOutID = ?";
$qryApp = $this->db->query($sqlApp, [
$userId,
$ioID
]);
if (!$qryApp) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update approve failed", $this->db);
exit;
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$ioID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di approve";
$this->insertUserActivityIo($ioID, $userId, "Approve", $userdesc);
$this->db->trans_commit();
$result = array(
"total" => 1,
"affected_rows" => $this->db->affected_rows()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function processIO()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$ioID = isset($prm["ioID"]) ? $prm["ioID"] : "";
if ($ioID == "" || $ioID == null) {
$this->sys_error("Item out ID not found");
exit;
}
$items = isset($prm["items"]) ? $prm["items"] : [];
if (count($items) == 0) {
$this->sys_error("Items cannot be empty");
exit;
}
$sqlApp = "UPDATE t_item_out SET
T_ItemOutStatus = 'Process',
T_ItemOutReceiveUserID = ?,
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qryApp = $this->db->query($sqlApp, [
$userId,
$ioID
]);
if (!$qryApp) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update Process failed", $this->db);
exit;
}
foreach ($items as $key => $item) {
$sqlQty = "UPDATE request_item_out_detail SET
RequestItemOutDetailQty = RequestItemOutDetailQty - ?,
RequestItemOutDetailLastUpdated = NOW(),
RequestItemOutDetailUserID = ?
WHERE RequestItemOutDetailID = ?";
$qryQty = $this->db->query($sqlQty, [
intval($item["T_ItemOutDetailQty"]),
$userId,
$item["T_ItemOutDetailRequestItemOutDetailID"]
]);
if (!$qryQty) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update qty request failed", $this->db);
exit;
}
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$ioID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di approve";
$this->insertUserActivityIo($ioID, $userId, "Process", $userdesc);
// generate jurnal sudah tidak dipakai 22-08-2025
// $this->generateJurnal($ioID);
// Insert item usage
$this->insertUsage($ioID, $userId);
$this->db->trans_commit();
$result = array(
"total" => 1,
"affected_rows" => $this->db->affected_rows()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
function insertUserActivityIo($ioID, $userId, $status, $userdesc)
{
try {
// insert log
$sql_json = "SELECT t_item_out.*, '' as detail
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry_json = $this->db->query($sql_json, [$ioID]);
if (!$qry_json) {
$this->db->trans_rollback();
$this->sys_error_db("select json io error");
exit;
}
$row_json = $qry_json->row_array();
$sql_json_detail = "SELECT t_item_out_detail.*
FROM t_item_out_detail
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?";
$qry_json_detail = $this->db->query($sql_json_detail, [$ioID]);
if ($qry_json_detail) {
$row_json["detail"] = $qry_json_detail->result_array();
} else {
$this->sys_error_db("select detail io error", $this->db);
exit;
}
$data_json = $row_json;
$sql_log = "INSERT INTO user_activity(
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
UserActivityRefID,
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES('IO',?,?,?,?,?,NOW())";
$qry_log = $this->db->query($sql_log, [
$status,
$userdesc,
$ioID,
json_encode($data_json),
$userId
]);
if (!$qry_log) {
$this->db->trans_rollback();
$this->sys_error_db("insert user activity error", $this->db);
exit;
}
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
function insertUserActivityRio($rioID, $userId, $status)
{
try {
// insert log
$sql_json = "SELECT request_item_out.*, '' as detail
FROM request_item_out
WHERE RequestItemOutIsActive = 'Y'
AND RequestItemOutID = ?";
$qry_json = $this->db->query($sql_json, [$rioID]);
if (!$qry_json) {
$this->db->trans_rollback();
$this->sys_error_db("select json rio error");
exit;
}
$row_json = $qry_json->row_array();
if ($status == "Partial") {
$userdesc = "Request Item out dengan kode " . $row_json['RequestItemOutNumber'] . " telah di kirim sebagian";
} else {
$userdesc = "Request Item out dengan kode " . $row_json['RequestItemOutNumber'] . " telah komplit";
}
$sql_json_detail = "SELECT request_item_out_detail.*
FROM request_item_out_detail
WHERE RequestItemOutDetailIsActive = 'Y'
AND RequestItemOutDetailRequestItemOutID = ?";
$qry_json_detail = $this->db->query($sql_json_detail, [$rioID]);
if ($qry_json_detail) {
$row_json["detail"] = $qry_json_detail->result_array();
} else {
$this->sys_error_db("select detail rio error", $this->db);
exit;
}
$data_json = $row_json;
$sql_log = "INSERT INTO user_activity(
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
UserActivityRefID,
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES('RIO',?,?,?,?,?,NOW())";
$qry_log = $this->db->query($sql_log, [
$status,
$userdesc,
$rioID,
json_encode($data_json),
$userId
]);
if (!$qry_log) {
$this->db->trans_rollback();
$this->sys_error_db("insert user activity error", $this->db);
exit;
}
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
function formatRupiah($angka)
{
// Ganti koma ke titik agar jadi desimal yang valid
$angka = str_replace(',', '.', $angka);
// Validasi input
if (!is_numeric($angka)) {
return 'Input tidak valid';
}
// Konversi ke float
$angka = (float)$angka;
// Bulatkan ke 3 angka desimal
$angka = round($angka, 3);
// Cek apakah angka desimalnya nol
if (fmod($angka, 1) == 0.0) {
// Tanpa desimal
$formatted = number_format($angka, 0, ',', '.');
} else {
// Dengan 3 angka desimal
$formatted = number_format($angka, 3, ',', '.');
}
return 'Rp ' . $formatted;
}
public function search()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$startDate = $prm["startDate"];
$endDate = $prm["endDate"];
$search = "";
if (isset($prm['search'])) {
$search = trim($prm["search"]);
if ($search != "") {
$search = '%' . $prm['search'] . '%';
} else {
$search = '%%';
}
}
$status = $prm["status"];
$filter = "";
if ($status != 'All') {
$filter .= " AND T_ItemOutStatus = '{$status}'";
}
$number_offset = 0;
$number_limit = 10;
if ($prm["current_page"] > 0) {
$number_offset = ($prm["current_page"] - 1) * $number_limit;
}
$sqlCount = "SELECT count(*) as total
FROM t_item_out
JOIN warehouse ON T_ItemOutWarehouseID = WarehouseID
AND WarehouseIsActive = 'Y'
JOIN division ON T_ItemOutDivisionID = DivisionID
AND DivisionIsActive = 'Y'
JOIN s_regional ON WarehouseS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y'
LEFT JOIN m_branch ON WarehouseM_BranchID = M_BranchID AND M_BranchIsActive = 'Y'
WHERE T_ItemOutIsActive = 'Y'
AND (T_ItemOutDate BETWEEN ? AND ?)
AND (T_ItemOutNumber LIKE ?)
$filter
ORDER BY T_ItemOutNumber DESC";
$qryCount = $this->db->query($sqlCount, [
$startDate,
$endDate,
$search
]);
$tot_count = 0;
$tot_page = 0;
if ($qryCount) {
$tot_count = $qryCount->result_array()[0]["total"];
$tot_page = ceil($tot_count / $number_limit);
} else {
$this->sys_error_db("item out count error", $this->db);
exit;
}
$sql = "SELECT T_ItemOutID,
T_ItemOutDate,
T_ItemOutNumber,
T_ItemOutNote,
T_ItemOutReceiveUserID,
T_ItemOutStatus,
T_ItemOutApproveID,
T_ItemOutIsConfirm,
WarehouseID,
WarehouseCode,
CASE
WHEN WarehouseType = 'B' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', M_BranchName)
WHEN WarehouseType = 'R' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', S_RegionalName)
ELSE ''
END WarehouseName,
WarehouseType,
DivisionID,
DivisionCode,
DivisionName
FROM t_item_out
JOIN warehouse ON T_ItemOutWarehouseID = WarehouseID
AND WarehouseIsActive = 'Y'
JOIN division ON T_ItemOutDivisionID = DivisionID
AND DivisionIsActive = 'Y'
JOIN s_regional ON WarehouseS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y'
LEFT JOIN m_branch ON WarehouseM_BranchID = M_BranchID AND M_BranchIsActive = 'Y'
WHERE T_ItemOutIsActive = 'Y'
AND (T_ItemOutDate BETWEEN ? AND ?)
AND (T_ItemOutNumber LIKE ?)
$filter
ORDER BY T_ItemOutNumber DESC
LIMIT ? OFFSET ?";
$qry = $this->db->query($sql, [
$startDate,
$endDate,
$search,
$number_limit,
$number_offset
]);
// echo $this->db->last_query();
// exit;
if ($qry) {
$rows = $qry->result_array();
} else {
$this->sys_error_db("get item out error", $this->db);
exit;
}
$result = array(
"totalPage" => $tot_page,
"totalFilter" => $tot_count,
"records" => $rows
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getWarehouse()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$regionalID = $prm["regionalID"];
$branchCode = $prm["branchCode"];
$filterBranch = "";
if (!$branchCode == "") {
$filterBranch .= " AND M_BranchCode = '{$branchCode}'";
}
$sql = "SELECT WarehouseID,
WarehouseCode,
CASE
WHEN WarehouseType = 'B' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', M_BranchName)
WHEN WarehouseType = 'R' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', S_RegionalName)
ELSE ''
END WarehouseName,
WarehouseType,
WarehouseIsDefault,
S_RegionalID,
S_RegionalName
FROM warehouse
JOIN s_regional ON WarehouseS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y'
LEFT JOIN m_branch ON WarehouseM_BranchID = M_BranchID AND M_BranchIsActive = 'Y'
WHERE WarehouseIsActive = 'Y'
AND WarehouseIsTransit = 'N'
AND WarehouseS_RegionalID = ?
$filterBranch
ORDER BY WarehouseID ASC
";
$qry = $this->db->query($sql, [$regionalID]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("get warehouse", $this->db);
exit;
}
$rows = $qry->result_array();
$result = array(
"records" => $rows,
"sql" => $this->db->last_query()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getDepartment()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$sql = "SELECT M_DepartmentID,
M_DepartmentCode,
M_DepartmentName
FROM m_department
WHERE M_DepartmentIsActive = 'Y'
ORDER BY M_DepartmentName ASC";
$qry = $this->db->query($sql, []);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("get Department", $this->db);
exit;
}
$rows = $qry->result_array();
$result = array(
"records" => $rows,
"sql" => $this->db->last_query()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getDivisionByUser()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
// $userId = $this->sys_user["M_UserID"];
$prm = $this->sys_input;
$userId = $prm["userId"];
$rows = [];
$query = "SELECT DISTINCT
DivisionID,
DivisionCode,
DivisionName
FROM division
WHERE DivisionIsActive = 'Y'
ORDER BY DivisionName ASC";
$exec = $this->db->query($query);
if ($exec) {
$rows = $exec->result_array();
} else {
$this->db->trans_rollback();
$this->sys_error_db("select division", $this->db);
exit;
}
if ($prm["act"] == "edit") {
$sql = "SELECT DISTINCT
DivisionID,
DivisionCode,
DivisionName
FROM division
JOIN m_userdivision ON M_UserDivisionDivisionID = DivisionID
WHERE DivisionIsActive = 'Y'
AND DivisionID = ?
ORDER BY M_UserDivisionID DESC
LIMIT 1";
$exec = $this->db->query($sql, [$prm["DivisionID"]]);
if ($exec) {
$row = $exec->result_array();
} else {
$this->sys_error_db("select division", $this->db);
exit;
}
} else {
$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) {
$row = $exec->result_array();
} 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);
}
}
public function getDetailItemOut()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$itemoutID = isset($prm["itemoutID"]) ? $prm["itemoutID"] : "";
if ($itemoutID == "" || $itemoutID == null) {
$this->sys_error("Invalid item out ID");
exit;
}
$sql = "SELECT
T_ItemOutDetailID as ioDetailID,
T_ItemOutDetailT_ItemOutID as ioDetailioID,
T_ItemOutDetailRequestItemOutID as ioDetailRequestioID,
T_ItemOutDetailM_ItemID as ioDetailItemID,
T_ItemOutDetailItemUnitID as ioDetailUnitID,
T_ItemOutDetailItemBatchNo,
IFNULL(T_ItemOutDetailQty, 0) as rioDReceiveQty,
T_ItemOutID as ioID,
T_ItemOutDate as ioDate,
T_ItemOutNumber as ioNumber,
T_ItemOutWarehouseID as ioWarehouseID,
T_ItemOutNote as ioNote,
T_ItemOutDivisionID as ioDivisionID,
RequestItemOutID as rioID,
RequestItemOutNumber as rioNumber,
RequestItemOutDetailID as rioDID,
RequestItemOutDetailM_ItemID as rioDItemID,
RequestItemOutDetailItemUnitID as rioDItemUnitID,
RequestItemOutDetailQty as rioDQty,
M_ItemID as itemID,
M_ItemCode as itemCode,
M_ItemDesc as itemDesc,
ItemUnitID as unitID,
ItemUnitCode as unitCode,
ItemUnitName as unitName,
StockID,
StockWarehouseID,
StockWarehouseAlmariID,
StockWarehouseRackID,
StockStockNumber,
StockItemID,
StockItemUnitID,
StockItemPrice,
StockBatchNo,
StockED,
StockLastUpdated,
StockUserID,
SUM(stock.StockQty) as StockQty
FROM t_item_out_detail
JOIN t_item_out ON T_ItemOutDetailT_ItemOutID = T_ItemOutID
AND T_ItemOutIsActive = 'Y'
JOIN request_item_out ON T_ItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
JOIN request_item_out_detail ON RequestItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutDetailM_ItemID = T_ItemOutDetailM_ItemID
AND RequestItemOutDetailItemUnitID = T_ItemOutDetailItemUnitID
AND RequestItemOutDetailIsActive = 'Y'
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN itemunit ON T_ItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN stock ON StockItemID = T_ItemOutDetailM_ItemID
AND StockItemUnitID = T_ItemOutDetailItemUnitID
AND StockWarehouseID = T_ItemOutWarehouseID
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
GROUP BY T_ItemOutDetailID
ORDER BY T_ItemOutDetailID DESC";
$qry = $this->db->query($sql, [$itemoutID]);
if (!$qry) {
$this->sys_error_db('ERROR, get detail item out', $this->db);
exit;
}
$rows = $qry->result_array();
foreach ($rows as $key => $value) {
$jsonStr = $value['T_ItemOutDetailItemBatchNo'];
$batches = [];
if (!empty($jsonStr)) {
$decode = json_decode($jsonStr);
if ($decode !== null && json_last_error() === JSON_ERROR_NONE) {
$batches = $decode;
} else {
$this->sys_error_db("[Error] decode json for batches number");
exit;
}
}
$rows[$key]['ItemRequest'] = $batches;
unset($rows[$key]['T_ItemOutDetailItemBatchNo']);
}
$result = array(
"records" => $rows
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function updateRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$date = isset($prm["date"]) ? $prm["date"] : "";
if ($date == "" || $date == null) {
$this->sys_error("Invalid Date Use");
exit;
}
$warehouseID = isset($prm["warehouseID"]) ? $prm["warehouseID"] : "";
if ($warehouseID == "" || $warehouseID == null) {
$this->sys_error("Warehouse masih kosong");
exit;
}
$note = "";
if (isset($prm["note"])) {
$note = trim($prm["note"]);
}
$divisionID = isset($prm["divisionID"]) ? $prm["divisionID"] : "";
if ($divisionID == "" || $divisionID == null) {
$this->sys_error("Division masih kosong");
exit;
}
$IOID = isset($prm["IOID"]) ? $prm["IOID"] : "";
if ($IOID == "" || $IOID == null) {
$this->sys_error("item out ID masih kosong");
exit;
}
$items = isset($prm["items"]) ? $prm["items"] : [];
if (count($items) == 0) {
$this->sys_error("Items cannot be empty");
exit;
}
$sql = "UPDATE t_item_out SET
T_ItemOutDate = ?,
T_ItemOutWarehouseID = ?,
T_ItemOutNote = ?,
T_ItemOutDivisionID = ?,
T_ItemOutUserID = ?,
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qry = $this->db->query($sql, [
$date,
$warehouseID,
$note,
$divisionID,
$userId,
$IOID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed update item out", $this->db);
exit;
}
$sql = "SELECT T_ItemOutDetailID
FROM t_item_out_detail
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?";
$qry = $this->db->query($sql, [$IOID]);
if (!$qry) {
$this->sys_error_db("select item out detail error", $this->db);
exit;
}
$dbIoDetailIDs = array_column($qry->result_array(), 'T_ItemOutDetailID');
// Buat array ioDetailID dari frontend
$activeIoDetailIDs = [];
foreach ($items as $item) {
if (!empty($item["ioDetailID"])) {
$activeIoDetailIDs[] = $item["ioDetailID"];
}
}
// Cari ID yang harus di-nonaktifkan (yang ada di database tapi tidak ada di frontend)
$toDeactivateIDs = array_diff($dbIoDetailIDs, $activeIoDetailIDs);
// Jika ada yang perlu di-deactivate
if (!empty($toDeactivateIDs)) {
$placeholders = implode(',', array_fill(0, count($toDeactivateIDs), '?'));
$sql = "UPDATE t_item_out_detail SET
T_ItemOutDetailIsActive = 'N',
T_ItemOutDetailLastUpdated = NOW(),
T_ItemOutDetailUserID = ?
WHERE T_ItemOutDetailID IN ($placeholders)";
$params = array_merge([$userId], $toDeactivateIDs);
$qry = $this->db->query($sql, $params);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, batch deactivate item out detail");
exit;
}
}
// Sekarang update atau insert yang dikirim frontend
foreach ($items as $item) {
$ioupdetailID = $item["ioDetailID"];
// encode json list batch number
$jsonBatchNo = "[]";
if (isset($item['ItemRequest']) && is_array($item['ItemRequest'])) {
$batches = $item['ItemRequest'];
if (sizeof($batches) > 0) {
$jsonResult = json_encode($batches);
if ($jsonResult === false) {
throw new Exception("[Error] Failed to encode json batch number");
} else {
$jsonBatchNo = $jsonResult;
}
}
}
if ($ioupdetailID) {
// UPDATE existing
$sql = "UPDATE t_item_out_detail SET
T_ItemOutDetailItemBatchNo = ?,
T_ItemOutDetailQty = ?,
T_ItemOutDetailLastUpdated = NOW(),
T_ItemOutDetailUserID = ?
WHERE T_ItemOutDetailID = ?";
$qry = $this->db->query($sql, [
$jsonBatchNo,
intval($item["rioDReceiveQty"]),
$userId,
$ioupdetailID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("ERROR, update item out detail");
exit;
}
} else {
// INSERT baru
$sql = "INSERT INTO t_item_out_detail(
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailRequestItemOutID,
T_ItemOutDetailRequestItemOutDetailID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailItemBatchNo,
T_ItemOutDetailQty,
T_ItemOutDetailCreated,
T_ItemOutDetailUserID) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), ?)";
$qry = $this->db->query($sql, [
$IOID,
$item["rioID"],
$item["rioDID"],
$item["itemID"],
$item["unitID"],
$jsonBatchNo,
intval($item["rioDReceiveQty"]),
$userId
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("failed to insert data table item out detail", $this->db);
exit;
}
}
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$IOID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di edit";
$this->insertUserActivityIo($IOID, $userId, "UPDATE", $userdesc);
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function rejectRequest()
{
try {
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$IOID = "";
if (isset($prm["IOID"])) {
$IOID = trim($prm["IOID"]);
}
$sql = "UPDATE t_item_out SET
T_ItemOutStatus = 'Rejected',
T_ItemOutUserID = ?,
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qry = $this->db->query($sql, [
$userId,
$IOID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed delete item out", $this->db);
exit;
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$IOID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di reject";
$this->insertUserActivityIo($IOID, $userId, "REJECTED", $userdesc);
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function deleteRequest()
{
try {
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$IOID = "";
if (isset($prm["IOID"])) {
$IOID = trim($prm["IOID"]);
}
$sql = "UPDATE t_item_out SET
T_ItemOutIsActive = 'N',
T_ItemOutUserID = ?,
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qry = $this->db->query($sql, [
$userId,
$IOID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed delete item out", $this->db);
exit;
}
$sqldetail = "UPDATE t_item_out_detail SET
T_ItemOutDetailIsActive = 'N',
T_ItemOutDetailLastUpdated = NOW(),
T_ItemOutDetailUserID = ?
WHERE T_ItemOutDetailT_ItemOutID = ?";
$qrydetail = $this->db->query($sqldetail, [
$userId,
$IOID
]);
if (!$qrydetail) {
$this->db->trans_rollback();
$this->sys_error_db("Failed delete item out detail", $this->db);
exit;
}
$sqlstatus = "UPDATE request_item_out SET
RequestItemOutStatus = 'Process',
RequestItemOutUserID = ?,
RequestItemOutLastUpdated = NOW()
WHERE RequestItemOutID = ?";
$qrystatus = $this->db->query($sqlstatus, [
$userId,
$prm["RIOID"]
]);
if (!$qrystatus) {
$this->db->trans_rollback();
$this->sys_error_db("Failed update request item out status", $this->db);
exit;
}
$sqlstatusdetail = "UPDATE request_item_out_detail SET
RequestItemOutDetailStatus = 'Process',
RequestItemOutDetailLastUpdated = NOW(),
RequestItemOutDetailUserID = ?
WHERE RequestItemOutDetailID = ?";
$qrystatusdetail = $this->db->query($sqlstatusdetail, [
$userId,
$prm["RIODID"]
]);
if (!$qrystatusdetail) {
$this->db->trans_rollback();
$this->sys_error_db("Failed update request item out detail status", $this->db);
exit;
}
$sql = "SELECT t_item_out.*
FROM t_item_out
WHERE T_ItemOutIsActive = 'Y'
AND T_ItemOutID = ?";
$qry = $this->db->query($sql, [$IOID]);
if (!$qry) {
$this->sys_error_db("select item out error", $this->db);
exit;
}
$row = $qry->row();
$userdesc = "Transaksi item out dengan kode " . $row->T_ItemOutNumber . " telah di hapus";
$this->insertUserActivityIo($IOID, $userId, "DELETE", $userdesc);
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function searchDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$search = "";
if (isset($prm['search'])) {
$search = trim($prm["search"]);
if ($search != "") {
$search = '%' . $prm['search'] . '%';
} else {
$search = '%%';
}
}
$IOID = "";
if (isset($prm["IOID"])) {
$IOID = trim($prm["IOID"]);
}
$number_offset = 0;
$number_limit = 10;
if ($prm["current_page"] > 0) {
$number_offset = ($prm["current_page"] - 1) * $number_limit;
}
$sqlCount = "SELECT count(*) as total
FROM t_item_out_detail
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN itemunit ON T_ItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
ORDER BY T_ItemOutDetailID DESC";
$qryCount = $this->db->query($sqlCount, [
$IOID
]);
$tot_count = 0;
$tot_page = 0;
if ($qryCount) {
$tot_count = $qryCount->result_array()[0]["total"];
$tot_page = ceil($tot_count / $number_limit);
} else {
$this->sys_error_db("item out detail count error", $this->db);
exit;
}
$sql = "SELECT T_ItemOutDetailID,
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailQty,
M_ItemID,
M_ItemCode,
M_ItemDesc,
ItemUnitID,
ItemUnitCode,
ItemUnitName,
ROW_NUMBER() OVER(ORDER BY T_ItemOutDetailID) RowNumber
FROM t_item_out_detail
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN itemunit ON T_ItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
ORDER BY T_ItemOutDetailID DESC
LIMIT ? OFFSET ?";
$qry = $this->db->query($sql, [
$IOID,
$number_limit,
$number_offset
]);
if ($qry) {
$rows = $qry->result_array();
} else {
$this->sys_error_db("get item out detail error", $this->db);
exit;
}
$result = array(
"totalPage" => $tot_page,
"totalFilter" => $tot_count,
"records" => $rows
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function searchItem()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$prm = $this->sys_input;
$search = "";
if (isset($prm["search"])) {
$search = trim($prm["search"]);
if ($search != "") {
$search = "%" . $prm["search"] . "%";
} else {
$search = "%%";
}
}
$warehouseID = $prm["warehouseID"];
$number_limit = 10;
$sql = "SELECT
M_ItemID,
M_ItemCode,
M_ItemDesc,
StockQty,
StockItemPrice,
StockBatchNo,
StockED,
StockWarehouseID
FROM stock
JOIN m_item ON M_ItemID = StockItemID
WHERE
StockWarehouseID = ?
AND StockQty > 0
AND M_ItemIsActive = 'Y'
AND (M_ItemCode LIKE ? OR M_ItemDesc LIKE ?)";
$qry = $this->db->query($sql, array($warehouseID, $search, $search));
if ($qry) {
$rows = $qry->result_array();
} else {
$this->db->trans_rollback();
$this->sys_error_db("select item error", $this->db);
exit;
}
$result = array(
"records" => $rows,
"total_filter" => sizeof($rows)
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getUnit()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$search = "";
if (isset($prm["search"])) {
$search = trim($prm["search"]);
if ($search != "") {
$search = "%" . $prm["search"] . "%";
} else {
$search = "%%";
}
}
$itemID = $prm["itemID"];
$sql = "SELECT
ItemUnitID,
ItemUnitCode,
ItemUnitName,
ItemUnitCreated,
ItemUnitLastUpdated,
ItemUnitIsActive,
ItemUnitUserID,
ItemUnitMapM_ItemID,
ItemUnitMapIsPurchase,
ItemUnitMapIsReport,
ItemUnitMapIsBase
FROM itemunit
JOIN itemunitmap ON ItemUnitMapItemUnitID = ItemUnitID AND ItemUnitMapIsActive ='Y'
AND ItemUnitMapM_ItemID = ?
WHERE ItemUnitIsActive = 'Y'
AND ItemUnitName LIKE ?
ORDER BY ItemUnitName ASC";
$query = $this->db->query($sql, [
$itemID,
$search
]);
if (!$query) {
$this->sys_error_db("item unit list", $this->db);
exit;
}
$rows = $query->result_array();
$result = array(
"records" => $rows,
"sql" => $this->db->last_query()
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function saveDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$itemID = "";
if (isset($prm["itemID"])) {
$itemID = trim($prm["itemID"]);
}
$itemUnitID = "";
if (isset($prm["itemUnitID"])) {
$itemUnitID = trim($prm["itemUnitID"]);
}
$qty = "";
if (isset($prm["qty"])) {
$qty = trim($prm["qty"]);
}
$IOID = "";
if (isset($prm["IOID"])) {
$IOID = trim($prm["IOID"]);
}
$qryChek = "SELECT count(*) as exist
FROM t_item_out_detail
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
AND T_ItemOutDetailM_ItemID = ?";
$exist = $this->db->query($qryChek, [
$IOID,
$itemID
]);
if ($exist) {
$row = $exist->row()->exist;
} else {
$this->sys_error_db("exist error", $this->db);
exit;
}
if ($row == 0) {
$sql = "INSERT INTO t_item_out_detail(
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailQty,
T_ItemOutDetailIsActive,
T_ItemOutDetailCreated,
T_ItemOutDetailUserID) VALUES(?,?,?,?,'Y',NOW(),?)";
$qry = $this->db->query($sql, [
$IOID,
$itemID,
$itemUnitID,
$qty,
$userId
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item out detail", $this->db);
exit;
}
$this->db->trans_commit();
$result = array("total" => 1, "records" => array("xId" => 0));
$this->sys_ok($result);
} else {
$errors = array();
$qryItem = "SELECT M_ItemDesc FROM m_item WHERE M_ItemID = ?";
$qryItem = $this->db->query($qryItem, [
$itemID
]);
if ($qryItem) {
$rowItem = $qryItem->row()->M_ItemDesc;
} else {
$this->db->trans_rollback();
$this->sys_error_db("Failed get item error", $this->db);
exit;
}
if ($row != 0) {
array_push($errors, array("msg" => "Data dengan item " . $rowItem . " 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);
}
}
public function updateDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$itemID = "";
if (isset($prm["itemID"])) {
$itemID = trim($prm["itemID"]);
}
$itemUnitID = "";
if (isset($prm["itemUnitID"])) {
$itemUnitID = trim($prm["itemUnitID"]);
}
$qty = "";
if (isset($prm["qty"])) {
$qty = trim($prm["qty"]);
}
$IOID = "";
if (isset($prm["IOID"])) {
$IOID = trim($prm["IOID"]);
}
$IODID = "";
if (isset($prm["IODID"])) {
$IODID = trim($prm["IODID"]);
}
$sqlCheck = "SELECT count(*) as exist
FROM t_item_out_detail
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?
AND T_ItemOutDetailM_ItemID = ?
AND T_ItemOutDetailItemUnitID = ?
AND T_ItemOutDetailID != ?";
$qryCheck = $this->db->query($sqlCheck, [
$IOID,
$itemID,
$itemUnitID,
$IODID
]);
if ($qryCheck && $qryCheck->result_array()[0]["exist"] > 0) {
$this->sys_error("Item dan satuan sudah ada");
exit;
}
$sql = "UPDATE t_item_out_detail SET
T_ItemOutDetailT_ItemOutID = ?,
T_ItemOutDetailM_ItemID = ?,
T_ItemOutDetailItemUnitID = ?,
T_ItemOutDetailQty = ?,
T_ItemOutDetailLastUpdated = NOW(),
T_ItemOutDetailUserID = ?
WHERE T_ItemOutDetailID = ?";
$qry = $this->db->query($sql, [
$IOID,
$itemID,
$itemUnitID,
$qty,
$userId,
$IODID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item out detail error", $this->db);
exit;
}
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function deleteDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$IODID = "";
if (isset($prm["IODID"])) {
$IODID = trim($prm["IODID"]);
}
$sql = "UPDATE t_item_out_detail SET
T_ItemOutDetailIsActive = 'N',
T_ItemOutDetailLastUpdated = NOW(),
T_ItemOutDetailUserID = ?
WHERE T_ItemOutDetailID = ?";
$qry = $this->db->query($sql, [
$userId,
$IODID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed delete item out detail error", $this->db);
exit;
}
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function orderConfirm()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$itemoutID = $prm["itemoutID"];
$sqlDetail = "SELECT T_ItemOutDetailID,
T_ItemOutDetailT_ItemOutID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailQty
FROM t_item_out_detail
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?";
$qryDetail = $this->db->query($sqlDetail, [$itemoutID]);
if ($qryDetail) {
$rows = $qryDetail->result_array();
} else {
$this->db->tans_rollback();
$this->sys_error_db("select item out detail error", $this->db);
exit;
}
// Ambil Warehouse ID
$sqlHeader = "SELECT T_ItemOutWarehouseID FROM t_item_out WHERE T_ItemOutIsActive = 'Y' AND T_ItemOutID = ?";
$qryHeader = $this->db->query($sqlHeader, [$itemoutID]);
if (!$qryHeader || $qryHeader->num_rows() == 0) {
$this->db->trans_rollback();
$this->sys_error("Item Out tidak ditemukan");
return;
}
$warehouseID = $qryHeader->row()->T_ItemOutWarehouseID;
// loop detail
foreach ($rows as $row) {
$itemID = $row["T_ItemOutDetailM_ItemID"];
$unitID = $row["T_ItemOutDetailItemUnitID"];
$qtyNeeded = $row["T_ItemOutDetailQty"];
// Ambil stok berdasarkan Warehouse, Item dan Unit
$sqlStock = "SELECT StockID, StockQty
FROM stock
WHERE StockWarehouseID = ?
AND StockItemID = ?
AND StockItemUnitID = ?
AND StockQty > 0
ORDER BY StockID ASC";
$qryStock = $this->db->query($sqlStock, [$warehouseID, $itemID, $unitID]);
if (!$qryStock) {
$this->db->trans_rollback();
$this->sys_error_db("select stock error", $this->db);
exit;
}
$stocks = $qryStock->result_array();
foreach ($stocks as $stock) {
if ($qtyNeeded <= 0) break;
$stockID = $stock["StockID"];
$stockQty = $stock["StockQty"];
if ($stockQty >= $qtyNeeded) {
// Kurangi stok langsung dengan SQL
$sqlUpdate = "UPDATE stock
SET StockQty = StockQty - ?
WHERE StockID = ?";
$this->db->query($sqlUpdate, [$qtyNeeded, $stockID]);
$qtyNeeded = 0;
}
}
// Jika setelah looping qtyNeeded masih > 0, berarti stok tidak cukup
if ($qtyNeeded > 0) {
$this->db->trans_rollback();
$this->sys_error("Stok tidak cukup untuk item ID: $itemID");
return;
}
}
// update approved
$sqlUpdate = "UPDATE t_item_out SET
T_ItemOutReceiveUserID= ?,
T_ItemOutStatus = 'Process',
T_ItemOutLastUpdated = NOW()
WHERE T_ItemOutID = ?";
$qryUpdate = $this->db->query($sqlUpdate, [$userId, $itemoutID]);
if (!$qryUpdate) {
$this->db->trans_rollback();
$this->sys_error_db("update item out error", $this->db);
exit;
}
$this->db->trans_commit();
$result = array("total" => 1);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function listRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$startDate = $prm["startDate"];
$endDate = $prm["endDate"];
$search = isset($prm["search"]) ? $prm["search"] : "";
$status = isset($prm["status"]) ? $prm["status"] : "";
$number_offset = 0;
$number_limit = 20;
if ($prm["current_page"] > 0) {
$number_offset = ($prm["current_page"] - 1) * $number_limit;
}
$sqlCount = "SELECT count(*) as total
FROM request_item_out_detail
JOIN request_item_out ON RequestItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
AND (RequestItemOutNumber LIKE ? )
AND (RequestItemOutStatus = ? OR ? = '' )
AND RequestItemOutDate BETWEEN ? AND ?
JOIN m_item ON RequestItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN stock ON StockItemID = RequestItemOutDetailM_ItemID
AND StockItemUnitID = RequestItemOutDetailItemUnitID
AND StockWarehouseID = RequestItemOutWarehouseID
WHERE RequestItemOutDetailIsActive = 'Y'
GROUP BY RequestItemOutDetailID
ORDER BY RequestItemOutDetailID DESC";
$qryCount = $this->db->query($sqlCount, ['%' . $search . '%', $status, $status, $startDate, $endDate]);
$tot_count = 0;
$tot_page = 0;
if ($qryCount) {
$tot_count = $qryCount->result_array()[0]["total"];
$tot_page = ceil($tot_count / $number_limit);
} else {
$this->sys_error_db("request item out count error", $this->db);
exit;
}
$sql = "SELECT RequestItemOutDetailID as rioDID,
RequestItemOutDetailM_ItemID as rioDItemID,
RequestItemOutDetailItemUnitID as rioDItemUnitID,
RequestItemOutDetailQty as rioDQty,
RequestItemOutDetailStatus as rioDStatus,
RequestItemOutID as rioID,
RequestItemOutDate as rioDate,
RequestItemOutNumber as rioNumber,
RequestItemOutNote as rioNote,
RequestItemOutDivisionID as rioDivisionID,
RequestItemOutStatus as rioStatus,
M_ItemID,
M_ItemCode,
M_ItemDesc,
StockID,
StockItemPrice,
SUM(StockQty) AS StockQty
FROM request_item_out_detail
JOIN request_item_out ON RequestItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
AND (RequestItemOutNumber LIKE ?)
AND (RequestItemOutStatus = ? OR ? = '' )
AND RequestItemOutDate BETWEEN ? AND ?
JOIN m_item ON RequestItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
JOIN stock ON StockItemID = RequestItemOutDetailM_ItemID
AND StockItemUnitID = RequestItemOutDetailItemUnitID
AND StockWarehouseID = RequestItemOutWarehouseID
WHERE RequestItemOutDetailIsActive = 'Y'
GROUP BY RequestItemOutDetailID
ORDER BY RequestItemOutDetailID DESC
LIMIT ? OFFSET ?";
$qry = $this->db->query($sql, [
'%' . $search . '%',
$status,
$status,
$startDate,
$endDate,
$number_limit,
$number_offset
]);
// echo $this->db->last_query();
// exit;
if ($qry) {
$rows = $qry->result_array();
} else {
$this->sys_error_db("request item out error", $this->db);
exit;
}
$result = array(
"totalPage" => $tot_page,
"totalFilter" => $tot_count,
"records" => $rows
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
function getDivisionUser()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$payload = $this->sys_input;
$user = $this->sys_user;
$regionalID = $user['S_RegionalID'];
$branchCode = $user['M_BranchCode'];
$loginType = $user['M_UserLocationFlag'];
$userID = $user['M_UserID'];
$sql = "SELECT M_UserDivisionID,
M_UserDivisionM_UserID,
M_UserDivisionDivisionID,
M_UserUsername,
DivisionName
FROM m_user
JOIN m_userdivision ON M_UserID = M_UserDivisionM_UserID
AND M_UserDivisionIsActive = 'Y'
JOIN division ON M_UserDivisionDivisionID = DivisionID
AND DivisionIsActive = 'Y'
WHERE M_UserIsActive = 'Y'
AND M_UserDivisionM_UserID = ?";
$qry = $this->db->query($sql, [$userID]);
if (!$qry) {
$this->sys_error_db("Error cek approval level");
exit;
}
$approvalDivision = $qry->result_array();
if (count($approvalDivision) == 0) {
$result = array(
'total' => 0,
'records' => []
);
$this->sys_ok($result);
exit;
} else {
$result = array(
"total" => 1,
"records" => $approvalDivision,
"sql" => $this->db->last_query()
);
$this->sys_ok($result);
}
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function approveRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$arrRequest = $prm["arrRequest"];
foreach ($arrRequest as $key => $value) {
$sql = "UPDATE request_item_out SET
RequestItemOutStatus = 'Process',
RequestItemOutApprovedDate = NOW(),
RequestItemOutApprovedUserID = ?,
RequestItemOutLastUpdated = NOW()
WHERE RequestItemOutID = ?";
$qry = $this->db->query($sql, [
$userId,
$value["rioID"]
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("update request item out error", $this->db);
exit;
}
$sqlDetail = "UPDATE request_item_out_detail SET
RequestItemOutDetailStatus = 'Process',
RequestItemOutDetailLastUpdated = NOW(),
RequestItemOutDetailUserID = ?
WHERE RequestItemOutDetailID = ?";
$qryDetail = $this->db->query($sqlDetail, [
$userId,
$value["rioDID"]
]);
if (!$qryDetail) {
$this->db->trans_rollback();
$this->sys_error_db("update request item out detail error", $this->db);
exit;
}
}
// insert log
$sql_json = "SELECT request_item_out.*, '' as detail
FROM request_item_out
WHERE RequestItemOutIsActive = 'Y'
AND RequestItemOutID = ?";
$qry_json = $this->db->query($sql_json, [$value["rioID"]]);
if (!$qry_json) {
$this->db->trans_rollback();
$this->sys_error_db("select json rio error");
exit;
}
$row_json = $qry_json->row_array();
$userdesc = "Request Item out dengan kode " . $row_json['RequestItemOutNumber'] . " telah di approve";
$sql_json_detail = "SELECT request_item_out_detail.*
FROM request_item_out_detail
WHERE RequestItemOutDetailIsActive = 'Y'
AND RequestItemOutDetailRequestItemOutID = ?";
$qry_json_detail = $this->db->query($sql_json_detail, [$value["rioID"]]);
if ($qry_json_detail) {
$row_json["detail"] = $qry_json_detail->result_array();
} else {
$this->sys_error_db("select detail rio error", $this->db);
exit;
}
$data_json = $row_json;
$sql_log = "INSERT INTO user_activity(
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
UserActivityRefID,
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES('RIO','Process',?,?,?,?,NOW())";
$qry_log = $this->db->query($sql_log, [
$userdesc,
$value["rioID"],
json_encode($data_json),
$userId
]);
if (!$qry_log) {
$this->db->trans_rollback();
$this->sys_error_db("insert user activity error", $this->db);
exit;
}
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function rejectedRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$this->db->trans_begin();
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$arrRequest = $prm["arrRequest"];
foreach ($arrRequest as $key => $value) {
$sql = "UPDATE request_item_out SET
RequestItemOutStatus = 'Rejected',
RequestItemOutUserID = ?,
RequestItemOutLastUpdated = NOW()
WHERE RequestItemOutID = ?";
$qry = $this->db->query($sql, [
$userId,
$value["rioID"]
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("update request item out error", $this->db);
exit;
}
$sqlDetail = "UPDATE request_item_out_detail SET
RequestItemOutDetailStatus = 'Rejected',
RequestItemOutDetailLastUpdated = NOW(),
RequestItemOutDetailUserID = ?
WHERE RequestItemOutDetailID = ?";
$qryDetail = $this->db->query($sqlDetail, [
$userId,
$value["rioDID"]
]);
if (!$qryDetail) {
$this->db->trans_rollback();
$this->sys_error_db("update request item out detail error", $this->db);
exit;
}
}
// insert log
$sql_json = "SELECT request_item_out.*, '' as detail
FROM request_item_out
WHERE RequestItemOutIsActive = 'Y'
AND RequestItemOutID = ?";
$qry_json = $this->db->query($sql_json, [$value["rioID"]]);
if (!$qry_json) {
$this->db->trans_rollback();
$this->sys_error_db("select json rio error");
exit;
}
$row_json = $qry_json->row_array();
$userdesc = "Request Item out dengan kode " . $row_json['RequestItemOutNumber'] . " telah di reject";
$sql_json_detail = "SELECT request_item_out_detail.*
FROM request_item_out_detail
WHERE RequestItemOutDetailIsActive = 'Y'
AND RequestItemOutDetailRequestItemOutID = ?";
$qry_json_detail = $this->db->query($sql_json_detail, [$value["rioID"]]);
if ($qry_json_detail) {
$row_json["detail"] = $qry_json_detail->result_array();
} else {
$this->sys_error_db("select detail rio error", $this->db);
exit;
}
$data_json = $row_json;
$sql_log = "INSERT INTO user_activity(
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
UserActivityRefID,
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES('RIO','Rejected',?,?,?,?,NOW())";
$qry_log = $this->db->query($sql_log, [
$userdesc,
$value["rioID"],
json_encode($data_json),
$userId
]);
if (!$qry_log) {
$this->db->trans_rollback();
$this->sys_error_db("insert user activity error", $this->db);
exit;
}
$this->db->trans_commit();
$result = array(
"total" => 1
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getItemRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userId = $this->sys_user["M_UserID"];
$warehouseID = isset($prm["warehouseID"]) ? $prm["warehouseID"] : "";
$divisionID = isset($prm["divisionID"]) ? $prm["divisionID"] : "";
$search = isset($prm["search"]) ? $prm["search"] : "";
$currentPage = isset($prm["currentPage"]) ? $prm["currentPage"] : 1;
$limit = 10;
$offset = ($currentPage - 1) * $limit;
$sqlCount = "SELECT COUNT(*) as total FROM (
SELECT *
FROM request_item_out_detail
JOIN request_item_out ON RequestItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
AND (RequestItemOutStatus = 'Process' OR RequestItemOutStatus = 'Partial')
AND RequestItemOutWarehouseID = ?
AND RequestItemOutDivisionID = ?
JOIN m_item ON RequestItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
AND (M_ItemDesc LIKE ?)
JOIN itemunit ON RequestItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN stock ON StockItemID = M_ItemID
AND StockItemUnitID = RequestItemOutDetailItemUnitID
AND StockWarehouseID = RequestItemOutWarehouseID
LEFT JOIN t_item_out_detail ON T_ItemOutDetailRequestItemOutID = RequestItemOutDetailRequestItemOutID
AND T_ItemOutDetailM_ItemID = RequestItemOutDetailM_ItemID
AND T_ItemOutDetailItemUnitID = RequestItemOutDetailItemUnitID
WHERE RequestItemOutDetailIsActive = 'Y'
AND (RequestItemOutDetailStatus = 'Process' OR RequestItemOutDetailStatus = 'Partial')
GROUP BY RequestItemOutDetailID) x";
$qryCount = $this->db->query($sqlCount, [$warehouseID, $divisionID, '%' . $search . '%']);
if (!$qryCount) {
$this->sys_error_db("count item list request error", $this->db);
exit;
}
$rowsCount = $qryCount->result_array();
$total = ceil($rowsCount[0]["total"] / $limit);
$sql = "SELECT
RequestItemOutDetailID as rioDID,
RequestItemOutDetailRequestItemOutID as rioDrioID,
RequestItemOutDetailM_ItemID as rioDItemID,
RequestItemOutDetailItemUnitID as rioDItemUnitID,
IFNULL(RequestItemOutDetailQty, 0) as rioDQty,
IFNULL(T_ItemOutDetailQty, 0) as rioDReceiveQty,
RequestItemOutDetailStatus as rioDStatus,
RequestItemOutID as rioID,
RequestItemOutDate as rioDate,
RequestItemOutNumber as rioNumber,
RequestItemOutWarehouseID as rioWarehouseID,
RequestItemOutS_RegionalID as rioRegionalID,
RequestItemOutM_BranchCode as rioBranchCode,
RequestItemOutNote as rioNote,
RequestItemOutDivisionID as rioDivisionID,
RequestItemOutStatus as rioStatus,
M_ItemID as itemID,
M_ItemCode as itemCode,
M_ItemDesc as itemDesc,
ItemUnitID as unitID,
ItemUnitCode as unitCode,
ItemUnitName as unitName,
StockID,
StockWarehouseID,
StockWarehouseAlmariID,
StockWarehouseRackID,
StockStockNumber,
StockItemID,
StockItemUnitID,
StockItemPrice,
StockBatchNo,
StockED,
StockLastUpdated,
StockUserID,
-- GROUP_CONCAT(CONCAT(StockBatchNo, ' (', StockQty, ')')) AS stockFull,
SUM(StockQty) AS StockQty
FROM request_item_out_detail
JOIN request_item_out ON RequestItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
AND (RequestItemOutStatus = 'Process' OR RequestItemOutStatus = 'Partial')
AND RequestItemOutWarehouseID = ?
AND RequestItemOutDivisionID = ?
JOIN m_item ON RequestItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
AND (M_ItemDesc LIKE ?)
JOIN itemunit ON RequestItemOutDetailItemUnitID = ItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN stock ON StockItemID = M_ItemID
AND StockItemUnitID = RequestItemOutDetailItemUnitID
AND StockWarehouseID = RequestItemOutWarehouseID
LEFT JOIN t_item_out_detail ON T_ItemOutDetailRequestItemOutID = RequestItemOutDetailRequestItemOutID
AND T_ItemOutDetailM_ItemID = RequestItemOutDetailM_ItemID
AND T_ItemOutDetailItemUnitID = RequestItemOutDetailItemUnitID
WHERE RequestItemOutDetailIsActive = 'Y'
AND (RequestItemOutDetailStatus = 'Process' OR RequestItemOutDetailStatus = 'Partial')
GROUP BY RequestItemOutDetailID
ORDER BY RequestItemOutNumber DESC
LIMIT ? OFFSET ?";
$qry = $this->db->query($sql, [$warehouseID, $divisionID, '%' . $search . '%', $limit, $offset]);
if (!$qry) {
$this->sys_error_db("select item request error", $this->db);
exit;
}
// echo $this->db->last_query();
// exit;
$rows = $qry->result_array();
foreach ($rows as $key => $value) {
$rows[$key]['ItemRequest'] = [];
}
$result = array(
"records" => $rows,
"total" => $total
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
// dijagain itemid dan itemunit harus sama
// agar di stock pemakaian tidak terjadi rancu jumlah stocknya karena berdasarkan itemunit
public function insertUsage($ioID, $userID)
{
try {
// 1. Ambil data dari t_item_out_detail
$this->db->trans_begin();
$sql_tio = "SELECT T_ItemOutID,
T_ItemOutDate,
T_ItemOutWarehouseID,
T_ItemOutDivisionID,
T_ItemOutDetailID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailItemBatchNo,
T_ItemOutDetailQty,
RequestItemOutS_RegionalID,
RequestItemOutM_BranchCode,
M_ItemDesc
FROM t_item_out_detail
JOIN t_item_out ON T_ItemOutDetailT_ItemOutID = T_ItemOutID
AND T_ItemOutIsActive = 'Y'
JOIN request_item_out ON T_ItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?";
$qry_tio = $this->db->query($sql_tio, [$ioID]);
if (!$qry_tio) {
$this->sys_error_db("select t_item_out error", $this->db);
exit;
}
$rows_tio = $qry_tio->result_array();
if (count($rows_tio) == 0) {
$this->sys_error("No data found in t_item_out_detail");
exit;
}
// 2. Ambil data existing dari item_usage
$sqlusage = "SELECT ItemUsageID,
ItemUsageS_RegionalID,
ItemUsageM_BranchCode,
ItemUsageDivisionID,
ItemUsageM_ItemID,
ItemUsageItemUnitID,
ItemUsageQty,
ItemUsagePrice
FROM item_usage WHERE ItemUsageIsActive = 'Y'";
$qryusage = $this->db->query($sqlusage, []);
if (!$qryusage) {
$this->db->trans_rollback();
$this->sys_error_db('get select usage error', $this->db);
exit;
}
$rowsusage = $qryusage->result_array();
// 3. Buat mapping untuk pencarian cepat (ItemID dan ItemUsageItemUnitID sebagai key)
$usage_map = [];
foreach ($rowsusage as $usage) {
$key = $usage['ItemUsageM_ItemID'] . '_' . $usage['ItemUsageItemUnitID'];
$usage_map[$key] = $usage;
}
// print_r($usage_map);
// exit;
// 4. Loop data t_item_out_detail
foreach ($rows_tio as $key => $value) {
// Decode batch JSON
$jsonStr = $value["T_ItemOutDetailItemBatchNo"];
$batches = [];
if (!empty($jsonStr)) {
$decode = json_decode($jsonStr, true);
if ($decode !== null && json_last_error() === JSON_ERROR_NONE) {
$batches = $decode;
} else {
$this->sys_error_db("[Error] decode json for batches number");
exit;
}
}
// Buat key untuk pengecekan
$check_key = $value["T_ItemOutDetailM_ItemID"] . '_' . $value["T_ItemOutDetailItemUnitID"];
// Cek apakah sudah ada di item_usage
if (isset($usage_map[$check_key])) {
// SUDAH ADA - Update qty dan proses detail
$existing_usage = $usage_map[$check_key];
$item_usage_id = $existing_usage['ItemUsageID'];
// Update qty di item_usage (opsional, sesuai kebutuhan)
$sql_update = "UPDATE item_usage
SET ItemUsageQty = ItemUsageQty + ?,
ItemUsageUserID = ?,
ItemUsageLastUpdated = NOW()
WHERE ItemUsageID = ?";
$qry_update = $this->db->query($sql_update, [
$value["T_ItemOutDetailQty"],
$userID,
$item_usage_id
]);
if (!$qry_update) {
$this->db->trans_rollback();
$this->sys_error_db("Failed update item usage", $this->db);
exit;
}
} else {
// BELUM ADA - Insert baru
$sql = "INSERT INTO item_usage(
ItemUsageS_RegionalID,
ItemUsageM_BranchCode,
ItemUsageDivisionID,
ItemUsageM_ItemID,
ItemUsageItemUnitID,
ItemUsageQty,
ItemUsagePrice,
ItemUsageIsActive,
ItemUsageUserID,
ItemUsageCreated) VALUES(?,?,?,?,?,?,?,?,'Y',?,NOW())";
$qry = $this->db->query($sql, [
$value["RequestItemOutS_RegionalID"],
$value["RequestItemOutM_BranchCode"],
$value["T_ItemOutDivisionID"],
$value["T_ItemOutDetailM_ItemID"],
$value["T_ItemOutDetailItemUnitID"],
$value["T_ItemOutDetailQty"],
$batches[0]["StockItemPrice"], // Ambil dari batch pertama
$userID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item usage", $this->db);
exit;
}
$item_usage_id = $this->db->insert_id();
}
// 5. Ambil existing detail untuk item_usage_id ini
$sql_detail = "SELECT ItemUsageDetailID,
ItemUsageDetailStockBatchNo,
ItemUsageDetailQtyReq
FROM item_usage_detail
WHERE ItemUsageDetailItemUsageID = ?";
$qry_detail = $this->db->query($sql_detail, [$item_usage_id]);
if (!$qry_detail) {
$this->db->trans_rollback();
$this->sys_error_db("Failed get item usage detail", $this->db);
exit;
}
$existing_details = $qry_detail->result_array();
// Buat mapping batch no untuk pencarian cepat
$detail_map = [];
foreach ($existing_details as $detail) {
$detail_map[$detail['ItemUsageDetailStockBatchNo']] = $detail;
}
// 6. Proses setiap batch
foreach ($batches as $k => $v) {
$batch_no = $v["StockBatchNo"];
// Cek apakah batch no sudah ada
if (isset($detail_map[$batch_no])) {
// BATCH SUDAH ADA - Update qty
$existing_detail = $detail_map[$batch_no];
$sql_update_detail = "UPDATE item_usage_detail
SET ItemUsageDetailQtyReq = ItemUsageDetailQtyReq + ?,
ItemUsageDetailUserID = ?,
ItemUsageDetailLastUpdated = NOW()
WHERE ItemUsageDetailID = ?";
$qry_update_detail = $this->db->query($sql_update_detail, [
floatval($v["QtyReq"]),
$userID,
$existing_detail['ItemUsageDetailID']
]);
if (!$qry_update_detail) {
$this->db->trans_rollback();
$this->sys_error_db("Failed update item usage detail", $this->db);
exit;
}
} else {
// BATCH BELUM ADA - Insert baru
$sql_insert_detail = "INSERT INTO item_usage_detail(
ItemUsageDetailItemUsageID,
ItemUsageDetailWarehouseID,
ItemUsageDetailWarehouseName,
ItemUsageDetailStockID,
ItemUsageDetailStockNumber,
ItemUsageDetailStockItemID,
ItemUsageDetailStockItemUnitID,
ItemUsageDetailItemUnitCode,
ItemUsageDetailItemUnitName,
ItemUsageDetailStockItemPrice,
ItemUsageDetailStockBatchNo,
ItemUsageDetailStockED,
ItemUsageDetailStockQty,
ItemUsageDetailQtyReq,
ItemUsageDetailUserID,
ItemUsageDetailCreated) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
$qry_insert_detail = $this->db->query($sql_insert_detail, [
$item_usage_id,
$v["WarehouseID"],
$v["WarehouseName"],
$v["StockID"],
$v["StockStockNumber"],
$v["StockItemID"],
$v["StockItemUnitID"],
$v["ItemUnitCode"],
$v["ItemUnitName"],
$v["StockItemPrice"],
$v["StockBatchNo"],
$v["StockED"],
$v["StockQty"],
$v["QtyReq"],
$userID
]);
if (!$qry_insert_detail) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item usage detail", $this->db);
exit;
}
}
}
}
$this->db->trans_commit();
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function insertItemUsage($ioID, $userID)
{
try {
$this->db->trans_begin();
$sql_tio = "SELECT T_ItemOutID,
T_ItemOutDate,
T_ItemOutWarehouseID,
T_ItemOutDivisionID,
T_ItemOutDetailID,
T_ItemOutDetailM_ItemID,
T_ItemOutDetailItemUnitID,
T_ItemOutDetailItemBatchNo,
T_ItemOutDetailQty,
RequestItemOutS_RegionalID,
RequestItemOutM_BranchCode,
M_ItemDesc
FROM t_item_out_detail
JOIN t_item_out ON T_ItemOutDetailT_ItemOutID = T_ItemOutID
AND T_ItemOutIsActive = 'Y'
JOIN request_item_out ON T_ItemOutDetailRequestItemOutID = RequestItemOutID
AND RequestItemOutIsActive = 'Y'
JOIN m_item ON T_ItemOutDetailM_ItemID = M_ItemID
AND M_ItemIsActive = 'Y'
WHERE T_ItemOutDetailIsActive = 'Y'
AND T_ItemOutDetailT_ItemOutID = ?";
$qry_tio = $this->db->query($sql_tio, [$ioID]);
if (!$qry_tio) {
$this->sys_error_db("select t_item_out error", $this->db);
exit;
}
$rows_tio = $qry_tio->result_array();
if (count($rows_tio) == 0) {
$this->sys_error("No data found in t_item_out_detail");
exit;
}
foreach ($rows_tio as $key => $value) {
$jsonStr = $value["T_ItemOutDetailItemBatchNo"];
$batches = [];
if (!empty($jsonStr)) {
$decode = json_decode($jsonStr, true);
if ($decode !== null && json_last_error() === JSON_ERROR_NONE) {
$batches = $decode;
} else {
$this->sys_error_db("[Error] decode json for batches number");
exit;
}
}
// cari harga per item,
$sqlstock = "SELECT *
FROM stock
WHERE StockItemID = ?
AND StockItemUnitID = ?
AND StockWarehouseID = ?";
$qrystock = $this->db->query($sqlstock, [
$value["T_ItemOutDetailM_ItemID"],
$value["T_ItemOutDetailItemUnitID"],
$value["T_ItemOutWarehouseID"]
]);
if (!$qrystock) {
$this->sys_error_db("select stock error", $this->db);
exit;
}
$rowstock = $qrystock->row_array();
if (!$rowstock) {
$this->sys_error("No stock found for item " . $value["M_ItemDesc"]);
exit;
}
$sql = "INSERT INTO item_usage(
ItemUsageS_RegionalID,
ItemUsageM_BranchCode,
ItemUsageDivisionID,
ItemUsageM_ItemID,
ItemUsageItemUnitID,
ItemUsageQty,
ItemUsagePrice,
ItemUsageIsActive,
ItemUsageUserID,
ItemUsageCreated) VALUES(?,?,?,?,?,?,?,?,'Y',?,NOW())";
$qry = $this->db->query($sql, [
$value["RequestItemOutS_RegionalID"],
$value["RequestItemOutM_BranchCode"],
$value["T_ItemOutDivisionID"],
$value["T_ItemOutDetailM_ItemID"],
$value["T_ItemOutDetailItemUnitID"],
$value["T_ItemOutDetailQty"],
$rowstock["StockItemPrice"],
$userID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item usage", $this->db);
exit;
}
$last_id = $this->db->insert_id();
foreach ($batches as $k => $v) {
$sql = "INSERT INTO item_usage_detail(
ItemUsageDetailItemUsageID,
ItemUsageDetailWarehouseID,
ItemUsageDetailWarehouseName,
ItemUsageDetailStockID,
ItemUsageDetailStockNumber,
ItemUsageDetailStockItemID,
ItemUsageDetailStockItemUnitID,
ItemUsageDetailItemUnitCode,
ItemUsageDetailItemUnitName,
ItemUsageDetailStockItemPrice,
ItemUsageDetailStockBatchNo,
ItemUsageDetailStockED,
ItemUsageDetailStockQty,
ItemUsageDetailQtyReq,
ItemUsageDetailUserID,
ItemUsageDetailCreated) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
$qry = $this->db->query($sql, [
$last_id,
$v["WarehouseID"],
$v["WarehouseName"],
$v["StockID"],
$v["StockStockNumber"],
$v["StockItemID"],
$v["StockItemUnitID"],
$v["ItemUnitCode"],
$v["ItemUnitName"],
$v["StockItemPrice"],
$v["StockBatchNo"],
$v["StockED"],
$v["StockQty"],
$v["QtyReq"],
$userID
]);
if (!$qry) {
$this->db->trans_rollback();
$this->sys_error_db("Failed insert item usage detail", $this->db);
exit;
}
}
}
$this->db->trans_commit();
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getItemBatchListing()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$batchNo = "%";
if ($prm['batchno'] != '') {
$batchNo = $prm['batchno'] . "%";
}
$sqlbatch = "SELECT
WarehouseID,
WarehouseName,
StockID,
StockStockNumber,
StockItemID,
StockItemUnitID,
ItemUnitCode,
ItemUnitName,
StockItemPrice,
StockBatchNo,
StockED,
StockQty
FROM warehouse
JOIN stock ON StockWarehouseID = WarehouseID
AND StockQty > 0
JOIN itemunit ON ItemUnitID = StockItemUnitID AND ItemUnitIsActive= 'Y'
WHERE WarehouseIsActive = 'Y' AND WarehouseIsTransit = 'N'
AND WarehouseS_RegionalID = ?
AND WarehouseM_BranchID = ?
AND StockItemID = ?
AND StockItemUnitID = ?
AND StockBatchNo LIKE ?";
$quebatch = $this->db->query($sqlbatch, [
$prm['regionalid'],
$prm['branchid'],
$prm['itemid'],
$prm['unitid'],
$batchNo
]);
if (!$quebatch) {
$this->sys_error_db("error get data draft detail transfer");
exit;
}
$batch = $quebatch->result_array();
$result = array(
'records' => $batch,
'total' => sizeof($batch)
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getlevel()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$payload = $this->sys_input;
$user = $this->sys_user;
$regionalID = $user['S_RegionalID'];
$branchCode = $user['M_BranchCode'];
$loginType = $user['M_UserLocationFlag'];
$userID = $user['M_UserID'];
$sql = "SELECT m_approve_level.* FROM m_user
JOIN m_approve_level
ON M_UserM_ApproveLevelID = M_ApproveLevelID
WHERE M_UserID = ?";
$qry = $this->db->query($sql, [$userID]);
if (!$qry) {
$this->sys_error_db("Error cek approval level");
exit;
}
$approvalLevel = $qry->result_array();
if (count($approvalLevel) == 0) {
$result = array(
'total' => 0,
'records' => []
);
$this->sys_ok($result);
exit;
} else {
$result = array(
"total" => 1,
"records" => $approvalLevel,
"sql" => $this->db->last_query()
);
$this->sys_ok($result);
}
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
}