isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $user = $this->sys_user; $start_date = $prm['start_date']; $end_date = $prm['end_date']; $search = '%' . $prm['search'] . '%'; $page = 0; $limit = 15; if ($prm['current_page'] > 0) { $page = ($prm['current_page'] - 1) * $limit; } $status = $prm['status']; $status_rm = ""; if ($status != "") { $status_rm .= " AND MutasiRequestStatus = '{$status}'"; } $sql = "SELECT DISTINCT MutasiRequestID, MutasiRequestDate, MutasiRequestNumber, MutasiRequestTotalValue, MutasiRequestStatus, MutasiRequestNote, MutasiRequestIsVerif, MutasiRequestVerifUserID, MutasiRequestVerifDate, MutasiRequestIsApproved, MutasiRequestApprovedUserID, MutasiRequestApprovedDate, itemCategoryID, itemCategoryName, a.M_BranchID as branch_asal_id, a.M_BranchCode as branch_asal_code, a.M_BranchName as branch_asal_name, b.M_BranchID as branch_tujuan_id, b.M_BranchCode as branch_tujuan_code, b.M_BranchName as branch_tujuan_name FROM mutasi_request JOIN item_category ON MutasiRequestItemCategoryID = itemCategoryID AND itemCategoryIsActive = 'Y' JOIN m_branch a ON MutasiRequestFromBranchID = a.M_BranchID AND a.M_BranchIsActive = 'Y' JOIN m_branch b ON MutasiRequestToBranchID = b.M_BranchID AND b.M_BranchIsActive = 'Y' WHERE MutasiRequestIsActive = 'Y' $status_rm AND (MutasiRequestNumber LIKE ?) AND MutasiRequestDate BETWEEN DATE(?) AND DATE(?) ORDER BY MutasiRequestID DESC"; $sqltotal = "SELECT COUNT(*) as total FROM ($sql) as x"; $qrytotal = $this->db->query($sqltotal, [$search, $start_date, $end_date]); if (!$qrytotal) { $this->sys_error_db("['Error'] get total data mutasi", $this->db); exit; } $total = $qrytotal->row_array()['total']; $sqldata = $sql . " LIMIT ? OFFSET ?"; $qrydata = $this->db->query($sqldata, [ $search, $start_date, $end_date, $limit, $page ]); if (!$qrydata) { $this->sys_error_db("[Error] get list data mutasi", $this->db); exit; } $rows = $qrydata->result_array(); $result = array( "total_page" => ceil($total / $limit), "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getCategory() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $search = '%' . $prm["search"] . '%'; $sql = "SELECT itemCategoryID, itemCategoryName FROM item_category WHERE itemCategoryIsActive = 'Y' AND itemCategoryName LIKE ? AND itemCategoryID IN (2,3) ORDER BY itemCategoryName ASC"; $qry = $this->db->query($sql, [$search]); if (!$qry) { $this->sys_error_db("[Error] Query getCategory"); return; } $rows = $qry->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getBranchAsal() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $user = $this->sys_user; $sql = "SELECT M_BranchID, M_BranchCode, M_BranchName FROM m_branch WHERE M_BranchIsActive = 'Y' AND M_BranchS_RegionalID = ?"; $qry = $this->db->query($sql, [$user['S_RegionalID']]); if (!$qry) { $this->sys_error_db("[Error] Query getBranchAsal"); return; } $rows = $qry->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getBranchTujuan() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $user = $this->sys_user; $search = '%' . $prm["search"] . '%'; $sql = "SELECT M_BranchID, M_BranchCode, M_BranchName FROM m_branch WHERE M_BranchIsActive = 'Y' AND M_BranchS_RegionalID = ? AND M_BranchID <> ? AND M_BranchName LIKE ? ORDER BY M_BranchName ASC"; $qry = $this->db->query($sql, [$user['S_RegionalID'], $user['M_BranchID'], $search]); if (!$qry) { $this->sys_error_db("[Error] Query getBranchTujuan"); return; } $rows = $qry->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getReceiveOrderPo() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $itemCategoryID = $prm["itemCategoryID"]; $branchAsalCode = $prm["branchAsalCode"]; $search = '%' . $prm["search"] . '%'; $sql = "SELECT DISTINCT ReceiveOrderPoID, ReceiveOrderPoNumber, ReceiveOrderPoIDate, ReceiveOrderPoWarehouseID, ReceiveOrderPoM_BranchCode FROM receive_order_po JOIN t_barcode_barang ON T_BarcodeBarangReceiveOrderPoID = ReceiveOrderPoID AND T_BarcodeBarangIsActive = 'Y' AND T_BarcodeBarangStockID <> 0 JOIN m_item ON T_BarcodeBarangM_ItemID = M_ItemID AND M_ItemIsActive = 'Y' AND M_ItemItem_CategoryID = ? WHERE ReceiveOrderPoIsActive = 'Y' AND ReceiveOrderPoM_BranchCode = ? AND ReceiveOrderPoIsHandover = 'Y' AND ReceiveOrderPoConfirmed = 'Y' AND (ReceiveOrderPoNumber LIKE ?) GROUP BY ReceiveOrderPoID"; $qry = $this->db->query($sql, [$itemCategoryID, $branchAsalCode, $search]); if (!$qry) { $this->sys_error_db("[Error] Query getReceiveOrderPo"); return; } $rows = $qry->result_array(); $result = array( "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getItemReceive() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $search = '%' . $prm["search"] . '%'; $warhouseID = $prm["warhouseID"]; $branchAsalCode = $prm["branchAsalCode"]; $receiveOrderPoID = $prm["receiveOrderPoID"]; $totalCount = 0; $totalPage = 0; $number_offset = 0; $number_limit = 15; if ($prm["current_page"] > 0) { $number_offset = ($prm["current_page"] - 1) * $number_limit; } $sql_branch = "SELECT M_BranchID, M_BranchCode FROM m_branch WHERE M_BranchIsActive = 'Y' AND M_BranchCode = ?"; $qry_branch = $this->db->query($sql_branch, [$branchAsalCode]); if (!$qry_branch) { $this->sys_error_db("[Error] Query getItem - branch"); return; } $row_branch = $qry_branch->result_array()[0]; $sql = "SELECT ro.ReceiveOrderPoID, ro.ReceiveOrderPoNumber, i.M_ItemID, i.M_ItemCode, i.M_ItemDesc, iu.ItemUnitID, iu.ItemUnitCode, iu.ItemUnitName, s.StockID, s.StockQty AS stock_total, COUNT(b.T_BarcodeBarangID) AS barcode_total, IFNULL(l.qty_locked, 0) AS qty_locked, (s.StockQty - IFNULL(l.qty_locked, 0)) AS qty_available, w.WarehouseID, 0 AS qty_mutasi FROM t_barcode_barang b JOIN receive_order_po ro ON b.T_BarcodeBarangReceiveOrderPoID = ro.ReceiveOrderPoID AND ro.ReceiveOrderPoIsActive = 'Y' AND ro.ReceiveOrderPoID = ? JOIN stock s ON s.StockID = b.T_BarcodeBarangStockID JOIN warehouse w ON s.StockWarehouseID = w.WarehouseID AND w.WarehouseIsActive = 'Y' AND w.WarehouseM_BranchID = ? JOIN m_item i ON i.M_ItemID = b.T_BarcodeBarangM_ItemID JOIN itemunit iu ON b.T_BarcodeBarangItemUnitID = iu.ItemUnitID LEFT JOIN ( SELECT MutasiStockLockStockID, SUM(MutasiStockLockQtyLocked) AS qty_locked FROM mutasi_stock_lock WHERE MutasiStockLockIsActive = 'Y' AND MutasiStockLockStatus = 'ACTIVE' AND MutasiStockLockType = 'INV' GROUP BY MutasiStockLockStockID ) l ON l.MutasiStockLockStockID = s.StockID WHERE s.StockWarehouseID = ? AND b.T_BarcodeBarangIsActive = 'Y' AND b.T_BarcodeBarangStockID <> 0 AND (i.M_ItemCode LIKE ? OR i.M_ItemDesc LIKE ?) GROUP BY ro.ReceiveOrderPoID, s.StockID, i.M_ItemID ORDER BY ro.ReceiveOrderPoID DESC"; $sqltotal = "SELECT COUNT(*) as total FROM ($sql) as x"; $qrytotal = $this->db->query($sqltotal, [$receiveOrderPoID, $row_branch['M_BranchID'], $warhouseID, $search, $search]); if ($qrytotal) { $totalCount = $qrytotal->result_array()[0]['total']; $totalPage = ceil($totalCount / $number_limit); } else { $this->sys_error_db("[Error] Query getItem - total", $this->db); exit; } $sql_list = $sql . " LIMIT ? OFFSET ?"; $qry = $this->db->query($sql_list, [$receiveOrderPoID, $row_branch['M_BranchID'], $warhouseID, $search, $search, $number_limit, $number_offset]); // echo $this->db->last_query(); // exit; if (!$qry) { $this->sys_error_db("[Error] Query getItem"); return; } $rows = $qry->result_array(); $result = array( "total_page" => $totalPage, "records" => $rows ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function saveMutasi() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; # VALIDASI HEADER # if (intval($prm["branch_asal_id"]) == intval($prm["branch_tujuan_id"])) { $this->sys_error("Branch Asal dan Branch Tujuan tidak boleh sama"); exit; } if (count($prm["list_mutasi"]) == 0) { $this->sys_error("Tidak ada item untuk dimutasi"); exit; } # CEK JENIS # $isInventaris = (intval($prm["category_id"]) === 2); $isAsset = (intval($prm["category_id"]) === 3); if ($isAsset && count($prm["list_mutasi"]) > 1) { $this->sys_error("Mutasi asset hanya boleh 1 item"); exit; } # HITUNG NILAI # $totalValue = 0; foreach ($prm["list_mutasi"] as $item) { if ($isInventaris) { if (intval($item['qty_mutasi']) <= 0 || intval($item['qty_mutasi']) > intval($item['qty_available'])) { $this->sys_error('QTY mutasi melebihi item yang tersedia'); exit; } $detailItems[] = [ 'receive_order_po_id' => $item['ReceiveOrderPoID'], 'receive_order_po_number' => $item['ReceiveOrderPoNumber'], 'item_id' => $item['M_ItemID'], 'itemunit_id' => $item['ItemUnitID'], 'stock_id' => $item['StockID'], 'warehouse_id' => $item['WarehouseID'], 'barcode_id' => 0, 'qty' => $item['qty_mutasi'], 'book_value' => 1, 'lock_type' => 'INV' ]; $totalValue = 1; } else { // ASSET if (intval($item['qty_mutasi']) != 1) { $this->sys_error("Qty asset harus 1"); exit; } // $asset = getAssetByItemID($item['M_ItemID']); // $itemBookValue = $asset->BookValue; // $totalValue = $itemBookValue; // $detailItems[] = [ // 'item_id' => $item['M_ItemID'], // 'itemunit_id' => $item['ItemUnitID'], // 'stock_id' => $item['StockID'], // 'warehouse_id' => $item['WarehouseID'], // 'barcode_id' => $item['T_BarcodeBarangID'], // 'qty' => 1, // 'book_value' => 1, // nanti diganti nilai buku // 'lock_type' => 'AST' // ]; // $totalValue = 1; // atau nilai buku asset } } # INSERT HEADER # $sql_header = "INSERT INTO mutasi_request( MutasiRequestDate, MutasiRequestNumber, MutasiRequestItemCategoryID, MutasiRequestFromBranchID, MutasiRequestToBranchID, MutasiRequestTotalValue, MutasiRequestNote, MutasiRequestStatus, MutasiRequestIsActive, MutasiRequestCreated, MutasiRequestUserID) VALUES(?,fn_numbering('RM'),?,?,?,?,?,'Draft','Y',NOW(),?)"; $qry_header = $this->db->query($sql_header, [ $prm['mutasi_date'], $prm['category_id'], $prm['branch_asal_id'], $prm['branch_tujuan_id'], $totalValue, $prm['note'], $user['M_UserID'] ]); if (!$qry_header) { $this->db->trans_rollback(); $this->sys_error_db("[Error] insert into table mutasi request", $this->db); exit; } $mrID = $this->db->insert_id(); # INSERT DETAIL # foreach ($detailItems as $d) { $sql_detail = "INSERT INTO mutasi_request_detail( MutasiRequestDetailMutasiRequestID, MutasiRequestDetailReceiveOrderPoID, MutasiRequestDetailReceiveOrderPoNumber, MutasiRequestDetailStockID, MutasiRequestDetailM_ItemID, MutasiRequestDetailItemUnitID, MutasiRequestDetailQty, MutasiRequestDetailBookValue, MutasiRequestDetailIsActive, MutasiRequestDetailCreated, MutasiRequestDetailUserID ) VALUES(?,?,?,?,?,?,?,?,'Y',NOW(),?)"; $qry_detail = $this->db->query($sql_detail, [ $mrID, $d['receive_order_po_id'], $d['receive_order_po_number'], $d['stock_id'], $d['item_id'], $d['itemunit_id'], $d['qty'], $d['book_value'], $user['M_UserID'] ]); if (!$qry_detail) { $this->db->trans_rollback(); $this->sys_error_db("['Error'] insert into table mutasi request detail", $this->db); exit; } // ambil detail_id $detail_id = $this->db->insert_id(); # VALIDASI STOCK # if ($d['lock_type'] === 'INV') { $sqlCheck = "SELECT COUNT(*) AS qty_available FROM t_barcode_barang b LEFT JOIN mutasi_stock_lock l ON l.MutasiStockLockT_BarcodeBarangID = b.T_BarcodeBarangID AND l.MutasiStockLockStatus = 'ACTIVE' AND l.MutasiStockLockIsActive = 'Y' WHERE b.T_BarcodeBarangReceiveOrderPoID = ? AND b.T_BarcodeBarangIsActive = 'Y' AND l.MutasiStockLockID IS NULL FOR UPDATE"; $row = $this->db->query($sqlCheck, [$d['receive_order_po_id']])->row(); if (!$row || $row->qty_available < $d['qty']) { $this->db->trans_rollback(); $this->sys_error("Stock tidak mencukupi (sudah di-lock)"); exit; } } else if ($d['lock_type'] === 'AST') { if (empty($d['barcode_id'])) { $this->db->trans_rollback(); $this->sys_error("Asset wajib memiliki barcode"); exit; } } // INSERT STOCK LOCK $sqlLock = "INSERT INTO mutasi_stock_lock( MutasiStockLockMutasiRequestID, MutasiStockLockMutasiRequestDetailID, MutasiStockLockM_ItemID, MutasiStockLockStockID, MutasiStockLockT_BarcodeBarangID, MutasiStockLockM_BranchID, MutasiStockLockWarehouseID, MutasiStockLockQtyLocked, MutasiStockLockType, MutasiStockLockStatus, MutasiStockLockIsActive, MutasiStockLockCreated, MutasiStockLockUserID ) VALUES(?,?,?,?,?,?,?,?,?,'ACTIVE','Y',NOW(),?)"; $qryLock = $this->db->query($sqlLock, [ $mrID, $detail_id, $d['item_id'], $d['stock_id'], $d['barcode_id'], $prm['branch_asal_id'], $d['warehouse_id'], $d['qty'], $d['lock_type'], $user['M_UserID'] ]); if (!$qryLock) { $this->db->trans_rollback(); $this->sys_error_db("[Error] insert table stock lock", $this->db); exit; } } $this->db->trans_commit(); $this->sys_ok("Request mutasi created successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function getItemMutasiUpdate() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $prm = $this->sys_input; $mutasiRequestID = $prm['mutasiRequestID']; $sql = "SELECT MutasiRequestDetailID, MutasiRequestDetailMutasiRequestID, MutasiRequestDetailReceiveOrderPoID AS ReceiveOrderPoID, MutasiRequestDetailReceiveOrderPoNumber AS ReceiveOrderPoNumber, M_ItemID, M_ItemCode, M_ItemDesc, ItemUnitID, ItemUnitCode, ItemUnitName, w.WarehouseID, s.StockID, s.StockQty AS stock_total, IFNULL(bc.barcode_total, 0) AS barcode_total, COUNT(DISTINCT lk.MutasiStockLockT_BarcodeBarangID) AS qty_locked, IFNULL(bc.barcode_total, 0) - COUNT(DISTINCT lk.MutasiStockLockT_BarcodeBarangID) AS qty_available, MutasiRequestDetailQty AS qty_mutasi FROM mutasi_request_detail JOIN mutasi_request ON MutasiRequestDetailMutasiRequestID = MutasiRequestID JOIN m_item ON MutasiRequestDetailM_ItemID = M_ItemID JOIN itemunit ON MutasiRequestDetailItemUnitID = ItemUnitID JOIN stock s ON MutasiRequestDetailStockID = s.StockID JOIN warehouse w ON s.StockWarehouseID = w.WarehouseID AND w.WarehouseIsActive = 'Y' -- total barcode per stock + PO LEFT JOIN ( SELECT b.T_BarcodeBarangStockID, b.T_BarcodeBarangReceiveOrderPoID, COUNT(*) AS barcode_total FROM t_barcode_barang b WHERE b.T_BarcodeBarangIsActive = 'Y' GROUP BY b.T_BarcodeBarangStockID, b.T_BarcodeBarangReceiveOrderPoID ) bc ON bc.T_BarcodeBarangStockID = s.StockID AND bc.T_BarcodeBarangReceiveOrderPoID = MutasiRequestDetailReceiveOrderPoID -- barcode yang sedang di-lock LEFT JOIN ( SELECT l.MutasiStockLockT_BarcodeBarangID, b.T_BarcodeBarangStockID, b.T_BarcodeBarangReceiveOrderPoID FROM mutasi_stock_lock l JOIN t_barcode_barang b ON b.T_BarcodeBarangID = l.MutasiStockLockT_BarcodeBarangID WHERE l.MutasiStockLockIsActive = 'Y' AND l.MutasiStockLockStatus = 'ACTIVE' AND l.MutasiStockLockType = 'INV' ) lk ON lk.T_BarcodeBarangStockID = s.StockID AND lk.T_BarcodeBarangReceiveOrderPoID = MutasiRequestDetailReceiveOrderPoID WHERE MutasiRequestDetailIsActive = 'Y' AND MutasiRequestDetailMutasiRequestID = ? GROUP BY MutasiRequestDetailID, s.StockID, bc.barcode_total ORDER BY MutasiRequestDetailID"; $qry = $this->db->query($sql, [$mutasiRequestID]); if (!$qry) { $this->sys_error_db("[Error] get item update", $this->db); exit; } $data = $qry->result_array(); $result = array( "records" => $data ); $this->sys_ok($result); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function saveEditMutasi() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; # VALIDASI HEADER # if (intval($prm["branch_asal_id"]) == intval($prm["branch_tujuan_id"])) { $this->sys_error("Branch Asal dan Branch Tujuan tidak boleh sama"); exit; } if (count($prm["list_mutasi"]) == 0) { $this->sys_error("Tidak ada item untuk dimutasi"); exit; } # CEK JENIS # $isInventaris = (intval($prm["category_id"]) === 2); $isAsset = (intval($prm["category_id"]) === 3); if ($isAsset && count($prm["list_mutasi"]) > 1) { $this->sys_error("Mutasi asset hanya boleh 1 item"); exit; } # HITUNG NILAI # $totalValue = 0; foreach ($prm["list_mutasi"] as $item) { if ($isInventaris) { if (intval($item['qty_mutasi']) <= 0 || intval($item['qty_mutasi']) > intval($item['qty_available'])) { $this->sys_error('QTY mutasi melebihi item yang tersedia'); exit; } $detailItems[] = [ 'MutasiRequestDetailID' => $item['MutasiRequestDetailID'], 'MutasiRequestID' => $item['MutasiRequestDetailMutasiRequestID'], 'receive_order_po_id' => $item['ReceiveOrderPoID'], 'receive_order_po_number' => $item['ReceiveOrderPoNumber'], 'item_id' => $item['M_ItemID'], 'itemunit_id' => $item['ItemUnitID'], 'stock_id' => $item['StockID'], 'warehouse_id' => $item['WarehouseID'], 'barcode_id' => 0, 'qty' => $item['qty_mutasi'], 'book_value' => 1, 'lock_type' => 'INV' ]; $totalValue = 1; } else { // ASSET if (intval($item['qty_mutasi']) != 1) { $this->sys_error("Qty asset harus 1"); exit; } // $asset = getAssetByItemID($item['M_ItemID']); // $itemBookValue = $asset->BookValue; // $totalValue = $itemBookValue; // $detailItems[] = [ // 'item_id' => $item['M_ItemID'], // 'itemunit_id' => $item['ItemUnitID'], // 'stock_id' => $item['StockID'], // 'warehouse_id' => $item['WarehouseID'], // 'barcode_id' => $item['T_BarcodeBarangID'], // 'qty' => 1, // 'book_value' => 1, // nanti diganti nilai buku // 'lock_type' => 'AST' // ]; // $totalValue = 1; // atau nilai buku asset } } # UPDATE MUTASI # $sql_mutasi = "UPDATE mutasi_request SET MutasiRequestDate = ?, MutasiRequestItemCategoryID = ?, MutasiRequestFromBranchID = ?, MutasiRequestToBranchID = ?, MutasiRequestTotalValue = ?, MutasiRequestNote = ?, MutasiRequestLastUpdated = NOW(), MutasiRequestUserID = ? WHERE MutasiRequestID = ?"; $qry_mutasi = $this->db->query($sql_mutasi, [ $prm['mutasi_date'], $prm['category_id'], $prm['branch_asal_id'], $prm['branch_tujuan_id'], $totalValue, $prm['note'], $user['M_UserID'], $prm['mutasi_request_id'] ]); if (!$qry_mutasi) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update mutasi request", $this->db); exit; } # check jika detail sudah ada # $sql_check_detail = "SELECT MutasiRequestDetailID, MutasiRequestDetailMutasiRequestID FROM mutasi_request_detail WHERE MutasiRequestDetailMutasiRequestID = ? AND MutasiRequestDetailIsActive = 'Y'"; $qry_check_detail = $this->db->query($sql_check_detail, [$prm['mutasi_request_id']]); if (!$qry_check_detail) { $this->db->trans_rollback(); $this->sys_error_db("[Error] get list check detail mutasi", $this->db); exit; } $list_detail_check = $qry_check_detail->result_array(); $array_detailID = array_column($list_detail_check, 'MutasiRequestDetailID'); $input_detail = array_column($detailItems, 'MutasiRequestDetailID'); $update_detail = []; $insert_detail = []; $delete_detail = []; foreach ($detailItems as $key => $value) { if (empty($value['MutasiRequestDetailID'])) { $insert_detail[] = $value; continue; } if (in_array($value['MutasiRequestDetailID'], $array_detailID)) { $update_detail[] = $value; } } foreach ($list_detail_check as $key => $value) { if (!in_array($value['MutasiRequestDetailID'], $input_detail)) { $delete_detail[] = $value; } } # UPDATE MUTASI DETAIL # foreach ($update_detail as $k => $v) { $sql_update_detail = "UPDATE mutasi_request_detail SET MutasiRequestDetailMutasiRequestID = ?, MutasiRequestDetailReceiveOrderPoID = ?, MutasiRequestDetailReceiveOrderPoNumber = ?, MutasiRequestDetailStockID = ?, MutasiRequestDetailM_ItemID = ?, MutasiRequestDetailItemUnitID = ?, MutasiRequestDetailQty = ?, MutasiRequestDetailBookValue = ?, MutasiRequestDetailLastUpdated = NOW(), MutasiRequestDetailUserID = ? WHERE MutasiRequestDetailID = ?"; $qry_update_detail = $this->db->query($sql_update_detail, [ $v['MutasiRequestID'], $v['receive_order_po_id'], $v['receive_order_po_number'], $v['stock_id'], $v['item_id'], $v['itemunit_id'], $v['qty'], $v['book_value'], $user['M_UserID'], $v['MutasiRequestDetailID'] ]); if (!$qry_update_detail) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update mutasi request detail", $this->db); exit; } # cek qty tersedia (inventaris) if ($v['lock_type'] === 'INV') { $sqlCheck = "SELECT COUNT(*) AS qty_available FROM t_barcode_barang b LEFT JOIN mutasi_stock_lock l ON l.MutasiStockLockT_BarcodeBarangID = b.T_BarcodeBarangID AND l.MutasiStockLockStatus = 'ACTIVE' AND l.MutasiStockLockIsActive = 'Y' WHERE b.T_BarcodeBarangReceiveOrderPoID = ? AND b.T_BarcodeBarangIsActive = 'Y' AND l.MutasiStockLockID IS NULL FOR UPDATE"; $row = $this->db->query($sqlCheck, [$v['receive_order_po_id']])->row(); if (!$row || $row->qty_available < $v['qty']) { $this->db->trans_rollback(); $this->sys_error("Stock tidak mencukupi (sudah di-lock)"); exit; } } else if ($v['lock_type'] === 'AST') { if (empty($v['barcode_id'])) { $this->db->trans_rollback(); $this->sys_error("Asset wajib memiliki barcode"); exit; } } # update stock lock $sql_update_stock_lock = "UPDATE mutasi_stock_lock SET MutasiStockLockMutasiRequestID = ?, MutasiStockLockMutasiRequestDetailID = ?, MutasiStockLockM_ItemID = ?, MutasiStockLockStockID = ?, MutasiStockLockT_BarcodeBarangID = ?, MutasiStockLockM_BranchID = ?, MutasiStockLockWarehouseID = ?, MutasiStockLockQtyLocked = ?, MutasiStockLockType = ?, MutasiStockLockLastUpdated = NOW(), MutasiStockLockUserID = ? WHERE MutasiStockLockMutasiRequestDetailID = ?"; $qry_update_stock_lock = $this->db->query($sql_update_stock_lock, [ $prm['mutasi_request_id'], $v['MutasiRequestDetailID'], $v['item_id'], $v['stock_id'], $v['barcode_id'], $prm['branch_asal_id'], $v['warehouse_id'], $v['qty'], $v['lock_type'], $user['M_UserID'], $v['MutasiRequestDetailID'] ]); if (!$qry_update_stock_lock) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update mutasi stock lock", $this->db); exit; } } # INSERT MUTASI DETAIL BARU # foreach ($insert_detail as $k => $v) { $sql_detail = "INSERT INTO mutasi_request_detail( MutasiRequestDetailMutasiRequestID, MutasiRequestDetailReceiveOrderPoID, MutasiRequestDetailReceiveOrderPoNumber, MutasiRequestDetailStockID, MutasiRequestDetailM_ItemID, MutasiRequestDetailItemUnitID, MutasiRequestDetailQty, MutasiRequestDetailBookValue, MutasiRequestDetailIsActive, MutasiRequestDetailCreated, MutasiRequestDetailUserID ) VALUES(?,?,?,?,?,?,?,?,'Y',NOW(),?)"; $qry_detail = $this->db->query($sql_detail, [ $prm['mutasi_request_id'], $v['receive_order_po_id'], $v['receive_order_po_number'], $v['stock_id'], $v['item_id'], $v['itemunit_id'], $v['qty'], $v['book_value'], $user['M_UserID'] ]); if (!$qry_detail) { $this->db->trans_rollback(); $this->sys_error_db("[Error] Re-insert table mutasi request detail", $this->db); exit; } $detail_id = $this->db->insert_id(); # cek qty tersedia (inventaris) if ($v['lock_type'] === 'INV') { $sqlCheck = "SELECT COUNT(*) AS qty_available FROM t_barcode_barang b LEFT JOIN mutasi_stock_lock l ON l.MutasiStockLockT_BarcodeBarangID = b.T_BarcodeBarangID AND l.MutasiStockLockStatus = 'ACTIVE' AND l.MutasiStockLockIsActive = 'Y' WHERE b.T_BarcodeBarangReceiveOrderPoID = ? AND b.T_BarcodeBarangIsActive = 'Y' AND l.MutasiStockLockID IS NULL FOR UPDATE"; $row = $this->db->query($sqlCheck, [$v['receive_order_po_id']])->row(); if (!$row || $row->qty_available < $v['qty']) { $this->db->trans_rollback(); $this->sys_error("Stock tidak mencukupi (sudah di-lock)"); exit; } } else if ($v['lock_type'] === 'AST') { if (empty($v['barcode_id'])) { $this->db->trans_rollback(); $this->sys_error("Asset wajib memiliki barcode"); exit; } } // INSERT LOCK $sqlLock = "INSERT INTO mutasi_stock_lock( MutasiStockLockMutasiRequestID, MutasiStockLockMutasiRequestDetailID, MutasiStockLockM_ItemID, MutasiStockLockStockID, MutasiStockLockT_BarcodeBarangID, MutasiStockLockM_BranchID, MutasiStockLockWarehouseID, MutasiStockLockQtyLocked, MutasiStockLockType, MutasiStockLockStatus, MutasiStockLockIsActive, MutasiStockLockCreated, MutasiStockLockUserID ) VALUES(?,?,?,?,?,?,?,?,?,'ACTIVE','Y',NOW(),?)"; $qryLock = $this->db->query($sqlLock, [ $prm['mutasi_request_id'], $detail_id, $v['item_id'], $v['stock_id'], $v['barcode_id'], $prm['branch_asal_id'], $v['warehouse_id'], $v['qty'], $v['lock_type'], $user['M_UserID'] ]); if (!$qryLock) { $this->db->trans_rollback(); $this->sys_error_db("[Error] edit mutasi, insert table stock lock", $this->db); exit; } } # DELETE MUTASI DETAIL # if (count($delete_detail) > 0) { $delete_id = array_column($delete_detail, 'MutasiRequestDetailID'); $placeholders = implode(', ', array_fill(0, count($delete_id), '?')); $delete_param = array_merge(array($user['M_UserID']), $delete_id); $sql_delete_detail = "UPDATE mutasi_request_detail SET MutasiRequestDetailIsActive = 'N', MutasiRequestDetailLastUpdated = NOW(), MutasiRequestDetailUserID = ? WHERE MutasiRequestDetailID IN ($placeholders)"; $qry_delete_detail = $this->db->query($sql_delete_detail, $delete_param); if (!$qry_delete_detail) { $this->db->trans_rollback(); $this->sys_error_db("[Error] delete mutasi request detail", $this->db); exit; } # delete mutasi stock lock $sql_update_stock_lock = "UPDATE mutasi_stock_lock SET MutasiStockLockIsActive = 'N', MutasiStockLockLastUpdated = NOW(), MutasiStockLockUserID = ? WHERE MutasiStockLockMutasiRequestDetailID = ?"; $qry_update_stock_lock = $this->db->query($sql_update_stock_lock, $delete_param); if (!$qry_update_stock_lock) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update mutasi stock lock", $this->db); exit; } } $this->db->trans_commit(); $this->sys_ok("Update mutasi successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function deleteMutasi() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; $mutasiRequestID = $prm['mutasiRequestID']; $sql_mutasi = "UPDATE mutasi_request SET MutasiRequestIsActive = 'N', MutasiRequestLastUpdated = NOW(), MutasiRequestUserID = ? WHERE MutasiRequestID = ?"; $qry_mutasi = $this->db->query($sql_mutasi, [ $user['M_UserID'], $mutasiRequestID ]); if (!$qry_mutasi) { $this->db->trans_rollback(); $this->sys_error_db('[Error] delete mutasi request', $this->db); exit; } $sql_mutasi_detail = "UPDATE mutasi_request_detail SET MutasiRequestDetailIsActive = 'N', MutasiRequestDetailLastUpdated = NOW(), MutasiRequestDetailUserID = ? WHERE MutasiRequestDetailMutasiRequestID = ?"; $qry_mutasi_detail = $this->db->query($sql_mutasi_detail, [ $user['M_UserID'], $mutasiRequestID ]); if (!$qry_mutasi_detail) { $this->db->trans_rollback(); $this->sys_error_db('[Error] delete mutasi detail', $this->db); exit; } $sql_stock_lock = "UPDATE mutasi_stock_lock SET MutasiStockLockIsActive = 'N', MutasiStockLockLastUpdated = NOW(), MutasiStockLockUserID = ? WHERE MutasiStockLockMutasiRequestID = ?"; $qry_stock_lock = $this->db->query($sql_stock_lock, [ $user['M_UserID'], $mutasiRequestID ]); if (!$qry_stock_lock) { $this->db->trans_rollback(); $this->sys_error_db('[Error] mutasi stock lock', $this->db); exit; } $this->db->trans_commit(); $this->sys_ok("Delete Request mutasi successfully"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } // Approved // ------------------------------ function getApproveLevel() { if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; } $userId = $this->sys_user["M_UserID"]; $sqlevel = "SELECT M_UserM_ApproveLevelID 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 approveMutasiRequest() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; # get data before $dataMrBefore = $this->getDataMutasiRequest($prm['mutasiRequestID']); if (intval($prm['approvelevel'] == 1)) { $sql = "UPDATE mutasi_request SET MutasiRequestStatus = 'Verified', MutasiRequestIsVerif = 'Y', MutasiRequestVerifUserID = ?, MutasiRequestVerifDate = NOW(), MutasiRequestLastUpdated = NOW(), MutasiRequestUserID = ? WHERE MutasiRequestID = ?"; $qry = $this->db->query($sql, [$user['M_UserID'], $user['M_UserID'], $prm['mutasiRequestID']]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("[Error] verif by manager", $this->db); exit; } $dataMrAfter = $this->getDataMutasiRequest($prm['mutasiRequestID']); $this->insertLogMutasiRequest($prm['mutasiRequestID'], 'VERIFIED', $dataMrBefore, $dataMrAfter, $user['M_UserID'], "Verified data mutasi request by user ID : {$user['M_UserID']}"); $this->insertUserActivity('MR', "Verified data mutasi request by user ID : {$user['M_UserID']}", 'VERIFIED', $prm['mutasiRequestID'], $user['M_UserID']); $this->db->trans_commit(); $this->sys_ok("Success Verified by manager"); } else if (intval($prm['approvelevel'] == 2)) { $sql = "UPDATE mutasi_request SET MutasiRequestStatus = 'Approved', MutasiRequestIsApproved = 'Y', MutasiRequestApprovedUserID = ?, MutasiRequestApprovedDate = NOW(), MutasiRequestLastUpdated = NOW(), MutasiRequestUserID = ? WHERE MutasiRequestID = ?"; $qry = $this->db->query($sql, [$user['M_UserID'], $user['M_UserID'], $prm['mutasiRequestID']]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("[Error] approve by kacab", $this->db); exit; } $dataMrAfter = $this->getDataMutasiRequest($prm['mutasiRequestID']); $this->insertLogMutasiRequest($prm['mutasiRequestID'], 'APPROVED', $dataMrBefore, $dataMrAfter, $user['M_UserID'], "Approved data mutasi request by user ID : {$user['M_UserID']}"); $this->insertUserActivity('MR', "Approved data mutasi request by user ID : {$user['M_UserID']}", 'APPROVED', $prm['mutasiRequestID'], $user['M_UserID']); $this->db->trans_commit(); $this->sys_ok("Success Approved by kacab"); } } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } function rejectMutasiRequest() { try { if (!$this->isLogin) { $this->sys_error("invalid token"); exit; } $this->db->trans_begin(); $prm = $this->sys_input; $user = $this->sys_user; $mrID = intval($prm["mutasiRequestID"]); $note = $prm["reject_note"]; # get data before $dataMrBefore = $this->getDataMutasiRequest($mrID); # cek mutasi $mutasi = $this->db->query("SELECT MutasiRequestStatus FROM mutasi_request WHERE MutasiRequestID = ? AND MutasiRequestIsActive = 'Y' FOR UPDATE ", [$mrID])->row(); if (!$mutasi) { $this->db->trans_rollback(); $this->sys_error("Data mutasi tidak ditemukan", $this->db); exit; } # validasi boleh reject atau tidak if (!in_array($mutasi->MutasiRequestStatus, ['Draft', 'Verified', 'Approved'])) { $this->db->trans_rollback(); $this->sys_error("Mutasi tidak dapat direject pada status ini"); exit; } #get username $getUser = $this->db->query("SELECT M_UserID, M_UserUsername FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?", [$user['M_UserID']])->row_array(); if (!$getUser) { $this->db->trans_rollback(); $this->sys_error_db("[Error] get username", $this->db); exit; } # update status mutasi to rejected $updMutasi = $this->db->query("UPDATE mutasi_request SET MutasiRequestStatus = 'Rejected', MutasiRequestNote = CONCAT_WS( '\n', NULLIF(MutasiRequestNote, ''), CONCAT('[REJECT] ', ?, ' by user ', ?) ), MutasiRequestLastUpdated = NOW() WHERE MutasiRequestID = ? ", [$note, $getUser['M_UserUsername'], $mrID]); if (!$updMutasi) { $this->db->trans_rollback(); $this->sys_error_db("[Error] update status mutasi", $this->db); exit; } # Release stock lock active $updLock = $this->db->query("UPDATE mutasi_stock_lock SET MutasiStockLockStatus = 'RELEASED', MutasiStockLockLastUpdated = NOW() WHERE MutasiStockLockMutasiRequestID = ? AND MutasiStockLockStatus = 'ACTIVE' AND MutasiStockLockIsActive = 'Y' ", [$mrID]); if (!$updLock) { $this->db->trans_rollback(); $this->sys_error_db("[Error] release stock lock", $this->db); exit; } $dataMrAfter = $this->getDataMutasiRequest($mrID); $this->insertLogMutasiRequest($mrID, 'REJECTED', $dataMrBefore, $dataMrAfter, $user['M_UserID'], "Rejected data mutasi request by user ID : {$user['M_UserID']}"); $this->insertUserActivity('MR', "Rejected data mutasi request by user ID : {$user['M_UserID']}", 'REJECTED', $mrID, $user['M_UserID']); $this->db->trans_commit(); $this->sys_ok("Mutasi berhasil direject"); } catch (Exception $exc) { $message = $exc->getMessage(); $this->sys_error($message); } } private function getDataMutasiRequest($id) { $sql = "SELECT * FROM mutasi_request WHERE MutasiRequestID = ?"; $qry = $this->db->query($sql, [$id]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("[Error] get mutasi request", $this->db); exit; } $header = $qry->row_array(); $sqldetail = "SELECT * FROM mutasi_request_detail WHERE MutasiRequestDetailMutasiRequestID = ? AND MutasiRequestDetailIsActive = 'Y'"; $qrydetail = $this->db->query($sqldetail, [$id]); if (!$qrydetail) { $this->db->trans_rollback(); $this->sys_error_db("[Error] get mutasi request detail", $this->db); exit; } $detail = $qrydetail->result_array(); $header['details'] = $detail; return $header; } // private function insertUserActivity( $code, $user_desc = '', $status, $reff_id, $userId ) { $sql_log = "INSERT INTO user_activity( UserActivityCode, UserActivityStatus, UserActivityDescription, UserActivityRefID, UserActivityUserID, UserActivityCreated ) VALUES(?,?,?,?,?,NOW())"; $qry_log = $this->db->query($sql_log, [ $code, $status, $user_desc, $reff_id, $userId ]); if (!$qry_log) { $this->db->trans_rollback(); $this->sys_error_db("insert log", $this->db); exit; } } private function insertLogMutasiRequest( $id, $type, $dataBefore, $dataAfter, $userID, $desc = '' ) { $sql = "INSERT INTO acc_one_log.mutasi_request_log( MutasiRequestLogMutasiRequestID, MutasiRequestLogType, MutasiRequestLogDesc, MutasiRequestLogJsonBefore, MutasiRequestLogJsonAfter, MutasiRequestLogUserID, MutasiRequestLogCreated ) VALUES(?,?,?,?,?,?,NOW())"; $qry = $this->db->query($sql, [ $id, $type, $desc, !empty($dataBefore) ? json_encode($dataBefore) : '', !empty($dataAfter) ? json_encode($dataAfter) : '', $userID ]); if (!$qry) { $this->db->trans_rollback(); $this->sys_error_db("[Error] insert log mutasi request", $this->db); exit; } } }