<?php

use BcMath\Number;

class ReceiveSuratJalan extends MY_Controller {
    var $db;
    public function index() {
        echo "Receive Surat Jalan API";
    }

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

    
    ## QUERY ##

    public function LookupEkspedisi() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $para = $this->sys_input;
            $type = $para['isInternal'];
            $name = "%";
            if ($para['expdName'] != "") {
                $name = $para['expdName'] . "%";
            }

            $sqlexp = "SELECT 
                ExpeditionID,
                ExpeditionName,
                ExpeditionIsInternal
            FROM expedition
            WHERE ExpeditionIsActive = 'Y'
                AND ExpeditionIsInternal = ?
                AND ExpeditionName LIKE ?";
            $qryexp = $this->db->query($sqlexp, [$type, $name]);
            if (!$qryexp) {
                $this->sys_error_db("error get listing expedition");
                exit;
            }

            $result = array(
                "records" => $qryexp->result_array(),
                "total" => sizeof($qryexp->result_array())
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    public function LookupEkspedisiStaff() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $para = $this->sys_input;
            $expID = $para['expID'];
            $name = "%";
            if ($para['staffName'] != "") {
                $name = $para['staffName'] . "%";
            }

            $sqlexp = "SELECT 
                ExpeditionStaffID,
                ExpeditionStaffName,
                ExpeditionStaffMobile
            FROM expeditionstaff
            WHERE ExpeditionStaffIsActive = 'Y'
                AND ExpeditionStaffExpeditionID = ?
                AND ExpeditionStaffName LIKE ?";
            $qryexp = $this->db->query($sqlexp, [$expID, $name]);
            if (!$qryexp) {
                $this->sys_error_db("error get listing expedition staff");
                exit;
            }

            $result = array(
                "records" => $qryexp->result_array(),
                "total" => sizeof($qryexp->result_array())
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    public function ListingBranch() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("Invalid Token");
                exit;
            }

            $prm = $this->sys_input;
            $user = $this->sys_user;
            $regID = $prm["S_RegionalID"];

            $sql = "SELECT M_BranchID, M_BranchCode, M_BranchName
                    FROM m_branch
                    WHERE M_BranchIsActive = 'Y'
                    AND M_BranchS_RegionalID = ?
                    AND (? = '' OR M_BranchCode = ? )";
            $qry = $this->db->query($sql, [$regID, $user['M_BranchCode'], $user['M_BranchCode']]);
            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 LookupWarehouse() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("Invalid Token");
                exit;
            }

            $payload = $this->sys_input;
            $user = $this->sys_user;
            $userId = $this->sys_user["M_UserID"];
            $regionalId =  $this->sys_user["S_RegionalID"];
            $sqlWhere = "";

            if ($user['M_UserLocationFlag'] == "R") {
                $sqlWhere = "AND WarehouseType = 'R'";
            }
            if ($user['M_UserLocationFlag'] == "RB" || $user['M_UserLocationFlag'] == "B") {
                $sqlWhere = "AND WarehouseType = 'B' AND WarehouseM_BranchID = {$user['M_BranchID']}";
            }

            $sql = "SELECT 
                    WarehouseID,
                    WarehouseCode,
                    CASE
                        WHEN WarehouseType = 'B' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', M_BranchName) 
                        WHEN WarehouseType = 'R' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', S_RegionalName) 
                    ELSE ''
                    END WarehouseName,
                    WarehouseType,
                    WarehouseIsDefault,
                    WarehouseS_RegionalID,
                    WarehouseM_BranchID,
                    S_RegionalID,
                    S_RegionalName
                    FROM warehouse
                    JOIN s_regional ON WarehouseS_RegionalID = S_RegionalID AND S_RegionalIsActive = 'Y'
                    LEFT JOIN m_branch ON WarehouseM_BranchID = M_BranchID AND M_BranchIsActive = 'Y'
                    where WarehouseS_RegionalID = ?
                    AND WarehouseIsActive = 'Y'
                    AND WarehouseIsTransit = 'N'
                    $sqlWhere
                    ORDER BY WarehouseName ASC ";
            $qry = $this->db->query($sql, [$regionalId]);
            if (!$qry) {
                $this->db->trans_rollback();
                $this->sys_error_db("select warehouse", $this->db);;
                exit;
            }

            $rows = $qry->result_array();

