<?php

class Fakturv3 extends MY_Controller
{
    var $db;
    public function index()
    {
        echo "Faktur";
    }

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

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

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

            $sql = "SELECT 
                    M_StaffID,
                    M_StaffName,
                    M_StaffCode
                FROM m_staff
                WHERE M_StaffM_BranchID = ?
                    AND M_StaffName LIKE ?
                    AND M_StaffIsActive = 'Y'
            ";
            $qry = $this->db->query($sql, [$branchid, $name]);
            if (!$qry) {
                $this->sys_error_db("[Error] get data staff");
                exit;
            }

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

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

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

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


            $sql = "SELECT
                    SupplierID,
                    SupplierCode,
                    SupplierName,
                    IFNULL(SupplierTermOfPayment, 0) AS SupplierTermOfPayment
                FROM supplier
                WHERE SupplierName LIKE ? 
                    AND SupplierIsActive = 'Y'";
            $qry = $this->db->query($sql, [$name]);
            if (!$qry) {
                $this->sys_error_db("[Error] get data supplier");
                exit;
            }

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

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

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

            $para = $this->sys_input;
            $supID = $para['supID'];
            $regionalID = $this->sys_user["S_RegionalID"];
            $branchID = $this->sys_user["M_BranchID"] ?? 0; // 0 untuk user regional

            $sql = "SELECT
                    PurchaseOrderID,
                    PurchaseOrderDate,
                    PurchaseOrderNumber,
                    PurchaseOrderDetailID
                FROM purchase_order
                JOIN purchase_order_detail 
                    ON PurchaseOrderDetailPurchaseOrderID = PurchaseOrderID
                    AND PurchaseOrderDetailIsActive = 'Y'
                JOIN warehouse ON WarehouseID = PurchaseOrderDetailWarehouseID 
                    AND WarehouseIsActive = 'Y'
                JOIN receive_order_po_detail
                    ON ReceiveOrderPoDetailPurchaseOrderDetailID = PurchaseOrderDetailID
                WHERE PurchaseOrderIsActive = 'Y'
                    AND PurchaseOrderStatus = 'Approved'
                    AND PurchaseOrderSupplierID = ?
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID = ?
                AND NOT EXISTS (
                    SELECT 1
                    FROM supplier_invoice_detail
                    WHERE SupplierInvoiceDetailReceiveOrderPoDetailID = ReceiveOrderPoDetailID
                    AND SupplierInvoiceDetailIsActive = 'Y'
                    AND SupplierInvoiceDetailIsVerified = 'Y'
                )
                GROUP BY PurchaseOrderID
                ";
            $qry = $this->db->query($sql, [$supID, $regionalID, $branchID]);
            if (!$qry) {
                $this->sys_error_db("[Error] get list PO");
                exit;
            }

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

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

            $para = $this->sys_input;
            $supID = $para['supID'];
            $regionalID = $this->sys_user["S_RegionalID"];
            $branchID = $this->sys_user["M_BranchID"] ?? 0; // 0 untuk user regional

            $sql = "SELECT
                    PurchaseOrderID,
                    PurchaseOrderDate,
                    PurchaseOrderNumber,
                    PurchaseOrderDetailID
                FROM purchase_order
                JOIN purchase_order_detail 
                    ON PurchaseOrderDetailPurchaseOrderID = PurchaseOrderID
                    AND PurchaseOrderDetailIsActive = 'Y'
                JOIN warehouse ON WarehouseID = PurchaseOrderDetailWarehouseID 
                    AND WarehouseIsActive = 'Y'
                JOIN receive_order_po_detail
                    ON ReceiveOrderPoDetailPurchaseOrderDetailID = PurchaseOrderDetailID
                WHERE PurchaseOrderIsActive = 'Y'
                    AND PurchaseOrderStatus = 'Approved'
                    AND PurchaseOrderSupplierID = ?
                    AND WarehouseS_RegionalID = ?
                    AND WarehouseM_BranchID = ?
                AND NOT EXISTS (
                    SELECT 1
                    FROM supplier_invoice_detail
                    WHERE SupplierInvoiceDetailReceiveOrderPoDetailID = ReceiveOrderPoDetailID
                    AND SupplierInvoiceDetailIsActive = 'Y'
                    AND SupplierInvoiceDetailIsVerified = 'Y'
                )
                GROUP BY PurchaseOrderID
                ";
            $qry = $this->db->query($sql, [$supID, $regionalID, $branchID]);
            if (!$qry) {
                $this->sys_error_db("[Error] get list PO");
                exit;
            }

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

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

            $para = $this->sys_input;
            $numPO = $para['numPO'];
            $supID = $para['supID'];

            $sql = "SELECT
                    PurchaseOrderID,
                    PurchaseOrderDate,
                    PurchaseOrderPaymentTerm,
                    PurchaseOrderNumber,
                    PurchaseOrderRefNumber,
                    PurchaseOrderTaxPercentPph,
                    PurchaseOrderTaxPercentPpn,
                    PurchaseOrderGrandTotal,
                    PurchaseOrderShippingCost,
                    PurchaseOrderDiscountAmount, 
                    PurchaseOrderDiscountPercent,
                    IF (PurchaseOrderDiscountAmount > 0, 
                        'R', 
                        'P'
                    ) AS DiscountType
                FROM purchase_order
                WHERE PurchaseOrderIsActive = 'Y'
                    AND PurchaseOrderNumber = ?
                    AND PurchaseOrderSupplierID = ?";
            $qry = $this->db->query($sql, [$numPO, $supID]);
            if (!$qry) {
                $this->sys_error_db("[Error] get detail PO");
                exit;
            }

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

