<?php

class JournalPenyesuaian extends MY_Controller {
    var $db;
    public function index() {
        echo "Jurnal Penyesuaian";
    }

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

    # QUERY #

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

            $sql = "SELECT 
                periodeID,
                periodeName,
                DATE_FORMAT(periodeStartDate, '%d %M %Y') AS periodeStartDate,
                DATE_FORMAT(periodeEndDate, '%d %M %Y') AS periodeEndDate
            FROM periode
            WHERE periodeIsActive = 'Y'
                AND periodeIsClosed = 'N'
            ORDER BY periodeID DESC";
            $que = $this->db->query($sql, []);
            if (!$que) {
                $this->sys_error_db("[Error] get daftar periode");
                exit;
            }

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

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

            $param = $this->sys_input;
            $sql = "SELECT
                JurnalTypeID,
                JurnalTypeCode,
                JurnalTypeName 
            FROM jurnal_type 
            WHERE JurnalTypeIsActive = 'Y'";
            $que = $this->db->query($sql, []);
            if (!$que) {
                $this->sys_error_db("[Error] get daftar tipe jurnal");
                exit;
            }

            $data = $que->result_array();
            $all = [
                'JurnalTypeID' => 0,
                'JurnalTypeCode' => "X",
                'JurnalTypeName' => "SEMUA"
            ];
            array_unshift($data, $all);

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

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

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

            $isFromBranch = " ";
            if ($user['M_BranchID'] != "0") {
                $isFromBranch .= " AND jurnalM_BranchCode = '{$user['M_BranchCode']}'";
            }

            $keyword = "%";
            if ($param['search'] != '') {
                $keyword .= $param['search'] . "%";
            }

            $row_limit = 5;
            $curr_page = (int)($param['currpage'] ?? 1);
            $row_offset = max(0, ($curr_page - 1) * $row_limit);

            $sql_base = "SELECT
                jurnalID,
                jurnalperiodeID,
                jurnalNo,
                jurnalTitle,
                jurnalDescription,
                jurnalDate,
                JurnalTypeID,
                JurnalTypeCode,
                JurnalTypeName,
                S_RegionalName,
                M_BranchName,
                M_BranchCompanyName
            FROM jurnal
            JOIN jurnal_type ON JurnalTypeID = jurnalJurnalTypeID
                AND JurnalTypeIsActive = 'Y'
            JOIN m_branch_company ON M_BranchCompanyID = jurnalM_BranchCompanyID
            JOIN s_regional ON S_RegionalID = JurnalS_RegionalID
            LEFT JOIN m_branch ON M_BranchCode = jurnalM_BranchCode
            WHERE jurnalperiodeID = ?
                AND JurnalS_RegionalID = ?
                AND jurnalIsClosed = 'Y'
                AND (jurnalJurnalTypeID = ? OR 0 = ?)
                AND jurnalDate BETWEEN DATE(?) AND DATE(?)
                AND jurnalNo LIKE ?
                AND jurnalIsPosted = 'Y'
                AND jurnalDalamPenyesuaian = 'N'
                AND jurnalIsActive = 'Y'" . $isFromBranch;
            
            $sql_data = $sql_base . " LIMIT ? OFFSET ? ";
            $que_data = $this->db->query($sql_data, [
                $param['periodeID'], $user['S_RegionalID'], 
                $param['typeJournalID'], $param['typeJournalID'], 
                $param['startdate'], $param['enddate'], $keyword,
                $row_limit, $row_offset
            ]);
            if (!$que_data) {
                $this->sys_error_db("[Error] get listing jurnal closed");
                exit;
            }

            // get total jurnal is closed
            $sql_total = "SELECT COUNT(*) AS total FROM ($sql_base) as x";
            $que_total = $this->db->query($sql_total, [
                $param['periodeID'], $user['S_RegionalID'], 
                $param['typeJournalID'], $param['typeJournalID'], 
                $param['startdate'], $param['enddate'], $keyword,
            ]);
            if (!$que_total) {
                $this->sys_error_db("[Error] get total all jurnal closed");
                exit;
            }

            $data = [
                "records" => $que_data->result_array(),
                "total" => $que_total->row_array()['total']
            ];

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

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

