<?php
class RequestmutasiApproved extends MY_Controller
{
    var $db;
    public function index()
    {
        echo "Request Mutasi API Approved";
    }

    public function __construct()
    {
        parent::__construct();
    }

    function search()
    {
        try {
            if (!$this->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;
        }
    }
}