    public function LookupRO()
    {
        try {
            if (!$this->isLogin) {
                $this->sys_error();
                exit;
            }

            $para = $this->sys_input;
            $branchID = $this->sys_user['M_BranchID'] ?? 0;
            $poID = $para['poID'];
            $supID = $para['supplierID'];

            $sql = "SELECT DISTINCT
                        ReceiveOrderPoID,
                        ReceiveOrderPoNumber,
                        ReceiveOrderPoSupplierID
                    FROM receive_order_po_detail
                    JOIN receive_order_po ON ReceiveOrderPoDetailReceiveOrderPoID = ReceiveOrderPoID
                        AND ReceiveOrderPoIsActive = 'Y'
                    JOIN warehouse ON WarehouseID = ReceiveOrderPoWarehouseID
                        AND WarehouseM_BranchID = ?
                    WHERE ReceiveOrderPoDetailIsActive = 'Y'
                        AND ReceiveOrderPoDetailPurchaseOrderID = ?
                        AND ReceiveOrderPoSupplierID = ?";
            $qry = $this->db->query($sql, [$branchID, $poID, $supID]);
            if (!$qry) {
                $this->sys_error_db("[Error] get list RO");
                exit;
            }

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

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

            $para = $this->sys_input;
            $roID = $para['roID'];
            $poID = $para['poID'];

            $name = "%";
            if ($para['name'] != "") {
                $name = $para['name'] . "%";
            }

            $page = 0;
            $limit = 5;
            if ($para['currpage'] > 0) {
                $page = ($para['currpage'] - 1) * $limit;
            }

            $sql = "SELECT 
                    ReceiveOrderPoDetailPurchaseOrderID,
                    ReceiveOrderPoDetailPurchaseOrderSummaryID,
                    ReceiveOrderPoDetailReceiveOrderPoID,
                    ReceiveOrderPoDetailID,
                    M_ItemID,
                    M_ItemCode,
                    M_ItemDesc,
                    ReceiveOrderPoItemUnitID,
                    unitreceive.ItemUnitName as ReceiveOrderPoItemUnitName,
                    ReceiveOrderPoDetailQty,
                    ReceiveOrderPoDetailPrice,
                    IF (PurchaseOrderSummaryDiscountType = 'R', 
                        PurchaseOrderSummaryDiscountRupiah, 
                        PurchaseOrderSummaryDiscountPercent
                    ) as Discount,
                    PurchaseOrderSummaryDiscountType, 
                    ReceiveOrderPoDetailDiskonPoProrata 
                FROM receive_order_po_detail
                JOIN receive_order_po ON ReceiveOrderPoDetailReceiveOrderPoID = ReceiveOrderPoID
                    AND ReceiveOrderPoIsActive = 'Y'
                JOIN purchase_order_summary ON ReceiveOrderPoDetailPurchaseOrderSummaryID = PurchaseOrderSummaryID
                    AND PurchaseOrderSummaryIsActive = 'Y'
                JOIN m_item ON M_ItemID = ReceiveOrderPoItemID
                    AND M_ItemIsActive = 'Y'
                JOIN itemunit unitreceive
                    ON unitreceive.ItemUnitID = ReceiveOrderPoItemUnitID
                WHERE ReceiveOrderPoDetailIsActive = 'Y'
                    AND ReceiveOrderPoDetailPurchaseOrderID = ?
                    AND ReceiveOrderPoID = ?
                    AND M_ItemDesc LIKE ?
                AND NOT EXISTS (
                        SELECT 1 
                        FROM supplier_invoice_detail 
                        WHERE SupplierInvoiceDetailReceiveOrderPoDetailID = ReceiveOrderPoDetailID
                        AND SupplierInvoiceDetailIsActive = 'Y'
                    )
                LIMIT ? OFFSET ?";
            $qry = $this->db->query($sql, [$poID, $roID, $name, $limit, $page]);
            if (!$qry) {
                $this->sys_error_db("[Error] get data item RO");
                exit;
            }

            $total = "SELECT COUNT(*) as total
                        FROM receive_order_po_detail
                        JOIN receive_order_po ON ReceiveOrderPoDetailReceiveOrderPoID = ReceiveOrderPoID
                            AND ReceiveOrderPoIsActive = 'Y'
                        JOIN purchase_order_summary ON ReceiveOrderPoDetailPurchaseOrderSummaryID = PurchaseOrderSummaryID
                            AND PurchaseOrderSummaryIsActive = 'Y'
                        JOIN m_item ON M_ItemID = ReceiveOrderPoItemID
                            AND M_ItemIsActive = 'Y'
                        JOIN itemunit unitreceive
                            ON unitreceive.ItemUnitID = ReceiveOrderPoItemUnitID
                        WHERE ReceiveOrderPoDetailIsActive = 'Y'
                            AND ReceiveOrderPoDetailPurchaseOrderID = ?
                            AND ReceiveOrderPoID = ?
                            AND M_ItemDesc LIKE ?
                        AND NOT EXISTS (
                            SELECT 1 
                            FROM supplier_invoice_detail 
                            WHERE SupplierInvoiceDetailReceiveOrderPoDetailID = ReceiveOrderPoDetailID
                            AND SupplierInvoiceDetailIsActive = 'Y'
                        )";
            $qryto = $this->db->query($total, [$poID, $roID, $name]);
            if (!$qryto) {
                $this->sys_error_db("[Error] get total item ro");
                exit;
            }

            $result = array(
                "records" => $qry->result_array(),
                "total" => $qryto->result_array()[0]['total'],
            );
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $para = $this->sys_input;
            $branchID = $this->sys_user['M_BranchID'] ?? 0; // 0 untuk user regional
            $date = $para['date'];
            $enddate = $para['enddate'];
            $status = $para['status'];
            $supplier = $para['supplier'];
            $page = $para['page'];
            $keyw = $para['nomor'];

            if ($supplier == "") {
                $supplier = "0";
            }

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

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

            $sqltal = "SELECT COUNT(*) as total
                FROM supplier_invoice
                JOIN supplier_invoice_detail
                    ON SupplierInvoiceID = SupplierInvoiceDetailSupplierInvoiceID
                JOIN receive_order_po
                    ON SupplierInvoiceDetailReceiveOrderPoID = ReceiveOrderPoID
                JOIN warehouse
                    ON ReceiveOrderPoWarehouseID = WarehouseID
                    AND WarehouseM_BranchID = ?
                JOIN supplier ON SupplierID = SupplierInvoiceSupplierID
                    AND SupplierIsActive = 'Y'
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceNumber LIKE ?
                    AND SupplierInvoiceDate >= DATE(?)
                    AND SupplierInvoiceDate <= DATE(?)
                    AND (? = 'All' OR SupplierInvoiceStatus = ?)
                    AND (? = '0' OR SupplierInvoiceSupplierID = ?)
                GROUP BY SupplierInvoiceID
            ";
            $quetal = $this->db->query($sqltal, [
                $branchID,
                $nomo,
                $date,
                $enddate,
                $status,
                $status,
                $supplier,
                $supplier
            ]);
            if (!$quetal) {
                $this->sys_error_db("[Error] get total data faktur");
                exit;
            }
            $total = $quetal->result_array()[0]['total'];

            $sqlfak = "SELECT 
                    SupplierInvoiceID,
                    SupplierInvoiceNumber,
                    SupplierInvoiceDate,
                    SupplierInvoiceDueDate,
                    SupplierInvoiceDraftPaymentDate,
                    SupplierInvoiceSupplierID,
                    SupplierName,
                    SupplierInvoiceStatus,
                    SupplierInvoiceNote,
                    SupplierInvoiceGrandTotal,
                    SupplierInvoiceTaxInvoiceNumber,
                    CASE
                        WHEN WarehouseType = 'B' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', M_BranchName) 
                        WHEN WarehouseType = 'R' THEN CONCAT(WarehouseCode,' ', WarehouseName, ' - ', S_RegionalName) 
                        ELSE ''
                    END as WarehouseName
                FROM supplier_invoice
                JOIN supplier_invoice_detail
                    ON SupplierInvoiceID = SupplierInvoiceDetailSupplierInvoiceID
                JOIN receive_order_po
                    ON SupplierInvoiceDetailReceiveOrderPoID = ReceiveOrderPoID
                JOIN warehouse
                    ON ReceiveOrderPoWarehouseID = WarehouseID
                    AND WarehouseM_BranchID = ?
                JOIN supplier ON SupplierID = SupplierInvoiceSupplierID
                    AND SupplierIsActive = 'Y'
                LEFT JOIN m_branch
                    ON M_BranchID = WarehouseM_BranchID
                LEFT JOIN s_regional 
                    ON S_RegionalID = WarehouseS_RegionalID
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceNumber LIKE ?
                    AND SupplierInvoiceDate >= DATE(?)
                    AND SupplierInvoiceDate <= DATE(?)
                    AND (? = 'All' OR SupplierInvoiceStatus = ?)
                    AND (? = '0' OR SupplierInvoiceSupplierID = ?)
                GROUP BY SupplierInvoiceID
                ORDER BY SUpplierInvoiceID DESC
                LIMIT ? OFFSET ?
            ";
            $quefak = $this->db->query($sqlfak, [
                $branchID,
                $nomo,
                $date,
                $enddate,
                $status,
                $status,
                $supplier,
                $supplier,
                $limit,
                $hal
            ]);
            if (!$quefak) {
                $this->sys_error_db("[Error] get list data faktur");
                exit;
            }

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

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

            $para = $this->sys_input;

            $sql = "SELECT 
                SupplierInvoiceID,
                SupplierInvoiceDate,
                SupplierInvoiceDueDate,
                SupplierInvoiceDraftPaymentDate,
                SupplierInvoiceSupplierID,
                SupplierName,
                SupplierCode,
                SupplierInvoicePurchaseOrderID,
                '' PurchaseOrderDate,
                '' PurchaseOrderNumber,
                SupplierInvoiceRefNumber,
                SupplierInvoiceDeliveryOrderNumber,
                SupplierInvoiceTaxInvoiceNumber,
                SupplierInvoiceTaxInvoiceDate,
                SupplierInvoiceTaxPercentPph,
                SupplierInvoiceTaxPercentPpn,
                SupplierInvoiceDiscountAmount,
                SupplierInvoiceDiscountPercent,
                SupplierInvoiceShippingCost,
                SupplierInvoiceAdjustmentAmount,
                SupplierInvoiceAdjustmentNote,
                SupplierInvoiceNote,
                IF (SupplierInvoiceDiscountAmount > 0, 
                    'R', 
                    'P'
                ) AS DiscountType,
                SupplierInvoiceReceiveOrderPoID,
                ReceiveOrderPoNumber
                FROM supplier_invoice
                JOIN supplier ON SupplierInvoiceSupplierID = SupplierID 
                JOIN receive_order_po ON ReceiveOrderPoID = SupplierInvoiceReceiveOrderPoID
                -- JOIN purchase_order ON SupplierInvoicePurchaseOrderID = PurchaseOrderID
                -- AND PurchaseOrderIsActive = 'Y'
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceID = ?";
            $que = $this->db->query($sql, $para['SInvoiceID']);
            if (!$que) {
                $this->sys_error_db('[Error] get detail data invoice');
                exit;
            }

            $sqldet = "SELECT 
                    SupplierInvoiceDetailID,
                    SupplierInvoiceDetailSupplierInvoiceID,
                    SupplierInvoiceDetailPurchaseOrderID,
                    SupplierInvoiceDetailPurchaseOrderSummaryID,
                    SupplierInvoiceDetailReceiveOrderPoID,
                    SupplierInvoiceDetailReceiveOrderPoDetailID,
                    SupplierInvoiceDetailItemID,
                    SupplierInvoiceDetailItemUnitID,
                    SupplierInvoiceDetailDescription,
                    SupplierInvoiceDetailQty,
                    SupplierInvoiceDetailPrice,
                    SupplierInvoiceDetailDiscountPercent,
                    SupplierInvoiceDetailDiscountDiscountRupiah,
                    SupplierInvoiceDetailDiscountDiscountType,
                    SupplierInvoiceDetailDiscountAmount,
                    SupplierInvoiceDetailDiscountPoProrata,
                    SupplierInvoiceDetailTotal,
                    M_ItemCode,
                    M_ItemDesc
                FROM supplier_invoice_detail
                JOIN m_item ON M_ItemID = SupplierInvoiceDetailItemID
                    AND M_ItemIsActive = 'Y'
                WHERE SupplierInvoiceDetailIsActive = 'Y' 
                    AND SupplierInvoiceDetailSupplierInvoiceID = ?";
            $quedet = $this->db->query($sqldet, [$para['SInvoiceID']]);
            if (!$quedet) {
                $this->sys_error_db("[Error] get detail item faktur");
                exit;
            }

            $data = $que->result_array()[0];
            $data['detail'] = $quedet->result_array();

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

    // ----------------------------------------------------------------------------------

    public function CreateFaktur()
    {
        try {
            if (!$this->isLogin) {
                $this->sys_error();
                exit;
            }

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

            $this->db->trans_begin();
            // $sqlnum = "SELECT `fn_numbering`('INV') as SINum";
            // $qrynum = $this->db->query($sqlnum, []);
            // if (!$qrynum) {
            //     $this->db->trans_rollback();
            //     $this->sys_error_db("[Error] failed generate number");
            //     exit;
            // }
            // $SINum = $qrynum->row_array()['SINum'];

            $areaid = $user['M_BranchID'];
            $areatype = 'B';
            if ($user['loginLevel'] == 'regional') {
                $areaid = $user['S_RegionalID'];
                $areatype = 'R';
            }

            $sqlusrdivisi = "SELECT M_UserDivisionDivisionID FROM m_userdivision 
                WHERE M_UserDivisionM_UserID = ? AND M_UserDivisionIsActive = 'Y'";
            $queusrdivisi = $this->db->query($sqlusrdivisi, [$user['M_UserID']]);
            if (!$queusrdivisi) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get user divisi", $this->db);
                exit;
            }
            $userDivID = $queusrdivisi->row_array()['M_UserDivisionDivisionID'];

            $sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;";
            $quenum = $this->db->query($sqlnum, ['PI', $userDivID, $areatype, $areaid, 'SM', 'Y']);
            if (!$quenum) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] generate number doc", $this->db);
                exit;
            }
            $numpd = $quenum->row_array()['numpd'];

            /*
            *== Validasi untuk mencegah double click simpan faktur   
            */
            $sqlcheck = "SELECT SupplierInvoiceID FROM supplier_invoice 
                    WHERE SupplierInvoiceTaxInvoiceNumber = ? 
                    AND SupplierInvoiceRefNumber = ?
                    AND SupplierInvoicePurchaseOrderID = ?
                    AND SupplierInvoiceGrandTotal = ?
                    AND SupplierInvoiceIsActive = 'Y'";

            $qrycheck = $this->db->query($sqlcheck, [
                $para['SITaxInvoiceNumber'],
                $para['SIRefNumber'],
                $para['SIPoID'],
                $para['SIGrandTotal']
            ]);

            if (!$qrycheck) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] checking for duplicate invoice");
                exit;
            }

            if ($qrycheck->num_rows() > 0) {
                $msg = "Faktur sudah dibuat. Hapus yang sudah ada lalu buat baru jika belum sesuai. Detail Faktur: No.Faktur {$para['SITaxInvoiceNumber']} | PO ID {$para['SIPoID']} | RefNumber {$para['SIRefNumber']} | GrandTotal {$para['SIGrandTotal']}";
                throw new Exception($msg);
            }

            $sqlinsert = "INSERT INTO supplier_invoice (
                SupplierInvoiceNumber,
                SupplierInvoicePurchaseOrderID,
                SupplierInvoiceDate,
                SupplierInvoiceDueDate,
                SupplierInvoiceDraftPaymentDate,
                SupplierInvoiceSupplierID,
                SupplierInvoiceRefNumber,
                SupplierInvoiceTaxInvoiceNumber,
                SupplierInvoiceTaxInvoiceDate,
                SupplierInvoiceSubTotal,
                SupplierInvoiceDiscountPercent,
                SupplierInvoiceDiscountAmount,
                SupplierInvoiceTaxPercentPph,
                SupplierInvoiceTaxAmountPph,
                SupplierInvoiceTaxPercentPpn,
                SupplierInvoiceTaxAmountPpn,
                SupplierInvoiceShippingCost,
                SupplierInvoiceAdjustmentAmount,
                SupplierInvoiceAdjustmentNote,
                SupplierInvoiceGrandTotal,
                SupplierInvoiceUnpaid,
                SupplierInvoiceNote,
                SupplierInvoiceReceiveDate,
                SupplierInvoiceReceivedBy,
                SupplierInvoiceStatus,
                SupplierInvoiceCreatedUserID
            ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
            $qryinsert = $this->db->query($sqlinsert, [
                $numpd,
                $para['SIPoID'],
                $para['SIDate'],
                $para['SIDueDate'],
                $para['SIDraftDate'],
                $para['SISupplierID'],
                $para['SIRefNumber'],
                $para['SITaxInvoiceNumber'],
                $para['SITaxInvoiceDate'],
                $para['SISubTotal'],
                $para['SIDiscountPercent'],
                $para['SIDiscountAmount'],
                $para['SITaxPercentPph'],
                $para['SITaxAmountPph'],
                $para['SITaxPercentPpn'],
                $para['SITaxAmountPpn'],
                $para['SIShippingCost'],
                $para['SIAdjustmentAmount'],
                $para['SIAdjustmentNote'],
                $para['SIGrandTotal'],
                $para['SIGrandTotal'],
                $para['SINote'],
                $para['SIReceiveDate'],
                $para['SIReceivedBy'],
                $para['SIStatus'],
                $userID
            ]);
            if (!$qryinsert) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] insert faktur");
                exit;
            }
            $fakturID = $this->db->insert_id();
            $itemData = $para['SIDetail'];

            foreach ($itemData as $key => $item) {
                $itemInsert = $this->InsertItemFaktur($fakturID, $item, $userID);
                if (!$itemInsert['status']) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert faktur detail");
                    exit;
                }
            }

            $sqldata = "SELECT * FROM supplier_invoice WHERE SupplierInvoiceID = ?";
            $quedata = $this->db->query($sqldata, [$fakturID]);
            if (!$quedata) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get last data inserted");
                exit;
            }

            $desc = 'create faktur no: ' . $numpd;
            $log = $this->InsertLogActivity("INV", "CREATE", $desc, $fakturID, $quedata->result_array()[0], $userID);
            if (!$log['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] log activity user on create faktur");
                exit;
            }

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

    public function UpdateFaktur()
    {
        try {
            if (!$this->isLogin) {
                $this->sys_error();
                exit;
            }
            $para = $this->sys_input;
            $fakturID = $para['fakturID'];
            $userID = $this->sys_user["M_UserID"];

            $this->db->trans_begin();

            $sqlupdate = "UPDATE supplier_invoice
                SET 
                    SupplierInvoicePurchaseOrderID = ?,
                    SupplierInvoiceDate = ?,
                    SupplierInvoiceDueDate = ?,
                    SupplierInvoiceSupplierID = ?,
                    SupplierInvoiceRefNumber = ?,
                    SupplierInvoiceTaxInvoiceNumber = ?,
                    SupplierInvoiceTaxInvoiceDate = ?,
                    SupplierInvoiceSubTotal = ?,
                    SupplierInvoiceDiscountPercent = ?,
                    SupplierInvoiceDiscountAmount = ?,
                    SupplierInvoiceTaxPercentPph = ?,
                    SupplierInvoiceTaxAmountPph = ?,
                    SupplierInvoiceTaxPercentPpn = ?,
                    SupplierInvoiceTaxAmountPpn = ?,
                    SupplierInvoiceShippingCost = ?,
                    SupplierInvoiceAdjustmentAmount = ?,
                    SupplierInvoiceAdjustmentNote = ?,
                    SupplierInvoiceGrandTotal = ?,
                    SupplierInvoiceUnpaid = ?,
                    SupplierInvoicePaidAmount = ?,
                    SupplierInvoiceNote = ?,
                    SupplierInvoiceStatus = ?,
                    SupplierInvoiceDraftPaymentDate = ?,
                    SupplierInvoiceLastUpdated = NOW(),
                    SupplierInvoiceLastUpdatedUserID = ?
                WHERE 
                    SupplierInvoiceID = ?";
            $qryupdate = $this->db->query($sqlupdate, [
                $para['SIPoID'],
                $para['SIDate'],
                $para['SIDueDate'],
                $para['SISupplierID'],
                $para['SIRefNumber'],
                $para['SITaxInvoiceNumber'],
                $para['SITaxInvoiceDate'],
                $para['SISubTotal'],
                $para['SIDiscountPercent'],
                $para['SIDiscountAmount'],
                $para['SITaxPercentPph'],
                $para['SITaxAmountPph'],
                $para['SITaxPercentPpn'],
                $para['SITaxAmountPpn'],
                $para['SIShippingCost'],
                $para['SIAdjustmentAmount'],
                $para['SIAdjustmentNote'],
                $para['SIGrandTotal'],
                $para['SIGrandTotal'],
                $para['SIPaidAmount'],
                $para['SINote'],
                $para['SIStatus'],
                $para['SIDraftDate'],
                $userID,
                $fakturID
            ]);
            if (!$qryupdate) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] error update faktur");
                exit;
            }

            $sqldel = "UPDATE supplier_invoice_detail 
                SET SupplierInvoiceDetailIsActive = 'N' 
                WHERE SupplierInvoiceDetailIsActive = 'Y'
                    AND SupplierInvoiceDetailSupplierInvoiceID = ?";
            $qrydel = $this->db->query($sqldel, [$fakturID]);
            if (!$qrydel) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] error de-activate item faktur");
                exit;
            }

            $itemData = $para['SIDetail'];
            foreach ($itemData as $key => $item) {
                $itemInsert = $this->InsertItemFaktur($fakturID, $item, $userID);
                if (!$itemInsert['status']) {
                    $this->sys_error_db("[Error] insert faktur");
                    exit;
                }
            }

            $sqldata = "SELECT * FROM supplier_invoice WHERE SupplierInvoiceID = ?";
            $quedata = $this->db->query($sqldata, [$fakturID]);
            if (!$quedata) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get last data updated");
                exit;
            }
            $data = $quedata->result_array()[0];

            $desc = 'update faktur no: ' . $data['SupplierInvoiceNumber'];
            $log = $this->InsertLogActivity("INV", "UPDATE", $desc, $fakturID, $data, $userID);
            if (!$log['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] log activity user on create faktur");
                exit;
            }

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

    function InsertItemFaktur($fakturID, $item, $userID): array
    {
        try {
            $sqlinsert = "INSERT INTO supplier_invoice_detail (
                SupplierInvoiceDetailSupplierInvoiceID,
                SupplierInvoiceDetailPurchaseOrderID,
                SupplierInvoiceDetailPurchaseOrderSummaryID,
                SupplierInvoiceDetailReceiveOrderPoID,
                SupplierInvoiceDetailReceiveOrderPoDetailID,
                SupplierInvoiceDetailItemID,
                SupplierInvoiceDetailItemUnitID,
                SupplierInvoiceDetailDescription,
                SupplierInvoiceDetailQty,
                SupplierInvoiceDetailPrice,
                SupplierInvoiceDetailDiscountPercent,
                SupplierInvoiceDetailDiscountDiscountRupiah,
                SupplierInvoiceDetailDiscountDiscountType,
                SupplierInvoiceDetailDiscountPoProrata,
                SupplierInvoiceDetailDiscountAmount,
                SupplierInvoiceDetailTotal,
                SupplierInvoiceDetailUnpaid,
                SupplierInvoiceDetailCreatedUserID
            ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
            $qryinsert = $this->db->query($sqlinsert, [
                $fakturID,
                $item['SIDPOID'],
                $item['SIDPOSummaryID'],
                $item['SIDROID'],
                $item['SIDRODetailID'],
                $item['SIDItemID'],
                $item['SIDItemUnitID'],
                $item['SIDDescription'],
                $item['SIDQty'],
                $item['SIDPrice'],
                $item['SIDDiscountPercent'],
                $item['SIDDiscountRupiah'],
                $item['SIDDiscountType'],
                $item['SIDDiscountPOProrata'],
                $item['SIDDiscountAmount'],
                $item['SIDTotal'],
                $item['SIDTotal'],
                $userID
            ]);
            if (!$qryinsert) {
                $this->db->trans_rollback();
                return [
                    'status' => false,
                    'message' => '[Error] insert item faktur'
                ];
            }

            return [
                'status' => true,
                'message' => 'Item successfully added to invoice'
            ];
        } catch (Exception $exc) {
            return [
                'status' => false,
                'message' => $exc->getMessage()
            ];
        }
    }

    function InsertLogActivity($Code, $Status, $Description, $RefID, $Data, $userID): array
    {
        try {
            $json = json_encode($Data);
            $sqllog = "INSERT INTO user_activity (
                UserActivityCode,
                UserActivityStatus,
                UserActivityDescription,
                UserActivityRefID,
                UserActivityData,
                UserActivityUserID,
                UserActivityCreated
            ) VALUES (?,?,?,?,?,?,NOW())";
            $quelog = $this->db->query($sqllog, [
                $Code,
                $Status,
                $Description,
                $RefID,
                $json,
                $userID
            ]);
            if (!$quelog) {
                $this->db->trans_rollback();
                return [
                    'status' => false,
                    'message' => '[Error] insert into user activity'
                ];
            }

            return [
                'status' => true,
                'message' => 'Log written'
            ];
        } catch (Exception $exc) {
            return [
                'status' => false,
                'message' => $exc->getMessage()
            ];
        }
    }

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

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

            $this->db->trans_begin();
            $sqldel = "UPDATE supplier_invoice 
                SET SupplierInvoiceIsActive = 'N' 
                WHERE SupplierInvoiceIsActive = 'Y' 
                    AND SupplierInvoiceID = ?";
            $qrydel = $this->db->query($sqldel, [$para['SInvoiceID']]);
            if (!$qrydel) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] error de-activate faktur");
                exit;
            }


            $sqldel2 = "UPDATE supplier_invoice_detail 
                SET SupplierInvoiceDetailIsActive = 'N' 
                WHERE SupplierInvoiceDetailIsActive = 'Y'
                    AND SupplierInvoiceDetailSupplierInvoiceID = ?";
            $qrydel2 = $this->db->query($sqldel2, [$para['SInvoiceID']]);
            if (!$qrydel2) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] error de-activate item faktur");
                exit;
            }

            $sqldata = "SELECT * FROM supplier_invoice WHERE SupplierInvoiceID = ?";
            $quedata = $this->db->query($sqldata, [$para['SInvoiceID']]);
            if (!$quedata) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get data deleted");
                exit;
            }
            $data = $quedata->result_array()[0];

            $desc = 'delete faktur no: ' . $data['SupplierInvoiceNumber'];
            $log = $this->InsertLogActivity("INV", "DELETE", $desc, $para['SInvoiceID'], $data, $userID);
            if (!$log['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] log activity user on create faktur");
                exit;
            }

            $this->db->trans_commit();
            $result = array(
                'status' => 'OK',
                'message' => 'succes delete'
            );
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

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

            $fakturID = $para['fakturID'];

            $this->db->trans_begin();
            // update status faktur ke approved
            $sqlupd = "UPDATE supplier_invoice SET 
                    SupplierInvoiceStatus = 'Verified',
                    SupplierInvoiceVerifiedDate = NOW(),
                    SupplierInvoiceVerifiedUserID = ?,
                    SupplierInvoiceLastUpdated = NOW(),
                    SupplierInvoiceLastUpdatedUserID = ?
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceID = ?";
            $queupd = $this->db->query($sqlupd, [$user['M_UserID'], $user['M_UserID'], $fakturID]);
            if (!$queupd) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status supplier invoice to verified");
                exit;
            }

            $sqldet = "UPDATE supplier_invoice_detail SET
                    SupplierInvoiceDetailIsVerified = 'Y',
                    SupplierInvoiceDetailLastUpdated = NOW(),
                    SupplierInvoiceDetailLastUpdatedUserID = ?
                WHERE SupplierInvoiceDetailSupplierInvoiceID = ? 
                    AND SupplierInvoiceDetailIsActive = 'Y'";
            $quedet = $this->db->query($sqldet, [$user['M_UserID'], $fakturID]);
            if (!$quedet) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status supplier invoice detail to verified");
                exit;
            }

            $this->db->trans_commit();
            $this->sys_ok("[Success] update status faktur to verified");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

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

            $fakturID = $para['fakturID'];

            $this->db->trans_begin();

            $sqlupd = "UPDATE supplier_invoice SET 
                    SupplierInvoiceStatus = 'Reject',
                    SupplierInvoiceLastUpdated = NOW(),
                    SupplierInvoiceLastUpdatedUserID = ?
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceID = ?";
            $queupd = $this->db->query($sqlupd, [$user['M_UserID'], $fakturID]);
            if (!$queupd) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status supplier invoice to rejected");
                exit;
            }

            // TODO: Need Confirmation
            // ? Apakah setelah reject, item faktur masih bisa difaktur lagi atau tidak?
            // Kalau bisa, maka perlu update detail supplier_invoice_detail ke N
            $sqldet = "UPDATE supplier_invoice_detail SET
                    SupplierInvoiceDetailIsActive = 'N',
                    SupplierInvoiceDetailLastUpdated = NOW(),
                    SupplierInvoiceDetailLastUpdatedUserID = ?
                WHERE SupplierInvoiceDetailSupplierInvoiceID = ? 
                    AND SupplierInvoiceDetailIsActive = 'Y' ";
            $quedet = $this->db->query($sqldet, [$user['M_UserID'], $fakturID]);
            if (!$quedet) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status supplier invoice detail to non active");
                exit;
            }

            $this->db->trans_commit();
            $this->sys_ok("[Success] update status faktur to reject");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

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

            $fakturID = $para['fakturID'];

            $this->db->trans_begin();
            // update status faktur ke approved
            $sqlupd = "UPDATE supplier_invoice SET 
                    SupplierInvoiceStatus = 'Approved',
                    SupplierInvoiceApprovedDate = NOW(),
                    SupplierInvoiceApprovedUserID = ?,
                    SupplierInvoiceLastUpdated = NOW(),
                    SupplierInvoiceLastUpdatedUserID = ?
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceID = ?";
            $queupd = $this->db->query($sqlupd, [$user['M_UserID'], $user['M_UserID'], $fakturID]);
            if (!$queupd) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] update status supplier invoice to approved");
                exit;
            }

            // get periode untuk jurnal
            // ----------------------------------------------------------------------------------------
            $sqlprd = "SELECT periodeID FROM periode 
                WHERE DATE(NOW()) BETWEEN DATE(periodeStartDate) AND DATE(periodeEndDate) 
                    AND periodeIsActive = 'Y'
                    AND periodeIsClosed = 'N'";
            $queprd = $this->db->query($sqlprd, []);
            if (!$queprd) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get periode jurnal");
                exit;
            }
            $periodeJurnal = $queprd->row_array()['periodeID'];

            // generate number jurnal
            $sqljno = "SELECT `fn_numbering`('J') AS numbering";
            $quejno = $this->db->query($sqljno, []);
            if (!$quejno) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] generate number jurnal");
                exit;
            }
            $jurnalNumber = $quejno->row_array()['numbering'];

            // get data faktur
            $sqlinv = "SELECT 
                    supplier_invoice.* ,
                    supplier_invoice_detail.*,
                    ReceiveOrderPoNumber,
                    ReceiveOrderPoM_BranchCode,
                    ReceiveOrderPoS_RegionalID
                FROM supplier_invoice
                JOIN supplier_invoice_detail ON SupplierInvoiceDetailSupplierInvoiceID = SupplierInvoiceID
                    AND SupplierInvoiceDetailIsActive = 'Y'
                JOIN receive_order_po ON SupplierInvoiceDetailReceiveOrderPoID = ReceiveOrderPoID
                    AND ReceiveOrderPoIsActive = 'Y'
                WHERE SupplierInvoiceIsActive = 'Y'
                    AND SupplierInvoiceID = ?";
            $queinv = $this->db->query($sqlinv, [$fakturID]);
            if (!$queinv) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get detail data faktur");
                exit;
            }
            $invoice = $queinv->result_array();
            $invoiceNumber = $invoice[0]['SupplierInvoiceNumber'];
            $invoiceDate = $invoice[0]['SupplierInvoiceDate'];
            $invDONumber = $invoice[0]['SupplierInvoiceDeliveryOrderNumber'];
            $invROList = [];
            foreach ($invoice as $key => $value) {
                if (!in_array($value['ReceiveOrderPoNumber'], $invROList)) {
                    $invROList[] = $value['ReceiveOrderPoNumber'];
                }
            }
            $invRONumbers = implode(", ", $invROList);

            $sqljrtype = "SELECT JurnalTypeID FROM jurnal_type WHERE JurnalTypeCode = 'AUTOINVOICE' AND JurnalTypeIsActive = 'Y'";
            $quejrtype = $this->db->query($sqljrtype, []);
            if (!$quejrtype) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get jurnal type");
                exit;
            }
            $jrtype = $quejrtype->result_array()[0]['JurnalTypeID'];

            // insert into table jurnal
            $sqljrnl = "INSERT INTO jurnal (
                    jurnalM_BranchCompanyID,
                    JurnalS_RegionalID,
                    jurnalM_BranchCode,
                    jurnalperiodeID,
                    jurnalNo,
                    jurnalTitle,
                    jurnalDescription,
                    jurnalDate,
                    jurnalJurnalTypeID,
                    jurnalM_UserID
                ) VALUES (?,?,?,?,?,?,?,NOW(),?,?)";
            $quejrnl = $this->db->query($sqljrnl, [
                $user['M_BranchCompanyID'],
                $invoice[0]['ReceiveOrderPoS_RegionalID'],
                $invoice[0]['ReceiveOrderPoM_BranchCode'],
                $periodeJurnal,
                $jurnalNumber,
                "Jurnal Tukar Faktur Nomor {$invoiceNumber} Tanggal {$invoiceDate}",
                "Faktur Nomor: {$invoiceNumber}, Tanggal: {$invoiceDate}, Nomor PO: {$invDONumber}, RO: {$invRONumbers}",
                $jrtype,
                $user['M_UserID']
            ]);
            if (!$quejrnl) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] insert into table jurnal");
                exit;
            }
            $jurnalID = $this->db->insert_id();

            // insert jurnal tx for GRNI (debit)
            $ship_cost = round(doubleval($invoice[0]['SupplierInvoiceShippingCost']), 2);
            $totalGRNI = 0;
            foreach ($invoice as $key => $inv) {
                $totalGRNI = $totalGRNI + (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata'])) + $ship_cost;
            }

            $sqlcoa = "SELECT coaID, coaDescription, coaAccountNo FROM coa WHERE coaAccountNo = ? AND coaIsActive = 'Y'";
            $quegrn = $this->db->query($sqlcoa, ['2110100030']);
            if (!$quegrn) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get coa id grn");
                exit;
            }
            $coaGRNI = $quegrn->result_array()[0];

            $insertgrni = $this->InsertJurnalTx(
                $jurnalID,
                $coaGRNI['coaID'],
                $coaGRNI['coaDescription'],
                $user['M_UserID'],
                round($totalGRNI, 2),
                0
            );
            if (!$insertgrni['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db($insertgrni['msg']);
                exit;
            }

            // insert jurnal tx for Pajak masukan (debit)
            $totalPajak = doubleval($invoice[0]['SupplierInvoiceTaxAmountPph']) + doubleval($invoice[0]['SupplierInvoiceTaxAmountPpn']);
            $quetax = $this->db->query($sqlcoa, ['1140101005']);
            if (!$quetax) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get coa id pajak masukan");
                exit;
            }
            $coaTax = $quetax->result_array()[0];

            $insertpajak = $this->InsertJurnalTx(
                $jurnalID,
                $coaTax['coaID'],
                $coaTax['coaDescription'],
                $user['M_UserID'],
                round($totalPajak, 2),
                0
            );
            if (!$insertpajak['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db($insertpajak['msg']);
                exit;
            }

            // insert jurnal tx hutang pph23 (kredit)
            $quepph = $this->db->query($sqlcoa, ['2120100003']);
            if (!$quepph) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get coa hutang pph 23 ");
                exit;
            }
            $coapph = $quepph->result_array()[0];

            $pphval = doubleval($invoice[0]['SupplierInvoiceTaxAmountPph']);

            $insertpph = $this->InsertJurnalTx(
                $jurnalID,
                $coapph['coaID'],
                $coapph['coaDescription'],
                $user['M_UserID'],
                0,
                round($pphval, 2)
            );
            if (!$insertpph['status']) {
                $this->db->trans_rollback();
                $this->sys_error_db($insertpajak['msg']);
                exit;
            }

            # insert shipping cost ke jurnal #
            $queryshipcost = $this->db->query($sqlcoa, ['5320700001']);
            if (!$queryshipcost) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get coa cost ");
                exit;
            }
            $coashipcost = $queryshipcost->result_array()[0];

            if ($ship_cost > 0.00) {
                $insertcost = $this->InsertJurnalTx(
                    $jurnalID,
                    $coashipcost['coaID'],
                    $coashipcost['coaDescription'],
                    $user['M_UserID'],
                    0,
                    $ship_cost
                );
                if (!$insertcost['status']) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] insert jurnal tx shipping cost");
                    exit;
                }
            }

            // insert jurnal tx hutang per item (kredit)
            foreach ($invoice as $key => $inv) {
                $sqlitem = "SELECT * FROM m_item WHERE M_ItemID = ?";
                $queitem = $this->db->query($sqlitem, [$inv['SupplierInvoiceDetailItemID']]);
                if (!$queitem) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] get item id");
                    exit;
                }
                $item = $queitem->row_array();

                if (empty($item) || empty($item['M_ItemItem_CategoryID'])) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("[Error] RO: {$inv['ReceiveOrderPoNumber']} item {$item['M_ItemDesc']} tidak ditemukan / kategori tidak ada");
                    exit;
                }

                if ($item['M_ItemItem_CategoryID'] == '1' && !empty($item['M_ItemNat_SubGroupID'])) {
                    $sqlsgp = "SELECT map_nat_group.* 
                        FROM map_nat_group
                        JOIN map_nat_subgroup ON MapNatSub_NatGroupID = MapNatGroup_NatGroupID
                            AND MapNatSub_IsActive = 'Y'
                        WHERE MapNatGroup_NatGroupID = ? 
                            AND MapNatSub_NatSubGroupID = ? 
                            AND MapNatGroup_IsActive = 'Y'";
                    $quesgp = $this->db->query($sqlsgp, [$item['M_ItemNat_GroupID'], $item['M_ItemNat_SubGroupID']]);
                    if (!$quesgp) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] get map_nat_subgroup");
                        exit;
                    }
                    $itemGroup = $quesgp->row_array();

                    if (
                        empty($itemGroup['MapNatGroup_Debt_coaID']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaAccNo']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaDesc'])
                    ) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] coa item tidak ditemukan / belum dimapping");
                        exit;
                    }

                    $price = (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata']));
                    // $taxPPH  =  doubleval($inv['SupplierInvoiceTaxPercentPph']) * $price / 100;
                    $taxPPN  =  doubleval($inv['SupplierInvoiceTaxPercentPpn']) * $price / 100;

                    $kredit = round($price + $taxPPN, 2);

                    $status = $this->InsertJurnalTx(
                        $jurnalID,
                        $itemGroup['MapNatGroup_Debt_coaID'],
                        $itemGroup['MapNatGroup_Debt_coaDesc'],
                        $user['M_UserID'],
                        0,
                        $kredit
                    );
                    if (!$status) {
                        $this->sys_error_db($status['msg']);
                        exit;
                    }
                } else if ($item['M_ItemItem_CategoryID'] == '2') {
                    // Mapping JurnalTx sama dengan Persediaan hanya beda CoA
                    // TODO: Update dengan CoA yang Benar

                    // Jika ItemNatsubGroup belum termapping return error
                    if (empty($item['M_ItemNat_SubGroupID'])) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] Item {$item['M_ItemDesc']} tidak memiliki Nat_SubGroupID");
                        exit;
                    };

                    $sqlsgp = "SELECT map_nat_group.* 
                        FROM map_nat_group
                        JOIN map_nat_subgroup ON MapNatSub_NatGroupID = MapNatGroup_NatGroupID
                            AND MapNatSub_IsActive = 'Y'
                        WHERE MapNatGroup_NatGroupID = ? 
                            AND MapNatSub_NatSubGroupID = ? 
                            AND MapNatGroup_IsActive = 'Y'";
                    $quesgp = $this->db->query($sqlsgp, [$item['M_ItemNat_GroupID'], $item['M_ItemNat_SubGroupID']]);
                    if (!$quesgp) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] get map_nat_subgroup");
                        exit;
                    }
                    $itemGroup = $quesgp->row_array();

                    if (
                        empty($itemGroup['MapNatGroup_Debt_coaID']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaAccNo']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaDesc'])
                    ) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] coa item tidak ditemukan / belum dimapping");
                        exit;
                    }

                    $price = (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata']));
                    // $taxPPH  =  doubleval($inv['SupplierInvoiceTaxPercentPph']) * $price / 100;
                    $taxPPN  =  doubleval($inv['SupplierInvoiceTaxPercentPpn']) * $price / 100;

                    $kredit = round($price + $taxPPN, 2);

                    $status = $this->InsertJurnalTx(
                        $jurnalID,
                        $itemGroup['MapNatGroup_Debt_coaID'],
                        $itemGroup['MapNatGroup_Debt_coaDesc'],
                        $user['M_UserID'],
                        0,
                        $kredit
                    );
                    if (!$status) {
                        $this->sys_error_db($status['msg']);
                        exit;
                    }
                } else if ($item['M_ItemItem_CategoryID'] == '3' && !empty($item['M_ItemFa_ClassID'])) {
                    $sqlsgp = "SELECT * FROM fa_class WHERE Fa_ClassID = ? AND Fa_ClassIsActive = 'Y'";
                    $quesgp = $this->db->query($sqlsgp, [$item['M_ItemFa_ClassID']]);
                    if (!$quesgp) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] get map_nat_subgroup");
                        exit;
                    }
                    $itemGroup = $quesgp->row_array();

                    if (empty($itemGroup)) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] fa class item tidak ditemukan / belum dimapping");
                        exit;
                    }

                    $price = (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata']));
                    // $taxPPH  =  doubleval($inv['SupplierInvoiceTaxPercentPph']) * $price / 100;
                    $taxPPN  =  doubleval($inv['SupplierInvoiceTaxPercentPpn']) * $price / 100;

                    $kredit = round($price +  $taxPPN, 2);

                    $status = $this->InsertJurnalTx(
                        $jurnalID,
                        $itemGroup['Fa_ClassCoaID'],
                        $itemGroup['Fa_ClassCoaDesc'],
                        $user['M_UserID'],
                        0,
                        $kredit
                    );
                    if (!$status) {
                        $this->sys_error_db($status['msg']);
                        exit;
                    }
                } else if ($item['M_ItemItem_CategoryID'] == '4') {
                    // Mapping JurnalTx sama dengan Persediaan hanya beda CoA
                    // TODO: Update dengan CoA yang Benar

                    // Jika ItemNatsubGroup belum termapping return error
                    if (empty($item['M_ItemNat_SubGroupID'])) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] Item {$item['M_ItemDesc']} tidak memiliki Nat_SubGroupID");
                        exit;
                    };

                    $sqlsgp = "SELECT map_nat_group.* 
                        FROM map_nat_group
                        JOIN map_nat_subgroup ON MapNatSub_NatGroupID = MapNatGroup_NatGroupID
                            AND MapNatSub_IsActive = 'Y'
                        WHERE MapNatGroup_NatGroupID = ? 
                            AND MapNatSub_NatSubGroupID = ? 
                            AND MapNatGroup_IsActive = 'Y'";
                    $quesgp = $this->db->query($sqlsgp, [$item['M_ItemNat_GroupID'], $item['M_ItemNat_SubGroupID']]);
                    if (!$quesgp) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] get map_nat_subgroup");
                        exit;
                    }
                    $itemGroup = $quesgp->row_array();

                    if (
                        empty($itemGroup['MapNatGroup_Debt_coaID']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaAccNo']) ||
                        empty($itemGroup['MapNatGroup_Debt_coaDesc'])
                    ) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("[Error] coa item tidak ditemukan / belum dimapping");
                        exit;
                    }

                    $price = (doubleval($inv['SupplierInvoiceDetailTotal']) - doubleval($inv['SupplierInvoiceDetailDiscountPoProrata']));
                    // $taxPPH  =  doubleval($inv['SupplierInvoiceTaxPercentPph']) * $price / 100;
                    $taxPPN  =  doubleval($inv['SupplierInvoiceTaxPercentPpn']) * $price / 100;

                    $kredit = round($price + $taxPPN, 2);

                    $status = $this->InsertJurnalTx(
                        $jurnalID,
                        $itemGroup['MapNatGroup_Debt_coaID'],
                        $itemGroup['MapNatGroup_Debt_coaDesc'],
                        $user['M_UserID'],
                        0,
                        $kredit
                    );
                    if (!$status) {
                        $this->sys_error_db($status['msg']);
                        exit;
                    }
                }
            }

            $sqlinvgr = "INSERT INTO jurnal_addon (
                jurnalAddOnJurnalID,
                jurnalAddOnCode,
                jurnalAddOnValue,
                jurnalAddOnCreated,
                jurnalAddOnCreatedUserID
            ) VALUES (?,?,?,NOW(),?)";
            $queinvgr = $this->db->query($sqlinvgr, [
                $jurnalID,
                'INVGR',
                $invoiceNumber,
                $user['M_UserID']
            ]);
            if (!$queinvgr) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] insert jurnal addon");
                exit;
            }
            // end------------------------------------------------------------------------------------------------


            $this->db->trans_commit();
            $this->sys_ok("[Success] update status faktur to approved");
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function InsertJurnalTx($jurnalID, $coaID, $desc, $userID, $debit = 0, $kredit = 0): array
    {
        try {
            $sql = "INSERT INTO jurnal_tx (
                jurnalTxJurnalID,
                jurnalTxCoaID,
                jurnalTxDescription,
                jurnalTxDebit,
                jurnalTxCredit,
                jurnalTxM_UserID
            ) VALUES (?,?,?,?,?,?)";
            $que = $this->db->query($sql, [$jurnalID, $coaID, $desc, $debit, $kredit, $userID]);
            if (!$que) {
                $this->db->trans_rollback();
                return [
                    'status' => false,
                    'msg' => "[Error] error insert into table jurnal tx"
                ];
            }

            return [
                'status' => true,
                'msg' => "[Success] insert into table jurnal tx"
            ];
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            return [
                'status' => false,
                'msg' => "[Error] {$message}"
            ];
        }
    }
}