            $sql = "SELECT
                jurnalTxID,
                jurnalTxJurnalID,
                jurnalTxCoaID,
                jurnalTxDescription,
                jurnalTxDebit,
                jurnalTxCredit,
                coaAccountNo,
                coaDescription,
                GROUP_CONCAT(jurnalAddOnCode SEPARATOR ', ') AS jurnalAddOnCode,
                GROUP_CONCAT(jurnalAddOnValue SEPARATOR ' | ') AS jurnalAddOnValue
            FROM jurnal_tx
            JOIN coa ON jurnalTxCoaID = coaID
                AND coaIsActive = 'Y'
            LEFT JOIN jurnal_addon ON jurnalTxID = jurnalAddOnJurnalTxID 
                AND jurnalAddOnIsActive = 'Y'
            WHERE jurnalTxJurnalID = ?
                AND jurnalTxIsActive = 'Y'
            GROUP BY jurnalTxID
            ORDER BY 
            CASE 
                WHEN jurnalTxDebit > 0 THEN 0
                ELSE 1
            END, jurnalTxID ASC";
            $que = $this->db->query($sql, [$param['jurnalID']]);
            if (!$que) {
                $this->sys_error_db("[Error] get detail data jurnal");
                exit;
            }

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

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

            $keyword = "%";
            if ($param['keyword'] != '') {
                $keyword = $param['keyword'] . "%";
            }

            $sql = "SELECT
                coaID,
                coaAccountNo,
                coaDescription
            FROM coa
            WHERE coaIsActive = 'Y'
                AND coaIsInput = 'Y'
                AND coaDescription LIKE ?";
            $que = $this->db->query($sql, [$keyword]);
            if (!$que) {
                $this->sys_error_db("[Error] get listint account");
                exit;
            }

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

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

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

            $isFromBranch = " ";
            if ($user['M_BranchID'] != "0") {
                $isFromBranch .= " AND jurnalM_BranchCode = '{$user['M_BranchCode']}' ";
            }

            $keyword = "%";
            if ($param['search'] != '') {
                $keyword .= $param['search'] . "%";
            }

            $row_limit = 5;
            $curr_page = (int)($param['currpage'] ?? 1);
            $row_offset = max(0, ($curr_page - 1) * $row_limit);

            $sql_base = "SELECT
                jurnalID,
                jurnalperiodeID,
                jurnalNo,
                jurnalTitle,
                jurnalDescription,
                jurnalDate,
                JurnalTypeID,
                JurnalTypeCode,
                JurnalTypeName,
                jurnalPenyesuaianStatus,
                S_RegionalName,
                M_BranchName,
                M_BranchCompanyName
            FROM jurnal
            JOIN jurnal_type ON JurnalTypeID = jurnalJurnalTypeID
                AND JurnalTypeIsActive = 'Y'
            JOIN m_branch_company ON M_BranchCompanyID = jurnalM_BranchCompanyID
            JOIN s_regional ON S_RegionalID = JurnalS_RegionalID
            LEFT JOIN m_branch ON M_BranchCode = jurnalM_BranchCode
            WHERE jurnalperiodeID = ?
                AND JurnalS_RegionalID = ?
                AND (jurnalJurnalTypeID = ? OR 0 = ?)
                AND jurnalDate BETWEEN DATE(?) AND DATE(?)
                AND jurnalNo LIKE ?
                AND jurnalIsPenyesuaian = 'Y'
                AND jurnalIsActive = 'Y'" . $isFromBranch;
            
            $sql_data = $sql_base . " LIMIT ? OFFSET ? ";
            $que_data = $this->db->query($sql_data, [
                $param['periodeID'], $user['S_RegionalID'], 
                $param['typeJournalID'], $param['typeJournalID'], 
                $param['startdate'], $param['enddate'], $keyword,
                $row_limit, $row_offset
            ]);
            if (!$que_data) {
                $this->sys_error_db("[Error] get listing jurnal closed");
                exit;
            }