            $result = array(
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($rows);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    public function LookupSuratJalan() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $para = $this->sys_input;
            $stardate = $para['startdate'];
            $enddate = $para['enddate'];
            $branchcode = $para['branchcode'];
            $status = $para['status'];
            $keyword = $para['search'];
            $currpage = $para['currpage'];

            $page = 0;
            $limit = 10;
            if ($currpage > 0) {
                $page = ($currpage - 1) * $limit;
            }

            $keyw = "%";
            if ($keyword != "") {
                $keyw = $keyword . "%";
            }

            $sqtot = "SELECT COUNT(*) as total
                FROM suratjalan
                JOIN t_goods_transfer ON T_GoodsTransferID = SuratJalanT_GoodsTransferID
                    AND T_GoodsTransferIsActive = 'Y'
                JOIN m_branch ON M_BranchCode = T_GoodsTransferToM_BranchCode
                    AND M_BranchIsActive = 'Y' 
                LEFT JOIN expeditionstaff ON ExpeditionStaffID = SuratJalanEkspedisiStaffID
                    AND ExpeditionStaffIsActive = 'Y'
                LEFT JOIN expedition ON ExpeditionID = SuratJalanEkspedisiID
                    AND ExpeditionIsActive = 'Y'
                LEFT JOIN m_user ON M_UserID = SuratJalanReceivedUserID
                    AND M_UserIsActive = 'Y'
                LEFT JOIN m_staff ON M_UserM_StaffID = M_StaffID
                    AND M_StaffIsActive = 'Y'
                WHERE SuratJalanIsActive = 'Y'
                    AND SuratJalanStatus != 'Draft' 
                    AND SuratJalanDate >= DATE(?) 
                    AND SuratJalanDate <= DATE(?) 
                    AND (? = 'ALL' OR T_GoodsTransferToM_BranchCode = ? )
                    AND (? = 'All' OR SuratJalanStatus = ? )
                    AND SuratJalanNumber LIKE ?";
            $qryto = $this->db->query($sqtot, [
                $stardate,
                $enddate,
                $branchcode,
                $branchcode,
                $status,
                $status,
                $keyw
            ]);

            $totalcount = 0;
            $totalpage = 0;
            if ($qryto) {
                $totalcount = $qryto->result_array()[0]['total'];
                $totalpage = ceil($totalcount / $limit);
            } else {
                $this->sys_error_db("count surat jalan error", $this->db);
                exit;
            }

            $sqlSJ = "SELECT 
                    SuratJalanID,
                    SuratJalanNumber,
                    SuratJalanDate,
                    SuratJalanNote,
                    M_BranchCode,
                    M_BranchName,
                    SuratJalanEkspedisiID,
                    ExpeditionID,
                    ExpeditionName,
                    ExpeditionIsInternal,
                    SuratJalanEkspedisiStaffID,
                    SuratJalanEkspedisiStaffContact,
                    ExpeditionStaffID,
                    ExpeditionStaffName,
                    ExpeditionStaffMobile,
                    SuratJalanStatus,
                    SuratJalanT_GoodsTransferID,
                    DATE_FORMAT(IF(SuratJalanReceivedDate = '0000-00-00 00:00:00' OR SuratJalanReceivedDate IS NULL, NULL, SuratJalanReceivedDate), '%d-%m-%Y') as SuratJalanReceivedDate,
                    SuratJalanReceivedNote,
                    SuratJalanReceivedWarehouseID,
                    SuratJalanReceivedConfirmed,
                    SuratJalanReceivedConfirmedDate,
                    SuratJalanReceivedConfirmedUserID,
                    M_StaffName
                FROM suratjalan
                JOIN t_goods_transfer ON T_GoodsTransferID = SuratJalanT_GoodsTransferID
                    AND T_GoodsTransferIsActive = 'Y'
                JOIN m_branch ON M_BranchCode = T_GoodsTransferToM_BranchCode
                    AND M_BranchIsActive = 'Y'
                LEFT JOIN expeditionstaff ON ExpeditionStaffID = SuratJalanEkspedisiStaffID
                    AND ExpeditionStaffIsActive = 'Y'
                LEFT JOIN expedition ON ExpeditionID = SuratJalanEkspedisiID
                    AND ExpeditionIsActive = 'Y'
                LEFT JOIN m_user ON M_UserID = SuratJalanReceivedUserID
                    AND M_UserIsActive = 'Y'
                LEFT JOIN m_staff ON M_UserM_StaffID = M_StaffID
                    AND M_StaffIsActive = 'Y'
                WHERE SuratJalanIsActive = 'Y'
                    AND SuratJalanStatus != 'Draft'
                    AND SuratJalanDate >= DATE(?) 
                    AND SuratJalanDate <= DATE(?) 
                    AND (? = 'ALL' OR T_GoodsTransferToM_BranchCode = ? )
                    AND (? = 'ALL' OR SuratJalanStatus = ? )
                    AND SuratJalanNumber LIKE ?
                    ORDER BY SuratJalanID DESC
                LIMIT ? OFFSET ?";
            $qrySJ = $this->db->query($sqlSJ, [
                $stardate,
                $enddate,
                $branchcode,
                $branchcode,
                $status,
                $status,
                $keyw,
                $limit,
                $page
            ]);
            if (!$qrySJ) {
                $this->sys_error_db("error get listing data surat jalan", $this->db);
                exit;
            }
            $list = $qrySJ->result_array();

            $result = array(
                "total" => $totalcount,
                "records" => $list
            );
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    public function LookupDetailSuratJalan() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $para = $this->sys_input;
            $user = $this->sys_user;

            $sqlSJ = "SELECT 
                suratjalan.*,
                ExpeditionID,
                ExpeditionName,
                ExpeditionIsInternal,
                ExpeditionStaffID,
                ExpeditionStaffName,
                ExpeditionStaffMobile,
                T_GoodsTransferID,
                T_GoodsTransferNum,
                T_GoodsTransferDate,
                T_GoodsTransferType
            FROM suratjalan
            JOIN t_goods_transfer ON SuratJalanT_GoodsTransferID = T_GoodsTransferID
                AND T_GoodsTransferIsActive = 'Y'
            JOIN expedition ON ExpeditionID = SuratJalanEkspedisiID
                AND ExpeditionIsActive = 'Y'
            JOIN expeditionstaff ON ExpeditionStaffID = SuratJalanEkspedisiStaffID
                AND ExpeditionStaffIsActive = 'Y'
            WHERE SuratJalanIsActive = 'Y'
                AND SuratJalanID = ?";
            $queSJ = $this->db->query($sqlSJ, [$para['SuratJalanID']]);
            if (!$queSJ) {
                $this->sys_error_db("[Error] get data detail surat jalan");
                exit;
            }
            $data = $queSJ->row_array();

            $sqlSJD = "SELECT 
                suratjalan_detail.*,
                T_GoodsTransferDetailItemBatchNo,
                T_GoodsTransferDetailItemBarNote,
                M_ItemCode,
                M_ItemDesc,
                ItemUnitCode,
                ItemUnitName
            FROM suratjalan
            JOIN suratjalan_detail ON SuratJalanDetailSuratJalanID = SuratJalanID
                AND SuratJalanDetailIsActive = 'Y'
            JOIN t_goods_transfer_detail ON SuratJalanDetailT_GoodsTransferDetailID = T_GoodsTransferDetailID
                AND T_GoodsTransferDetailIsActive = 'Y'
            JOIN m_item ON M_ItemID = SuratJalanDetailM_ItemID
                AND M_ItemIsActive = 'Y' 
            LEFT JOIN itemunit ON ItemUnitID = SuratJalanDetailItemUnitID
                AND ItemUnitIsActive = 'Y'
            WHERE SuratJalanIsActive = 'Y'
                AND SuratJalanID = ?";
            $queSJD = $this->db->query($sqlSJD, [$para['SuratJalanID']]);
            if (!$queSJD) {
                $this->sys_error_db("[Error] get data detail surat jalan");
                exit;
            }
            $detail = $queSJD->result_array();

            if ($data['T_GoodsTransferType'] === 'P') {
                foreach ($detail as $key => $obj) {
                    $jsonStr = $obj['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]['ItemRequest'] = $batches;
                    unset($detail[$key]['T_GoodsTransferDetailItemBatchNo']);
                }
            } else {
                foreach ($detail as $key => $obj) {
                    $jsonStr = $obj['T_GoodsTransferDetailItemBarNote'];
                    $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]['ItemRequest'] = $batches;
                    unset($detail[$key]['T_GoodsTransferDetailItemBarNote']);
                }
            }


            $data['detail'] = $detail;
            $result = array(
                "records" => $data,
                "total" => sizeof($data)
            );
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    ## MUTATIONS ##
    public function TestInput() {
        if (!$this->isLogin) {
            $this->sys_error("invalid token");
            exit;
        }

        $data = $this->sys_input;
        $detail = $data['detail'];
        $user = $this->sys_user;
        $userId = $user["M_UserID"];
        $this->sys_ok($data);
    }

    public function SaveReceiveSJ() {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $data = $this->sys_input;
            $detail = $data['detail'];
            $user = $this->sys_user;
            $userId = $user["M_UserID"];

            $this->db->trans_begin();

            ## UPDATE SURATjALAN  ##
            $sqlSJ = "UPDATE suratjalan 
                SET SuratJalanStatus = ?,
                    SuratJalanReceivedDate = NOW(),
                    SuratJalanReceivedUserID = ?,
                    SuratJalanReceivedNote = ?,
                    SuratJalanReceivedWarehouseID = ?,
                    SuratJalanLastUpdated = NOW(),
                    SuratJalanUserID = ?
                WHERE SuratJalanID = ?";
            $qrySJ = $this->db->query($sqlSJ, [
                $data['i_status'], $userId, $data['i_receivenotes'], 
                $data['i_receivewarehouse']['WarehouseID'], 
                $userId, $data['SuratJalanID']
            ]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update surat jalan");
                exit;
            }

            foreach ($detail as $key => $obj) {
                $sqlSJD = "UPDATE suratjalan_detail SET 
                    SuratJalanDetailQtyReceived = ?, 
                    SuratJalanDetailLastUpdated = NOW(), 
                    SuratJalanDetailUserID = ? 
                WHERE SuratJalanDetailID = ?";
                $queSJD = $this->db->query($sqlSJD, [
                    $obj['SuratJalanDetailQtyReceived'],  
                    $userId, $obj['SuratJalanDetailID']
                ]);
                if (!$queSJD) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] update surat jalan");
                    exit;
                }

                $jsonObj  = "[]";
                if (isset($obj['ItemRequest']) && is_array($obj['ItemRequest'])) {
                    $batches = $obj['ItemRequest'];
                    if (sizeof($batches) > 0) {
                        $jsonResult = json_encode($batches);
                        if ($jsonResult === false) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] encode json batch number persediaan");
                            exit;
                        } else {
                            $jsonObj = $jsonResult;
                        }
                    }
                }

                if (strtolower($data['i_tftype']) === "persediaan") {
                    $sqltf = "UPDATE t_goods_transfer_detail SET
                        T_GoodsTransferDetailItemBatchNo = ? 
                    WHERE T_GoodsTransferDetailID = ?";
                    $quetf = $this->db->query($sqltf, [$jsonObj, $obj['SuratJalanDetailT_GoodsTransferDetailID']]);
                    if (!$quetf) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update surat jalan");
                        exit;
                    }
                } else {
                    $sqltf = "UPDATE t_goods_transfer_detail SET
                        T_GoodsTransferDetailItemBarNote = ? 
                    WHERE T_GoodsTransferDetailID = ?";
                    $quetf = $this->db->query($sqltf, [$jsonObj, $obj['SuratJalanDetailT_GoodsTransferDetailID']]);
                    if (!$quetf) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update surat jalan");
                        exit;
                    }
                }
            }

            # Check if all received #
            $partialRec = false;
            foreach ($detail as $key => $obj) {
                if (intval($obj['SuratJalanDetailQty'] != intval($obj['SuratJalanDetailQtyReceived']))) {
                    $partialRec = true;
                }
            }

            ## UPDATE STOCK JIKA CONFIRMED ##
            if (strtolower($data['i_status']) === 'completed' && strtolower($data['i_tftype']) === "persediaan") {
                $this->confirmReceive($data, $detail, $user);
                $this->generateJurnalRegional($data, $detail, $user);
                $this->generateJurnalCabang($data, $detail, $user);
                
                if ($partialRec) {
                    $this->generateJurnalDiff($data, $detail, $user);
                }
            }

            if (strtolower($data['i_status']) === 'completed' && strtolower($data['i_tftype']) === "non persediaan") {
                $this->confirmReceive($data, $detail, $user);
                $this->generateJurnalRegional($data, $detail, $user);
                $this->generateJurnalCabang($data, $detail, $user);
                
                if ($partialRec) {
                    $this->generateJurnalDiff($data, $detail, $user);
                }
            }

            ## GET LAST INSERTED DATA ##
            $sqlgetSJ = "SELECT * FROM suratjalan WHERE SuratJalanID = ? AND SuratJalanIsActive = 'Y'";
            $quegetSJ = $this->db->query($sqlgetSJ, [$data['SuratJalanID']]);
            if (!$quegetSJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get last inserted data from table suratjalan");
                exit;
            }
            $lastSJ = $quegetSJ->row_array();

            $sqlgetSJD = "SELECT * FROM suratjalan_detail WHERE SuratJalanDetailSuratJalanID = ? AND SuratJalanDetailIsActive = 'Y'";
            $quegetSJD = $this->db->query($sqlgetSJD, [$data['SuratJalanID']]);
            if (!$quegetSJD) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get last inserted data from table suratjalan_detail");
                exit;
            }
            $lastSJD = $quegetSJD->result_array();
            $lastSJ['detail'] = $lastSJD;

            ## INSERT INTO LOG ACTIVITY ##
            $msg = "Surat Jalan nomor: {$lastSJ['SuratJalanNumber']}, Tanggal: {$lastSJ['SuratJalanDate']}";
            $this->insertUserActivty($data['SuratJalanID'], "UPDATE", $userId, $msg, json_encode($lastSJ));

            $this->db->trans_commit();
            $result = array(
                "total" => 1,
                "msg" => $msg,
                "records" => $lastSJ
            );
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function confirmReceive($data, $detail, $user) {
        ## UPDATE STATUS SURATJALAN ##
        $sqlsj = "UPDATE suratjalan SET 
            SuratJalanStatus = 'Completed', 
            SuratJalanReceivedConfirmed = 'Y',
            SuratJalanReceivedConfirmedDate = NOW(), 
            SuratJalanReceivedConfirmedUserID = ? 
        WHERE SuratJalanID = ? AND SuratJalanIsActive = 'Y'";
        $quesj = $this->db->query($sqlsj, [$user['M_UserID'], $data['SuratJalanID']]);
        if (!$quesj) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] update status surat jalan");
            exit;
        }

        ## UPDATE STATUS T_GOODS_TRANSFER ##
        $sqltf = "UPDATE t_goods_transfer SET 
            T_GoodsTransferStatus = 'Completed' 
        WHERE T_GoodsTransferID IN (
            SELECT T_GoodsTransferID
            FROM suratjalan
            JOIN t_goods_transfer ON T_GoodsTransferID = SuratJalanT_GoodsTransferID
                AND T_GoodsTransferNum = SuratJalanT_GoodsTransferNum
            WHERE SuratJalanID = ?
                AND SuratJalanNumber = ?
                AND T_GoodsTransferIsActive = 'Y'
        )
        AND T_GoodsTransferIsActive = 'Y'";
        $quetf = $this->db->query($sqltf, [$data['SuratJalanID'], $data['SuratJalanNumber']]);
        if (!$quetf) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] update status transfer request");
            exit;
        }


        ## UPDATE STOCK ##
        if (strtolower($data['i_tftype']) == 'persediaan') {
            foreach ($detail as $key => $obj) {
                # UPDATE STOCK IN BRANCH WAREHOUSE #
                $sqlwh = "SELECT 
                    StockID,
                    IFNULL(StockQty, 0) as StockQty,
                    WarehouseID,
                    WarehouseName
                FROM warehouse
                LEFT JOIN stock ON StockWarehouseID = WarehouseID 
                    AND StockItemID = ?
                    AND StockItemUnitID = ?
                    AND StockBatchNo = ?
                    AND WarehouseIsActive = 'Y'
                WHERE WarehouseIsTransit = ?
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID = ?";

                # SQL FOR STOCKKCARD #
                $sqlcard = "INSERT INTO stockcard (
                    StockCardWarehouseID,
                    StockCardDatetime,
                    StockCardItemID,
                    StockCardItemUnitID,
                    StockCardBatchNo,
                    StockCardED,
                    StockCardReffID,
                    StockCardStatus,
                    StockCardBefore,
                    StockCardIn,
                    StockCardOut,
                    StockCardAfter,
                    StockCardUserID
                ) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?,?,?)";

                foreach ($obj['ItemRequest'] as $key => $ele) {
                    $quewhb = $this->db->query($sqlwh, [
                        $ele['StockItemID'], $ele['StockItemUnitID'], 
                        $ele['StockBatchNo'], 'N', $user['S_RegionalID'], $user['M_BranchID']
                    ]);
                    $branchwh = $quewhb->row_array();

                    if (is_null($branchwh['WarehouseID'])) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] warehouse destination null");
                        exit;                    
                    }

                    if (is_null($branchwh['StockID'])) {
                        # INSERT STOCK CABANG #
                        $sqlupdtsit = "INSERT INTO stock (
                            StockWarehouseID,
                            StockStockNumber,
                            StockItemID,
                            StockItemUnitID,
                            StockItemPrice,
                            StockBatchNo,
                            StockED,
                            StockQty,
                            StockUserID,
                            StockLastUpdated
                        ) VALUES (?,fn_numbering('SN'),?,?,?,?,?,?,?,NOW())";
                        $queupdtsit = $this->db->query($sqlupdtsit, [
                            $branchwh['WarehouseID'],
                            $ele['StockItemID'],
                            $ele['StockItemUnitID'],
                            $ele['StockItemPrice'],
                            $ele['StockBatchNo'],
                            $ele['StockED'],
                            $ele['QtyReceive'],
                            $user['M_UserID']
                        ]);
                        if (!$queupdtsit) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock to warehouse cabang");
                            exit;
                        }
                        $stockid = $this->db->insert_id();

                        # INSERT STOCK CARD #
                        $quecard = $this->db->query($sqlcard, [
                            $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'],
                            $ele['StockBatchNo'], $ele['StockED'], $stockid, 
                            'MRB', 0, $ele['QtyReceive'], 0, $ele['QtyReceive'], $user['M_UserID']
                        ]);
                        if (!$quecard) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock card persediaan");
                            exit;
                        }
                    } else {
                        # UPDATE STOCK CABANG #
                        $sqlupdtrst = "UPDATE stock SET
                            StockQty = StockQty + ?,
                            StockLastUpdated = NOW()
                        WHERE StockID = ?";
                        $queupdtrst = $this->db->query($sqlupdtrst, [$ele['QtyReceive'], $branchwh['StockID']]);
                        if (!$queupdtrst) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] update stock to warehouse");
                            exit;
                        }

                        # INSERT INTO STOCK CARD #
                        $after = intval($ele['QtyReceive']) + intval($branchwh['StockQty']);
                        $quecard = $this->db->query($sqlcard, [
                            $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'],
                            $ele['StockBatchNo'], $ele['StockED'], $branchwh['StockID'], 'MRB', 
                            $branchwh['StockQty'], $ele['QtyReceive'], 0, $after, $user['M_UserID']
                        ]);
                        if (!$quecard) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock card");
                            exit;
                        }
                    }

                    # GET DATA STOCK IN WAREHOUSE TRANSIT #
                    $quetrsit = $this->db->query($sqlwh, [
                        $ele['StockItemID'], $ele['StockItemUnitID'], 
                        $ele['StockBatchNo'], 'Y', $user['S_RegionalID'], 0
                    ]);
                    if (!$quetrsit) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] check wh transit persediaan");
                        exit;
                    }
                    $transit = $quetrsit->row_array();

                    # UDPATE STOCK CARD INTRANSIT #
                    $aftertr =  intval($transit['StockQty']) - intval($ele['QtyReceive']);
                    $quecardtr = $this->db->query($sqlcard, [
                        $transit['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'], 
                        $ele['StockBatchNo'], $ele['StockED'], $transit['StockID'], 'MWT', 
                        $transit['StockQty'], 0, $ele['QtyReceive'], $aftertr, $user['M_UserID']
                    ]);
                    if (!$quecardtr) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update stockcard in transit persediaan");
                        exit;
                    }

                    # UPDATE STOCK IN TRANSIT #
                    $sqltrs = "UPDATE stock SET 
                        StockQty = StockQty - ?,
                        StockLastUpdated = NOW()
                    WHERE StockID = ?";
                    $quetrs = $this->db->query($sqltrs, [$ele['QtyReceive'], $transit['StockID']]);
                    if (!$quetrs) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update stock in transit");
                        exit;
                    }

                    # INSERT INTO STOCK LOG #
                    $sqllog = "INSERT INTO stocklog (
                        StockLogWarehouseID,
                        StockLogDateTime,
                        StockLogItemID,
                        StockLogItemUnitID,
                        StockLogStockNumber,
                        StockLogBatchNo,
                        StockLogED,
                        StockLogReffID,
                        StockLogStatus,
                        StockLogQty,
                        StockLogUserID
                    ) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?)";
                    $quelog = $this->db->query($sqllog, [
                        $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'], 
                        $ele['StockStockNumber'], $ele['StockBatchNo'], $ele['StockED'], 
                        $obj['SuratJalanDetailT_GoodsTransferDetailID'], 'TTW', $ele['QtyReceive'], $user['M_UserID']
                    ]);
                    if (!$quelog) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] insert into stock log");
                        exit;
                    }
                }
            }
        } else {
            foreach ($detail as $key => $obj) {
                $sqlwh = "SELECT 
                    StockID,
                    IFNULL(StockQty, 0) as StockQty,
                    WarehouseID,
                    WarehouseName
                FROM warehouse
                LEFT JOIN stock ON StockWarehouseID = WarehouseID 
                    AND StockItemID = ?
                    AND StockItemUnitID = ?
                    AND WarehouseIsActive = 'Y'
                WHERE WarehouseIsTransit = ?
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID = ?";

                # SQL FOR STOCKKCARD #
                $sqlcard = "INSERT INTO stockcard (
                    StockCardWarehouseID,
                    StockCardDatetime,
                    StockCardItemID,
                    StockCardItemUnitID,
                    StockCardBatchNo,
                    StockCardED,
                    StockCardReffID,
                    StockCardStatus,
                    StockCardBefore,
                    StockCardIn,
                    StockCardOut,
                    StockCardAfter,
                    StockCardUserID
                ) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?,?,?)";

                foreach ($obj['ItemRequest'] as $key => $ele) {
                    $quewhb = $this->db->query($sqlwh, [
                        $ele['StockItemID'], $ele['StockItemUnitID'], 
                        'N', $user['S_RegionalID'], $user['M_BranchID']
                    ]);
                    $branchwh = $quewhb->row_array();
                    if (is_null($branchwh['WarehouseID'])) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] warehouse destination null");
                        exit;                    
                    }

                    if (is_null($branchwh['StockID'])) {
                        $sqlupdtsit = "INSERT INTO stock (
                            StockWarehouseID,
                            StockStockNumber,
                            StockItemID,
                            StockItemUnitID,
                            StockItemPrice,
                            StockQty,
                            StockUserID,
                            StockLastUpdated
                        ) VALUES (?,fn_numbering('SN'),?,?,?,?,?,NOW())";
                        $queupdtsit = $this->db->query($sqlupdtsit, [
                            $branchwh['WarehouseID'],
                            $ele['StockItemID'],
                            $ele['StockItemUnitID'],
                            $ele['StockItemPrice'],
                            $ele['QtyReceive'],
                            $user['M_UserID']
                        ]);
                        if (!$queupdtsit) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock to warehouse cabang");
                            exit;
                        }
                        $stockid = $this->db->insert_id();

                        # INSERT STOCK CARD #
                        $quecard = $this->db->query($sqlcard, [
                            $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'],
                            '', '', $stockid, 'MRB', 0, $ele['QtyReceive'], 0, $ele['QtyReceive'], 
                            $user['M_UserID']
                        ]);
                        if (!$quecard) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock card non persediaan");
                            exit;
                        }
                    } else {
                        # UPDATE STOCK #
                        $sqlupdtrst = "UPDATE stock SET
                            StockQty = StockQty + ?,
                            StockLastUpdated = NOW()
                        WHERE StockID = ?";
                        $queupdtrst = $this->db->query($sqlupdtrst, [$ele['QtyReceive'], $branchwh['StockID']]);
                        if (!$queupdtrst) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] update stock to warehouse");
                            exit;
                        }

                        # INSERT INTO STOCK CARD #
                        $after = intval($ele['QtyReceive']) + intval($branchwh['StockQty']);
                        $quecard = $this->db->query($sqlcard, [
                            $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'],
                            '', '', $branchwh['StockID'], 'MRB', $branchwh['StockQty'], 
                            $ele['QtyReceive'], 0, $after, $user['M_UserID']
                        ]);
                        if (!$quecard) {
                            $this->db->trans_rollback();
                            $this->sys_error_db("[Error] insert stock card");
                            exit;
                        }
                    }
                    
                    # GET STOCK IN WAREHOUSE TRANSIT #
                    $sqltrn = $sqlwh . " AND StockQty >= ?";
                    $quetrsit = $this->db->query($sqltrn, [
                        $ele['StockItemID'], $ele['StockItemUnitID'], 
                        'Y', $user['S_RegionalID'], 0, $ele['QtyReceive']
                    ]);
                    if (!$quetrsit) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] check wh transit non persediaan");
                        exit;
                    }
                    $transit = $quetrsit->row_array();

                    # UPDATE STOCK CARD IN TRANSIT #
                    $aftertr = intval($transit['StockQty']) - intval($ele['QtyReceive']);
                    $quecardtr = $this->db->query($sqlcard, [
                        $transit['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'], 
                        '', '', $transit['StockID'], 'MWT', $transit['StockQty'], 0,
                        $ele['QtyReceive'], $aftertr, $user['M_UserID']
                    ]);
                    if (!$quecardtr) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] stock card in transit non persediaan");
                        exit;
                    }

                    # UPDATE STOCK IN TRANSIT #
                    $sqltrs = "UPDATE stock SET 
                        StockQty = StockQty - ?,
                        StockLastUpdated = NOW()
                    WHERE StockID = ?";
                    $quetrs = $this->db->query($sqltrs, [$ele['QtyReceive'], $transit['StockID']]);
                    if (!$quetrs) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update stock in transit");
                        exit;
                    }

                    # INSERT INTO STOCK LOG #
                    $sqllog = "INSERT INTO stocklog (
                        StockLogWarehouseID,
                        StockLogDateTime,
                        StockLogItemID,
                        StockLogItemUnitID,
                        StockLogStockNumber,
                        StockLogBatchNo,
                        StockLogED,
                        StockLogReffID,
                        StockLogStatus,
                        StockLogQty,
                        StockLogUserID
                    ) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?)";
                    $quelog = $this->db->query($sqllog, [
                        $branchwh['WarehouseID'], $ele['StockItemID'], $ele['StockItemUnitID'], 
                        $ele['StockStockNumber'], '', '', $obj['SuratJalanDetailT_GoodsTransferDetailID'], 
                        'TTW', $ele['QtyReceive'], $user['M_UserID']
                    ]);
                    if (!$quelog) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] insert into stock log");
                        exit;
                    }
                }
            }
        }

    }

    function generateJurnalRegional($data, $detail, $user) {
        ## CHECK JOURNAL TIME PERIOD ##
        $sqlperiod = "SELECT periodeID FROM periode WHERE DATE(NOW()) BETWEEN periodeStartDate AND periodeEndDate";
        $queperiod = $this->db->query($sqlperiod, []);
        if (!$queperiod) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] check periode");
            exit;
        }
        $periode = $queperiod->row_array();
        if (empty($periode)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] periode waktu tidak ditemukan");
            exit;
        }

        ## GENERATE JURNAL NUMBER ##
        $sqlnum = "SELECT `fn_numbering`('J') as JNumber";
        $qrynum = $this->db->query($sqlnum, []);
        if (!$qrynum) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] generate jurnal number");
            exit;
        }
        $JurnalNumber = $qrynum->row()->JNumber;

        ## GET JURNAL TYPE ID ##
        $sqltype = "SELECT JurnalTypeID as Jtype FROM jurnal_type WHERE JurnalTypeCode = ?";
        $qrytype = $this->db->query($sqltype, ['AUTOGOODRECEIVE']);
        if (!$qrytype) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $Jurnaltype = $qrytype->row()->Jtype;

        $title = "Auto Penerimaan Barang dari Transfer Regional - Jurnal Regional";
        $descp = "Surat Jalan Number: {$data['SuratJalanNumber']}, Tanggal: {$data['SuratJalanDate']}, Asal: Regional {$user['S_RegionalName']}";
        $jdate = date('Y-m-d');

        $sqljur = "INSERT INTO jurnal (
            jurnalM_BranchCompanyID,
            JurnalS_RegionalID,
            jurnalM_BranchCode,
            jurnalperiodeID,
            jurnalNo,
            jurnalTitle,
            jurnalDescription,
            jurnalDate,
            jurnalJurnalTypeID,
            jurnalCreated,
            jurnalM_UserID
        ) VALUES (?,?,?,?,?,?,?,?,?,NOW(),?)";
        $quejur = $this->db->query($sqljur, [
            $user['M_BranchCompanyID'], $user['S_RegionalID'], '', 
            $periode['periodeID'], $JurnalNumber, $title, $descp, 
            $jdate, $Jurnaltype, $user['M_UserID']
        ]);
        if (!$quejur) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $jurnalID = $this->db->insert_id();

        $sqljurtx = "INSERT INTO jurnal_tx (
            jurnalTxJurnalID,
            jurnalTxCoaID,
            jurnalTxDescription,
            jurnalTxDebit,
            jurnalTxCredit,
            jurnalTxM_UserID
        ) VALUES (?,?,?,?,?,?)";

        $total = 0.00;
        foreach ($detail as $key => $obj) {
            $subtotal = 0.00;
            foreach ($obj['ItemRequest'] as $key => $ele) {
                $harga = intval($ele['QtyReceive']) * doubleval($ele['StockItemPrice']);
                $subtotal = round($subtotal + $harga, 2);
            }
            $total = $total + $subtotal;
        }

        ## GET COA ID  ##
        $sqlcoa = "SELECT coaID, coaDescription FROM coa WHERE coaAccountNo = ? AND coaIsActive = 'Y'";
        $quecoa = $this->db->query($sqlcoa, ['1150700001']);
        if (!$quecoa) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] get coa id");
            exit;
        }
        $coa = $quecoa->row_array();
        if (empty($coa)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] coa null or not found");
            exit;
        }

        # INSERT JURNAL TX FOR IN TRANSIT #
        $quetx = $this->db->query($sqljurtx, [
            $jurnalID, $coa['coaID'], $coa['coaDescription'], 
            0, $total, $user['M_UserID']
        ]);
        if (!$quetx) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] error insert jurnal tx intransit reg");
            exit;
        }

        # GET COA FOR R/K #
        if (strtolower($data['i_tftype']) == 'persediaan') {
            $sqlRK = "SELECT 
                Map_RkCabang_Rk_TypeID,
                Map_RkCabang_SRegionalID,
                Map_RkCabang_BranchCode,
                Map_RkCabang_CoaID,
                Map_RkCabang_CoaAccountNo,
                Map_RkCabang_CoaDescription
            FROM map_rk_cabang
            JOIN rk_type ON Map_RkCabang_Rk_TypeID = Rk_TypeID AND Rk_TypeIsActive ='Y'
                AND Rk_TypeCode = 'STOK'
            WHERE Map_RkCabang_IsActive = 'Y'
                AND Map_RkCabang_SRegionalID = ?
                AND Map_RkCabang_BranchCode = ?";
            $queRK = $this->db->query($sqlRK, [$user['S_RegionalID'], $user['M_BranchCode']]);
            if (!$queRK) {
                $this->db->trans_rollback();
                $this->sys_error("[Error] get coa rk regional");
                exit;
            }
            $coaRK = $queRK->row_array();
            if (empty($coaRK)) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] coa rk regional stock null or not found");
                exit;
            }
        } else {
            $sqlRK = "SELECT 
                Map_RkCabang_Rk_TypeID,
                Map_RkCabang_SRegionalID,
                Map_RkCabang_BranchCode,
                Map_RkCabang_CoaID,
                Map_RkCabang_CoaAccountNo,
                Map_RkCabang_CoaDescription
            FROM map_rk_cabang
            JOIN rk_type ON Map_RkCabang_Rk_TypeID = Rk_TypeID AND Rk_TypeIsActive ='Y'
                AND Rk_TypeCode = 'AKTIVA'
            WHERE Map_RkCabang_IsActive = 'Y'
                AND Map_RkCabang_SRegionalID = ?
                AND Map_RkCabang_BranchCode = ?";
            $queRK = $this->db->query($sqlRK, [$user['S_RegionalID'], $user['M_BranchCode']]);
            if (!$queRK) {
                $this->db->trans_rollback();
                $this->sys_error("[Error] get coa rk regional");
                exit;
            }
            $coaRK = $queRK->row_array();
            if (empty($coaRK)) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] coa rk regional aktiva null or not found");
                exit;
            }
        }

        # INSERT JURNAL TX FOR R/K #
        $quetx = $this->db->query($sqljurtx, [
            $jurnalID, $coaRK['Map_RkCabang_CoaID'], $coaRK['Map_RkCabang_CoaDescription'], 
            $total, 0, $user['M_UserID']
        ]);
        if (!$quetx) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] insert into jurnal tx");
            exit;
        }
        $jurnalTXID = $this->db->insert_id();

        # INSERT JURNAL ADDON #
        $sqladdon = "INSERT INTO jurnal_addon (
            jurnalAddOnJurnalID,
            jurnalAddOnJurnalTxID,
            jurnalAddOnCode,
            jurnalAddOnValue,
            jurnalAddOnCreated,
            jurnalAddOnCreatedUserID
        ) VALUES (?,?,?,?,NOW(),?)";
        $queaddon = $this->db->query($sqladdon, [
            $jurnalID, $jurnalTXID, 'SENDGOODRDST', $data['SuratJalanNumber'], $user['M_UserID']
        ]);
        if (!$queaddon) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] insert into jurnal addon");
            exit;
        }
    }

    function generateJurnalCabang($data, $detail, $user) {
        ## CHECK JOURNAL TIME PERIOD ##
        $sqlperiod = "SELECT periodeID FROM periode WHERE DATE(NOW()) BETWEEN periodeStartDate AND periodeEndDate";
        $queperiod = $this->db->query($sqlperiod, []);
        if (!$queperiod) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] check periode");
            exit;
        }
        $periode = $queperiod->row_array();
        if (empty($periode)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] periode waktu tidak ditemukan");
            exit;
        }

        ## GENERATE JURNAL NUMBER ##
        $sqlnum = "SELECT `fn_numbering`('J') as JNumber";
        $qrynum = $this->db->query($sqlnum, []);
        if (!$qrynum) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] generate jurnal number");
            exit;
        }
        $JurnalNumber = $qrynum->row()->JNumber;

        ## GET JURNAL TYPE ID ##
        $sqltype = "SELECT JurnalTypeID as Jtype FROM jurnal_type WHERE JurnalTypeCode = ?";
        $qrytype = $this->db->query($sqltype, ['AUTOGOODRECEIVE']);
        if (!$qrytype) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $Jurnaltype = $qrytype->row()->Jtype;

        $title = "Auto Penerimaan Barang dari Transfer Regional - Jurnal Cabang";
        $descp = "Surat Jalan Number: {$data['SuratJalanNumber']}, Tanggal: {$data['SuratJalanDate']}, Asal: Regional {$user['S_RegionalName']}";
        $jdate = date('Y-m-d');

        $sqljur = "INSERT INTO jurnal (
            jurnalM_BranchCompanyID,
            JurnalS_RegionalID,
            jurnalM_BranchCode,
            jurnalperiodeID,
            jurnalNo,
            jurnalTitle,
            jurnalDescription,
            jurnalDate,
            jurnalJurnalTypeID,
            jurnalCreated,
            jurnalM_UserID
        ) VALUES (?,?,?,?,?,?,?,?,?,NOW(),?)";
        $quejur = $this->db->query($sqljur, [
            $user['M_BranchCompanyID'], $user['S_RegionalID'], $user['M_BranchCode'], 
            $periode['periodeID'], $JurnalNumber, $title, $descp, 
            $jdate, $Jurnaltype, $user['M_UserID']
        ]);
        if (!$quejur) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $jurnalID = $this->db->insert_id();

        $sqljurtx = "INSERT INTO jurnal_tx (
            jurnalTxJurnalID,
            jurnalTxCoaID,
            jurnalTxDescription,
            jurnalTxDebit,
            jurnalTxCredit,
            jurnalTxM_UserID
        ) VALUES (?,?,?,?,?,?)";

        $total = 0.00;
        foreach ($detail as $key => $obj) {
            if (strtolower($data['i_tftype']) == 'persediaan') {
                $subtotal = 0.00;
                foreach ($obj['ItemRequest'] as $key => $ele) {
                    $harga = intval($ele['QtyReceive']) * doubleval($ele['StockItemPrice']);
                    $subtotal = round($subtotal + $harga, 2);
                }

                $sqlcoaitem = "SELECT 
                    MapNatSub_PersediaanCoaID,
                    MapNatSub_PersediaanCoaDescription,
                    MapNatSub_PersediaanCoaAccountNo
                FROM m_item 
                JOIN map_nat_subgroup ON MapNatSub_NatGroupID = M_ItemNat_GroupID
                    AND MapNatSub_NatSubGroupID = M_ItemNat_SubGroupID
                    AND MapNatSub_IsActive = 'Y'
                WHERE M_ItemID = ?";
                $quecoaitem = $this->db->query($sqlcoaitem, [$obj['SuratJalanDetailM_ItemID']]);
                if (!$quecoaitem) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] get coa item");
                    exit;
                }
                $coaItem = $quecoaitem->row_array();
                if (empty($coaItem)) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] coa item null or not found");
                    exit;
                }

                # INSERT JURNAL TX #
                $quejurtx = $this->db->query($sqljurtx, [
                    $jurnalID, $coaItem['MapNatSub_PersediaanCoaID'], 
                    $coaItem['MapNatSub_PersediaanCoaDescription'], 
                    $subtotal, 0, $user['M_UserID']
                ]);
                if (!$quejurtx) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert into jurnal tx persediaan");
                    exit;
                }

                $total = $total + $subtotal;
            } else {
                $subtotal = 0.00;
                foreach ($obj['ItemRequest'] as $key => $ele) {
                    $harga = intval($ele['QtyReceive']) * doubleval($ele['StockItemPrice']);
                    $subtotal = round($subtotal + $harga, 2);
                }

                $sqlcoaitem = "SELECT 
                    MapNatSub_BiayaCoaID,
                    MapNatSub_BiayaCoaAccountNo,
                    MapNatSub_BiayaCoaDescription
                FROM m_item 
                JOIN map_nat_subgroup ON MapNatSub_NatGroupID = M_ItemNat_GroupID
                    AND MapNatSub_NatSubGroupID = M_ItemNat_SubGroupID
                    AND MapNatSub_IsActive = 'Y'
                WHERE M_ItemID = ?";
                $quecoaitem = $this->db->query($sqlcoaitem, [$obj['SuratJalanDetailM_ItemID']]);
                if (!$quecoaitem) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] get coa item non persediaan");
                    exit;
                }
                $coaItem = $quecoaitem->row_array();
                if (empty($coaItem)) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] coa item non persediaan null or not found");
                    exit;
                }

                # INSERT JURNAL TX #
                $quejurtx = $this->db->query($sqljurtx, [
                    $jurnalID, $coaItem['MapNatSub_BiayaCoaID'], 
                    $coaItem['MapNatSub_BiayaCoaDescription'], 
                    $subtotal, 0, $user['M_UserID']
                ]);
                if (!$quejurtx) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert into jurnal tx non persediaan");
                    exit;
                }

                $total = $total + $subtotal;
            }
        }

        # GET COA FOR R/K #
        if (strtolower($data['i_tftype']) == 'persediaan') {
            $sqlRK = "SELECT 
                Map_RkCabang_Rk_TypeID,
                Map_RkCabang_SRegionalID,
                Map_RkCabang_BranchCode,
                Map_RkCabang_CoaID,
                Map_RkCabang_CoaAccountNo,
                Map_RkCabang_CoaDescription
            FROM map_rk_cabang
            JOIN rk_type ON Map_RkCabang_Rk_TypeID = Rk_TypeID AND Rk_TypeIsActive ='Y'
                AND Rk_TypeCode = 'STOK'
            WHERE Map_RkCabang_IsActive = 'Y'
                AND Map_RkCabang_SRegionalID = ?
                AND Map_RkCabang_BranchCode = ?";
            $queRK = $this->db->query($sqlRK, [$user['S_RegionalID'], '']);
            if (!$queRK) {
                $this->db->trans_rollback();
                $this->sys_error("[Error] get coa rk regional");
                exit;
            }
            $coaRK = $queRK->row_array();
            if (empty($coaRK)) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] coa rk regional stock null or not found");
                exit;
            }
        } else {
            $sqlRK = "SELECT 
                Map_RkCabang_Rk_TypeID,
                Map_RkCabang_SRegionalID,
                Map_RkCabang_BranchCode,
                Map_RkCabang_CoaID,
                Map_RkCabang_CoaAccountNo,
                Map_RkCabang_CoaDescription
            FROM map_rk_cabang
            JOIN rk_type ON Map_RkCabang_Rk_TypeID = Rk_TypeID AND Rk_TypeIsActive ='Y'
                AND Rk_TypeCode = 'AKTIVA'
            WHERE Map_RkCabang_IsActive = 'Y'
                AND Map_RkCabang_SRegionalID = ?
                AND Map_RkCabang_BranchCode = ?";
            $queRK = $this->db->query($sqlRK, [$user['S_RegionalID'], '']);
            if (!$queRK) {
                $this->db->trans_rollback();
                $this->sys_error("[Error] get coa rk regional");
                exit;
            }
            $coaRK = $queRK->row_array();
            if (empty($coaRK)) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] coa rk regional aktiva null or not found");
                exit;
            }
        }

        # INSERT JURNAL TX FOR R/K #
        $quetx = $this->db->query($sqljurtx, [
            $jurnalID, $coaRK['Map_RkCabang_CoaID'], $coaRK['Map_RkCabang_CoaDescription'], 
            0, $total, $user['M_UserID']
        ]);
        if (!$quetx) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] insert into jurnal tx");
            exit;
        }
        $jurnalTXID = $this->db->insert_id();

        # INSERT JURNAL ADDON #
        $sqladdon = "INSERT INTO jurnal_addon (
            jurnalAddOnJurnalID,
            jurnalAddOnJurnalTxID,
            jurnalAddOnCode,
            jurnalAddOnValue,
            jurnalAddOnCreated,
            jurnalAddOnCreatedUserID
        ) VALUES (?,?,?,?,NOW(),?)";
        $queaddon = $this->db->query($sqladdon, [
            $jurnalID, $jurnalTXID, 'SENDGOODRDST', $data['SuratJalanNumber'], $user['M_UserID']
        ]);
        if (!$queaddon) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] insert into jurnal addon");
            exit;
        }
    }

    function generateJurnalDiff($data, $detail, $user) {
        ## CHECK JOURNAL TIME PERIOD ##
        $sqlperiod = "SELECT periodeID FROM periode WHERE DATE(NOW()) BETWEEN periodeStartDate AND periodeEndDate";
        $queperiod = $this->db->query($sqlperiod, []);
        if (!$queperiod) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] check periode");
            exit;
        }
        $periode = $queperiod->row_array();
        if (empty($periode)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] periode waktu tidak ditemukan");
            exit;
        }

        ## GENERATE JURNAL NUMBER ##
        $sqlnum = "SELECT `fn_numbering`('J') as JNumber";
        $qrynum = $this->db->query($sqlnum, []);
        if (!$qrynum) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] generate jurnal number");
            exit;
        }
        $JurnalNumber = $qrynum->row()->JNumber;

        ## GET JURNAL TYPE ID ##
        $sqltype = "SELECT JurnalTypeID as Jtype FROM jurnal_type WHERE JurnalTypeCode = ?";
        $qrytype = $this->db->query($sqltype, ['AUTOGOODRECEIVE']);
        if (!$qrytype) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $Jurnaltype = $qrytype->row()->Jtype;

        $title = "Auto Penerimaan Barang dari Transfer Regional - Jurnal Investigasi Perbedaan Stock";
        $descp = "Surat Jalan Number: {$data['SuratJalanNumber']}, Tanggal: {$data['SuratJalanDate']}, Asal: Regional {$user['S_RegionalName']}";
        $jdate = date('Y-m-d');

        $sqljur = "INSERT INTO jurnal (
            jurnalM_BranchCompanyID,
            JurnalS_RegionalID,
            jurnalM_BranchCode,
            jurnalperiodeID,
            jurnalNo,
            jurnalTitle,
            jurnalDescription,
            jurnalDate,
            jurnalJurnalTypeID,
            jurnalCreated,
            jurnalM_UserID
        ) VALUES (?,?,?,?,?,?,?,?,?,NOW(),?)";
        $quejur = $this->db->query($sqljur, [
            $user['M_BranchCompanyID'], $user['S_RegionalID'], '', 
            $periode['periodeID'], $JurnalNumber, $title, $descp, 
            $jdate, $Jurnaltype, $user['M_UserID']
        ]);
        if (!$quejur) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get id jurnal type");
            exit;
        }
        $jurnalID = $this->db->insert_id();

        $sqljurtx = "INSERT INTO jurnal_tx (
            jurnalTxJurnalID,
            jurnalTxCoaID,
            jurnalTxDescription,
            jurnalTxDebit,
            jurnalTxCredit,
            jurnalTxM_UserID
        ) VALUES (?,?,?,?,?,?)";

        $total = 0.00;
        foreach ($detail as $key => $obj) {
            $subtotal = 0.00;
            foreach ($obj['ItemRequest'] as $key => $ele) {
                $harga = (intval($ele['QtyReq']) - intval($ele['QtyReceive'])) * doubleval($ele['StockItemPrice']);
                $subtotal = round($subtotal + $harga, 2);
            }
            $total = $total + $subtotal;
        }

        ## GET COA ID  ##
        $sqlcoa = "SELECT coaID, coaDescription FROM coa WHERE coaAccountNo = ? AND coaIsActive = 'Y'";
        $quecoa = $this->db->query($sqlcoa, ['1150700001']);
        if (!$quecoa) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] get coa id");
            exit;
        }
        $coa = $quecoa->row_array();
        if (empty($coa)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] coa null or not found");
            exit;
        }

        # INSERT JURNAL TX FOR IN TRANSIT #
        $quetx = $this->db->query($sqljurtx, [
            $jurnalID, $coa['coaID'], $coa['coaDescription'], 
            0, $total, $user['M_UserID']
        ]);
        if (!$quetx) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] error insert jurnal tx intransit diff");
            exit;
        }

        # STOCK DALAM INVESTIGASI #
        $sqlCoaInvestigasi = "SELECT coaID, coaDescription FROM coa WHERE coaAccountNo = '1150700002' AND coaIsActive = 'Y'";
        $qryCoaInvestigasi = $this->db->query($sqlCoaInvestigasi);
        if (!$qryCoaInvestigasi) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] get coa investigasi");
            exit;
        }
        $coaInvest = $qryCoaInvestigasi->row_array();
        if (empty($coaInvest)) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] coa null or not found");
            exit;
        }

        $queinv = $this->db->query($sqljurtx, [
            $jurnalID, $coaInvest['coaID'], $coaInvest['coaDescription'],
            $total, 0, $user['M_UserID']
        ]);
        if (!$queinv) {
            $this->db->trans_rollback();
            $this->sys_error("[Error] insert jurnal tx investigasi diff");
            exit;
        }
        $jurnalTXID = $this->db->insert_id();

        # INSERT JURNAL ADDON #
        $sqladdon = "INSERT INTO jurnal_addon (
            jurnalAddOnJurnalID,
            jurnalAddOnJurnalTxID,
            jurnalAddOnCode,
            jurnalAddOnValue,
            jurnalAddOnCreated,
            jurnalAddOnCreatedUserID
        ) VALUES (?,?,?,?,NOW(),?)";
        $queaddon = $this->db->query($sqladdon, [
            $jurnalID, $jurnalTXID, 'SENDGOODRDST', $data['SuratJalanNumber'], $user['M_UserID']
        ]);
        if (!$queaddon) {
            $this->db->trans_rollback();
            $this->sys_error_db("[Error] insert into jurnal addon");
            exit;
        }
    }

    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, [
            'RSJ',
            $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;
        }
    }
}