<?php

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

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

    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 CreateSuratJalanFromTF()
    {
        try {
            if (!$this->isLogin) {
                $this->sys_error("invalid token");
                exit;
            }

            $userID = $this->sys_user["M_UserID"];
            $para = $this->sys_input;

            $this->db->trans_begin();
            $sqlnum = "SELECT `fn_numbering`('SJ') as SJNumber";
            $qrynum = $this->db->query($sqlnum, []);
            $SJNumber = $qrynum->row()->SJNumber;

            $sqlSJ = "INSERT INTO suratjalan (
                        SuratJalanNumber,
                        SuratJalanDate,
                        SuratJalanNote,
                        SuratJalanT_GoodsTransferID,
                        SuratJalanT_GoodsTransferNum,
                        SuratJalanUserID
                    ) VALUES (?,?,?,?,?,?)";
            $qrySJ = $this->db->query($sqlSJ, [
                $SJNumber,
                $para['GoodsTfDate'],
                $para['GoodsTfNotes'],
                $para['GoodsTfID'],
                $para['GoodsTfNum'],
                $userID
            ]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("failed to insert data table surat jalan");
                exit;
            }

            $SJalanID = $this->db->insert_id();
            foreach ($para['detail'] as $key => $detail) {
                $sqlSJD = "INSERT INTO suratjalan_detail (
                            SuratJalanDetailSuratJalanID,
                            SuratJalanDetailPurchaseRequestFlagID,
                            SuratJalanDetailT_GoodsTransferDetailID,
                            SuratJalanDetailM_ItemID,
                            SuratJalanDetailQty,
                            SuratJalanDetailItemUnitID,
                            SuratJalanDetailUserID
                        ) VALUES (?,?,?,?,?,?,?)";
                $qrySJD = $this->db->query($sqlSJD, [
                    $SJalanID,
                    $detail['PurchaseRequestFlagID'],
                    $detail['TGoodsTFDetailID'],
                    $detail['PurchaseRequestDetailM_ItemID'],
                    $detail['PurchaseRequestFlagQtyRest'],
                    $detail['PurchaseRequestDetailItemUnitID'],
                    $userID
                ]);
                if (!$qrySJD) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("failed to insert data table surat jalan detail");
                    exit;
                }
            }

            $this->db->trans_commit();
            $this->sys_ok("success create surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $user = $this->sys_user;
            $para = $this->sys_input;
            $SJalanID = $para['SJalanID'];
            $TGoodID = $para['TGoodID'];
            $Detail = $para['detail'];

            $this->db->trans_begin();
            $sqlSJ = "UPDATE suratjalan 
                SET SuratJalanStatus = 'Process'
                WHERE SuratJalanID = ? 
                    AND SuratJalanIsActive = 'Y'";
            $qrySJ = $this->db->query($sqlSJ, [$SJalanID]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status surat jalan -> konfirmasi");
                exit;
            }

            $sqlTF = "UPDATE t_goods_transfer 
                SET T_GoodsTransferStatus = 'Process'
                WHERE T_GoodsTransferID = ? 
                    AND T_GoodsTransferIsActive = 'Y'";
            $qryTF = $this->db->query($sqlTF, [$TGoodID]);
            if (!$qryTF) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update rollback TF request status");
                exit;
            }

            // move stock from warehouse to transit
            foreach ($Detail as $key => $value) {
                $ItemID = $value['SuratJalanDetailM_ItemID'];
                $QtyTF = $value['SuratJalanDetailQty'];

                $whstock = "SELECT 
                        WarehouseID, 
                        WarehouseName,  
                        WarehouseIsTransit,
                        stock.*
                    FROM stock
                    JOIN warehouse ON StockWarehouseID = WarehouseID
                        AND WarehouseIsActive = 'Y'
                    WHERE StockItemID = ? 
                        AND WarehouseS_RegionalID = ?
                        AND WarehouseM_BranchID = ?
                        AND WarehouseIsActive = 'Y'";
                $whstqry = $this->db->query($whstock, [
                    $ItemID,
                    $user['S_RegionalID'],
                    $user['M_BranchID']
                ]);
                if (!$whstqry) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] get warehouse id dan stock qty");
                    exit;
                }
                $listWH = $whstqry->result_array();

                $WHtransit = array_filter($listWH, function ($list) {
                    return $list['WarehouseIsTransit'] === 'Y';
                });
                $WHtransit = array_values($WHtransit);
                if (empty($WHtransit)) {
                    $this->db->trans_rollback();
                    $this->sys_error("[Error] warehouse transit not found");
                    exit;
                }

                $WHstock = array_filter($listWH, function ($list) use ($QtyTF) {
                    return $list['WarehouseIsTransit'] === 'N' && intval($list['StockQty']) >= intval($QtyTF);
                });
                $WHstock = array_values($WHstock);
                if (empty($WHstock)) {
                    $this->db->trans_rollback();
                    $this->sys_error("[Error] stock item warehouse not found or sufficient");
                    exit;
                }
                $WHstock[0]['StockQty'] = intval($WHstock[0]['StockQty']) - intval($QtyTF);
                $WHtransit[0]['StockQty'] = intval($WHtransit[0]['StockQty']) + intval($QtyTF);
                $newarr = [$WHstock[0], $WHtransit[0]];

                foreach ($newarr as $key => $val) {
                    $updsto = "UPDATE stock 
                        SET StockQty = ?
                        WHERE StockID = ? 
                            AND StockWarehouseID = ?";
                    $qrysto = $this->db->query($updsto, [
                        $val['StockQty'],
                        $val['StockID'],
                        $val['WarehouseID']
                    ]);
                    if (!$qrysto) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] update stock qty to wh transit");
                        exit;
                    }
                }

                // insert into stocklog
                $slog = "INSERT INTO stocklog (
                        StockLogWarehouseID,
                        StockLogDateTime,
                        StockLogItemID,
                        StockLogItemUnitID,
                        StockLogStockNumber,
                        StockLogBatchNo,
                        StockLogED,
                        StockLogReffID,
                        StockLogStatus,
                        StockLogQty,
                        StockLogUserID
                    ) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?)";
                $qlog = $this->db->query($slog, [
                    $WHstock[0]['WarehouseID'],
                    $WHstock[0]['StockItemID'],
                    $WHstock[0]['StockItemUnitID'],
                    $WHstock[0]['StockStockNumber'],
                    $WHstock[0]['StockBatchNo'],
                    $WHstock[0]['StockED'],
                    $value['SuratJalanDetailT_GoodsTransferDetailID'],
                    "WTT",
                    $QtyTF,
                    $user['M_UserID'],
                ]);
                if (!$qlog) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert stocklog");
                    exit;
                }
            }

            $sql_json = "SELECT suratjalan.*, '' as details
            FROM suratjalan
            WHERE SuratJalanID = ?";
            $qry_json = $this->db->query($sql_json, [$para['SJalanID']]);
            if (!$qry_json) {
                $this->db->trans_rollback();
                $this->sys_error_db("select json tf error");
                exit;
            }
            $row_json = $qry_json->row_array();

            $descActivity = "Konfirmasi surat jalan {$row_json['SuratJalanNumber']}, status {$row_json['SuratJalanStatus']}";

            $sql_json_detail = "SELECT suratjalan_detail.* 
                FROM suratjalan_detail
                WHERE SuratJalanDetailSuratJalanID = ?";
            $qry_json_detail = $this->db->query($sql_json_detail, [$para['SJalanID']]);
            if ($qry_json_detail) {
                $row_json["details"] = $qry_json_detail->result_array();
            } else {
                $this->sys_error_db("select detail tf error", $this->db);
                exit;
            }

            $data_json = $row_json;

            $this->insertUserActivty($para['SJalanID'], 'CONFIRM', $this->sys_user["M_UserID"], $descActivity, json_encode($data_json));

            $this->db->trans_commit();
            $this->sys_ok("[Success] konfirmasi surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $user = $this->sys_user;
            $para = $this->sys_input;
            $SJalanID = $para['SJalanID'];
            $TGoodID = $para['TGoodID'];
            $Detail = $para['detail'];

            $this->db->trans_begin();
            $sqlsj = "UPDATE suratjalan SET SuratJalanStatus = 'Process' WHERE SuratJalanID = ? AND SuratJalanIsActive = 'Y'";
            $quesj = $this->db->query($sqlsj, [$SJalanID]);
            if (!$quesj) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status surat jalan -> process");
                exit;
            }

            $sqltf = "UPDATE t_goods_transfer SET T_GoodsTransferStatus = 'Process' WHERE T_GoodsTransferID = ? AND T_GoodsTransferIsActive = 'Y'";
            $quetf = $this->db->query($sqltf, [$TGoodID]);
            if (!$quetf) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update rollback TF request status");
                exit;
            }

            foreach ($Detail as $key => $value) {
                $itemID = $value['SuratJalanDetailM_ItemID'];
                $quantityTF = intval($value['SuratJalanDetailQty']);
                $branchID = $value['M_BranchID'];
                $regionalID = $value['PurchaseRequestFlagS_RegionalID'];

                // get stock item from other warehouse except the requester
                $sqlstock = "SELECT
                    WarehouseID, 
                    WarehouseName,  
                    WarehouseIsTransit,
                    stock.*
                FROM warehouse
                JOIN stock ON StockWarehouseID = WarehouseID
                    AND StockItemID = ?
                WHERE WarehouseIsActive = 'Y'
                    AND WarehouseIsTransit = 'N'
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID != ?";
                $questock = $this->db->query($sqlstock, [$itemID, $regionalID, $branchID]);
                if (!$questock) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] get stock from other warehouse");
                    exit;
                }
                $stockWH = $questock->result_array();

                $sisaTF = $quantityTF;
                foreach ($stockWH as $key => $wh) {
                    $stock = intval($wh['StockQty']);
                    if ($stock >= $sisaTF && $sisaTF != 0) {
                        $sisaTF = $stock - $sisaTF;
                    } else if ($sisaTF != 0) {
                        $sisaTF = $sisaTF - $stock;
                    }

                    // update stock
                    $sqlupstock = "UPDATE stock SET ";
                }
            }

            $this->db->trans_commit();
            $this->sys_ok("[Success] konfirmasi surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $para = $this->sys_input;

            $mustFields = ['EkspeID', 'EkspeStaffID', 'EkspeStaffHP', 'SJStatus', 'SJalanID'];
            $missFields = [];
            foreach ($mustFields as $field) {
                if (empty($para[$field])) {
                    $missFields[] = $field;
                }
            }
            if (!empty($missFields)) {
                $this->sys_error("Missing fields: " . implode(", ", $missFields));
                exit;
            }

            $this->db->trans_begin();
            $sqlSJ = "UPDATE suratjalan 
                SET SuratJalanNote = ?,
                    SuratJalanEkspedisiID = ?,
                    SuratJalanEkspedisiStaffID = ?,
                    SuratJalanEkspedisiStaffContact = ?,
                    SuratJalanStatus = ?
                WHERE SuratJalanID = ? 
                    AND SuratJalanIsActive = 'Y'";
            $qrySJ = $this->db->query($sqlSJ, [
                $para['SJNote'],
                $para['EkspeID'],
                $para['EkspeStaffID'],
                $para['EkspeStaffHP'],
                $para['SJStatus'],
                $para['SJalanID']
            ]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("error update surat jalan");
                exit;
            }

            $sql_json = "SELECT suratjalan.*, '' as details
            FROM suratjalan
            WHERE SuratJalanID = ?";
            $qry_json = $this->db->query($sql_json, [$para['SJalanID']]);
            if (!$qry_json) {
                $this->db->trans_rollback();
                $this->sys_error_db("select json tf error");
                exit;
            }
            $row_json = $qry_json->row_array();

            $descActivity = "Update surat jalan {$row_json['SuratJalanNumber']}, status {$para['SJStatus']}";

            $sql_json_detail = "SELECT suratjalan_detail.* 
                FROM suratjalan_detail
                WHERE SuratJalanDetailSuratJalanID = ?";
            $qry_json_detail = $this->db->query($sql_json_detail, [$para['SJalanID']]);
            if ($qry_json_detail) {
                $row_json["details"] = $qry_json_detail->result_array();
            } else {
                $this->sys_error_db("select detail tf error", $this->db);
                exit;
            }

            $data_json = $row_json;

            $this->insertUserActivty($para['SJalanID'], 'UPDATE', $this->sys_user["M_UserID"], $descActivity, json_encode($data_json));

            $this->db->trans_commit();
            $this->sys_ok("success update surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $para = $this->sys_input;

            $this->db->trans_begin();

            // update status data tabel suratjalan
            $sqlSJ = "UPDATE suratjalan 
                SET SuratJalanIsActive = 'N'
                WHERE SuratJalanID = ? 
                    AND SuratJalanIsActive = 'Y'";
            $qrySJ = $this->db->query($sqlSJ, [$para['SJalanID']]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("error delete data surat jalan");
                exit;
            }

            // 
            $sqlcurr = "SELECT 
                    SuratJalanDetailID,
                    SuratJalanDetailQty as qtySJ,
                    PurchaseRequestFlagQtyRest as tfRest,
                    PurchaseRequestFlagQtyProses tfProses,
                    PurchaseRequestFlagID
                FROM suratjalan_detail
                JOIN purchase_request_flag ON PurchaseRequestFlagID = SuratJalanDetailPurchaseRequestFlagID
                WHERE SuratJalanDetailSuratJalanID = ?
                    AND SuratJalanDetailIsActive = 'Y'";
            $qrycurr = $this->db->query($sqlcurr, [$para['SJalanID']]);
            if (!$qrycurr) {
                $this->db->trans_rollback();
                $this->sys_error_db("error get current data detail");
                exit;
            }
            $currdetail = $qrycurr->result_array();

            foreach ($currdetail as $key => $value) {
                $currqty = intval($value['qtySJ']);
                $restqty = intval($value['tfRest']);
                $prosqty = intval($value['tfProses']);

                $newRes = $restqty - $currqty;
                $newPrs = $prosqty - $currqty;

                $sqlflag = "UPDATE purchase_request_flag
                    SET PurchaseRequestFlagQtyRest = ?,
                        PurchaseRequestFlagQtyProses = ?
                    WHERE PurchaseRequestFlagID = ?
                        AND PurchaseRequestFlagIsActive = 'Y'";
                $qryflag = $this->db->query($sqlflag, [$newRes, $newPrs, $value['PurchaseRequestFlagID']]);
                if (!$qryflag) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("error reverse qty proses dan rest flag");
                    exit;
                }
            }

            $sqlSJD = "UPDATE suratjalan_detail 
                SET SuratJalanDetailIsActive = 'N'
                WHERE SuratJalanDetailSuratJalanID = ? 
                    AND SuratJalanDetailIsActive = 'Y'";
            $qrySJD = $this->db->query($sqlSJD, [$para['SJalanID']]);
            if (!$qrySJD) {
                $this->db->trans_rollback();
                $this->sys_error_db("error delete data surat jalan detail");
                exit;
            }

            $sqlTF = "UPDATE t_goods_transfer 
                SET T_GoodsTransferStatus = 'Draft' 
                WHERE T_GoodsTransferID = ? 
                    AND T_GoodsTransferIsActive = 'Y'";
            $qryTF = $this->db->query($sqlTF, [$para['TGoodID']]);
            if (!$qryTF) {
                $this->db->trans_rollback();
                $this->sys_error_db("error update rollback TF request status");
                exit;
            }

            $sql_json = "SELECT suratjalan.*, '' as details
            FROM suratjalan
            WHERE SuratJalanID = ?";
            $qry_json = $this->db->query($sql_json, [$para['SJalanID']]);
            if (!$qry_json) {
                $this->db->trans_rollback();
                $this->sys_error_db("select json tf error");
                exit;
            }
            $row_json = $qry_json->row_array();

            $descActivity = "Hapus surat jalan {$row_json['SuratJalanNumber']}";

            $sql_json_detail = "SELECT suratjalan_detail.* 
                FROM suratjalan_detail
                WHERE SuratJalanDetailSuratJalanID = ?";
            $qry_json_detail = $this->db->query($sql_json_detail, [$para['SJalanID']]);
            if ($qry_json_detail) {
                $row_json["details"] = $qry_json_detail->result_array();
            } else {
                $this->sys_error_db("select detail tf error", $this->db);
                exit;
            }

            $data_json = $row_json;

            $this->insertUserActivty($para['SJalanID'], 'DELETE', $this->sys_user["M_UserID"], $descActivity, json_encode($data_json));

            $this->db->trans_commit();
            $this->sys_ok("success batalkan surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $para = $this->sys_input;
            $sjID = $para['SuratJalanID'];
            $page = $para['page'];

            $sqlSJ = "SELECT 
                    SuratJalanID,
                    SuratJalanNumber,
                    SuratJalanDate,
                    SuratJalanNote,
                    SuratJalanStatus,
                    ExpeditionName,
                    ExpeditionIsInternal,
                    COALESCE(ExpeditionID, 0) as ExpeditionID,
                    ExpeditionName,
                    COALESCE(ExpeditionStaffID, 0) as ExpeditionStaffID,
                    ExpeditionStaffName,
                    ExpeditionStaffMobile
                FROM suratjalan
                LEFT JOIN expedition ON ExpeditionID = SuratJalanEkspedisiID
                    AND ExpeditionIsActive = 'Y'
                LEFT JOIN expeditionstaff ON ExpeditionStaffID = SuratJalanEkspedisiStaffID
                    AND ExpeditionStaffIsActive = 'Y'
                WHERE SuratJalanIsActive = 'Y'
                    AND SuratJalanID = ?";
            $qrySJ = $this->db->query($sqlSJ, [$sjID]);
            if (!$qrySJ) {
                $this->sys_error_db("error get surat jalan");
                exit;
            }
            $suratj = $qrySJ->result_array()[0];

            $sjdtot = "SELECT COUNT(*) as total
                FROM suratjalan_detail
                JOIN m_item ON M_ItemID = SuratJalanDetailM_ItemID
                    AND M_ItemIsActive = 'Y'
                LEFT JOIN itemunit ON ItemUnitID = SuratJalanDetailItemUnitID
                    AND ItemUnitIsActive = 'Y'
                WHERE SuratJalanDetailIsActive = 'Y'
                    AND SuratJalanDetailSuratJalanID = ?";
            $qrytot = $this->db->query($sjdtot, [$sjID]);
            if (!$qrytot) {
                $this->sys_error_db("error get detail surat jaalan");
                exit;
            }
            $detailtotal = $qrytot->result_array()[0]['total'];

            $pg = 0;
            $limit = 5;
            if (!$page > 0) {
                $pg = ($page - 1) * $limit;
            }

            $sqlSJD = "SELECT 
                    SuratJalanDetailID,
                    SuratJalanDetailT_GoodsTransferDetailID,
                    SuratJalanDetailM_ItemID,
                    SuratJalanDetailQty,
                    SuratJalanDetailItemUnitID,
                    M_ItemCode,
                    M_ItemDesc,
                    ItemUnitCode,
                    ItemUnitName,
                    PurchaseRequestFlagS_RegionalID,
                    M_BranchID
                FROM suratjalan_detail
                JOIN purchase_request_flag ON SuratJalanDetailPurchaseRequestFlagID = PurchaseRequestFlagID
                    AND PurchaseRequestFlagIsActive = 'Y'
                JOIN m_branch ON M_BranchCode = PurchaseRequestFlagM_BranchCode
                    AND M_BranchIsActive = 'Y'
                JOIN m_item ON M_ItemID = SuratJalanDetailM_ItemID
                    AND M_ItemIsActive = 'Y'
                LEFT JOIN itemunit ON ItemUnitID = SuratJalanDetailItemUnitID
                    AND ItemUnitIsActive = 'Y'
                WHERE SuratJalanDetailIsActive = 'Y'
                    AND SuratJalanDetailSuratJalanID = ?
                LIMIT ? OFFSET ?";
            $qrySJD = $this->db->query($sqlSJD, [$sjID, $limit, $pg]);
            if (!$qrySJD) {
                $this->sys_error_db("error get detail surat jaalan");
                exit;
            }
            $suratj['detail'] = $qrySJD->result_array();
            $suratj['detailtotal'] = $detailtotal;

            $result = array(
                "records" => $suratj,
            );

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

    public function ListingSuratJalan()
    {
        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' 
                WHERE SuratJalanIsActive = 'Y' 
                    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
            ]);
            if (!$qryto) {
                $this->sys_error_db("error get listing data surat jalan");
                exit;
            }
            $total = $qryto->result_array()[0]['total'];

            $sqlSJ = "SELECT 
                    SuratJalanID,
                    SuratJalanNumber,
                    SuratJalanDate,
                    M_BranchCode,
                    M_BranchName,
                    SuratJalanEkspedisiID,
                    SuratJalanEkspedisiStaffID,
                    ExpeditionStaffName,
                    SuratJalanStatus,
                    SuratJalanT_GoodsTransferID
                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'
                WHERE SuratJalanIsActive = 'Y'
                    AND SuratJalanDate >= DATE(?) 
                    AND SuratJalanDate <= DATE(?) 
                    AND (? = 'ALL' OR T_GoodsTransferToM_BranchCode = ? )
                    AND (? = 'ALL' OR SuratJalanStatus = ? )
                    AND SuratJalanNumber LIKE ?
                ORDER BY SuratJalanDate 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");
                exit;
            }
            $list = $qrySJ->result_array();

            $result = array(
                "records" => $list,
                "total" => $total
            );
            $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;
            $regID = $prm["S_RegionalID"];

            $sql = "SELECT M_BranchID, M_BranchCode, M_BranchName
                    FROM m_branch
                    WHERE M_BranchIsActive = 'Y'
                    AND M_BranchS_RegionalID = ?";
            $qry = $this->db->query($sql, [$regID]);
            if (!$qry) {
                $this->sys_error_db("Failed to get Branches from RegionalID: {$regID}", $this->db);
                exit;
            }
            $rst = $qry->result_array();

            $this->sys_ok(["records" => $rst]);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $user = $this->sys_user;
            $para = $this->sys_input;
            $BranchCode = $para['M_BranchCode'];
            $SJDate = $para['SuratJalanDate'];
            $SJalanID = $para['SuratJalanID'];

            // check periode & get periodeID
            $sqlper = "SELECT 
                    periodeID
                FROM periode
                WHERE ? BETWEEN periodeStartDate AND periodeEndDate";
            $qryper = $this->db->query($sqlper, [$SJDate]);
            if (!$qryper) {
                $this->sys_error_db("error get periode");
                exit;
            }
            $periodeID = $qryper->result_array()[0]['periodeID'];
            if (!$periodeID) {
                $this->sys_error("Periode waktu untuk surat jalan tidak tersedia");
                exit;
            }
            $this->db->trans_begin();

            // generate jurnal number
            $sqlnum = "SELECT `fn_numbering`('J') as JNumber";
            $qrynum = $this->db->query($sqlnum, []);
            $JNumber = $qrynum->row()->JNumber;

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

            // insert into jurnal db
            $jurnalTitle = "Auto Jurnal Transfer Barang ke Cabang " . $BranchCode . " Tanggal " . $SJDate;
            $jurnalDesc = "Auto Jurnal Transfer Barang ke Cabang " . $BranchCode . " Tanggal " . $SJDate;

            $sqljur = "INSERT INTO jurnal (
                    jurnalM_BranchCompanyID,
                    JurnalS_RegionalID,
                    jurnalM_BranchCode,
                    jurnalperiodeID,
                    jurnalNo,
                    jurnalTitle,
                    jurnalDescription,
                    jurnalDate,
                    jurnalJurnalTypeID
                ) VALUES (?,?,?,?,?,?,?,?,?)";
            $qryjur = $this->db->query($sqljur, [
                $user['M_BranchCompanyID'],
                $user['S_RegionalID'],
                '',
                $periodeID,
                $JNumber,
                $jurnalTitle,
                $jurnalDesc,
                $SJDate,
                $Jtype
            ]);
            if (!$qryjur) {
                $this->db->trans_rollback();
                $this->sys_error_db("error insert data to table jurnal");
                exit;
            }
            $JurnalID = $this->db->insert_id();

            // insert jurnal_tx db
            $sqlitm = "SELECT DISTINCT
                    SuratJalanDetailID,
                    SuratJalanDetailM_ItemID as itemID,
                    SuratJalanDetailQty,
                    StockWarehouseID,
                    M_ItemDesc,
                    StockItemPrice as price,
                    MapNatSub_PersediaanCoaID as coaID,
                    MapNatSub_PersediaanCoaDescription as descc
                FROM suratjalan_detail
                JOIN stock ON StockItemID  = SuratJalanDetailM_ItemID 
                    AND SuratJalanDetailIsActive = 'Y'
                JOIN warehouse ON WarehouseID = StockWarehouseID
                    AND WarehouseIsActive = 'Y' 
                    AND WarehouseIsTransit = 'N'
                JOIN m_item ON M_ItemID = SuratJalanDetailM_ItemID
                JOIN map_nat_subgroup ON M_ItemNat_SubGroupID = MapNatSub_NatSubGroupID
                    AND MapNatSub_IsActive = 'Y'
                    AND M_ItemIsActive = 'Y'
                WHERE SuratJalanDetailIsActive = 'Y'
                    AND SuratJalanDetailSuratJalanID = ?
                    AND WarehouseS_RegionalID = ?";
            $qryitm = $this->db->query($sqlitm, [$SJalanID, $user['S_RegionalID']]);
            if (!$qryitm) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] errog get item data transfer");
                exit;
            }
            $item = $qryitm->result_array();

            $total = 0;
            foreach ($item as $key => $val) {
                $harga = intval($val['SuratJalanDetailQty']) * intval($val['price']);
                $total = $total + $harga;
            }

            $sqljtx = "INSERT INTO jurnal_tx (
                jurnalTxJurnalID,
                jurnalTxCoaID,
                jurnalTxDescription,
                jurnalTxDebit,
                jurnalTxCredit
            ) VALUES (?,?,?,?,?)";
            $qrydbt = $this->db->query($sqljtx, [
                $JurnalID,
                382,
                "STOCK DALAM PERJALANAN",
                $total,
                0
            ]);
            if (!$qrydbt) {
                $this->db->trans_rollback();
                $this->sys_error_db("error insert data debit jurnal tx");
                exit;
            }
            $jurnalTxID = $this->db->insert_id();

            foreach ($item as $key => $value) {
                $jtxDesc = $value['descc'] . " - " . $value['M_ItemDesc'];
                $harga = intval($value['SuratJalanDetailQty']) * intval($value['price']);

                $qryjtx = $this->db->query($sqljtx, [
                    $JurnalID,
                    $value['coaID'],
                    $jtxDesc,
                    0,
                    $harga
                ]);
                if (!$qryjtx) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("error insert data credit jurnal tx");
                    exit;
                }
            }

            // insert jutnal addon
            $sqladdon = "INSERT INTO jurnal_addon (
                    jurnalAddOnJurnalID,
                    jurnalAddOnJurnalTxID,
                    jurnalAddOnCode,
                    jurnalAddOnValue,
                    jurnalAddOnCreated
                ) VALUES (?,?,?,?,NOW())";
            $qryaddon = $this->db->query($sqladdon, [
                $JurnalID,
                $jurnalTxID,
                'SENDGOODRDST',
                $BranchCode
            ]);
            if (!$qryaddon) {
                $this->db->trans_rollback();
                $this->sys_error_db("error insert data to table jurnal addon");
                exit;
            }

            $this->db->trans_commit();
            $this->sys_ok("success generate jurnal: {$JNumber}");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $para = $this->sys_input;
            $date = $para['date'];

            $sql = "SELECT 
                    periodeID
                FROM periode
                WHERE ? BETWEEN periodeStartDate AND periodeEndDate";
            $qry = $this->db->query($sql, [$date]);
            if (!$qry) {
                $this->sys_error_db("error get periode");
                exit;
            }
            $periodeID = $qry->result_array()[0]['periodeID'];
            if (!$periodeID) {
                $this->sys_error("Periode waktu jurnal belum tersedia");
                exit;
            }

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


    // NOT USED (FOR DEVELOPMENT ONLY) //s

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

            $user = $this->sys_user;
            $para = $this->sys_input;
            $itemID = $para['itemID'];
            $qtyTF = $para['qtyTF'];

            $whstock = "SELECT 
                    WarehouseID, 
                    WarehouseName, 
                    StockID, 
                    StockQty, 
                    WarehouseIsTransit
                FROM stock
                JOIN warehouse ON StockWarehouseID = WarehouseID
                    AND WarehouseIsActive = 'Y'
                WHERE StockItemID = ? 
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID = ?
                    AND WarehouseIsActive = 'Y'";
            $whstqry = $this->db->query($whstock, [
                $itemID,
                $user['S_RegionalID'],
                $user['M_BranchID']
            ]);
            if (!$whstqry) {
                $this->db->sys_error_db("[Error] get warehouse id dan stock qty");
                exit;
            }
            $listWH = $whstqry->result_array();

            $WHtransit = array_filter($listWH, function ($list) {
                return $list->WarehouseIsTransit === 'Y';
            });
            if (empty($WHtransit)) {
                $this->db->sys_error_db("[Error] warehouse transit not found");
                exit;
            }

            $WHstock = array_filter($listWH, function ($list) use ($qtyTF) {
                return $list->WarehouseIsTransit === 'N' && $list->StockQty >= intval($qtyTF);
            });
            if (empty($WHstock)) {
                $this->db->sys_error_db("[Error] stock item warehouse not found or sufficient");
                exit;
            }

            $WHstock[0]['StockQty'] = intval($WHstock[0]['StockQty']) - intval($qtyTF);
            $WHtransit[0]['StockQty'] = intval($WHtransit[0]['StockQty']) + intval($qtyTF);
            $newarr = [$WHstock[0], $WHtransit[0]];

            $this->db->trans_begin();
            foreach ($newarr as $key => $value) {
                $updsto = "UPDATE stock 
                    SET StockQty = ?
                    WHERE StockItemID = ? 
                        AND StockWarehouseID = ?";
                $qrysto = $this->db->query($updsto, [
                    $value['StockQty'],
                    $value['StockID'],
                    $value['WarehouseID']
                ]);
                if (!$qrysto) {
                    $this->db->trans_rollback();
                    $this->db->sys_error_db("[Error] update stock qty to wh transit");
                    exit;
                }
            }
            $this->db->trans_commit();

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

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

            $getreg = "SELECT * FROM s_regional WHERE S_RegionalIsActive = 'Y'";
            $qryreg = $this->db->query($getreg, []);
            if (!$qryreg) {
                $this->db->sys_error_db("[Error] get listing regional");
                exit;
            }
            $regional = $qryreg->result_array();

            $this->db->trans_begin();
            $whid = 1000;
            foreach ($regional as $key => $value) {
                $code = "WH0" . $whid;
                $name = "Gudang Transit Regional " . $value['S_RegionalName'];
                $sqlins = "INSERT INTO warehouse (
                    WarehouseID,
                    WarehouseCode,
                    WarehouseName,
                    WarehouseType,
                    WarehouseS_RegionalID,
                    WarehouseM_BranchID,
                    WarehouseIsTransit,
                    WarehouseUserID
                ) vALUES (?,?,?,?,?,?,?,?)";
                $qryins = $this->db->query($sqlins, [
                    $whid,
                    $code,
                    $name,
                    'R',
                    $value['S_RegionalID'],
                    0,
                    'Y',
                    0
                ]);
                if (!$qryins) {
                    $this->db->trans_rollback();
                    $this->db->sys_error_db("[Error] create a warehouse transit");
                    exit;
                }

                $whid = $whid + 1;
            }
            $this->db->trans_commit();

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

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

            $getcab = "SELECT 
                    M_BranchID, 
                    M_BranchName, 
                    M_BranchS_RegionalID 
                FROM m_branch 
                WHERE M_BranchIsActive = 'Y'";
            $qrycab = $this->db->query($getcab, []);
            if (!$qrycab) {
                $this->db->sys_error_db("[Error] get listing cabang");
                exit;
            }
            $cabang = $qrycab->result_array();

            $this->db->trans_begin();
            $whid = 1021;
            foreach ($cabang as $key => $value) {
                $code = "WH0" . $whid;
                $name = "Gudang Transit Cabang " . $value['M_BranchName'];
                $sqlins = "INSERT INTO warehouse (
                    WarehouseID,
                    WarehouseCode,
                    WarehouseName,
                    WarehouseType,
                    WarehouseS_RegionalID,
                    WarehouseM_BranchID,
                    WarehouseIsTransit,
                    WarehouseUserID
                ) vALUES (?,?,?,?,?,?,?,?)";
                $qryins = $this->db->query($sqlins, [
                    $whid,
                    $code,
                    $name,
                    'B',
                    $value['M_BranchS_RegionalID'],
                    $value['M_BranchID'],
                    'Y',
                    0
                ]);
                if (!$qryins) {
                    $this->db->trans_rollback();
                    $this->db->sys_error_db("[Error] create a warehouse transit");
                    exit;
                }

                $whid = $whid + 1;
            }
            $this->db->trans_commit();

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

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

            $userID = $this->sys_user["M_UserID"];
            $para = $this->sys_input;

            $mustFields = ["SJDate", "TransferID", "TransferNum", "EkspedID", "EkspedStaffID", "EkspedStaffHP"];
            $missFields = [];
            foreach ($mustFields as $field) {
                if (empty($para[$field])) {
                    $missFields[] = $field;
                }
            }
            if (!empty($missFields)) {
                $this->sys_error("Missing fields: " . implode(", ", $missFields));
                exit;
            }

            $this->db->trans_begin();
            $sqlnum = "SELECT `fn_numbering`('SJ') as SJNumber";
            $qrynum = $this->db->query($sqlnum, []);
            $SJNumber = $qrynum->row()->SJNumber;

            $sqlSJ = "INSERT INTO suratjalan (
                        SuratJalanNumber,
                        SuratJalanDate,
                        SuratJalanNote,
                        SuratJalanT_GoodsTransferID,
                        SuratJalanT_GoodsTransferNum,
                        SuratJalanEkspedisiID,
                        SuratJalanEkspedisiStaffID,
                        SuratJalanEkspedisiStaffContact,
                        SuratJalanUserID
                    ) VALUES (?,?,?,?,?,?,?,?,?)";
            $qrySJ = $this->db->query($sqlSJ, [
                $SJNumber,
                $para['SJDate'],
                $para['SJNote'],
                $para['TransferID'],
                $para['TransferNum'],
                $para['EkspedID'],
                $para['EkspedStaffID'],
                $para['EkspedStaffHP'],
                $userID
            ]);
            if (!$qrySJ) {
                $this->db->trans_rollback();
                $this->sys_error_db("failed to insert data table surat jalan");
                exit;
            }

            $SJalanID = $this->db->insert_id();
            foreach ($para['SJDetail'] as $key => $detail) {
                $sqlSJD = "INSERT INTO suratjalan_detail (
                            SuratJalanDetailSuratJalanID,
                            SuratJalanDetailM_ItemID,
                            SuratJalanDetailQty,
                            SuratJalanDetailItemUnitID,
                            SuratJalanDetailUserID
                        ) VALUES (?,?,?,?,?)";
                $qrySJD = $this->db->query($sqlSJD, [
                    $SJalanID,
                    $detail['itemID'],
                    $detail['itemQty'],
                    $detail['itemUnitID'],
                    $userID
                ]);
                if (!$qrySJD) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("failed to insert data table surat jalan detail");
                    exit;
                }
            }

            $sql_json = "SELECT suratjalan.*, '' as details
            FROM suratjalan
            WHERE SuratJalanID = ?";
            $qry_json = $this->db->query($sql_json, [$para['SJalanID']]);
            if (!$qry_json) {
                $this->db->trans_rollback();
                $this->sys_error_db("select json tf error");
                exit;
            }
            $row_json = $qry_json->row_array();

            $descActivity = "Surat jalan dengan number {$SJNumber} telah dibuat";

            $sql_json_detail = "SELECT suratjalan_detail.* 
                FROM suratjalan_detail
                WHERE SuratJalanDetailSuratJalanID = ?";
            $qry_json_detail = $this->db->query($sql_json_detail, [$para['SJalanID']]);
            if ($qry_json_detail) {
                $row_json["details"] = $qry_json_detail->result_array();
            } else {
                $this->sys_error_db("select detail tf error", $this->db);
                exit;
            }

            $data_json = $row_json;

            $this->insertUserActivty($para['SJalanID'], 'NEW', $this->sys_user["M_UserID"], $descActivity, json_encode($data_json));

            $this->db->trans_commit();
            $this->sys_ok("success create surat jalan");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function insertUserActivty($id, $type, $userID, $desc = '', $data = '')
    {
        $sql = "INSERT INTO user_activity (
                    UserActivityCode,
                    UserActivityStatus,
                    UserActivityDescription,
                    UserActivityRefID,
                    UserActivityData,
                    UserActivityUserID,
                    UserActivityCreated
                ) VALUES (
                    ?, ?, ?, ?, ?, ?, NOW()
                )";

        // Eksekusi query dengan parameter yang diberikan
        $exec = $this->db->query($sql, [
            'SJ',
            $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;
        }
    }
}