            // get total jurnal is closed
            $sql_total = "SELECT COUNT(*) AS total FROM ($sql_base) as x";
            $que_total = $this->db->query($sql_total, [
                $param['periodeID'], $user['S_RegionalID'], 
                $param['typeJournalID'], $param['typeJournalID'], 
                $param['startdate'], $param['enddate'], $keyword,
            ]);
            if (!$que_total) {
                $this->sys_error_db("[Error] get total all jurnal closed");
                exit;
            }

            $data = [
                "records" => $que_data->result_array(),
                "total" => $que_total->row_array()['total']
            ];

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

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

            $param = $this->sys_input;

            $sql = "SELECT
                jurnalTxID,
                jurnalTxJurnalID,
                jurnalTxCoaID,
                jurnalTxDescription,
                jurnalTxDebit,
                jurnalTxCredit,
                coaAccountNo,
                coaDescription,
                GROUP_CONCAT(jurnalAddOnCode SEPARATOR ', ') AS jurnalAddOnCode,
                GROUP_CONCAT(jurnalAddOnValue SEPARATOR ' | ') AS jurnalAddOnValue
            FROM jurnal_tx
            JOIN coa ON jurnalTxCoaID = coaID
                AND coaIsActive = 'Y'
            LEFT JOIN jurnal_addon ON jurnalTxID = jurnalAddOnJurnalTxID 
                AND jurnalAddOnIsActive = 'Y'
            WHERE jurnalTxJurnalID = ?
                AND jurnalTxIsActive = 'Y'
            GROUP BY jurnalTxID
            ORDER BY jurnalTxID ASC";
            $que = $this->db->query($sql, [$param['jurnalID']]);
            if (!$que) {
                $this->sys_error_db("[Error] get detail data jurnal penyesuaian");
                exit;
            }

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


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

            $this->db->trans_begin();
            $param = $this->sys_input;
            $user = $this->sys_user;

