1741 lines
72 KiB
PHP
1741 lines
72 KiB
PHP
<?php
|
|
|
|
class TransferRequest extends MY_Controller
|
|
{
|
|
var $db;
|
|
|
|
public function index()
|
|
{
|
|
echo "Goods Transfer Request/Requester 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 getStatus()
|
|
{
|
|
try {
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
}
|
|
|
|
$rst = [
|
|
["value" => 0, "title" => "All"],
|
|
["value" => 1, "title" => "Draft"],
|
|
["value" => 2, "title" => "Pending"],
|
|
["value" => 3, "title" => "Approved"],
|
|
["value" => 4, "title" => "Rejected"],
|
|
["value" => 5, "title" => "Paid"],
|
|
["value" => 6, "title" => "Completed"]
|
|
];
|
|
|
|
$this->sys_ok(["records" => $rst]);
|
|
} catch (Exception $exc) {
|
|
$message = $exc->getMessage();
|
|
$this->sys_error($message);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
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
|
|
FROM t_goods_transfer
|
|
JOIN m_branch ON T_GoodsTransferToM_BranchCode = M_BranchCode
|
|
AND M_BranchIsActive = 'Y'
|
|
WHERE T_GoodsTransferIsActive = 'Y'
|
|
AND T_GoodsTransferFromS_RegionalID = ?
|
|
AND T_GoodsTransferNum LIKE ?
|
|
AND T_GoodsTransferToM_BranchCode LIKE ?
|
|
AND T_GoodsTransferType = 'P'
|
|
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 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);
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
// Check for debug mode
|
|
$isDebug = isset($data['isDebug']) && $data['isDebug'] === true;
|
|
|
|
if ($isDebug) {
|
|
$this->db->trans_start(true); // Auto rollback mode
|
|
} else {
|
|
$this->db->trans_start();
|
|
}
|
|
|
|
// $sqlnum = "SELECT `fn_numbering`('TR') AS GoodsTfNum";
|
|
// $quenum = $this->db->query($sqlnum, []);
|
|
// if (!$quenum) {
|
|
// throw new Exception("[Error] Failed to generate transfer request number");
|
|
// }
|
|
// $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 generate number for TF request. " . json_encode($this->db->error()));
|
|
}
|
|
$goodsTfNum = $quenum->row_array()['numpd'];
|
|
|
|
$sqlTG = "INSERT INTO t_goods_transfer (
|
|
T_GoodsTransferFromS_RegionalID,
|
|
T_GoodsTransferToM_BranchCode,
|
|
T_GoodsTransferNum,
|
|
T_GoodsTransferNotes,
|
|
T_GoodsTransferDate,
|
|
T_GoodsTransferType,
|
|
T_GoodsTransferStatus,
|
|
T_GoodsTransferIsActive,
|
|
T_GoodsTransferCreatedAt,
|
|
T_GoodsTransferM_UserID
|
|
) VALUES (?,?,?,?,?,?,?,'Y',NOW(),?)";
|
|
$queTG = $this->db->query($sqlTG, [
|
|
$data["S_RegionalID"],
|
|
$data["M_BranchCode"],
|
|
$goodsTfNum,
|
|
$data["GoodsTfNotes"],
|
|
$data["GoodsTfDate"],
|
|
'P',
|
|
$data["GoodsTfStatus"],
|
|
$userID
|
|
]);
|
|
if (!$queTG) {
|
|
throw new Exception("[Error] Failed to insert into table t_goods_transfer. " . json_encode($this->db->error()));
|
|
}
|
|
$tGoodsTFID = $this->db->insert_id();
|
|
|
|
$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 batch number
|
|
$jsonBatchNo = "[]";
|
|
if (isset($value['ItemRequest']) && is_array($value['ItemRequest'])) {
|
|
$batches = $value['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;
|
|
}
|
|
}
|
|
}
|
|
|
|
$sqlTGD = "INSERT INTO t_goods_transfer_detail (
|
|
T_GoodsTransferDetailIDT_GoodsTransferID,
|
|
T_GoodsTransferDetailT_PurchaseRequestFlagID,
|
|
T_GoodsTransferDetailM_ItemID,
|
|
T_GoodsTransferDetailItemUnitID,
|
|
T_GoodsTransferDetailItemBatchNo,
|
|
T_GoodsTransferDetailQty,
|
|
T_GoodsTransferDetailQtyTF,
|
|
T_GoodsTransferDetailCreatedAt,
|
|
T_GoodsTransferDetailM_UserID
|
|
) VALUES (?,?,?,?,?,?,?,NOW(),?)";
|
|
$queTGD = $this->db->query($sqlTGD, [
|
|
$tGoodsTFID,
|
|
$flagID,
|
|
$itemID,
|
|
$unitID,
|
|
$jsonBatchNo,
|
|
$QtyStart,
|
|
$QtyTfRes,
|
|
$userID
|
|
]);
|
|
if (!$queTGD) {
|
|
throw new Exception("[Error] Failed to insert TF goods detail. " . json_encode($this->db->error()));
|
|
}
|
|
$TGoodsTFDetailID = $this->db->insert_id();
|
|
$datadetail[$key]['TGoodsTFDetailID'] = $TGoodsTFDetailID;
|
|
|
|
// jika status verified
|
|
if ($data["GoodsTfStatus"] == 'Verified') {
|
|
|
|
$this->moveStockToTransit($value, $data["S_RegionalID"], $userID, $TGoodsTFDetailID);
|
|
|
|
$sqlUpdFlag = "UPDATE purchase_request_flag
|
|
SET PurchaseRequestFlagQtyRest = ?,
|
|
PurchaseRequestFlagQtyProses = PurchaseRequestFlagQtyProses + ?
|
|
WHERE PurchaseRequestFlagID = ?
|
|
AND PurchaseRequestFlagIsActive = 'Y'";
|
|
$queUpdFlag = $this->db->query($sqlUpdFlag, [$QtyTfRes, $QtyTfRes, $flagID]);
|
|
if (!$queUpdFlag) {
|
|
throw new Exception("[Error] Failed to update quantity in table purchase_request_flag. " . 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, [$tGoodsTFID]);
|
|
if (!$quetfgood) {
|
|
throw new Exception("[Error] Failed to get last inserted transfer data. " . 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, [$tGoodsTFID]);
|
|
if (!$quetfdetail) {
|
|
throw new Exception("[Error] Failed to get last inserted transfer detail data. " . json_encode($this->db->error()));
|
|
}
|
|
$lastTFDetail = $quetfdetail->result_array();
|
|
$lastTFData['detail'] = $lastTFDetail;
|
|
|
|
$msg = "Transfer Request nomor: {$lastTFData['T_GoodsTransferNum']}, tanggal: {$lastTFData['T_GoodsTransferDate']}, type: {$lastTFData['T_GoodsTransferType']}";
|
|
$this->insertUserActivty($tGoodsTFID, "CREATE", $userID, $msg, json_encode($lastTFData));
|
|
|
|
$this->db->trans_complete();
|
|
$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();
|
|
|
|
$sqlTG = "UPDATE t_goods_transfer SET
|
|
T_GoodsTransferFromS_RegionalID = ?,
|
|
T_GoodsTransferToM_BranchCode = ?,
|
|
T_GoodsTransferNum = ?,
|
|
T_GoodsTransferNotes = ?,
|
|
T_GoodsTransferDate = ?,
|
|
T_GoodsTransferStatus = ?,
|
|
T_GoodsTransferLastUpdated = NOW(),
|
|
T_GoodsTransferM_UserID = ?
|
|
WHERE T_GoodsTransferID = ?
|
|
AND T_GoodsTransferIsActive = 'Y'";
|
|
$queTG = $this->db->query($sqlTG, [
|
|
$data["S_RegionalID"],
|
|
$data["M_BranchCode"],
|
|
$data["GoodsTfNum"],
|
|
$data["GoodsTfNotes"],
|
|
$data["GoodsTfDate"],
|
|
$data["GoodsTfStatus"],
|
|
$userID,
|
|
$data["GoodsTfID"]
|
|
]);
|
|
if (!$queTG) {
|
|
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);
|
|
}
|
|
|
|
$sqlUpdToN = "UPDATE t_goods_transfer_detail SET T_GoodsTransferDetailIsActive = 'N' WHERE T_GoodsTransferDetailIDT_GoodsTransferID = ?";
|
|
$queUpdToN = $this->db->query($sqlUpdToN, [$data["GoodsTfID"]]);
|
|
if (!$queUpdToN) {
|
|
throw new Exception("[Error] Failed to update all detail records to inactive. " . json_encode($this->db->error()));
|
|
}
|
|
|
|
$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 batch number
|
|
$jsonBatchNo = "[]";
|
|
if (isset($value['ItemRequest']) && is_array($value['ItemRequest'])) {
|
|
$batches = $value['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;
|
|
}
|
|
}
|
|
}
|
|
|
|
$sqlTGD = "INSERT INTO t_goods_transfer_detail (
|
|
T_GoodsTransferDetailIDT_GoodsTransferID,
|
|
T_GoodsTransferDetailT_PurchaseRequestFlagID,
|
|
T_GoodsTransferDetailM_ItemID,
|
|
T_GoodsTransferDetailItemUnitID,
|
|
T_GoodsTransferDetailItemBatchNo,
|
|
T_GoodsTransferDetailQty,
|
|
T_GoodsTransferDetailQtyTF,
|
|
T_GoodsTransferDetailCreatedAt,
|
|
T_GoodsTransferDetailM_UserID
|
|
) VALUES (?,?,?,?,?,?,?,NOW(),?)";
|
|
$queTGD = $this->db->query($sqlTGD, [
|
|
$data["GoodsTfID"],
|
|
$flagID,
|
|
$itemID,
|
|
$unitID,
|
|
$jsonBatchNo,
|
|
$QtyStart,
|
|
$QtyTfRes,
|
|
$userID
|
|
]);
|
|
if (!$queTGD) {
|
|
throw new Exception("[Error] Failed to insert TF goods detail. " . json_encode($this->db->error()));
|
|
}
|
|
$TGoodsTFDetailID = $this->db->insert_id();
|
|
$datadetail[$key]['TGoodsTFDetailID'] = $TGoodsTFDetailID;
|
|
|
|
// jika status verified
|
|
if ($data["GoodsTfStatus"] == 'Verified' && $data['actverif'] == 'V') {
|
|
|
|
$this->moveStockToTransit($value, $data["S_RegionalID"], $userID, $TGoodsTFDetailID);
|
|
|
|
$sqlUpdFlag = "UPDATE purchase_request_flag
|
|
SET PurchaseRequestFlagQtyRest = ?,
|
|
PurchaseRequestFlagQtyProses = PurchaseRequestFlagQtyProses + ?
|
|
WHERE PurchaseRequestFlagID = ?
|
|
AND PurchaseRequestFlagIsActive = 'Y'";
|
|
$queUpdFlag = $this->db->query($sqlUpdFlag, [$QtyTfRes, $QtyTfRes, $flagID]);
|
|
if (!$queUpdFlag) {
|
|
throw new Exception("[Error] Failed to update quantity in table purchase_request_flag. " . 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 updated transfer data. " . 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 updated transfer detail data. " . json_encode($this->db->error()));
|
|
}
|
|
$lastTFDetail = $quetfdetail->result_array();
|
|
$lastTFData['detail'] = $lastTFDetail;
|
|
|
|
$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'];
|
|
$lastSourceStockQty = $itemReq['StockQty'];
|
|
|
|
//* 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 = ?
|
|
AND StockBatchNo = ? ORDER BY StockID DESC LIMIT 1";
|
|
$qryCekTransit = $this->db->query($sqlCekTransit, [
|
|
$transitWhId,
|
|
$itemID,
|
|
$unitID,
|
|
$batchNo
|
|
]);
|
|
if (!$qryCekTransit) {
|
|
$err = json_encode($this->db->error());
|
|
throw new Exception("Failed to cek stock on warehouseId (ID: {$transitWhId}). DB Error: $err");
|
|
}
|
|
|
|
// *Insert or Update Row Stock Warehouse Transit
|
|
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();
|
|
|
|
$sql = "UPDATE t_goods_transfer SET
|
|
T_GoodsTransferIsActive = 'N',
|
|
T_GoodsTransferDeleted = NOW(),
|
|
T_GoodsTransferM_UserID = ?
|
|
WHERE T_GoodsTransferID = ?
|
|
AND T_GoodsTransferIsActive = 'Y'";
|
|
$qry = $this->db->query($sql, [$userID, $goodsTfID]);
|
|
if (!$qry) {
|
|
$this->db->trans_rollback();
|
|
$this->sys_error_db("Gagal menghapus Transfer Request (ID: {$goodsTfID}). Error:", $this->db);
|
|
exit;
|
|
}
|
|
|
|
$sqldet = "UPDATE t_goods_transfer_detail SET
|
|
T_GoodsTransferDetailIsActive = 'N',
|
|
T_GoodsTransferDetailDeletedAt = NOW(),
|
|
T_GoodsTransferDetailM_UserID = ?
|
|
WHERE T_GoodsTransferDetailIDT_GoodsTransferID = ? AND T_GoodsTransferDetailIsActive = 'Y'
|
|
";
|
|
$qdet = $this->db->query($sqldet, [$userID, $goodsTfID]);
|
|
if (!$qdet) {
|
|
$this->db->trans_rollback();
|
|
$this->sys_error_db("failed delete detail transfer request item. Error:", $this->db);
|
|
exit;
|
|
}
|
|
|
|
$sql_json = "SELECT t_goods_transfer.*, '' as details
|
|
FROM t_goods_transfer
|
|
WHERE T_GoodsTransferID = ?";
|
|
$qry_json = $this->db->query($sql_json, [$goodsTfID]);
|
|
if (!$qry_json) {
|
|
$this->db->trans_rollback();
|
|
$this->sys_error_db("select json tf error");
|
|
exit;
|
|
}
|
|
$row_json = $qry_json->row_array();
|
|
|
|
$descActivity = "Hapus transfer request {$row_json['T_GoodsTransferNum']}";
|
|
|
|
$sql_json_detail = "SELECT t_goods_transfer_detail.*
|
|
FROM t_goods_transfer_detail
|
|
WHERE T_GoodsTransferDetailIDT_GoodsTransferID = ?";
|
|
$qry_json_detail = $this->db->query($sql_json_detail, [$goodsTfID]);
|
|
if ($qry_json_detail) {
|
|
$row_json["details"] = $qry_json_detail->result_array();
|
|
} else {
|
|
$this->sys_error_db("select detail tf error", $this->db);
|
|
exit;
|
|
}
|
|
|
|
$data_json = $row_json;
|
|
|
|
$this->insertUserActivty($goodsTfID, 'DELETE', $userID, $descActivity, json_encode($data_json));
|
|
$this->db->trans_commit();
|
|
|
|
$this->sys_ok("Berhasil menghapus Transfer Request (ID: {$goodsTfID})");
|
|
} 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'];
|
|
$currpage = $prm['currpage'];
|
|
|
|
$page = 0;
|
|
$limit = 5;
|
|
if ($currpage > 0) {
|
|
$page = ($currpage - 1) * $limit;
|
|
}
|
|
|
|
// Get total count (unchanged)
|
|
$sqltotal = "SELECT
|
|
COUNT(DISTINCT PurchaseRequestDetailID) as total
|
|
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
|
|
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 = ?
|
|
)";
|
|
$quetotal = $this->db->query($sqltotal, [
|
|
$regionalid,
|
|
$branchCodeDestin,
|
|
$regionalid,
|
|
$branchCodeDestin
|
|
]);
|
|
if (!$quetotal) {
|
|
$this->sys_error_db("error get total listing tf request");
|
|
exit;
|
|
}
|
|
$total = $quetotal->result_array()[0]['total'];
|
|
|
|
if (intval($total) === 0) {
|
|
$this->sys_ok(["records" => [], "total" => $total]);
|
|
exit;
|
|
}
|
|
|
|
// Simplified main query - removing stock-related JOINs
|
|
$sqlist = "SELECT
|
|
PurchaseRequestDate,
|
|
PurchaseRequestNumber,
|
|
PurchaseRequestDetailM_ItemID,
|
|
PurchaseRequestDetailItemUnitID,
|
|
M_ItemDesc,
|
|
unitreq.ItemUnitID as RequestItemUnitID,
|
|
unitreq.ItemUnitName as RequestItemUnitName,
|
|
PurchaseRequestFlagID,
|
|
PurchaseRequestFlagQty,
|
|
PurchaseRequestFlagQtyRest,
|
|
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 unitreq
|
|
ON unitreq.ItemUnitID = PurchaseRequestDetailItemUnitID
|
|
AND unitreq.ItemUnitIsActive = 'Y'
|
|
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 = ?
|
|
)
|
|
ORDER BY PurchaseRequestDate ASC, PurchaseRequestNumber ASC
|
|
LIMIT ? OFFSET ?";
|
|
|
|
$quelist = $this->db->query($sqlist, [
|
|
$regionalid,
|
|
$branchCodeDestin,
|
|
$regionalid,
|
|
$branchCodeDestin,
|
|
$limit,
|
|
$page
|
|
]);
|
|
if (!$quelist) {
|
|
$this->sys_error_db("error get listing detail request transfer");
|
|
exit;
|
|
}
|
|
|
|
$rows = $quelist->result_array();
|
|
|
|
foreach ($rows as $key => $value) {
|
|
$itemID = $value['PurchaseRequestDetailM_ItemID'];
|
|
$reqUnitID = $value['RequestItemUnitID'];
|
|
$reqUnitName = $value['RequestItemUnitName'];
|
|
|
|
// Query semua stock yang tersedia di Gudang
|
|
$stockGudang = $this->getStockForItemRequested($itemID, $regionalid);
|
|
$rows[$key]['StockGudang'] = $stockGudang;
|
|
|
|
// Cek dulu apakah salah satu UnitStock ada yang == UnitReq
|
|
$hasDirectMatch = $this->checkStockReqUnitMatch($stockGudang, $reqUnitID);
|
|
|
|
$unpackData = $this->checkConversionPossibility($stockGudang, $reqUnitID, $reqUnitName, $itemID);
|
|
$hasUnpackOption = $unpackData['UnpackData']['CanUnpack'] ?? false;
|
|
|
|
$rows[$key]['CanDirectUse'] = $hasDirectMatch;
|
|
$rows[$key]['CanUnpack'] = $hasUnpackOption;
|
|
$rows[$key]['UnpackData'] = $unpackData['UnpackData'];
|
|
|
|
$rows[$key]['ItemRequest'] = [];
|
|
}
|
|
|
|
$result = array(
|
|
"records" => $rows,
|
|
"total" => $total
|
|
);
|
|
|
|
$this->sys_ok($result);
|
|
} catch (Exception $exc) {
|
|
$message = $exc->getMessage();
|
|
$this->sys_error($message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ambil semua stock untuk ItemID di gudang regionalId meskipun beda batch dan UnitItem
|
|
* @param : int ItemID, int RegionalID
|
|
* @return : array of objects
|
|
*/
|
|
private function getStockForItemRequested($itemID, $regionalID)
|
|
{
|
|
$sqlStock = "SELECT
|
|
stock.StockID,
|
|
stock.StockItemUnitID,
|
|
itemunit.ItemUnitName as StockItemUnitName,
|
|
stock.StockQty,
|
|
stock.StockBatchNo,
|
|
stock.StockED,
|
|
stock.StockStockNumber,
|
|
stock.StockItemPrice
|
|
FROM warehouse
|
|
JOIN stock ON StockWarehouseID = WarehouseID
|
|
AND stock.StockQty > 0
|
|
JOIN itemunit ON ItemUnitID = stock.StockItemUnitID
|
|
AND itemunit.ItemUnitIsActive = 'Y'
|
|
WHERE WarehouseS_RegionalID = ?
|
|
AND WarehouseIsTransit = 'N'
|
|
AND WarehouseType = 'R'
|
|
AND WarehouseIsActive = 'Y'
|
|
AND stock.StockItemID = ?
|
|
ORDER BY stock.StockED ASC, stock.StockQty DESC";
|
|
|
|
$qryStock = $this->db->query($sqlStock, [$regionalID, $itemID]);
|
|
|
|
if (!$qryStock) {
|
|
return [];
|
|
}
|
|
|
|
return $qryStock->result_array();
|
|
}
|
|
|
|
/**
|
|
* Cek apakah ada Stock memiliki ItemUnit yang sama dengan Unit Request
|
|
* @param : array($stockGudang), int(reqUnitID)
|
|
* @return : boolean, true jika ada
|
|
*/
|
|
private function checkStockReqUnitMatch($stockGudang, $reqUnitID)
|
|
{
|
|
foreach ($stockGudang as $stock) {
|
|
if ($stock['StockItemUnitID'] == $reqUnitID) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Cek semua kemungkinan Konversi Unit
|
|
* Misal: UnitReq = BUAH, tapi di stock ada LUSIN, dan KODI. Maka akan ada beberapa ConversionOptions
|
|
* @param : array($stockGudang), int($reqUnitID), string($reqUnitName), int($itemID)
|
|
* @return : object
|
|
*/
|
|
private function checkConversionPossibility($stockGudang, $reqUnitID, $reqUnitName, $itemID)
|
|
{
|
|
$conversionOptions = [];
|
|
$uniqueCombinations = [];
|
|
|
|
foreach ($stockGudang as $stock) {
|
|
$stockUnitID = $stock['StockItemUnitID'];
|
|
$stockUnitName = $stock['StockItemUnitName'];
|
|
|
|
if ($stockUnitID != $reqUnitID) {
|
|
$sqlConv = "SELECT * FROM unitconvert
|
|
WHERE UnitConvertFromItemUnitID = ?
|
|
AND UnitConvertToItemUnitID = ?
|
|
AND UnitConvertIsActive = 'Y'
|
|
LIMIT 1";
|
|
$qryConv = $this->db->query($sqlConv, [$stockUnitID, $reqUnitID]);
|
|
|
|
$conversionKey = $stockUnitID . '_' . $reqUnitID;
|
|
|
|
// Hanya tambah ke conversionOptions jika FromItemUnitID dan ToItemUnitID berbeda dengan existing
|
|
if ($qryConv && $qryConv->num_rows() > 0 && !in_array($conversionKey, $uniqueCombinations)) {
|
|
$conversionData = $qryConv->row();
|
|
$conversionOptions[] = [
|
|
"FromItemUnitID" => $stockUnitID,
|
|
"FromItemUnitName" => $stockUnitName,
|
|
"ToItemUnitID" => $reqUnitID,
|
|
"ToItemUnitName" => $reqUnitName,
|
|
"UnitConvertAmount" => $conversionData->UnitConvertAmount
|
|
];
|
|
|
|
$uniqueCombinations[] = $conversionKey;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($conversionOptions)) {
|
|
return [
|
|
'MustUnpack' => true,
|
|
'UnpackData' => [
|
|
"M_ItemID" => $itemID,
|
|
"CanUnpack" => false,
|
|
"ReasonCannotUnpack" => "Tidak ditemukan konversi dari unit stock yang tersedia ke unit request {$reqUnitName}"
|
|
]
|
|
];
|
|
} else {
|
|
return [
|
|
'MustUnpack' => true,
|
|
'UnpackData' => [
|
|
"M_ItemID" => $itemID,
|
|
"CanUnpack" => true,
|
|
"ConversionOptions" => $conversionOptions
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
public function getDraftDetail()
|
|
{
|
|
try {
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
exit;
|
|
}
|
|
$prm = $this->sys_input;
|
|
$regID = $this->sys_user["S_RegionalID"];
|
|
$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_GoodsTransferDetailItemBatchNo,
|
|
PurchaseRequestFlagStatus,
|
|
T_GoodsTransferVerifiedBy,
|
|
T_GoodsTransferVerifiedDate
|
|
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 data draft detail transfer");
|
|
exit;
|
|
}
|
|
|
|
$detail = $qry->result_array();
|
|
|
|
foreach ($detail as $key => $value) {
|
|
$jsonStr = $value['T_GoodsTransferDetailItemBatchNo'];
|
|
$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;
|
|
}
|
|
}
|
|
$detail[$key]['StockGudang'] = [];
|
|
|
|
// Foreach batches update StockQty dengan Query Baru
|
|
foreach ($batches as &$batch) {
|
|
$sqlCekStock = "SELECT stock.StockID,
|
|
stock.StockItemUnitID,
|
|
itemunit.ItemUnitName as StockItemUnitName,
|
|
stock.StockQty,
|
|
stock.StockBatchNo,
|
|
stock.StockED,
|
|
stock.StockStockNumber,
|
|
stock.StockItemPrice
|
|
FROM stock
|
|
JOIN itemunit ON ItemUnitID = stock.StockItemUnitID
|
|
AND itemunit.ItemUnitIsActive = 'Y'
|
|
WHERE StockID = ?";
|
|
$qryCekStock = $this->db->query($sqlCekStock, [$batch->StockID]);
|
|
if (!$qryCekStock) {
|
|
$this->sys_error_db("[Error] Query StockQty yang terbaru untuk ItemRequest");
|
|
exit;
|
|
}
|
|
|
|
$batch->StockQty = $qryCekStock->row()->StockQty;
|
|
$detail[$key]['StockGudang'][] = $qryCekStock->row();
|
|
}
|
|
unset($batch);
|
|
|
|
$detail[$key]['ItemRequest'] = $batches;
|
|
unset($detail[$key]['T_GoodsTransferDetailItemBatchNo']);
|
|
}
|
|
|
|
$result = array(
|
|
"records" => $detail,
|
|
"total" => sizeof($detail)
|
|
);
|
|
$this->sys_ok($result);
|
|
} catch (Exception $exc) {
|
|
$message = $exc->getMessage();
|
|
$this->sys_error($message);
|
|
}
|
|
}
|
|
|
|
public function processTransfer()
|
|
{
|
|
try {
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
exit;
|
|
}
|
|
|
|
$userID = $this->sys_user["M_UserID"];
|
|
$data = $this->sys_input;
|
|
$tfdetail = $data['detail'];
|
|
|
|
foreach ($tfdetail as $key => $value) {
|
|
$reqFlagID = $data['PurchaseRequestFlagID'];
|
|
$reqTFQty = $data['PurchaseRequestFlagQtyRest'];
|
|
|
|
$sqlgetproc = "SELECT SELECT PurchaseRequestFlagQtyProses FROM purchase_request_flag
|
|
WHERE PurchaseRequestFlagID = ? AND PurchaseRequestFlagIsActive = 'Y'";
|
|
$qrygetproc = $this->db->query($sqlgetproc, [$reqFlagID]);
|
|
if (!$qrygetproc) {
|
|
$this->sys_error_db("error get current purchase request flag process quantity");
|
|
exit;
|
|
}
|
|
$qtyProc = $qrygetproc->result_array()[0]['PurchaseRequestFlagQtyProses'];
|
|
|
|
$this->db->trans_begin();
|
|
|
|
$procQtyUpdt = intval($qtyProc) + intval($reqTFQty);
|
|
$sqlupdtproc = "UPDATE purchase_request_flag
|
|
SET
|
|
PurchaseRequestFlagQtyProses = ?,
|
|
PurchaseRequestFlagLastUpdated = NOW(),
|
|
PurchaseRequestFlagUserID = ?
|
|
WHERE PurchaseRequestFlagID = ?
|
|
AND PurchaseRequestFlagIsActive = 'Y'";
|
|
$qryupdtproc = $this->db->query($sqlupdtproc, [$procQtyUpdt, $userID, $reqFlagID]);
|
|
if (!$qryupdtproc) {
|
|
$this->db->trans_rollback();
|
|
$this->sys_error_db('error update flag update process qty');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$this->db->trans_commit();
|
|
$this->sys_ok("Berhasil mengupdate Qty process (ID: {$data['GoodsTfID']})");
|
|
} 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,
|
|
ItemUnitName,
|
|
StockItemPrice,
|
|
StockBatchNo,
|
|
StockED,
|
|
StockQty
|
|
FROM warehouse
|
|
JOIN stock ON StockWarehouseID = WarehouseID
|
|
AND StockQty > 0
|
|
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 = ?
|
|
AND StockBatchNo LIKE ?";
|
|
$quebatch = $this->db->query($sqlbatch, [
|
|
$prm['regionalid'],
|
|
$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 getUnpackItemBatchListing()
|
|
{
|
|
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,
|
|
ItemUnitName,
|
|
StockItemPrice,
|
|
StockBatchNo,
|
|
StockED,
|
|
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 IN ? -- Bedanya dengan yang getItemBatchListing
|
|
AND StockBatchNo LIKE ?";
|
|
$quebatch = $this->db->query($sqlbatch, [
|
|
$prm['regionalid'],
|
|
$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 unpackingStock()
|
|
{
|
|
try {
|
|
if (!$this->isLogin) {
|
|
$this->sys_error("Invalid Token");
|
|
exit;
|
|
}
|
|
|
|
$prm = $this->sys_input;
|
|
$stockNo = $prm['StockStockNumber'];
|
|
$stockBatchNo = $prm['StockBatchNo'];
|
|
$unpackQty = intval($prm['UnpackQty']); // Qty yang mau di unpack dalam Unit Stock
|
|
$toItemUnitID = $prm['ToItemUnitID'];
|
|
$convertAmount = $prm['UnitConvertAmount'];
|
|
|
|
|
|
if ($prm['isDebug'] == true) {
|
|
$this->db->trans_start(true);
|
|
} else {
|
|
$this->db->trans_start();
|
|
}
|
|
|
|
/* *== Input Validation ==* */
|
|
// UnitConvertAmount can't 0
|
|
if ($convertAmount <= 0) {
|
|
throw new Exception("UnitConvertAmount tidak boleh <= 0");
|
|
}
|
|
|
|
// Query Stock by StockNumber and BatchNo
|
|
$sqlCekStock = "SELECT stock.*,
|
|
ItemUnitName as StockUnitName
|
|
FROM stock
|
|
JOIN itemunit
|
|
ON ItemUnitID = StockItemUnitID
|
|
WHERE StockStockNumber = ? AND StockBatchNo = ? ";
|
|
$qryCekStock = $this->db->query($sqlCekStock, [$stockNo, $stockBatchNo]);
|
|
|
|
if (!$qryCekStock || $qryCekStock->num_rows() == 0) {
|
|
$error = json_encode($this->db->error(), JSON_PRETTY_PRINT);
|
|
throw new Exception("Error Query DB $error atau Tidak Ditemukan Stock dengan StockNumber {$stockNo} dan Batch $stockBatchNo");
|
|
}
|
|
|
|
// Take the StockID
|
|
$rstCek = $qryCekStock->row();
|
|
$stockID = $rstCek->StockID;
|
|
$stockQty = $rstCek->StockQty;
|
|
$stockUnitName = $rstCek->StockUnitName;
|
|
|
|
// Validate StockQty >= UnpackQty
|
|
if ($stockQty < $unpackQty) {
|
|
throw new Exception("Unpack Qty tidak boleh melebih Stock Qty");
|
|
}
|
|
|
|
$qryLogs = [];
|
|
|
|
// Update StockQty = StockQty - UnpackQty
|
|
$newStockQty = $stockQty - $unpackQty;
|
|
$sqlUp = "UPDATE stock SET StockQty = ? WHERE StockID = ?";
|
|
$qryUp = $this->db->query($sqlUp, [$newStockQty, $stockID]);
|
|
|
|
if (!$qryUp) {
|
|
throw new Exception("Failed to update StockQty");
|
|
} else {
|
|
$qryLogs["update_qty_unpack"] = "Berhasil existing stock dari $stockQty $stockUnitName to {$newStockQty} {$stockUnitName}";
|
|
|
|
$sql = "SELECT stock.*, ItemUnitName as StockUnitName
|
|
FROM stock
|
|
JOIN itemunit ON ItemUnitID = StockItemUnitID
|
|
WHERE StockID = ?";
|
|
$qry = $this->db->query($sql, [$stockID]);
|
|
$updatedStock = $qry->row();
|
|
}
|
|
|
|
// Insert Log, with StockLogStatus = UP_OUT
|
|
$sqlUpLog = "INSERT INTO stocklog (
|
|
StockLogWarehouseID, StockLogDateTime, StockLogItemID,
|
|
StockLogItemUnitID, StockLogStockNumber, StockLogBatchNo,
|
|
StockLogED, StockLogStatus, StockLogQty, StockLogUserID
|
|
) VALUES (?,NOW(),?,?,?,?,?,?,?,?)";
|
|
$qryUpLog = $this->db->query($sqlUpLog, [
|
|
$rstCek->StockWarehouseID,
|
|
$rstCek->StockItemID,
|
|
$rstCek->StockItemUnitID,
|
|
$rstCek->StockStockNumber,
|
|
$rstCek->StockBatchNo,
|
|
$rstCek->StockED,
|
|
'UP_OUT',
|
|
$unpackQty, // OUT sesuai UnpackQty
|
|
$this->sys_user['M_UserID']
|
|
]);
|
|
|
|
if (!$qryUpLog) {
|
|
throw new Exception("Failed to insert stocklog for UP_OUT");
|
|
} else {
|
|
$qryLogs["insert_log_up_out"] = "Berhasil stocklog UP_OUT {$rstCek->StockQty} {$stockUnitName} for StockNumber {$rstCek->StockStockNumber}";
|
|
}
|
|
|
|
|
|
$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 StockID: {$stockID}");
|
|
}
|
|
|
|
$beforeQty = 0;
|
|
if ($qryLastSourceCard->num_rows() > 0) {
|
|
$beforeQty = $qryLastSourceCard->row()->StockCardAfter;
|
|
} else {
|
|
$beforeQty = $stockQty;
|
|
}
|
|
|
|
$afterQty = $beforeQty - $unpackQty;
|
|
|
|
// Insert Stockcard for source stock (OUT)
|
|
$sqlInsSourceCard = "INSERT INTO stockcard (
|
|
StockCardWarehouseID, StockCardDatetime, StockCardItemID,
|
|
StockCardItemUnitID, StockCardBatchNo, StockCardED,
|
|
StockCardReffID, StockCardStatus,
|
|
StockCardBefore, StockCardIn, StockCardOut, StockCardAfter,
|
|
StockCardUserID
|
|
) VALUES (?, NOW(), ?, ?, ?, ?, ?, 'UP_OUT', ?, 0, ?, ?, ?)";
|
|
|
|
$qryInsSourceCard = $this->db->query($sqlInsSourceCard, [
|
|
$rstCek->StockWarehouseID,
|
|
$rstCek->StockItemID,
|
|
$rstCek->StockItemUnitID,
|
|
$rstCek->StockBatchNo,
|
|
$rstCek->StockED,
|
|
$stockID,
|
|
$beforeQty,
|
|
$unpackQty,
|
|
$afterQty,
|
|
$this->sys_user['M_UserID']
|
|
]);
|
|
|
|
if (!$qryInsSourceCard) {
|
|
throw new Exception("Failed to insert stockcard for source stock (UP_OUT)");
|
|
} else {
|
|
$qryLogs["insert_card_up_out"] = `Berhasil stockcard UP_OUT pada StockCardID: {$this->db->insert_id()}dengan StockCardReffID: {$stockID}`;
|
|
}
|
|
|
|
// Insert new row stock hasil unpack
|
|
$sqlIn = "INSERT INTO stock (
|
|
StockWarehouseAlmariID, StockWarehouseRackID,
|
|
StockWarehouseID,StockStockNumber,
|
|
StockBatchNo,StockItemID,StockItemUnitID,
|
|
StockED,StockItemPrice,
|
|
StockQty,StockLastUpdated,StockUserID
|
|
) VALUES (0, 0, ?, fn_numbering('SN'), ?, ?, ?, ?, ?, ?, NOW(), ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
StockItemPrice = VALUES(StockItemPrice),
|
|
StockQty = StockQty + VALUES(StockQty),
|
|
StockLastUpdated = NOW(),
|
|
StockUserID = VALUES(StockUserID);";
|
|
|
|
$qtyConverted = $unpackQty * $convertAmount;
|
|
$priceConverted = $rstCek->StockItemPrice / $convertAmount;
|
|
|
|
$qryIn = $this->db->query($sqlIn, [
|
|
$rstCek->StockWarehouseID,
|
|
$rstCek->StockBatchNo,
|
|
$rstCek->StockItemID,
|
|
$toItemUnitID,
|
|
$rstCek->StockED,
|
|
$priceConverted,
|
|
$qtyConverted,
|
|
$this->sys_user['M_UserID']
|
|
]);
|
|
|
|
if (!$qryIn) {
|
|
$error = json_encode($this->db->error(), JSON_PRETTY_PRINT);
|
|
throw new Exception("Failed to insert new stock for unpacking. DB Error: $error");
|
|
}
|
|
|
|
// Query Stock Hasil Unpack yang Baru untuk data Stocklog dan Stockcard
|
|
$sql = "SELECT stock.*, ItemUnitName as StockUnitName
|
|
FROM stock
|
|
JOIN itemunit ON ItemUnitID = StockItemUnitID
|
|
WHERE StockWarehouseID = ?
|
|
AND StockItemID = ? AND StockItemUnitID = ?
|
|
AND StockBatchNo = ? AND StockED = ?";
|
|
|
|
$qry = $this->db->query($sql, [
|
|
$rstCek->StockWarehouseID,
|
|
$rstCek->StockItemID,
|
|
$toItemUnitID,
|
|
$rstCek->StockBatchNo,
|
|
$rstCek->StockED
|
|
]);
|
|
|
|
if (!$qry) {
|
|
$err = json_encode($this->db->error(), JSON_PRETTY_PRINT);
|
|
throw new Exception("Error select row stock hasil unpacking");
|
|
}
|
|
$unpackResultStock = $qry->row();
|
|
|
|
$qryLogs["insert_new_stock"] = "Berhasil insert Stock No. {$unpackResultStock->StockStockNumber} after unpacking Stock No. {$rstCek->StockStockNumber} dari {$unpackQty} {$stockUnitName} ke {$qtyConverted} {$unpackResultStock->StockUnitName}";
|
|
|
|
// Log hasil konversi with StockLogStatus = UP_IN
|
|
$sqlUpLog = "INSERT INTO stocklog (
|
|
StockLogWarehouseID, StockLogDateTime, StockLogItemID,
|
|
StockLogItemUnitID, StockLogStockNumber, StockLogBatchNo,
|
|
StockLogED, StockLogStatus, StockLogQty, StockLogUserID
|
|
) VALUES (?,NOW(),?,?,?,?,?,?,?,?)";
|
|
$qryUpLog = $this->db->query($sqlUpLog, [
|
|
$unpackResultStock->StockWarehouseID,
|
|
$unpackResultStock->StockItemID,
|
|
$unpackResultStock->StockItemUnitID,
|
|
$unpackResultStock->StockStockNumber,
|
|
$unpackResultStock->StockBatchNo,
|
|
$unpackResultStock->StockED,
|
|
'UP_IN',
|
|
$qtyConverted, // IN sesuai stock hasil konversi jangan ambil StockQty jaga2 kalau StockQty=StcokQty+convertedQty
|
|
$this->sys_user['M_UserID']
|
|
]);
|
|
|
|
if (!$qryUpLog) {
|
|
throw new Exception("Failed to insert stocklog for UP_IN");
|
|
} else {
|
|
$qryLogs["insert_log_up_in"] = "Berhasil stocklog UP_IN {$qtyConverted} {$unpackResultStock->StockUnitName}";
|
|
}
|
|
|
|
$sqlLastRstCard = "SELECT StockCardAfter FROM stockcard
|
|
WHERE StockCardReffID = ? ORDER BY StockCardID DESC LIMIT 1";
|
|
$qryLastRstCard = $this->db->query($sqlLastRstCard, [$unpackResultStock->StockID]);
|
|
if (!$qryLastRstCard) {
|
|
throw new Exception("Failed to query last stockcard entry for destination stock ID: {$unpackResultStock->StockID}");
|
|
}
|
|
|
|
$destBeforeQty = 0;
|
|
if ($qryLastRstCard->num_rows() > 0) {
|
|
$destBeforeQty = $qryLastRstCard->row()->StockCardAfter;
|
|
} else {
|
|
// If no previous stockcard for unpack result stock. Ambil StockQty
|
|
$destBeforeQty = $unpackResultStock->StockQty - $qtyConverted;
|
|
}
|
|
|
|
$destAfterQty = $destBeforeQty + $qtyConverted;
|
|
|
|
// Insert Stockcard for destination stock (IN)
|
|
$sqlInsDestCard = "INSERT INTO stockcard (
|
|
StockCardWarehouseID, StockCardDatetime, StockCardItemID,
|
|
StockCardItemUnitID, StockCardBatchNo, StockCardED,
|
|
StockCardReffID, StockCardStatus,
|
|
StockCardBefore, StockCardIn, StockCardOut, StockCardAfter,
|
|
StockCardUserID
|
|
) VALUES (?, NOW(), ?, ?, ?, ?, ?, 'UP_IN', ?, ?, 0, ?, ?)";
|
|
|
|
$qryInsDestCard = $this->db->query($sqlInsDestCard, [
|
|
$unpackResultStock->StockWarehouseID,
|
|
$unpackResultStock->StockItemID,
|
|
$unpackResultStock->StockItemUnitID,
|
|
$unpackResultStock->StockBatchNo,
|
|
$unpackResultStock->StockED,
|
|
$unpackResultStock->StockID,
|
|
$destBeforeQty,
|
|
$qtyConverted,
|
|
$destAfterQty,
|
|
$this->sys_user['M_UserID']
|
|
]);
|
|
|
|
if (!$qryInsDestCard) {
|
|
throw new Exception("Failed to insert stockcard for destination stock (UP_IN)");
|
|
} else {
|
|
$qryLogs["insert_card_up_in"] = `Berhasil stockcard UP_OUT pada StockCardID: {$this->db->insert_id()}dengan StockCardReffID: {$stockID}`;
|
|
}
|
|
|
|
$this->db->trans_complete();
|
|
|
|
$this->sys_ok([
|
|
"OldStock" => $rstCek,
|
|
"UpdatedStock" => $updatedStock,
|
|
"UnpackResultStock" => $unpackResultStock,
|
|
"TranssactionLogs" => $qryLogs
|
|
]);
|
|
} catch (Exception $e) {
|
|
$this->db->trans_rollback();
|
|
$message = $e->getMessage();
|
|
$this->sys_error($message);
|
|
}
|
|
}
|
|
|
|
function insertUserActivty($id, $type, $userID, $desc = '', $data = '')
|
|
{
|
|
$sql = "INSERT INTO user_activity (
|
|
UserActivityCode,
|
|
UserActivityStatus,
|
|
UserActivityDescription,
|
|
UserActivityRefID,
|
|
UserActivityData,
|
|
UserActivityUserID,
|
|
UserActivityCreated
|
|
) VALUES (
|
|
?, ?, ?, ?, ?, ?, NOW()
|
|
)";
|
|
|
|
// Eksekusi query dengan parameter yang diberikan
|
|
$exec = $this->db->query($sql, [
|
|
'TR',
|
|
$type,
|
|
$desc,
|
|
$id,
|
|
$data,
|
|
$userID
|
|
]);
|
|
|
|
// Jika query gagal, lempar error
|
|
if (!$exec) {
|
|
$this->sys_error_db("Error inserting user activity", $this->db);
|
|
$this->db->trans_rollback();
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|