Files
be-accone/application/controllers/mockup/purchase/transfer/TransferRequestNP.php

1128 lines
47 KiB
PHP

<?php
class TransferRequestNP extends MY_Controller
{
var $db;
public function index()
{
echo "Transfer Request/Requester Non Persediaan API";
}
public function __construct()
{
parent::__construct();
}
public function getBranches()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$regID = $prm["S_RegionalID"];
$sql = "SELECT M_BranchID, M_BranchCode, M_BranchName
FROM m_branch
WHERE M_BranchIsActive = 'Y'
AND M_BranchS_RegionalID = ?";
$qry = $this->db->query($sql, [$regID]);
if (!$qry) {
$this->sys_error_db("Failed to get Branches from RegionalID: {$regID}", $this->db);
exit;
}
$rst = $qry->result_array();
$this->sys_ok(["records" => $rst]);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function search()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$payload = $this->sys_input;
$regionalID = $this->sys_user["S_RegionalID"];
$startDate = $payload["startDate"];
$endDate = $payload["endDate"];
$search = $payload['search'];
if ($search == "") {
$search = "%";
}
$status = $payload["StatusName"];
if (strtolower($status) == 'all') {
$status = "%";
}
$cabangcode = $payload["M_BranchCode"];
if (strtolower($cabangcode) == 'all') {
$cabangcode = "%";
}
$offset = 0;
$limit = 10;
if ($payload["currentPage"] > 0) {
$offset = ($payload["currentPage"] - 1) * $limit;
}
$sql = "SELECT
t_goods_transfer.*,
M_BranchID,
M_BranchCode,
M_BranchName,
DivisionCode,
DivisionName
FROM t_goods_transfer
JOIN m_branch ON T_GoodsTransferToM_BranchCode = M_BranchCode
AND M_BranchIsActive = 'Y'
JOIN division ON DivisionID = T_GoodsTransferDivisionID
AND DivisionIsActive = 'Y'
WHERE T_GoodsTransferIsActive = 'Y'
AND T_GoodsTransferFromS_RegionalID = ?
AND T_GoodsTransferNum LIKE ?
AND T_GoodsTransferToM_BranchCode LIKE ?
AND T_GoodsTransferType = 'NP'
AND T_GoodsTransferStatus LIKE ?
AND T_GoodsTransferDate BETWEEN DATE(?) AND DATE(?)
ORDER BY T_GoodsTransferDate DESC";
$sqldata = $sql . " LIMIT ? OFFSET ?";
$quedata = $this->db->query($sqldata, [
$regionalID,
$search,
$cabangcode,
$status,
$startDate,
$endDate,
$limit,
$offset
]);
if (!$quedata) {
$this->sys_error_db("[Error] get data");
exit;
}
$data = $quedata->result_array();
$sqltotal = "SELECT COUNT(*) AS total FROM ($sql) as x";
$quetotal = $this->db->query($sqltotal, [
$regionalID,
$search,
$cabangcode,
$status,
$startDate,
$endDate
]);
if (!$quetotal) {
$this->sys_error_db("[Error] get total data");
exit;
}
$total = $quetotal->result_array()[0]['total'];
$result = array(
"records" => $data,
"total" => $total
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getDivision()
{
try {
if (!$this->isLogin) {
$this->sys_error("invalid token");
exit;
}
$sqldiv = "SELECT
DivisionID,
DivisionCode,
DivisionName
FROM division
WHERE DivisionIsActive = 'Y'";
$quediv = $this->db->query($sqldiv, []);
if (!$quediv) {
$this->sys_error_db("[Error] get listing data divisi");
exit;
}
$result = $quediv->result_array();
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getListDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$regionalid = $prm['regionalid'];
$branchIDOrigin = $prm['branchIDorigin'];
$branchCodeDestin = $prm['branchcodedestin'];
$divisionID = $prm['divisionID'];
$currpage = $prm['currpage'];
$page = 0;
$limit = 5;
if ($currpage > 0) {
$page = ($currpage - 1) * $limit;
}
$sql = "SELECT
PurchaseRequestDate,
PurchaseRequestNumber,
PurchaseRequestDetailM_ItemID,
PurchaseRequestDetailItemUnitID,
M_ItemDesc,
ItemUnitName,
PurchaseRequestFlagID,
PurchaseRequestFlagQty,
PurchaseRequestFlagQtyRest,
COALESCE(SUM(CASE WHEN WarehouseID IS NOT NULL AND StockItemId IS NOT NULL THEN StockQty ELSE 0 END), 0) as StockGudang,
PurchaseRequestFlagStatus
FROM purchase_request_flag
JOIN purchase_request_detail ON PurchaseRequestDetailID = PurchaseRequestFlagPurchaseRequestDetailID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN purchase_request ON PurchaseRequestID = PurchaseRequestDetailPurchaseRequestID
AND PurchaseRequestIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemIsActive = 'Y'
AND M_ItemItem_CategoryID != 1
JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN m_itemdivision ON M_ItemDivisionM_ItemID = M_ItemID
AND M_ItemDivisionIsActive = 'Y'
AND M_ItemDivisionDivisionID = ?
JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID
AND WarehouseIsTransit = 'N'
AND WarehouseM_BranchID = 0
AND WarehouseIsActive = 'Y'
LEFT JOIN stock ON StockItemId = M_ItemID AND StockWarehouseID = WarehouseID
WHERE PurchaseRequestFlagIsActive = 'Y'
AND FIND_IN_SET('TF', PurchaseRequestFlagStatus)
AND PurchaseRequestDetailStatus = 'Read'
AND PurchaseRequestFlagIsClosed = 'N'
AND PurchaseRequestS_RegionalID = ?
AND PurchaseRequestM_BranchCode = ?
AND NOT EXISTS (
SELECT 1
FROM t_goods_transfer
JOIN t_goods_transfer_detail ON T_GoodsTransferDetailIDT_GoodsTransferID = T_GoodsTransferID
AND T_GoodsTransferDetailIsActive = 'Y'
WHERE T_GoodsTransferDetailT_PurchaseRequestFlagID = PurchaseRequestFlagID
AND T_GoodsTransferFromS_RegionalID = ?
AND T_GoodsTransferToM_BranchCode = ?
)
GROUP BY PurchaseRequestFlagID, PurchaseRequestNumber";
$sqllist = $sql . " LIMIT ? OFFSET ?";
$quelist = $this->db->query($sqllist, [
$divisionID,
$regionalid,
$branchCodeDestin,
$regionalid,
$branchCodeDestin,
$limit,
$page
]);
if (!$quelist) {
$this->db->sys_error_db("[Error] get data list tf request non persediaan");
exit;
}
$data = $quelist->result_array();
$sqltotal = "SELECT COUNT(*) AS total FROM ($sql) as x";
$quetotal = $this->db->query($sqltotal, [
$divisionID,
$regionalid,
$branchCodeDestin,
$regionalid,
$branchCodeDestin
]);
if (!$quetotal) {
$this->db->sys_error_db("[Error] get data list tf request non persediaan");
exit;
}
$total = $quetotal->result_array()[0]['total'];
$result = array(
"records" => $data,
"total" => $total
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getListStock()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$sql = "SELECT
WarehouseID,
WarehouseName,
StockID,
StockStockNumber,
StockWarehouseID,
StockItemID,
StockItemUnitID,
StockItemPrice,
ItemUnitName,
StockQty
FROM warehouse
JOIN stock ON StockWarehouseID = WarehouseID
AND WarehouseIsActive = 'Y' AND WarehouseIsTransit = 'N'
JOIN itemunit ON ItemUnitID = StockItemUnitID AND ItemUnitIsActive= 'Y'
WHERE WarehouseS_RegionalID = ?
AND WarehouseM_BranchID = 0
AND StockItemID = ?
AND StockItemUnitID = ?";
$que = $this->db->query($sql, [$prm['regionalid'], $prm['itemid'], $prm['unitid']]);
if (!$que) {
$this->db->sys_error_db("[Error] list stock item");
exit;
}
$data = $que->result_array();
$result = array(
"records" => $data,
"total" => sizeof($data)
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getDraftDetail()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$goodTfID = $prm['goodTfID'];
$sql = "SELECT
PurchaseRequestDate,
PurchaseRequestNumber,
PurchaseRequestDetailM_ItemID,
PurchaseRequestDetailItemUnitID,
M_ItemDesc,
ItemUnitName,
COALESCE(SUM(CASE WHEN WarehouseID IS NOT NULL AND StockItemId IS NOT NULL THEN StockQty ELSE 0 END), 0) as StockGudang,
PurchaseRequestFlagID,
T_GoodsTransferDetailQty as PurchaseRequestFlagQty,
T_GoodsTransferDetailQtyTF as PurchaseRequestFlagQtyRest,
T_GoodsTransferDetailItemBarNote,
PurchaseRequestFlagStatus
FROM t_goods_transfer
LEFT JOIN t_goods_transfer_detail ON T_GoodsTransferDetailIDT_GoodsTransferID = T_GoodsTransferID
AND T_GoodsTransferDetailIsActive = 'Y'
JOIN purchase_request_flag ON PurchaseRequestFlagID = T_GoodsTransferDetailT_PurchaseRequestFlagID
AND PurchaseRequestFlagIsActive = 'Y'
JOIN purchase_request_detail ON PurchaseRequestDetailID = PurchaseRequestFlagPurchaseRequestDetailID
AND PurchaseRequestDetailIsActive = 'Y'
JOIN purchase_request ON PurchaseRequestID = PurchaseRequestDetailPurchaseRequestID
AND PurchaseRequestIsActive = 'Y'
JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
AND M_ItemItem_CategoryID != 1
AND M_ItemIsActive = 'Y'
JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID
AND ItemUnitIsActive = 'Y'
JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
AND M_BranchIsActive = 'Y'
JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID
AND WarehouseIsTransit = 'N'
AND WarehouseM_BranchID = 0
AND WarehouseIsActive = 'Y'
LEFT JOIN stock ON StockItemId = M_ItemID
AND StockWarehouseID = WarehouseID
WHERE PurchaseRequestFlagIsActive = 'Y'
AND T_GoodsTransferID = ?
AND T_GoodsTransferIsActive = 'Y'
GROUP BY PurchaseRequestNumber, PurchaseRequestFlagID";
$qry = $this->db->query($sql, [$goodTfID]);
if (!$qry) {
$this->sys_error_db("[Error] get detail transfer request non persediaan");
exit;
}
$detail = $qry->result_array();
foreach ($detail as $key => $value) {
$jsonStr = $value['T_GoodsTransferDetailItemBarNote'];
$barnote = [];
if (!empty($jsonStr)) {
$decode = json_decode($jsonStr);
if ($decode !== null && json_last_error() === JSON_ERROR_NONE) {
$barnote = $decode;
} else {
$this->sys_error_db("[Error] decode json for barnote");
exit;
}
}
$detail[$key]['ItemRequest'] = $barnote;
unset($detail[$key]['T_GoodsTransferDetailItemBarNote']);
}
$result = array(
"records" => $detail,
"total" => sizeof($detail)
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function createTfRequest()
{
try {
if (!$this->isLogin) {
throw new Exception("Invalid Token");
}
$user = $this->sys_user;
$userID = $this->sys_user["M_UserID"];
$data = $this->sys_input;
$datadetail = $data['detail'];
$this->db->trans_begin();
// generate tf number
// $sqlnum = "SELECT `fn_numbering`('TR') AS GoodsTfNum";
// $quenum = $this->db->query($sqlnum, []);
// if (!$quenum) {
// throw new Exception("[Error] Failed to generate transfer request number. " . json_encode($this->db->error()));
// }
// $GoodsTfNum = $quenum->row()->GoodsTfNum;
$areaid = $user['M_BranchID'];
$areatype = 'B';
if ($user['loginLevel'] == 'regional') {
$areaid = $user['S_RegionalID'];
$areatype = 'R';
}
$sqlusrdivisi = "SELECT M_UserDivisionDivisionID FROM m_userdivision
WHERE M_UserDivisionM_UserID = ? AND M_UserDivisionIsActive = 'Y'";
$queusrdivisi = $this->db->query($sqlusrdivisi, [$user['M_UserID']]);
if (!$queusrdivisi) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get user divisi", $this->db);
exit;
}
$userDivID = $queusrdivisi->row_array()['M_UserDivisionDivisionID'];
$sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;";
$quenum = $this->db->query($sqlnum, ['ST', $userDivID, $areatype, $areaid, 'SM', 'Y']);
if (!$quenum) {
throw new Exception("[Error] Failed to generate number for TF request NP. " . json_encode($this->db->error()));
}
$GoodsTfNum = $quenum->row_array()['numpd'];
$sqlTrf = "INSERT INTO t_goods_transfer (
T_GoodsTransferFromS_RegionalID,
T_GoodsTransferToM_BranchCode,
T_GoodsTransferDivisionID,
T_GoodsTransferNum,
T_GoodsTransferNotes,
T_GoodsTransferDate,
T_GoodsTransferType,
T_GoodsTransferStatus,
T_GoodsTransferCreatedAt,
T_GoodsTransferM_UserID
) VALUES (?,?,?,?,?,?,'NP',?,NOW(),?)";
$queTrf = $this->db->query($sqlTrf, [
$data["S_RegionalID"],
$data["M_BranchCode"],
$data["DivisionID"],
$GoodsTfNum,
$data["GoodsTfNotes"],
$data["GoodsTfDate"],
$data["GoodsTfStatus"],
$userID
]);
if (!$queTrf) {
throw new Exception("[Error] Failed to insert into table t_goods_transfer. " . json_encode($this->db->error()));
}
$TGoodsTrfID = $this->db->insert_id();
// insert detail item tf into t_goods_transfer_detail
foreach ($datadetail as $key => $value) {
$flagID = $value['PurchaseRequestFlagID'];
$itemID = $value['PurchaseRequestDetailM_ItemID'];
$unitID = $value['PurchaseRequestDetailItemUnitID'];
$QtyStart = intval($value['PurchaseRequestFlagQty']);
$QtyTfRes = intval($value['PurchaseRequestFlagQtyRest']);
// encode json list barnote
$jsonBarnote = "[]";
if (isset($value['ItemRequest']) && is_array($value['ItemRequest'])) {
$barnote = $value['ItemRequest'];
if (sizeof($barnote) > 0) {
$json = json_encode($barnote);
if ($json === false) {
throw new Exception("[Error] Failed to encode json batch number");
} else {
$jsonBarnote = $json;
}
}
}
$sqlTfDtl = "INSERT INTO t_goods_transfer_detail (
T_GoodsTransferDetailIDT_GoodsTransferID,
T_GoodsTransferDetailT_PurchaseRequestFlagID,
T_GoodsTransferDetailM_ItemID,
T_GoodsTransferDetailItemUnitID,
T_GoodsTransferDetailItemBarNote,
T_GoodsTransferDetailQty,
T_GoodsTransferDetailQtyTF,
T_GoodsTransferDetailCreatedAt,
T_GoodsTransferDetailM_UserID
) VALUES (?,?,?,?,?,?,?,NOW(),?)";
$queTfDtl = $this->db->query($sqlTfDtl, [
$TGoodsTrfID,
$flagID,
$itemID,
$unitID,
$jsonBarnote,
$QtyStart,
$QtyTfRes,
$userID
]);
if (!$queTfDtl) {
throw new Exception("[Error] Failed to insert detail tf data into t_goods_transfer_detail. " . json_encode($this->db->error()));
}
$TGoodsTFDetailID = $this->db->insert_id();
$datadetail[$key]['TGoodsTFDetailID'] = $TGoodsTFDetailID;
// update flag jika status verified
if ($data['GoodsTfStatus'] == 'Verified') {
$this->moveStockToTransit($value, $data['S_RegionalID'], $userID, $TGoodsTFDetailID);
$sqlUpdateFlag = "UPDATE purchase_request_flag
SET PurchaseRequestFlagQtyRest = ?,
PurchaseRequestFlagQtyProses = PurchaseRequestFlagQtyProses + ?
WHERE PurchaseRequestFlagID = ?
AND PurchaseRequestFlagIsActive = 'Y'";
$qflag = $this->db->query($sqlUpdateFlag, [$QtyTfRes, $QtyTfRes, $flagID]);
if (!$qflag) {
throw new Exception("[Error] Failed updating purchase request flag quantities. " . json_encode($this->db->error()));
}
}
}
// get last inserted data
$sqltfgood = "SELECT * FROM t_goods_transfer WHERE T_GoodsTransferIsActive = 'Y' AND T_GoodsTransferID = ?";
$quetfgood = $this->db->query($sqltfgood, [$TGoodsTrfID]);
if (!$quetfgood) {
throw new Exception("[Error] Failed to get last data inserted. " . json_encode($this->db->error()));
}
$lastTFData = $quetfgood->row_array();
$sqltfdetail = "SELECT * FROM t_goods_transfer_detail WHERE T_GoodsTransferDetailIsActive = 'Y' AND T_GoodsTransferDetailIDT_GoodsTransferID = ?";
$quetfdetail = $this->db->query($sqltfdetail, [$TGoodsTrfID]);
if (!$quetfdetail) {
throw new Exception("[Error] Failed to get last data detail inserted. " . json_encode($this->db->error()));
}
$lastTFDetail = $quetfdetail->result_array();
$lastTFData['detail'] = $lastTFDetail;
// insert log user activity
$msg = "Transfer Request nomor: {$lastTFData['T_GoodsTransferNum']}, tanggal: {$lastTFData['T_GoodsTransferDate']}, type: {$lastTFData['T_GoodsTransferType']}";
$this->insertUserActivty($TGoodsTrfID, "CREATE", $userID, $msg, json_encode($lastTFData));
$this->db->trans_commit();
$result = array(
"total" => 1,
"msg" => $msg,
"records" => $lastTFData
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->db->trans_rollback();
$this->sys_error($message);
}
}
public function updateTfRequest()
{
try {
if (!$this->isLogin) {
throw new Exception("Invalid Token");
}
$user = $this->sys_user;
$userID = $this->sys_user["M_UserID"];
$data = $this->sys_input;
// print_r($data['actverif']);
// print_r($data['editqty']);
// print_r(json_encode($data['detail']));
// exit;
$this->db->trans_begin();
// update table header t_goods_transfer
$sqlTrf = "UPDATE t_goods_transfer SET
T_GoodsTransferFromS_RegionalID = ?,
T_GoodsTransferToM_BranchCode = ?,
T_GoodsTransferDivisionID = ?,
T_GoodsTransferNum = ?,
T_GoodsTransferNotes = ?,
T_GoodsTransferDate = ?,
T_GoodsTransferStatus = ?,
T_GoodsTransferLastUpdated = NOW(),
T_GoodsTransferM_UserID = ?
WHERE T_GoodsTransferID = ?
AND T_GoodsTransferIsActive = 'Y'";
$queTrf = $this->db->query($sqlTrf, [
$data["S_RegionalID"],
$data["M_BranchCode"],
$data["DivisionID"],
$data["GoodsTfNum"],
$data["GoodsTfNotes"],
$data["GoodsTfDate"],
$data["GoodsTfStatus"],
$userID,
$data["GoodsTfID"]
]);
if (!$queTrf) {
throw new Exception("[Error] Failed to update table t_goods_transfer. " . json_encode($this->db->error()));
}
// approve or verif tf request
if (($data["GoodsTfStatus"] == 'Verified' && $data['actverif'] == 'V') || $data["GoodsTfStatus"] == 'Approved') {
$this->toVerifOrApprove($data["GoodsTfID"], $user);
}
// update detail t_goods status to N
$sqlTFdtltoN = "UPDATE t_goods_transfer_detail SET T_GoodsTransferDetailIsActive = 'N' WHERE T_GoodsTransferDetailIDT_GoodsTransferID = ?";
$qeuTFdtltoN = $this->db->query($sqlTFdtltoN, [$data["GoodsTfID"]]);
if (!$qeuTFdtltoN) {
throw new Exception("[Error] Failed to update all detail to N. " . json_encode($this->db->error()));
}
// update detail table t_goods_transfer_detail
$datadetail = $data['detail'];
foreach ($datadetail as $key => $value) {
$flagID = $value['PurchaseRequestFlagID'];
$itemID = $value['PurchaseRequestDetailM_ItemID'];
$unitID = $value['PurchaseRequestDetailItemUnitID'];
$QtyStart = intval($value['PurchaseRequestFlagQty']);
$QtyTfRes = intval($value['PurchaseRequestFlagQtyRest']);
// encode json list barnote
$jsonBarnote = "[]";
if (isset($value['ItemRequest']) && is_array($value['ItemRequest'])) {
$barnote = $value['ItemRequest'];
if (sizeof($barnote) > 0) {
$json = json_encode($barnote);
if ($json === false) {
throw new Exception("[Error] Failed to encode json batch number");
} else {
$jsonBarnote = $json;
}
}
}
$sqlTfDtl = "INSERT INTO t_goods_transfer_detail (
T_GoodsTransferDetailIDT_GoodsTransferID,
T_GoodsTransferDetailT_PurchaseRequestFlagID,
T_GoodsTransferDetailM_ItemID,
T_GoodsTransferDetailItemUnitID,
T_GoodsTransferDetailItemBarNote,
T_GoodsTransferDetailQty,
T_GoodsTransferDetailQtyTF,
T_GoodsTransferDetailCreatedAt,
T_GoodsTransferDetailM_UserID
) VALUES (?,?,?,?,?,?,?,NOW(),?)";
$queTfDtl = $this->db->query($sqlTfDtl, [
$data["GoodsTfID"],
$flagID,
$itemID,
$unitID,
$jsonBarnote,
$QtyStart,
$QtyTfRes,
$userID
]);
if (!$queTfDtl) {
throw new Exception("[Error] Failed to insert detail tf data into t_goods_transfer_detail. " . json_encode($this->db->error()));
}
$TGoodsTFDetailID = $this->db->insert_id();
$datadetail[$key]['TGoodsTFDetailID'] = $TGoodsTFDetailID;
// update flag jika status verified
if ($data['GoodsTfStatus'] == 'Verified' && $data['actverif'] == 'V') {
$this->moveStockToTransit($value, $data['S_RegionalID'], $userID, $TGoodsTFDetailID);
$sqlUpdateFlag = "UPDATE purchase_request_flag
SET PurchaseRequestFlagQtyRest = ?,
PurchaseRequestFlagQtyProses = PurchaseRequestFlagQtyProses + ?
WHERE PurchaseRequestFlagID = ?
AND PurchaseRequestFlagIsActive = 'Y'";
$qflag = $this->db->query($sqlUpdateFlag, [$QtyTfRes, $QtyTfRes, $flagID]);
if (!$qflag) {
throw new Exception("[Error] Failed updating purchase request flag quantities. " . json_encode($this->db->error()));
}
}
}
// get last inserted data
$sqltfgood = "SELECT * FROM t_goods_transfer WHERE T_GoodsTransferIsActive = 'Y' AND T_GoodsTransferID = ?";
$quetfgood = $this->db->query($sqltfgood, [$data["GoodsTfID"]]);
if (!$quetfgood) {
throw new Exception("[Error] Failed to get last data inserted. " . json_encode($this->db->error()));
}
$lastTFData = $quetfgood->row_array();
$sqltfdetail = "SELECT * FROM t_goods_transfer_detail WHERE T_GoodsTransferDetailIsActive = 'Y' AND T_GoodsTransferDetailIDT_GoodsTransferID = ?";
$quetfdetail = $this->db->query($sqltfdetail, [$data["GoodsTfID"]]);
if (!$quetfdetail) {
throw new Exception("[Error] Failed to get last data detail inserted. " . json_encode($this->db->error()));
}
$lastTFDetail = $quetfdetail->result_array();
$lastTFData['detail'] = $lastTFDetail;
// insert log user activity
$msg = "Transfer Request nomor: {$lastTFData['T_GoodsTransferNum']}, tanggal: {$lastTFData['T_GoodsTransferDate']}, type: {$lastTFData['T_GoodsTransferType']}";
$this->insertUserActivty($data["GoodsTfID"], "UPDATE", $userID, $msg, json_encode($lastTFData));
$this->db->trans_commit();
$result = array(
"total" => 1,
"msg" => $msg,
"records" => $lastTFData
);
$this->sys_ok($result);
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->db->trans_rollback();
$this->sys_error($message);
}
}
/**
* Pindah Stock ke WH Transit jika Verified
* @param array $detailTf - The detail of the transfer with ItemRequest info
* @param int $regionalID - The regional ID to find the appropriate transit warehouse
* @param int $userID - The user ID performing the operation
* @param int $TGoodsTFDetailID - The ID of the transfer detail
* @return void
* @throws Exception if any validation or database operation fails
*/
private function moveStockToTransit($detailTf, $regionalID, $userID, $TGoodsTFDetailID)
{
//* Validasi StockQty bisa memenuhi
foreach ($detailTf['ItemRequest'] as $itemRequest) {
$stockID = $itemRequest['StockID'];
$qtyReq = intval($itemRequest['QtyReq']);
$sqlCheck = "SELECT StockQty FROM stock WHERE StockID = ?";
$qryCheck = $this->db->query($sqlCheck, [$stockID]);
if (!$qryCheck || $qryCheck->num_rows() === 0) {
$err = json_encode($this->db->error());
throw new Exception($err);
}
if ($qryCheck->row()->StockQty < $qtyReq) {
$sqlItem = "SELECT M_ItemDesc, ItemUnitName
FROM stock
JOIN m_item ON M_ItemID = StockItemID
JOIN itemunit ON ItemUnitID = StockItemUnitID
WHERE StockID = ?";
$qryItem = $this->db->query($sqlItem, [$stockID]);
$itemInfo = $qryItem->row_array();
throw new Exception("Err: Perhatikan Qty Stock dan Request. Tidak bisa verifikasi karena Stock Item {$itemInfo['M_ItemDesc']}
tersisa " . ($qryCheck ? $qryCheck->row()->StockQty : 0) . " {$itemInfo['ItemUnitName']},
sedangkan request {$qtyReq} {$itemInfo['ItemUnitName']}");
}
}
//* Query Warehouse Transit where WHRegionalID == $data[S_RegionalID]
$sqlWh = "SELECT WarehouseID FROM warehouse WHERE WarehouseS_RegionalID = ?
AND WarehouseIsTransit = 'Y' AND WarehouseIsActive = 'Y'
AND WarehouseType = 'R' ORDER BY WarehouseID DESC LIMIT 1";
$qryWh = $this->db->query($sqlWh, [$regionalID]);
if (!$qryWh || $qryWh->num_rows() === 0) {
throw new Exception("Transit warehouse not found for Regional ID: {$regionalID}");
}
$transitWhId = $qryWh->row()->WarehouseID;
foreach ($detailTf['ItemRequest'] as $itemReq) {
$stockID = $itemReq['StockID'];
$qtyReq = intval($itemReq['QtyReq']);
$stockNumber = $itemReq['StockStockNumber'];
$batchNo = $itemReq['StockBatchNo'] ?? '';
$itemID = $itemReq['StockItemID'];
$unitID = $itemReq['StockItemUnitID'];
$itemPrice = $itemReq['StockItemPrice'];
$expDate = $itemReq['StockED'];
$warehouseID = $itemReq['WarehouseID'];
//* Update Kurangi Existing Stock Qty
$sqlUpdt = "UPDATE stock SET StockQty = StockQty - ?,
StockLastUpdated = NOW(), StockUserID = ?
WHERE StockID = ?";
$qryUpdt = $this->db->query($sqlUpdt, [$qtyReq, $userID, $stockID]);
if (!$qryUpdt) {
throw new Exception("Failed to update source stock quantity (ID: {$stockID})");
}
//* Create / Update Transit Stock
$sqlCekTransit = "SELECT StockID FROM stock
WHERE StockWarehouseID = ?
AND StockItemID = ? AND StockItemUnitID = ? ORDER BY StockID DESC LIMIT 1";
$qryCekTransit = $this->db->query($sqlCekTransit, [
$transitWhId,
$itemID,
$unitID
]);
if (!$qryCekTransit) {
$err = json_encode($this->db->error());
throw new Exception("Failed to cek stock on warehouseId (ID: {$transitWhId}). DB Error: $err");
}
if ($qryCekTransit->num_rows() > 0) {
$transitStockID = $qryCekTransit->row()->StockID;
$sqlUpdTransit = "UPDATE stock SET StockQty = StockQty + ?,
StockLastUpdated = NOW(), StockUserID = ?
WHERE StockID = ?";
$qryUpdTransit = $this->db->query($sqlUpdTransit, [
$qtyReq,
$userID,
$transitStockID
]);
if (!$qryUpdTransit) {
throw new Exception("Failed to update transit stock quantity (ID: {$transitStockID})");
}
} else {
$sqlInsTransit = "INSERT INTO stock (
StockWarehouseID, StockItemID, StockItemUnitID,
StockBatchNo, StockQty, StockStockNumber,
StockItemPrice, StockED,
StockLastUpdated, StockUserID
) VALUES (?, ?, ?, ?, ?, fn_numbering('SN'), ?, ?, NOW(), ?)";
$qryInsTransit = $this->db->query($sqlInsTransit, [
$transitWhId,
$itemID,
$unitID,
$batchNo,
$qtyReq,
$itemPrice,
$expDate,
$userID
]);
if (!$qryInsTransit) {
throw new Exception("Failed to insert new transit stock for Item ID: {$itemID}");
}
$transitStockID = $this->db->insert_id();
}
//* Log Stock Movement (WTT - Warehouse To Transit)
// Log hanya dari sumber ke transit
$sqlLog = "INSERT INTO stocklog (
StockLogWarehouseID, StockLogDateTime, StockLogItemID,
StockLogItemUnitID, StockLogStockNumber, StockLogBatchNo,
StockLogED, StockLogReffID, StockLogStatus, StockLogQty, StockLogUserID)
VALUES (?, NOW(), ?, ?, ?, ?, ?, ?, 'WTT', ?, ?)";
$qryLog = $this->db->query($sqlLog, [
$warehouseID,
$itemID,
$unitID,
$stockNumber,
$batchNo,
$expDate,
$TGoodsTFDetailID,
$qtyReq,
$userID
]);
if (!$qryLog) {
throw new Exception("Failed to log source warehouse movement");
}
// * Query Stockcard where StockCardReffID == $stockID ORDER BY StockCardID DESC LIMIT 1
// * Insert Stockcard WH Sumber ke Transit (OUT)
// StockCardBefore = Previous StockCardAfter, StockCardIn=0, StockCardOut= qtyReg, StockCardAfter = PreviousCardAfter - qtyReq
$sqlLastSourceCard = "SELECT StockCardAfter FROM stockcard
WHERE StockCardReffID = ? ORDER BY StockCardID DESC LIMIT 1";
$qryLastSourceCard = $this->db->query($sqlLastSourceCard, [$stockID]);
if (!$qryLastSourceCard) {
throw new Exception("Failed to query last stockcard entry for source stock ID: {$stockID}");
}
$beforeQty = 0;
if ($qryLastSourceCard->num_rows() > 0) {
$beforeQty = $qryLastSourceCard->row()->StockCardAfter;
} else {
$beforeQty = $lastSourceStockQty;
}
$afterQty = $beforeQty - $qtyReq;
// Insert Stockcard for source warehouse (OUT)
$sqlInsSourceCard = "INSERT INTO stockcard (
StockCardWarehouseID, StockCardDatetime, StockCardItemID,
StockCardItemUnitID, StockCardBatchNo, StockCardED,
StockCardReffID, StockCardStatus,
StockCardBefore, StockCardIn, StockCardOut, StockCardAfter,
StockCardUserID
) VALUES (?, NOW(), ?, ?, ?, ?, ?, 'MWT', ?, 0, ?, ?, ?)";
$qryInsSourceCard = $this->db->query($sqlInsSourceCard, [
$warehouseID,
$itemID,
$unitID,
$batchNo,
$expDate,
$stockID,
$beforeQty,
$qtyReq,
$afterQty,
$userID
]);
if (!$qryInsSourceCard) {
throw new Exception("Failed to insert stockcard for source warehouse ID: {$warehouseID}");
}
// * Query Stockcard where StockCardReffID == $transitStockID ORDER BY StockCardID DESC LIMIT 1
// * Insert Stockcard WH Transit (IN)
// New row with StockReffID = $transitStockID, StockCardIn = qtyReq, StockCardOut = 0, StockCardAfter = PreviousCardAfter + qtyReq
$sqlLastTransitCard = "SELECT StockCardAfter FROM stockcard
WHERE StockCardReffID = ? ORDER BY StockCardID DESC LIMIT 1";
$qryLastTransitCard = $this->db->query($sqlLastTransitCard, [$transitStockID]);
if (!$qryLastTransitCard) {
throw new Exception("Failed to query last stockcard entry for transit stock ID: {$transitStockID}");
}
$transitBeforeQty = 0;
if ($qryLastTransitCard->num_rows() > 0) {
$transitBeforeQty = $qryLastTransitCard->row()->StockCardAfter;
} else {
$sqlTransitQty = "SELECT StockQty FROM stock WHERE StockID = ?";
$qryTransitQty = $this->db->query($sqlTransitQty, [$transitStockID]);
if (!$qryTransitQty || $qryTransitQty->num_rows() === 0) {
throw new Exception("Failed to get current stock quantity for transit stock ID: {$transitStockID}");
}
$transitBeforeQty = $qryTransitQty->row()->StockQty - $qtyReq; // Subtract qtyReq since we've already added it
}
$transitAfterQty = $transitBeforeQty + $qtyReq;
// Insert Stockcard for transit warehouse (IN)
$sqlInsTransitCard = "INSERT INTO stockcard (
StockCardWarehouseID, StockCardDatetime, StockCardItemID,
StockCardItemUnitID, StockCardBatchNo, StockCardED,
StockCardReffID, StockCardStatus,
StockCardBefore, StockCardIn, StockCardOut, StockCardAfter, StockCardUserID
) VALUES (?, NOW(), ?, ?, ?, ?, ?, 'MWF', ?, ?, 0, ?, ?)";
$qryInsTransitCard = $this->db->query($sqlInsTransitCard, [
$transitWhId,
$itemID,
$unitID,
$batchNo,
$expDate,
$transitStockID,
$transitBeforeQty,
$qtyReq,
$transitAfterQty,
$userID
]);
if (!$qryInsTransitCard) {
throw new Exception("Failed to insert stockcard for transit warehouse ID: {$transitWhId}");
}
}
// Return true to indicate success
return true;
}
public function deleteTfRequest()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
}
$userID = $this->sys_user["M_UserID"];
$goodsTfID = $this->sys_input["GoodsTfID"];
$this->db->trans_begin();
// update tf header status
$sqlTrf = "UPDATE t_goods_transfer SET
T_GoodsTransferIsActive = 'N',
T_GoodsTransferDeleted = NOW(),
T_GoodsTransferM_UserID = ?
WHERE T_GoodsTransferID = ? AND T_GoodsTransferIsActive = 'Y'";
$queTrf = $this->db->query($sqlTrf, [$userID, $goodsTfID]);
if (!$queTrf) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update TF status to N");
exit;
}
// update tf detail status
$sqlTrfDtl = "UPDATE t_goods_transfer_detail SET
T_GoodsTransferDetailIsActive = 'N',
T_GoodsTransferDetailDeletedAt = NOW(),
T_GoodsTransferDetailM_UserID = ?
WHERE T_GoodsTransferDetailIDT_GoodsTransferID = ? AND T_GoodsTransferDetailIsActive = 'Y'";
$queTrfDtl = $this->db->query($sqlTrfDtl, [$userID, $goodsTfID]);
if (!$queTrfDtl) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update status TF detail to N");
exit;
}
// get last inserted data
$sqltfgood = "SELECT * FROM t_goods_transfer WHERE T_GoodsTransferIsActive = 'Y' AND T_GoodsTransferID = ?";
$quetfgood = $this->db->query($sqltfgood, [$goodsTfID]);
if (!$quetfgood) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get last data inserted");
exit;
}
$lastTFData = $quetfgood->row_array();
// insert log user activity
$msg = "Transfer Request nomor: {$lastTFData['T_GoodsTransferNum']}, tanggal: {$lastTFData['T_GoodsTransferDate']}, type: {$lastTFData['T_GoodsTransferType']}";
$this->insertUserActivty($goodsTfID, "DELETE", $userID, $msg, json_encode($lastTFData));
$this->db->trans_commit();
$this->sys_ok("[Success] Delete TF Request number: {$lastTFData['T_GoodsTransferNum']}");
} catch (Exception $exc) {
$message = $exc->getMessage();
$this->sys_error($message);
}
}
public function getUserLevel()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$userId = $this->sys_user["M_UserID"];
$sqlevel = "SELECT * FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?";
$qulevel = $this->db->query($sqlevel, [$userId]);
if (!$qulevel) {
$this->sys_error_db("[Error] get approval level user");
exit;
}
$data = $qulevel->row_array();
$this->sys_ok($data);
}
function insertUserActivty($tfid, $type, $userid, $desc = '', $data = '')
{
$sql = "INSERT INTO user_activity (
UserActivityCode,
UserActivityStatus,
UserActivityDescription,
UserActivityRefID,
UserActivityData,
UserActivityUserID,
UserActivityCreated
) VALUES (?,?,?,?,?,?,NOW())";
$que = $this->db->query($sql, ['TR', $type, $desc, $tfid, $data, $userid]);
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] insert into table user activity");
exit;
}
}
function toVerifOrApprove($id, $user)
{
$sqlevl = "SELECT * FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?";
$quelvl = $this->db->query($sqlevl, [$user['M_UserID']]);
if (!$quelvl) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] get user level");
exit;
}
$level = $quelvl->row_array()['M_UserM_ApproveLevelID'];
if ($level == '1') {
$sql = "UPDATE t_goods_transfer SET
T_GoodsTransferVerifiedBy = ?,
T_GoodsTransferVerifiedDate = NOW(),
T_GoodsTransferLastUpdated = NOW()
WHERE T_GoodsTransferID = ?
AND T_GoodsTransferIsActive = 'Y'";
$que = $this->db->query($sql, [$user['M_UserID'], $id]);
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update verified by manager");
exit;
}
} elseif ($level == '2') {
$sql = "UPDATE t_goods_transfer SET
T_GoodsTransferApprovedBy = ?,
T_GoodsTransferApprovedDate = NOW(),
T_GoodsTransferLastUpdated = NOW()
WHERE T_GoodsTransferID = ?
AND T_GoodsTransferIsActive = 'Y'";
$que = $this->db->query($sql, [$user['M_UserID'], $id]);
if (!$que) {
$this->db->trans_rollback();
$this->sys_error_db("[Error] update approve kareg");
exit;
}
}
}
}