            # Update old jurnal #
            $sql_oldjurnal = "UPDATE jurnal 
                SET jurnalDalamPenyesuaian = 'Y'
                WHERE jurnalID = ?";
            $que_oldjurnal = $this->db->query($sql_oldjurnal, [$param['oldJurnalID']]);
            if (!$que_oldjurnal) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status penyesuaian");
                exit;
            }
            
            # Generate jurnal number #
            $sql_jurnalno = "SELECT `fn_numbering`('J') AS numbering";
            $que_jurnalno = $this->db->query($sql_jurnalno, []);
            if (!$que_jurnalno) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] generate jurnal number");
                exit;
            }
            $JurnalNo = $que_jurnalno->row_array()['numbering'];

            # GET current periode id #
            $sql_periode = "SELECT periodeID FROM periode WHERE periodeIsActive = 'Y'
                AND periodeIsClosed = 'N'
                AND DATE(NOW()) BETWEEN DATE(periodeStartDate) AND DATE(periodeEndDate)";
            $que_periode = $this->db->query($sql_periode, []);
            if (!$que_periode) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get periode id");
                exit;
            }
            if (!$que_periode->num_rows() === 0) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] waktu periode tidak ditemukan");
                exit;
            }
            $JurnalPeriodeID = $que_periode->row_array()['periodeID'];

            # GET jurnal type #
            $JurnalTypeCode = $param['jurnalTypeCode'];
            if ($JurnalTypeCode != '' && substr($JurnalTypeCode, 0, 4) === 'AUTO') {
                $JurnalTypeCode = substr($JurnalTypeCode, 4);
            }

            $sql_jurnaltype = "SELECT JurnalTypeID FROM jurnal_type WHERE JurnalTypeCode LIKE ? 
                AND JurnalTypeIsActive = 'Y' AND JurnalTypeIsAuto = 'N'";
            $que_jurnaltype = $this->db->query($sql_jurnaltype, ['%' . $JurnalTypeCode]);
            if (!$que_jurnaltype) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get jurnal type id/code");
                exit;
            }
            $JurnalTypeID = $que_jurnaltype->row_array()['JurnalTypeID'];

            # INSERT jurnal header #
            $title = "Jurnal Penyesuaian dari Jurnal Nomor " . $param['jurnalNo'];
            $descp = "Penyesuaian Jurnal Nomor {$param['jurnalNo']} tanggal {$param['jurnalDate']}";

            $sql_header_jurnal = "INSERT INTO jurnal (
                jurnalM_BranchCompanyID,
                JurnalS_RegionalID,
                jurnalM_BranchCode,
                jurnalperiodeID,
                jurnalNo,
                jurnalTitle,
                jurnalDescription,
                jurnalDate,
                jurnalJurnalTypeID,
                jurnalIsPenyesuaian,
                jurnalPenyesuaianStatus,
                jurnalM_UserID
            ) VALUES (?,?,?,?,?,?,?,NOW(),?,'Y','draft', ?)";
            $que_header_jurnal = $this->db->query($sql_header_jurnal, [
                $user['M_BranchCompanyID'], $user['S_RegionalID'], $user['M_BranchCode'],
                $JurnalPeriodeID, $JurnalNo, $title, $descp, $JurnalTypeID, $user['M_UserID']
            ]);
            if (!$que_header_jurnal) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] insert jurnal header");
                exit;
            }
            $JurnalID = $this->db->insert_id();
            
            foreach ($param['detailtrx'] as $key => $obj) {
                $sql_transac_jurnal = "INSERT INTO jurnal_tx (
                    jurnalTxJurnalID,
                    jurnalTxCoaID,
                    jurnalTxDescription,
                    jurnalTxDebit,
                    jurnalTxCredit,
                    jurnalTxM_UserID
                ) VALUES (?,?,?,?,?,?)";
                $que_transac_jurnal = $this->db->query($sql_transac_jurnal, [
                    $JurnalID, $obj['coaID'], $obj['coaDescription'], 
                    $obj['debit'], $obj['kredit'], $user['M_UserID']
                ]);
                if (!$que_transac_jurnal) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert jurnal tx");
                    exit;
                }
                $JurnalTxID = $this->db->insert_id();

                $sql_addon_jurnal = "INSERT INTO jurnal_addon (
                    jurnalAddOnJurnalID,
                    jurnalAddOnJurnalTxID,
                    jurnalAddOnCode,
                    jurnalAddOnValue,
                    jurnalAddOnCreated,
                    jurnalAddOnCreatedUserID
                ) VALUES (?,?,?,?,NOW(),?)";
                $que_addon_jurnal = $this->db->query($sql_addon_jurnal, [
                    $JurnalID, $JurnalTxID, $obj['infocode'], $obj['info'], $user['M_UserID']
                ]);
                if (!$que_addon_jurnal) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert jurnal addon");
                    exit;
                }
            }

            $this->db->trans_commit();
            $this->sys_ok("[Success] insert Jurnal Penyesuaian");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();
            $param = $this->sys_input;

            $sql_update = "UPDATE jurnal SET 
                jurnalPenyesuaianStatus = ?,
                jurnalLastUpdated = NOW()
            WHERE jurnalID = ?";
            $que_update = $this->db->query($sql_update, [
                $param['status'], $param['jurnalID']
            ]);
            if (!$que_update) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status {$param['status']} jurnal koreksi");
                exit;
            }

            $this->db->trans_commit();
            $this->sys_ok("[success] jurnal koreksi {$param['status']}");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $user = $this->sys_user;
            $sql = "SELECT
                M_ApproveLevelID,
                M_ApproveLevelName,
                DivisionID,
                DivisionName,
                DivisionKodeSurat
            FROM m_user
            LEFT JOIN m_approve_level ON M_ApproveLevelID = M_UserM_ApproveLevelID
                AND M_ApproveLevelIsActive = 'Y'
            JOIN m_userdivision ON M_UserDivisionM_UserID = M_UserID
                AND M_UserDivisionIsActive = 'Y'
            JOIN division ON DivisionID = M_UserDivisionDivisionID
                AND DivisionIsActive = 'Y'
            WHERE M_UserID = ?";
            $que = $this->db->query($sql, [$user['M_UserID']]);
            if (!$que) {
                $this->sys_error_db("[Error] get user approve level");
                exit;
            }

            $result = $que->row_array();
            if (!$result) {
                $result = array(
                    "M_ApproveLevelID" => 0,
                    "M_ApproveLevelName" => ''
                );
            }

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