<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Invoice extends Client_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('invoice_model');
        $this->load->library('gst');

    }

    public function manage_invoice($action = NULL, $id = NULL, $item_id = NULL)
    {
        $data['page'] = lang('invoices');
        $data['title'] = lang('invoices');
        $data['breadcrumbs'] = lang('invoices');
        $data['page_title'] = lang('invoices');
        $data['page_description'] = 'Overview of your business performance';
        $data['header_filters'] = array();
        $data['header_filter_extras_html'] = '';
        if ($action == 'all_payments') {
            $data['sub_active'] = lang('payments_received');
        } else {
            $data['sub_active'] = lang('invoice');
        }
        if (!empty($item_id)) {
            $data['item_info'] = $this->invoice_model->check_by(array('items_id' => $item_id), 'tbl_items');
        }
        $data['dataTables'] = true;
        if (!empty($id) && $action != 'payments_details') {
            // get all invoice info by id
            $data['invoice_info'] = $this->invoice_model->check_by(array('invoices_id' => $id), 'tbl_invoices');
            if (empty($data['invoice_info'])) {
                redirect('client/invoice/manage_invoice');
            }
            $client_id = client_id();
            if ($client_id != $data['invoice_info']->client_id) {
                redirect('client/invoice/manage_invoice');
            }
        }
        if ($action == 'create_invoice') {
            $data['active'] = 2;
        } else {
            $data['active'] = 1;
        }
        $user_id = $this->session->userdata('user_id');
        $client_id = $this->session->userdata('client_id');
        // get all client
        $this->invoice_model->_table_name = 'tbl_client';
        $this->invoice_model->_order_by = 'client_id';
        $data['all_client'] = $this->invoice_model->get();

        // get all client
        $data['all_invoices_info'] = $this->db->where(array('client_id' => $client_id))->get('tbl_invoices')->result();

        if ($action == 'invoice_details') {
            $data['title'] = "Invoice Details"; //Page title
            if (empty($data['invoice_info']) || $data['invoice_info']->show_client == 'No') {
                set_message('error', lang('no_data_found'));
                redirect('client/invoice/manage_invoice');
            }
            $data['invoice_print_html'] = $this->load->view('client/invoice/invoice_pdf', $data, TRUE);
            $subview = 'invoice_details';
        } elseif ($action == 'payment') {
            $data['title'] = "Invoice Payment"; //Page title
            $subview = 'payment';
        } elseif ($action == 'payments_details') {
            $data['page'] = lang('payments');
            $data['title'] = "Payments Details"; //Page title
            $subview = 'payments_details';
            // get payment info
            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->_order_by = 'invoices_id';
            $data['all_payments_info'] = $this->invoice_model->get_by(array('invoices_id !=' => '0', 'paid_by' => $this->session->userdata('client_id')), FALSE);
            // get payment info by id
            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->_order_by = 'payments_id';
            $data['payments_info'] = $this->invoice_model->get_by(array('payments_id' => $id), TRUE);

            $client_id = client_id();
            if (empty($data['payments_info'])) {
                set_message('error', lang('no_data_found'));
                redirect('client/invoice/all_payments');
            }
            if ($client_id != $data['payments_info']->paid_by) {
                redirect('client/invoice/all_payments');
            }

            $invoice_info = $this->invoice_model->check_by(array('invoices_id' => $data['payments_info']->invoices_id), 'tbl_invoices');
            $default_currency = $this->invoice_model->check_by(array('code' => config_item('default_currency')), 'tbl_currencies');
            $currency = !empty($data['payments_info']->system_currency)
                ? $this->invoice_model->check_by(array('code' => $data['payments_info']->system_currency), 'tbl_currencies')
                : $default_currency;
            if (empty($currency)) {
                $currency = $default_currency;
            }
            $invoice_ref = !empty($invoice_info->reference_no) ? $invoice_info->reference_no : '-';
            $data['page_title'] = !empty($data['payments_info']->trans_id) ? $data['payments_info']->trans_id : lang('payment_details');
            $data['page_description'] = lang('invoice') . ': ' . $invoice_ref . ' - ' . display_date($data['payments_info']->payment_date) . ' - ' . display_money($data['payments_info']->amount, !empty($currency->symbol) ? $currency->symbol : default_currency());
            $data['header_badge_html'] = '<span class="inline-flex items-center rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-xs font-semibold text-emerald-700 dark:border-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300">' . html_escape(lang('payment')) . '</span>';
            $data['header_actions'] = array(
                array(
                    'label' => 'PDF',
                    'icon' => 'download',
                    'href' => base_url('client/invoice/payments_pdf/' . $data['payments_info']->payments_id),
                    'style' => 'primary',
                ),
            );

            $per_page = 15;
            $this->db->where('paid_by', $client_id);
            $total_payments = (int) $this->db->count_all_results('tbl_payments');
            $total_pages = max(1, (int) ceil($total_payments / $per_page));
            $current_page = (int) $this->input->get('page', true);
            if ($current_page < 1) {
                $newer_count = (int) $this->db
                    ->where('paid_by', $client_id)
                    ->where('payments_id >', $data['payments_info']->payments_id)
                    ->count_all_results('tbl_payments');
                $current_page = (int) floor($newer_count / $per_page) + 1;
            }
            if ($current_page > $total_pages) {
                $current_page = $total_pages;
            }
            $offset = ($current_page - 1) * $per_page;

            $this->db
                ->select('tbl_payments.payments_id, tbl_payments.trans_id, tbl_payments.amount, tbl_payments.created_date, tbl_payments.invoices_id, tbl_client.name as client_name')
                ->from('tbl_payments')
                ->join('tbl_client', 'tbl_client.client_id = tbl_payments.paid_by', 'left')
                ->where('tbl_payments.paid_by', $client_id)
                ->order_by('tbl_payments.payments_id', 'DESC')
                ->limit($per_page, $offset);
            $data['payment_sidebar_items'] = $this->db->get()->result();
            $data['payment_sidebar_page'] = $current_page;
            $data['payment_sidebar_pages'] = $total_pages;
            $data['payment_sidebar_total'] = $total_payments;
        } elseif ($action == 'invoice_history') {
            $data['title'] = "Invoice History"; //Page title
            $subview = 'invoice_history';
        } elseif ($action == 'email_invoice') {
            $data['title'] = "Email Invoice"; //Page title
            $subview = 'email_invoice';
            $data['editor'] = $this->data;
        } elseif ($action == 'send_reminder') {
            $data['title'] = "Send Remainder"; //Page title
            $subview = 'send_reminder';
            $data['editor'] = $this->data;
        } else {
            $data['title'] = lang('invoices');
            $subview = 'manage_invoice';
            $data['header_actions'] = array(
                array(
                    'label' => lang('request') . ' ' . lang('refund_items'),
                    'icon' => 'archive',
                    'href' => base_url('client/invoice/refund_itemslist'),
                    'style' => 'success',
                ),
            );
            $invoice_filter_items = array(
                array('label' => lang('all'), 'active' => true, 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => '', 'data-client-invoice-filter-label' => lang('all'))),
                array('label' => lang('unpaid'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'not_paid', 'data-client-invoice-filter-label' => lang('unpaid'))),
                array('label' => lang('paid'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'paid', 'data-client-invoice-filter-label' => lang('paid'))),
                array('label' => lang('partially_paid'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'partially_paid', 'data-client-invoice-filter-label' => lang('partially_paid'))),
                array('label' => lang('overdue'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'overdue', 'data-client-invoice-filter-label' => lang('overdue'))),
                array('label' => lang('cancelled'), 'divider_before' => true, 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'cancelled', 'data-client-invoice-filter-label' => lang('cancelled'))),
                array('label' => lang('recurring'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'recurring', 'data-client-invoice-filter-label' => lang('recurring'))),
                array('label' => lang('last_month'), 'divider_before' => true, 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'last_month', 'data-client-invoice-filter-label' => lang('last_month'))),
                array('label' => lang('this_months'), 'attrs' => array('data-client-invoice-filter-action' => '1', 'data-client-invoice-filter' => 'this_months', 'data-client-invoice-filter-label' => lang('this_months'))),
            );
            $data['header_filters'] = array(
                array(
                    'label' => lang('filter_by'),
                    'icon' => 'sliders-horizontal',
                    'selected_label' => lang('all'),
                    'attrs' => array('id' => 'client-invoice-header-filter'),
                    'items' => $invoice_filter_items,
                ),
            );
        }
        $user_info = $this->invoice_model->check_by(array('user_id' => $user_id), 'tbl_users');
        $data['role'] = $user_info->role_id;
        $data['subview'] = $this->load->view('client/invoice/' . $subview, $data, TRUE);
        $this->load->view('client/_layout_main', $data); //page load
    }

    public function invoiceList($filterBy = null)
    {
        if ($this->input->is_ajax_request()) {
            $this->load->model('datatables');
            $this->datatables->table = 'tbl_invoices';
            $this->datatables->column_order = array('reference_no', 'status', 'invoice_date', 'due_date');
            $this->datatables->column_search = array('reference_no', 'status', 'invoice_date', 'due_date');
            $this->datatables->order = array('invoices_id' => 'desc');
            $where_in = null;
            $client_id = $this->session->userdata('client_id');
            if (empty($filterBy)) {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status !=' => 'draft');
            }
            if ($filterBy == 'recurring') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status !=' => 'draft', 'recurring' => 'Yes');
            } else if ($filterBy == 'paid') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status' => 'Paid');
            } else if ($filterBy == 'not_paid') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status' => 'Unpaid');
            } else if ($filterBy == 'partially_paid') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status' => 'partially_paid');
            } else if ($filterBy == 'cancelled') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status' => 'Cancelled');
            } else if ($filterBy == 'overdue') {
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'UNIX_TIMESTAMP(due_date) <' => safe_strtotime(date('Y-m-d')));
                $status = array('partially_paid', 'Unpaid', 'Cancelled');
                $where_in = array('status', $status);
            } else if ($filterBy == 'last_month' || $filterBy == 'this_months') {
                if ($filterBy == 'last_month') {
                    $month = date('Y-m', safe_strtotime('-1 months'));
                } else {
                    $month = date('Y-m');
                }
                $where = array('show_client' => 'Yes', 'client_id' => $client_id, 'status !=' => 'draft', 'invoice_month' => $month);
            }
            // get all invoice
            $fetch_data = $this->datatables->get_client_invoices($filterBy);

            $data = array();
            $status_classes = array(
                lang('fully_paid') => 'border border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-300',
                lang('paid') => 'border border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-300',
                lang('draft') => 'border border-slate-200 bg-slate-50 text-slate-600 dark:border-slate-600 dark:bg-slate-700/40 dark:text-slate-200',
                lang('partially_paid') => 'border border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-300',
                lang('sent') => 'border border-sky-200 bg-sky-50 text-sky-700 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-300',
                lang('cancelled') => 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300',
                lang('not_paid') => 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300',
                lang('unpaid') => 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300',
                'Cancelled' => 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300',
                'Unpaid' => 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300',
                'Paid' => 'border border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-300',
            );
            foreach ($fetch_data as $_key => $v_invoices) {
                $action = null;

                if ($this->invoice_model->get_payment_status($v_invoices->invoices_id) == lang('fully_paid')) {
                    $invoice_status = lang('fully_paid');
                } elseif ($this->invoice_model->get_payment_status($v_invoices->invoices_id) == lang('draft')) {
                    $invoice_status = lang('draft');
                } elseif ($this->invoice_model->get_payment_status($v_invoices->invoices_id) == lang('partially_paid')) {
                    $invoice_status = lang('partially_paid');
                } elseif ($v_invoices->status != 'Cancelled' && $v_invoices->emailed == 'Yes') {
                    $invoice_status = lang('sent');
                } else {
                    $invoice_status = $this->invoice_model->get_payment_status($v_invoices->invoices_id);
                }

                $sub_array = array();
                $invoice_url = base_url() . 'client/invoice/manage_invoice/invoice_details/' . $v_invoices->invoices_id;
                $name = '<a class="break-words font-semibold text-primary hover:text-primary/80 dark:text-sky-300 dark:hover:text-sky-200" href="' . $invoice_url . '">' . html_escape($v_invoices->reference_no) . '</a>';
                $sub_array[] = $name;
                $payment_status = $this->invoice_model->get_payment_status($v_invoices->invoices_id);
                $overdue = null;
                if (safe_strtotime($v_invoices->due_date) < safe_strtotime(date('Y-m-d')) && $payment_status != lang('fully_paid') && $payment_status != lang('cancelled')) {
                    $overdue .= '<span class="inline-flex items-center rounded-full border border-rose-200 bg-rose-50 px-2 py-0.5 text-[11px] font-bold uppercase leading-none tracking-wide text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300">' . lang("overdue") . '</span>';
                }
                $sub_array[] = '<div class="flex flex-wrap items-center gap-2">' . display_date($v_invoices->due_date) . $overdue . '</div>';
                $sub_array[] = '<span class="font-semibold text-foreground">' . display_money($this->invoice_model->calculate_to('total', $v_invoices->invoices_id), client_currency($v_invoices->client_id)) . '</span>';
                $sub_array[] = '<span class="font-semibold text-foreground">' . display_money($this->invoice_model->calculate_to('invoice_due', $v_invoices->invoices_id), client_currency($v_invoices->client_id)) . '</span>';
                $recurring = null;
                if ($v_invoices->recurring == 'Yes') {
                    $recurring = '<span data-toggle="tooltip" data-placement="top" title="' . lang("recurring") . '" class="inline-flex h-6 w-6 items-center justify-center rounded-full border border-violet-200 bg-violet-50 text-violet-700 dark:border-violet-500/30 dark:bg-violet-500/10 dark:text-violet-300"><i data-lucide="repeat" class="h-3.5 w-3.5"></i></span>';
                }
                $status_class = !empty($status_classes[$invoice_status])
                    ? $status_classes[$invoice_status]
                    : 'border border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-300';
                $sub_array[] = "<div class='flex flex-wrap items-center gap-2'><span class='inline-flex items-center rounded-full px-2.5 py-1 text-[11px] font-bold uppercase leading-none tracking-wide " . $status_class . "'>" . $invoice_status . "</span>" . $recurring . "</div>";

                $data[] = $sub_array;
            }
            render_table($data, $where, $where_in);
        } else {
            redirect('client/dashboard');
        }
    }

    public function refund_itemslist($id = NULL)
    {
        $data['page'] = lang('invoices');
        $data['title'] = lang('invoices');
        $data['page_title'] = lang('invoices');
        $data['page_description'] = 'Overview of your business performance';
		$data['dataTables'] = true;
        $data['breadcrumbs'] = lang('refund') . ' ' . lang('items');
        $data['header_actions_html'] = btn_modal(
            'client/invoice/refund_items',
            lang('refund_items'),
            lang('refund_items'),
            '',
            'archive',
            array('class' => 'inline-flex items-center gap-2 rounded-xl border border-slate-900 bg-slate-900 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-800 dark:border-slate-100 dark:bg-slate-100 dark:text-slate-900 dark:hover:bg-white')
        );
        $data['subview'] = $this->load->view('client/invoice/refund_itemslist', $data, TRUE);
        $this->load->view('client/_layout_main', $data); //page load
    }

    public function RefundList()
    {
        if ($this->input->is_ajax_request()) {
            $this->load->model('datatables');
            $this->load->model('return_stock_model');
            $this->datatables->table = 'tbl_return_stock';
            $this->datatables->column_order = array('reference_no', 'return_stock_date', 'due_date', 'status', 'amount');
            $this->datatables->column_search = array('reference_no', 'return_stock_date', 'due_date', 'status', 'amount');
            $this->datatables->order = array('return_stock_id' => 'desc');
            $client_id = $this->session->userdata('client_id');
            $where = array('module' => 'client', 'module_id' => $client_id);

            $fetch_data = make_datatables($where);

            $data = array();
            foreach ($fetch_data as $_key => $v_return_stock) {
                if (!empty($v_return_stock)) {
                    $action = null;
                    $sub_array = array();
                    $currency = $this->return_stock_model->check_by(array('code' => config_item('default_currency')), 'tbl_currencies');

                    $sub_array[] = '<a href="' . base_url() . 'client/invoice/return_stock_details/' . $v_return_stock->return_stock_id . '">' . ($v_return_stock->reference_no) . '</a>';

                    $sub_array[] = display_date($v_return_stock->return_stock_date);
                    $sub_array[] = display_money($this->return_stock_model->calculate_to('return_stock_due', $v_return_stock->return_stock_id), $currency->symbol);
                    $status = $this->return_stock_model->get_payment_status($v_return_stock->return_stock_id);
                    if ($status == ('fully_paid')) {
                        $bg = "success";
                    } elseif ($status == ('partially_paid')) {
                        $bg = "warning";
                    } elseif ($v_return_stock->emailed == 'Yes') {
                        $bg = "info";
                    } else {
                        $bg = "danger";
                    }
                    $sub_array[] = '<span class="badge bg-' . $bg . '">' . lang($status) . '</span>';
                    if ($v_return_stock->status == 'Pending' && $v_return_stock->created_by == my_id()) {
                        $action .= ajax_anchor(base_url("client/invoice/delete_return_stock/" . $v_return_stock->return_stock_id), lang('delete'), array("class" => "", "title" => lang('delete'), "data-fade-out-on-success" => "#table_" . $_key)) . ' ';
                    }
                    $action .= btn_view('client/invoice/return_stock_details/' . $v_return_stock->return_stock_id) . ' ';
                    $sub_array[] = $action;
                    $data[] = $sub_array;
                }
            }
            render_table($data, $where);
        } else {
            redirect('client/dashboard');
        }
    }

    public function delete_return_stock($id)
    {
        $this->load->model('return_stock_model');
        $return_stock_info = $this->return_stock_model->check_by(array('return_stock_id' => $id), 'tbl_return_stock');
        if (!empty($return_stock_info) && $return_stock_info->status == 'Pending') {
            $this->return_stock_model->_table_name = 'tbl_return_stock_items';
            $this->return_stock_model->delete_multiple(array('return_stock_id' => $id));

            $this->return_stock_model->_table_name = 'tbl_return_stock_payments';
            $this->return_stock_model->delete_multiple(array('return_stock_id' => $id));

            $this->return_stock_model->_table_name = 'tbl_return_stock';
            $this->return_stock_model->_primary_key = 'return_stock_id';
            $this->return_stock_model->delete($id);

            $type = "success";
            if (!empty($return_stock_info->reference_no)) {
                $val = $return_stock_info->reference_no;
            } else {
                $val = NULL;
            }
            $activity = array(
                'user' => $this->session->userdata('user_id'),
                'module' => 'return_stock',
                'module_field_id' => $id,
                'activity' => ('activity_delete_return_stock'),
                'icon' => 'fa fa-truck',
                'value1' => $val,

            );
            $this->return_stock_model->_table_name = 'tbl_activities';
            $this->return_stock_model->_primary_key = 'activities_id';
            $this->return_stock_model->save($activity);

            echo json_encode(array("status" => $type, 'message' => lang('activity_delete_return_stock')));
            exit();
        } else {
            echo json_encode(array("status" => 'error', 'message' => lang('there_in_no_value')));
            exit();
        }
    }

    public function pdf_invoice($id)
    {
        $data['title'] = "Invoice PDF"; //Page title
        $data['invoice_info'] = $this->invoice_model->check_by(array('invoices_id' => $id), 'tbl_invoices');
        if (empty($data['invoice_info'])) {
            redirect('client/invoice/manage_invoice');
        }
        $client_id = client_id();
        if ($client_id != $data['invoice_info']->client_id) {
            redirect('client/invoice/manage_invoice');
        }
        $this->load->helper('dompdf');
        $viewfile = $this->load->view('client/invoice/invoice_pdf', $data, TRUE);
        pdf_create($viewfile, 'Invoice  # ' . $data['invoice_info']->reference_no);
    }

    public function payments_pdf($id)
    {
        $data['title'] = "Payments PDF"; //Page title
        // get payment info by id
        $this->invoice_model->_table_name = 'tbl_payments';
        $this->invoice_model->_order_by = 'payments_id';
        $data['payments_info'] = $this->invoice_model->get_by(array('payments_id' => $id), TRUE);
        $client_id = client_id();
        if ($client_id != $data['payments_info']->paid_by) {
            redirect('client/invoice/all_payments');
        }
        $this->load->helper('dompdf');
        $viewfile = $this->load->view('admin/invoice/payments_pdf', $data, TRUE);
        pdf_create($viewfile, 'Payment  # ' . $data['payments_info']->trans_id);
    }

    public function all_payments($id = NULL)
    {
        $data['breadcrumbs'] = lang('payments');
        $data['page'] = lang('payments');
        $data['page_title'] = lang('all_payments');
        $data['page_description'] = 'Overview of your business performance';
        $data['dataTables'] = true;
        if (!empty($id)) {
            $data['invoice_info'] = $this->invoice_model->check_by(array('invoices_id' => $id), 'tbl_invoices');
            if (empty($data['invoice_info'])) {
                redirect('client/invoice/manage_invoice');
            }
            // get payment info by id
            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->_order_by = 'payments_id';
            $data['payments_info'] = $this->invoice_model->get_by(array('payments_id' => $id), TRUE);

            $data['title'] = "Edit Payments"; //Page title
            $subview = 'edit_payments';
        } else {
            $data['title'] = "All Payments"; //Page title
            $subview = 'all_payments';
            $data['header_actions_html'] = btn_modal(
                'client/invoice/batch_payment?reset=1',
                'Batch Payment',
                'Batch Payment',
                'xl',
                'credit-card',
                array('class' => 'inline-flex items-center gap-2 rounded-xl border border-violet-600 bg-violet-600 px-4 py-2.5 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-violet-500 dark:border-violet-500 dark:bg-violet-500 dark:hover:bg-violet-400')
            );
        }
        // get payment info
        $this->invoice_model->_table_name = 'tbl_payments';
        $this->invoice_model->_order_by = 'invoices_id';
        $data['all_payments_info'] = $this->invoice_model->get_by(array('paid_by' => $this->session->userdata('client_id')), FALSE);

        $user_id = $this->session->userdata('user_id');
        $user_info = $this->invoice_model->check_by(array('user_id' => $user_id), 'tbl_users');
        $data['role'] = $user_info->role_id;

        $data['subview'] = $this->load->view('client/invoice/' . $subview, $data, TRUE);
        $this->load->view('client/_layout_main', $data); //page load
    }

    public function paymentList($filterBy = null, $search_by = null)
    {
        if ($this->input->is_ajax_request()) {
            $this->load->model('datatables');
            $this->datatables->table = 'tbl_payments';
            $this->datatables->select = array(
                'tbl_payments.*',
                'tbl_invoices.invoice_date',
                'tbl_invoices.date_saved',
                'tbl_invoices.reference_no',
                'tbl_client.name',
                'tbl_payment_methods.method_name'
            );
            $this->datatables->join_table = array('tbl_invoices', 'tbl_client', 'tbl_payment_methods');
            $this->datatables->join_where = array(
                'tbl_payments.invoices_id=tbl_invoices.invoices_id',
                'tbl_payments.paid_by=tbl_client.client_id',
                'tbl_payment_methods.payment_methods_id=tbl_payments.payment_method'
            );
            $this->datatables->column_order = array(
                'tbl_payments.payment_date',
                'tbl_invoices.invoice_date',
                'tbl_invoices.reference_no',
                'tbl_client.name',
                'tbl_payments.amount',
                'tbl_payment_methods.method_name',
                null
            );
            $this->datatables->column_search = array(
                'tbl_payments.trans_id',
                'tbl_payments.payment_date',
                'tbl_invoices.invoice_date',
                'tbl_invoices.reference_no',
                'tbl_client.name',
                'tbl_payments.amount',
                'tbl_payment_methods.method_name',
                'tbl_payments.payment_method'
            );
            $this->datatables->order = array('tbl_payments.payments_id' => 'desc');

            $client_id = client_id();
            $where = array('tbl_payments.paid_by' => $client_id);

            if (!empty($search_by)) {
                if ($search_by == 'by_invoice') {
                    $where['tbl_payments.invoices_id'] = $filterBy;
                }
            } else {
                if ($filterBy == 'last_month' || $filterBy == 'this_months') {
                    if ($filterBy == 'last_month') {
                        $month = date('m', safe_strtotime('-1 months'));
                        $year = date('Y', safe_strtotime('-1 months'));
                    } else {
                        $month = date('m');
                        $year = date('Y');
                    }
                    $where['year_paid'] = $year;
                    $where['month_paid'] = $month;
                } else if ($filterBy == 'today') {
                    $where['UNIX_TIMESTAMP(payment_date)'] = safe_strtotime(date('Y-m-d'));
                } else if (!empty($filterBy) && strstr((string) $filterBy, '_')) {
                    $where['year_paid'] = str_replace('_', '', $filterBy);
                }
            }

            $fetch_data = make_datatables($where);
            $data = array();
            foreach ($fetch_data as $_key => $v_payments_info) {
                if (empty($v_payments_info)) {
                    continue;
                }

                if (!empty($v_payments_info->system_currency)) {
                    $currency = $this->invoice_model->check_by(array('code' => $v_payments_info->system_currency), 'tbl_currencies');
                } else if (!empty($v_payments_info->client_currency)) {
                    $currency = $this->invoice_model->check_by(array('code' => $v_payments_info->client_currency), 'tbl_currencies');
                } else {
                    $currency = $this->invoice_model->client_currency_symbol($client_id);
                }
                if (empty($currency)) {
                    $currency = $this->invoice_model->check_by(array('code' => config_item('default_currency')), 'tbl_currencies');
                }

                $invoice_id = !empty($v_payments_info->invoices_id) ? (int) $v_payments_info->invoices_id : 0;
                $method_name = !empty($v_payments_info->method_name) ? $v_payments_info->method_name : $v_payments_info->payment_method;
                $action = btn_view('client/invoice/manage_invoice/payments_details/' . $v_payments_info->payments_id) . ' ';
                $action .= '<a data-toggle="tooltip" data-placement="top" href="' . base_url('client/invoice/payments_pdf/' . $v_payments_info->payments_id) . '" title="' . lang('pdf') . '" class="btn mb-1 h-7 gap-0.5 btn-info btn-xs ml-1"><i data-lucide="file-text" class="h-3.5 w-3.5"></i></a>';

                $sub_array = array();
                $sub_array[] = '<a class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300" href="' . base_url('client/invoice/manage_invoice/payments_details/' . $v_payments_info->payments_id) . '">' . display_date($v_payments_info->payment_date) . '</a>';
                $sub_array[] = !empty($v_payments_info->invoice_date) ? display_date($v_payments_info->invoice_date) : '-';
                $sub_array[] = '<a class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300" href="' . base_url('client/invoice/manage_invoice/invoice_details/' . $invoice_id) . '">' . (!empty($v_payments_info->reference_no) ? $v_payments_info->reference_no : '-') . '</a>';
                $sub_array[] = !empty($v_payments_info->name) ? $v_payments_info->name : lang('undefined_client');
                $sub_array[] = display_money($v_payments_info->amount, $currency->symbol);
                $sub_array[] = !empty($method_name) ? $method_name : '-';
                $sub_array[] = $action;
                $data[] = $sub_array;
            }

            render_table($data, $where);
        } else {
            redirect('client/dashboard');
        }
    }

    public function batch_payment()
    {
        $this->load->helper('string');

        if ($this->input->get('reset', true) == '1') {
            $this->clear_client_batch_payment_draft();
        }

        $page = (int) $this->input->get('page', true);
        $per_page = (int) $this->input->get('per_page', true);
        if ($page < 1) {
            $page = 1;
        }
        if (!in_array($per_page, array(10, 25, 50), true)) {
            $per_page = 10;
        }

        $client_id = (int) client_id();
        $total_invoices = $this->count_client_batch_payment_invoices($client_id);
        $total_pages = $total_invoices > 0 ? (int) ceil($total_invoices / $per_page) : 1;
        if ($page > $total_pages) {
            $page = $total_pages;
        }

        $draft = $this->get_client_batch_payment_draft();
        $rows = array();
        $invoice_rows = $this->get_client_batch_payment_invoice_page($client_id, $per_page, ($page - 1) * $per_page);
        foreach ((array) $invoice_rows as $invoice_row) {
            $invoice_id = (int) $invoice_row->invoices_id;
            $draft_row = !empty($draft[$invoice_id]) ? $draft[$invoice_id] : array();
            $invoice_currency = get_sales_currency($invoice_row);
            $rows[] = array(
                'invoices_id' => $invoice_id,
                'reference_no' => !empty($invoice_row->reference_no) ? $invoice_row->reference_no : ('INV-' . $invoice_id),
                'invoice_date' => $invoice_row->invoice_date,
                'due_date' => $invoice_row->due_date,
                'payment_date' => isset($draft_row['payment_date']) ? $draft_row['payment_date'] : date('Y-m-d'),
                'payment_methods_id' => isset($draft_row['payment_methods_id']) ? $draft_row['payment_methods_id'] : '',
                'trans_id' => isset($draft_row['trans_id']) ? $draft_row['trans_id'] : random_string('nozero', 6),
                'amount' => isset($draft_row['amount']) ? $draft_row['amount'] : '',
                'due_amount' => round((float) $invoice_row->due_amount, 2),
                'currency_symbol' => !empty($invoice_currency->symbol) ? $invoice_currency->symbol : client_currency($client_id),
            );
        }

        $data['batch_rows'] = $rows;
        $data['batch_page'] = $page;
        $data['batch_per_page'] = $per_page;
        $data['batch_total_pages'] = $total_pages;
        $data['batch_total_invoices'] = $total_invoices;
        $data['batch_draft_total'] = $this->get_client_batch_payment_draft_total($draft);
        $data['payment_methods'] = $this->db->order_by('method_name', 'asc')->get('tbl_payment_methods')->result();
        $data['redirect_to'] = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : base_url('client/invoice/all_payments');
        $data['subview'] = $this->load->view('client/invoice/batch_payment', $data, false);
        $this->load->view('client/_layout_modal', $data);
    }

    public function save_batch_payments()
    {
        $this->load->helper('string');

        $is_ajax = $this->input->is_ajax_request();
        $draft = $this->merge_client_batch_payment_draft_from_request();
        $redirect_to = $this->input->post('redirect_to', TRUE);
        if (empty($redirect_to) || strpos($redirect_to, base_url()) !== 0) {
            $redirect_to = base_url('client/invoice/all_payments');
        }

        $processed = 0;
        $errors = array();
        $client_id = (int) client_id();

        foreach ($draft as $invoice_id => $draft_row) {
            $invoice_id = (int) $invoice_id;
            $paid_amount = isset($draft_row['amount']) ? (float) $draft_row['amount'] : 0;
            if (empty($invoice_id) || $paid_amount <= 0) {
                continue;
            }

            $invoice_info = $this->invoice_model->check_by(array(
                'invoices_id' => $invoice_id,
                'client_id' => $client_id,
                'show_client' => 'Yes',
            ), 'tbl_invoices');
            if (empty($invoice_info)) {
                $errors[] = lang('no_data_found');
                continue;
            }

            $invoice_label = !empty($invoice_info->reference_no) ? $invoice_info->reference_no : ('#' . $invoice_id);
            $due_amount = round((float) $this->invoice_model->calculate_to('invoice_due', $invoice_id), 2);
            if ($due_amount <= 0) {
                continue;
            }
            if ($paid_amount > $due_amount) {
                $errors[] = $invoice_label . ': ' . lang('overpaid_amount');
                continue;
            }

            $payment_method = isset($draft_row['payment_methods_id']) ? trim($draft_row['payment_methods_id']) : '';
            if ($payment_method === '') {
                $errors[] = $invoice_label . ': ' . lang('payment_method') . ' is required';
                continue;
            }

            $payment_date = isset($draft_row['payment_date']) ? trim($draft_row['payment_date']) : '';
            if ($payment_date === '') {
                $payment_date = date('Y-m-d');
            }
            $payment_date = date('Y-m-d', safe_strtotime($payment_date));
            if (!finance_guard_accounting_period($payment_date, lang('invoice_payment'))) {
                $errors[] = $invoice_label . ': ' . lang('accounting_period_closed');
                continue;
            }

            $trans_id = isset($draft_row['trans_id']) ? trim($draft_row['trans_id']) : '';
            if ($trans_id === '') {
                $trans_id = random_string('nozero', 6);
            }

            $currency = $this->invoice_model->check_by(array('code' => $invoice_info->currency), 'tbl_currencies');
            $data = array(
                'invoices_id' => $invoice_id,
                'paid_by' => $client_id,
                'payment_method' => $payment_method,
                'currency' => !empty($currency->symbol) ? $currency->symbol : $invoice_info->currency,
                'amount' => $paid_amount,
                'payment_date' => $payment_date,
                'trans_id' => $trans_id,
                'notes' => '',
                'month_paid' => date("m", safe_strtotime($payment_date)),
                'year_paid' => date("Y", safe_strtotime($payment_date)),
            );

            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->_primary_key = 'payments_id';
            $this->invoice_model->save($data);

            $remaining_due = round((float) $this->invoice_model->calculate_to('invoice_due', $invoice_id), 2);
            update('tbl_invoices', array('invoices_id' => $invoice_id), array(
                'status' => ($remaining_due == 0) ? 'Paid' : 'partially_paid',
            ));
            $this->refresh_project_finance_cache($invoice_id);

            $activity = array(
                'user' => $this->session->userdata('user_id'),
                'module' => 'invoice',
                'module_field_id' => $invoice_id,
                'activity' => 'activity_new_payment',
                'icon' => 'fa-usd',
                'value1' => display_money($paid_amount, client_currency($client_id)),
                'value2' => $invoice_label,
            );
            $this->invoice_model->_table_name = 'tbl_activities';
            $this->invoice_model->_primary_key = 'activities_id';
            $this->invoice_model->save($activity);

            $processed++;
        }

        if (!empty($processed)) {
            set_message('success', $processed . ' payment(s) recorded successfully');
        }
        if (!empty($errors)) {
            foreach (array_slice($errors, 0, 5) as $error) {
                set_message('error', $error);
            }
        }
        if (empty($processed) && empty($errors)) {
            set_message('error', lang('there_in_no_value'));
        }

        if (!empty($processed)) {
            $this->clear_client_batch_payment_draft();
        }

        if ($is_ajax) {
            $message = !empty($processed)
                ? $processed . ' payment(s) recorded successfully'
                : (!empty($errors) ? implode('<br>', array_slice($errors, 0, 5)) : lang('there_in_no_value'));

            return $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode(array(
                    'status' => !empty($processed) ? 'success' : 'error',
                    'message' => $message,
                    'reload_page' => !empty($processed),
                )));
        }

        redirect($redirect_to);
    }

    public function save_batch_payment_draft()
    {
        if (!$this->input->is_ajax_request()) {
            show_404();
        }

        $draft = $this->merge_client_batch_payment_draft_from_request();
        return $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode(array(
                'status' => true,
                'draft_count' => count($draft),
                'draft_total' => $this->get_client_batch_payment_draft_total($draft),
            )));
    }

    public function save_invoice($id = NULL)
    {

        $data = $this->invoice_model->array_from_post(array('reference_no', 'client_id', 'tax', 'discount'));

        $data['due_date'] = date('Y-m-d', safe_strtotime($this->input->post('due_date', TRUE)));

        $data['notes'] = $this->input->post('notes', TRUE);

        $data['allow_paypal'] = $this->input->post('allow_paypal', TRUE) == 'on' ? 'Yes' : 'No';
        $data['allow_2checkout'] = $this->input->post('allow_2checkout', TRUE) == 'on' ? 'Yes' : 'No';
        $data['allow_stripe'] = $this->input->post('allow_stripe', TRUE) == 'on' ? 'Yes' : 'No';
        $data['allow_bitcoin'] = $this->input->post('allow_bitcoin', TRUE) == 'on' ? 'Yes' : 'No';

        $currency = $this->invoice_model->client_currency_symbol($data['client_id']);
        $data['currency'] = $currency->code;

        // get all client
        $this->invoice_model->_table_name = 'tbl_invoices';
        $this->invoice_model->_primary_key = 'invoices_id';
        if (!empty($id)) {
            $invoice_id = $id;
            $this->invoice_model->save($data, $id);
        } else {
            $invoice_id = $this->invoice_model->save($data);
        }

        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'invoice',
            'module_field_id' => $invoice_id,
            'activity' => 'activity_invoice_created',
            'icon' => 'fa-circle-o',
            'value1' => $data['reference_no']
        );
        $this->invoice_model->_table_name = 'tbl_activities';
        $this->invoice_model->_primary_key = 'activities_id';
        $this->invoice_model->save($activity);
        $this->refresh_project_finance_cache($invoice_id);

        // messages for user
        $type = "success";
        $message = lang('invoice_created');
        set_message($type, $message);
        redirect('client/invoice/manage_invoice');
    }

    public function add_item($id = NULL)
    {

        $data = $this->invoice_model->array_from_post(array('invoices_id', 'item_order'));
        $quantity = $this->input->post('quantity', TRUE);
        $array_data = $this->invoice_model->array_from_post(array('item_name', 'item_desc', 'item_tax_rate', 'unit_cost'));

        foreach ($quantity as $key => $value) {
            $data['quantity'] = $value;
            $data['item_name'] = $array_data['item_name'][$key];
            $data['item_desc'] = $array_data['item_desc'][$key];
            $data['unit_cost'] = $array_data['unit_cost'][$key];
            $data['item_tax_rate'] = $array_data['item_tax_rate'][$key];
            $sub_total = $data['unit_cost'] * $data['quantity'];

            $data['item_tax_total'] = ($data['item_tax_rate'] / 100) * $sub_total;
            $data['total_cost'] = $sub_total + $data['item_tax_total'];

            // get all client
            $this->invoice_model->_table_name = 'tbl_items';
            $this->invoice_model->_primary_key = 'items_id';
            if (!empty($id)) {
                $items_id = $id;
                $this->invoice_model->save($data, $id);
            } else {
                $items_id = $this->invoice_model->save($data);
            }
        }
        $this->refresh_project_finance_cache($data['invoices_id']);
        $type = "success";
        $message = lang('invoice_item_added');
        set_message($type, $message);
        redirect('client/invoice/manage_invoice/invoice_details/' . $data['invoices_id']);
    }

    public function change_status($action, $id)
    {
        $where = array('invoices_id' => $id);
        if ($action == 'hide') {
            $data = array('show_client' => 'No');
        } else {
            $data = array('show_client' => 'Yes');
        }
        $this->invoice_model->set_action($where, $data, 'tbl_invoices');
        // messages for user
        $type = "success";
        $message = lang('invoice_' . $action);
        set_message($type, $message);
        redirect('client/invoice/manage_invoice/invoice_details/' . $id);
    }

    public function delete($action, $invoices_id, $item_id = NULL)
    {
        $invoice_info = $this->invoice_model->check_by(array('invoices_id' => $invoices_id), 'tbl_invoices');
        $payment_info = null;
        if ($action == 'delete_payment') {
            $payment_info = $this->invoice_model->check_by(array('payments_id' => $invoices_id), 'tbl_payments');
        }
        if ($action == 'delete_item') {
            $this->invoice_model->_table_name = 'tbl_items';
            $this->invoice_model->_primary_key = 'items_id';
            $this->invoice_model->delete($item_id);
            if (!empty($invoice_info->project_id)) {
                finance_report_model()->refresh_project_finance_summary((int) $invoice_info->project_id);
            }
        } elseif ($action == 'delete_invoice') {
            $this->invoice_model->_table_name = 'tbl_items';
            $this->invoice_model->delete_multiple(array('invoices_id' => $invoices_id));

            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->delete_multiple(array('invoices_id' => $invoices_id));

            $this->invoice_model->_table_name = 'tbl_invoices';
            $this->invoice_model->_primary_key = 'invoices_id';
            $this->invoice_model->delete($invoices_id);
            if (!empty($invoice_info->project_id)) {
                finance_report_model()->refresh_project_finance_summary((int) $invoice_info->project_id);
            }
        } elseif ($action == 'delete_payment') {
            $this->invoice_model->_table_name = 'tbl_payments';
            $this->invoice_model->_primary_key = 'payments_id';
            $this->invoice_model->delete($invoices_id);
            if (!empty($payment_info->invoices_id)) {
                $this->refresh_project_finance_cache((int) $payment_info->invoices_id);
            }
        }
        $type = "success";
        if ($action == 'delete_item') {
            $text = lang('invoice_item_deleted');
            set_message($type, $text);
            redirect('client/invoice/manage_invoice/invoice_details/' . $invoices_id);
        } elseif ($action == 'delete_payment') {
            $text = lang('payment_deleted');
            set_message($type, $text);
            redirect('client/invoice/manage_invoice/all_payments');
        } else {
            $text = lang('deleted_invoice');
            set_message($type, $text);
            redirect('client/invoice/manage_invoice');
        }
    }

    public function get_payment($invoices_id)
    {

        $due = round($this->invoice_model->calculate_to('invoice_due', $invoices_id), 2);

        $paid_amount = $this->input->post('amount', TRUE);

        if ($paid_amount != 0) {
            if ($paid_amount > $due) {
                // messages for user
                $type = "error";
                $message = lang('overpaid_amount');
                set_message($type, $message);
                redirect('client/invoice/manage_invoice/payment/' . $invoices_id);
            } else {

                $inv_info = $this->invoice_model->check_by(array('invoices_id' => $invoices_id), 'tbl_invoices');

                $data = array(
                    'invoices_id' => $invoices_id,
                    'paid_by' => $inv_info->client_id,
                    'payment_method' => $this->input->post('payment_method', TRUE),
                    'currency' => $this->input->post('currency', TRUE),
                    'amount' => $paid_amount,
                    'payment_date' => date('Y-m-d', safe_strtotime($this->input->post('payment_date', TRUE))),
                    'trans_id' => $this->input->post('trans_id', true),
                    'notes' => $this->input->post('notes', true),
                    'month_paid' => date("m", safe_strtotime($this->input->post('payment_date', TRUE))),
                    'year_paid' => date("Y", safe_strtotime($this->input->post('payment_date', TRUE))),
                );
                if (!finance_guard_accounting_period($data['payment_date'], lang('invoice_payment'))) {
                    redirect('client/invoice/manage_invoice/payment/' . $invoices_id);
                    return;
                }

                $this->invoice_model->_table_name = 'tbl_payments';
                $this->invoice_model->_primary_key = 'payments_id';
                $this->invoice_model->save($data);
                $this->refresh_project_finance_cache($invoices_id);

                $activity = array(
                    'user' => $this->session->userdata('user_id'),
                    'module' => 'invoice',
                    'module_field_id' => $invoices_id,
                    'activity' => 'activity_new_payment',
                    'icon' => 'fa-usd',
                    'value1' => display_money($paid_amount, $inv_info->client_id),
                    'value2' => $inv_info->reference_no,
                );
                $this->invoice_model->_table_name = 'tbl_activities';
                $this->invoice_model->_primary_key = 'activities_id';
                $this->invoice_model->save($activity);

                if ($this->input->post('send_thank_you') == 'on') {
                    $this->send_payment_email($invoices_id, $paid_amount); //send thank you email
                }
            }
        }
        // messages for user
        $type = "success";
        $message = lang('generate_payment');
        set_message($type, $message);
        redirect('client/invoice/manage_invoice/invoice_details/' . $invoices_id);
    }

    public function update_payemnt($payments_id)
    {
        $data = array(
            'amount' => $this->input->post('amount', TRUE),
            'payment_method' => $this->input->post('payment_method', TRUE),
            'payment_date' => date('Y-m-d', safe_strtotime($this->input->post('payment_date', TRUE))),
            'notes' => $this->input->post('notes', TRUE),
            'month_paid' => date("m", safe_strtotime($this->input->post('payment_date', TRUE))),
            'year_paid' => date("Y", safe_strtotime($this->input->post('payment_date', TRUE))),
        );
        if (!finance_guard_accounting_period($data['payment_date'], lang('invoice_payment'))) {
            redirect('client/invoice/manage_invoice/all_payments');
            return;
        }
        $this->invoice_model->_table_name = 'tbl_payments';
        $this->invoice_model->_primary_key = 'payments_id';
        $this->invoice_model->save($data, $payments_id);
        $this->refresh_project_finance_cache_by_payment_id($payments_id);

        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'invoice',
            'module_field_id' => $payments_id,
            'activity' => 'activity_update_payment',
            'icon' => 'fa-usd',
            'value1' => $data['amount'],
            'value2' => $data['payment_date'],
        );
        $this->invoice_model->_table_name = 'tbl_activities';
        $this->invoice_model->_primary_key = 'activities_id';
        $this->invoice_model->save($activity);

        // messages for user
        $type = "success";
        $message = lang('generate_payment');
        set_message($type, $message);
        redirect('client/invoice/manage_invoice/all_payments');
    }

    private function refresh_project_finance_cache($invoices_id)
    {
        $invoice_info = $this->invoice_model->check_by(array('invoices_id' => (int) $invoices_id), 'tbl_invoices');
        if (!empty($invoice_info) && !empty($invoice_info->project_id)) {
            finance_report_model()->refresh_project_finance_summary((int) $invoice_info->project_id);
        }
    }

    private function refresh_project_finance_cache_by_invoice_id($invoices_id)
    {
        $this->refresh_project_finance_cache($invoices_id);
    }

    private function refresh_project_finance_cache_by_payment_id($payments_id)
    {
        $payment_info = $this->invoice_model->check_by(array('payments_id' => (int) $payments_id), 'tbl_payments');
        if (!empty($payment_info) && !empty($payment_info->invoices_id)) {
            $this->refresh_project_finance_cache((int) $payment_info->invoices_id);
        }
    }

    private function client_batch_payment_expressions()
    {
        $item_total_expr = 'COALESCE((SELECT SUM(tbl_items.total_cost) FROM tbl_items WHERE tbl_items.invoices_id = tbl_invoices.invoices_id), 0)';
        $tax_total_expr = 'COALESCE((SELECT SUM(tbl_items.item_tax_total) FROM tbl_items WHERE tbl_items.invoices_id = tbl_invoices.invoices_id), 0)';
        $paid_total_expr = 'COALESCE((SELECT SUM(tbl_payments.amount) FROM tbl_payments WHERE tbl_payments.invoices_id = tbl_invoices.invoices_id), 0)';
        $discount_expr = 'COALESCE(tbl_invoices.discount_total, 0)';
        $adjustment_expr = 'COALESCE(tbl_invoices.adjustment, 0)';
        $total_expr = 'GREATEST((' . $item_total_expr . ' - ' . $discount_expr . ' + ' . $adjustment_expr . ' + ' . $tax_total_expr . '), 0)';
        return array(
            'due_expr' => 'GREATEST((' . $total_expr . ' - ' . $paid_total_expr . '), 0)',
        );
    }

    private function apply_client_batch_payment_scope($client_id)
    {
        $expressions = $this->client_batch_payment_expressions();
        $this->db->from('tbl_invoices');
        $this->db->where('tbl_invoices.client_id', (int) $client_id);
        $this->db->where('tbl_invoices.show_client', 'Yes');
        $this->db->where('tbl_invoices.status !=', 'draft');
        $this->db->where('tbl_invoices.status !=', 'Cancelled');
        $this->db->where('tbl_invoices.status !=', 'cancelled');
        $this->db->where($expressions['due_expr'] . ' > 0', null, false);
        return $expressions;
    }

    private function count_client_batch_payment_invoices($client_id)
    {
        $this->apply_client_batch_payment_scope($client_id);
        return (int) $this->db->count_all_results();
    }

    private function get_client_batch_payment_invoice_page($client_id, $limit = 10, $offset = 0)
    {
        $expressions = $this->apply_client_batch_payment_scope($client_id);
        $this->db->select('tbl_invoices.invoices_id, tbl_invoices.client_id, tbl_invoices.reference_no, tbl_invoices.invoice_date, tbl_invoices.due_date, tbl_invoices.currency', false);
        $this->db->select($expressions['due_expr'] . ' AS due_amount', false);
        $this->db->order_by('tbl_invoices.due_date', 'ASC');
        $this->db->order_by('tbl_invoices.invoices_id', 'DESC');
        $this->db->limit((int) $limit, (int) $offset);
        return $this->db->get()->result();
    }

    private function client_batch_payment_draft_session_key()
    {
        return 'client_invoice_batch_payment_draft_' . (int) $this->session->userdata('user_id');
    }

    private function get_client_batch_payment_draft()
    {
        $draft = $this->session->userdata($this->client_batch_payment_draft_session_key());
        return is_array($draft) ? $draft : array();
    }

    private function set_client_batch_payment_draft(array $draft)
    {
        $this->session->set_userdata($this->client_batch_payment_draft_session_key(), $draft);
    }

    private function clear_client_batch_payment_draft()
    {
        $this->session->unset_userdata($this->client_batch_payment_draft_session_key());
    }

    private function merge_client_batch_payment_draft_from_request()
    {
        $draft = $this->get_client_batch_payment_draft();
        $invoice_ids = (array) $this->input->post('invoice_ids', TRUE);
        $payment_dates = (array) $this->input->post('payment_date', TRUE);
        $payment_methods = (array) $this->input->post('payment_methods_id', TRUE);
        $trans_ids = (array) $this->input->post('trans_id', TRUE);
        $amounts = (array) $this->input->post('amount', TRUE);

        foreach ($invoice_ids as $invoice_id) {
            $invoice_id = (int) $invoice_id;
            if (empty($invoice_id)) {
                continue;
            }
            $existing = !empty($draft[$invoice_id]) ? $draft[$invoice_id] : array();
            $draft[$invoice_id] = array(
                'payment_date' => isset($payment_dates[$invoice_id]) ? trim($payment_dates[$invoice_id]) : (isset($existing['payment_date']) ? $existing['payment_date'] : ''),
                'payment_methods_id' => isset($payment_methods[$invoice_id]) ? trim($payment_methods[$invoice_id]) : (isset($existing['payment_methods_id']) ? $existing['payment_methods_id'] : ''),
                'trans_id' => isset($trans_ids[$invoice_id]) ? trim($trans_ids[$invoice_id]) : (isset($existing['trans_id']) ? $existing['trans_id'] : ''),
                'amount' => isset($amounts[$invoice_id]) ? trim($amounts[$invoice_id]) : (isset($existing['amount']) ? $existing['amount'] : ''),
            );
        }

        $this->set_client_batch_payment_draft($draft);
        return $draft;
    }

    private function get_client_batch_payment_draft_total(array $draft)
    {
        $total = 0;
        foreach ($draft as $row) {
            $total += isset($row['amount']) ? (float) $row['amount'] : 0;
        }
        return $total;
    }

    function send_payment_email($invoices_id, $paid_amount)
    {
        $inv_info = $this->invoice_model->check_by(array('invoices_id' => $invoices_id), 'tbl_invoices');
        $email_template = email_templates(array('email_group' => 'payment_email'), $inv_info->client_id);
        $message = $email_template->template_body;
        $subject = $email_template->subject;

        $currency = $inv_info->currency;
        $reference = $inv_info->reference_no;

        $invoice_currency = str_replace("{INVOICE_CURRENCY}", $currency, $message);
        $reference = str_replace("{INVOICE_REF}", $reference, $invoice_currency);
        $amount = str_replace("{PAID_AMOUNT}", $paid_amount, $reference);
        $message = str_replace("{SITE_NAME}", config_item('company_name'), $amount);

        $data['message'] = $message;
        $message = $this->load->view('email_template', $data, TRUE);
        $client_info = $this->invoice_model->check_by(array('client_id' => $inv_info->client_id), 'tbl_client');

        $address = $client_info->email;

        $params['recipient'] = $address;

        $params['subject'] = '[ ' . config_item('company_name') . ' ]' . ' ' . $subject;
        $params['message'] = $message;
        $params['resourceed_file'] = '';
        $this->invoice_model->send_email($params);
    }

    public function send_invoice_email($invoice_id)
    {

        $ref = $this->input->post('ref', TRUE);
        $subject = $this->input->post('subject', TRUE);
        $message = $this->input->post('message', TRUE);

        $client_name = str_replace("{CLIENT}", $this->input->post('client_name', TRUE), $message);
        $Ref = str_replace("{REF}", $ref, $client_name);
        $Amount = str_replace("{AMOUNT}", $this->input->post('amount'), $Ref);
        $Currency = str_replace("{CURRENCY}", $this->input->post('currency', TRUE), $Amount);
        $link = str_replace("{INVOICE_LINK}", base_url() . 'admin/invoice/invoice_details/' . $invoice_id, $Currency);
        $message = str_replace("{SITE_NAME}", config_item('company_name'), $link);


        $this->send_email_invoice($invoice_id, $message, $subject); // Email Invoice

        $data = array('emailed' => 'Yes', 'date_sent' => date("Y-m-d H:i:s", time()));

        $this->invoice_model->_table_name = 'tbl_invoices';
        $this->invoice_model->_primary_key = 'invoices_id';
        $this->invoice_model->save($data, $invoice_id);

        // Log Activity
        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'invoice',
            'module_field_id' => $invoice_id,
            'activity' => 'activity_invoice_sent',
            'icon' => 'fa-envelope',
            'value1' => $ref
        );
        $this->invoice_model->_table_name = 'tbl_activities';
        $this->invoice_model->_primary_key = 'activities_id';
        $this->invoice_model->save($activity);
    }

    function send_email_invoice($invoice_id, $message, $subject)
    {
        $invoice_info = $this->invoice_model->check_by(array('invoices_id' => $invoice_id), 'tbl_invoices');
        $client_info = $this->invoice_model->check_by(array('client_id' => $invoice_info->client_id), 'tbl_client');

        $recipient = $client_info->email;

        $data['message'] = $message;

        $message = $this->load->view('email_template', $data, TRUE);


        $params = array(
            'recipient' => $recipient,
            'subject' => $subject,
            'message' => $message
        );

        $params['resourceed_file'] = '';
        $this->invoice_model->send_email($params);
    }

    public function tax_rates($action = NULL, $id = NULL)
    {

        $data['page'] = lang('sales');
        $data['sub_active'] = lang('tax_rates');
        if ($action == 'edit_tax_rates') {
            $data['active'] = 2;
            if (!empty($id)) {
                $data['tax_rates_info'] = $this->invoice_model->check_by(array('tax_rates_id' => $id), 'tbl_tax_rates');
            }
        } else {
            $data['active'] = 1;
        }
        if ($action == 'delete_tax_rates') {
            $this->invoice_model->_table_name = 'tbl_tax_rates';
            $this->invoice_model->_primary_key = 'tax_rates_id';
            $this->invoice_model->delete($id);
            // messages for user
            $type = "success";
            $message = lang('tax_deleted');
            set_message($type, $message);
            redirect('client/invoice/tax_rates');
        } else {
            $data['title'] = "Tax Rates Info"; //Page title
            $subview = 'tax_rates';
        }
        $user_id = $this->session->userdata('user_id');
        $user_info = $this->invoice_model->check_by(array('user_id' => $user_id), 'tbl_users');
        $data['role'] = $user_info->role_id;

        $data['subview'] = $this->load->view('client/invoice/' . $subview, $data, TRUE);
        $this->load->view('client/_layout_main', $data); //page load
    }

    public function save_tax_rate($id = NULL)
    {
        $data = $this->invoice_model->array_from_post(array('tax_rate_name', 'tax_rate_percent'));

        $this->invoice_model->_table_name = 'tbl_tax_rates';
        $this->invoice_model->_primary_key = 'tax_rates_id';
        $id = $this->invoice_model->save($data, $id);

        // Log Activity
        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'invoice',
            'module_field_id' => $id,
            'activity' => 'activity_taxt_rate_set',
            'icon' => 'fa-circle-o',
            'value1' => $data['tax_rate_name'],
        );
        $this->invoice_model->_table_name = 'tbl_activities';
        $this->invoice_model->_primary_key = 'activities_id';
        $this->invoice_model->save($activity);

        // messages for user
        $type = "success";
        $message = lang('tax_added');
        set_message($type, $message);
        redirect('client/invoice/tax_rates');
    }

    public
    function refund_items()
    {
        $data['title'] = lang('refund_items');
        $data['breadcrumbs'] = lang('refund') . ' ' . lang('items');
        $data['all_invoices'] = $this->db->where(array('client_id' => client_id(), 'status !=' => 'Paid'))->get('tbl_invoices')->result();
         $this->load->view('client/invoice/refund_items', $data, FALSE);
        // $this->load->view('client/_layout_modal', $data);
    }

    public
    function select_item($invoice_id)
    {
        $data['title'] = lang('refund_items');
        $data['breadcrumbs'] = lang('refund_items');
        $data['invoice_info'] = get_row('tbl_invoices', array('invoices_id' => $invoice_id, 'client_id' => client_id()));
        if (empty($data['invoice_info'])) {
            set_message('error', lang('no_data_found'));
            redirect('client/invoice/refund_itemslist');
        }
        $payment_status = $this->invoice_model->get_payment_status($data['invoice_info']->invoices_id);
        if ($data['invoice_info']->status == 'Paid' || $payment_status == lang('fully_paid') || $payment_status == 'fully_paid') {
            set_message('error', lang('there_in_no_value'));
            redirect('client/invoice/refund_itemslist');
        }
        $data['subview'] = $this->load->view('client/invoice/select_refund_items', $data, true);
        $this->load->view('client/_layout_main', $data);
    }

    public function submit_refund_items($invoice_id)
    {

        $this->load->model('return_stock_model');
        $invoice_info = get_row('tbl_invoices', array('invoices_id' => $invoice_id, 'client_id' => client_id()));
        if (empty($invoice_info)) {
            set_message('error', lang('no_data_found'));
            redirect('client/invoice/refund_itemslist');
        }
        $reference_no = $this->return_stock_model->generate_return_stock_number();
        $data['reference_no'] = $reference_no;
        $data['invoices_id'] = $invoice_id;
        $data['module'] = 'client';
        $data['module_id'] = client_id();
        $data['return_stock_date'] = date('Y-m-d');
        $data['due_date'] = date('Y-m-d', safe_strtotime('+7 days'));
        $data['tax'] = $invoice_info->tax;
        $data['total_tax'] = $invoice_info->total_tax;
        $data['permission'] = $invoice_info->permission;
        $data['discount_type'] = $invoice_info->discount_type;
        $data['discount_percent'] = $invoice_info->discount_percent;
        $data['user_id'] = $invoice_info->user_id;
        $data['main_status'] = 'Pending';
        $data['status'] = 'Pending';
        $data['adjustment'] = $invoice_info->adjustment;
        $data['discount_total'] = $invoice_info->discount_total;
        $data['show_quantity_as'] = $invoice_info->show_quantity_as;
        $data['update_stock'] = 'No';
        $tax['tax_name'] = $this->input->post('total_tax_name', TRUE);
        $tax['total_tax'] = $this->input->post('total_tax', TRUE);
        $data['total_tax'] = json_encode($tax);
        $i_tax = 0;
        if (!empty($tax['total_tax'])) {
            foreach ($tax['total_tax'] as $v_tax) {
                $i_tax += $v_tax;
            }
        }
        $data['tax'] = $i_tax;

        // get all client
        $this->return_stock_model->_table_name = 'tbl_return_stock';
        $this->return_stock_model->_primary_key = 'return_stock_id';
        if (!empty($id)) {
            $return_stock_id = $id;
            $this->return_stock_model->save($data, $id);
            $action = ('return_stock_updated');
            $msg = lang('return_stock_updated');

        } else {
            $data['created_by'] = my_id();
            $return_stock_id = $this->return_stock_model->save($data);
            $action = ('return_stock_created');
            $msg = lang('return_stock_created');
        }

        $items_data = $this->input->post('items', true);
        if (!empty($items_data)) {
            $index = 0;
            foreach ($items_data as $items) {
                $items['return_stock_id'] = $return_stock_id;
                $items['invoice_items_id'] = $items['items_id'];
                $tax = 0;
                if (!empty($items['taxname'])) {
                    foreach ($items['taxname'] as $tax_name) {
                        $tax_rate = explode("|", $tax_name);
                        $tax += $tax_rate[1];
                    }
                    $items['item_tax_name'] = $items['taxname'];
                    unset($items['taxname']);
                    $items['item_tax_name'] = json_encode($items['item_tax_name']);
                }
                if (empty($items['saved_items_id'])) {
                    $items['saved_items_id'] = 0;
                }

                $price = $items['quantity'] * $items['unit_cost'];
                $items['item_tax_total'] = ($price / 100 * $tax);
                $items['total_cost'] = $price;

                // get all client
                $this->return_stock_model->_table_name = 'tbl_return_stock_items';
                $this->return_stock_model->_primary_key = 'items_id';
                $items_id = $this->return_stock_model->save($items);
                $index++;
            }
        }
        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'return_stock',
            'module_field_id' => $return_stock_id,
            'activity' => $action,
            'icon' => 'fa fa-truck',
            'link' => 'admin/return_stock/return_stock_details/' . $return_stock_id,
            'value1' => $data['reference_no']
        );
        $this->return_stock_model->_table_name = 'tbl_activities';
        $this->return_stock_model->_primary_key = 'activities_id';
        $this->return_stock_model->save($activity);

        $data['return_stock_id'] = $return_stock_id;
        $this->send_email_return_stock($invoice_id, $data); // Email Invoice


        // messages for user
        $type = "success";
        $message = $msg;
        set_message($type, $message);
        redirect('client/invoice/return_stock_details/' . $return_stock_id);
    }

    function send_email_return_stock($invoice_id, $data)
    {
        $invoice_info = $this->invoice_model->check_by(array('invoices_id' => $invoice_id), 'tbl_invoices');
        $email_template = email_templates(array('email_group' => 'invoice_item_refund_request'), $invoice_info->client_id);
        $message = $email_template->template_body;
        $subject = $email_template->subject;

        $reference = str_replace("{REF}", $invoice_info->reference_no, $message);
        $amount = str_replace("{INVOICE_LINK}", 'admin/return_stock/return_stock_details/' . $data['return_stock_id'], $reference);
        $message = str_replace("{SITE_NAME}", config_item('company_name'), $amount);
        $params['subject'] = '[ ' . config_item('company_name') . ' ]' . ' ' . $subject;
        $params['message'] = $message;
        $params['resourceed_file'] = '';

        $users = array($data['user_id'], my_department_head($data['user_id']));
        if (!empty($users)) {
            foreach ($users as $v_user) {
                $login_info = $this->invoice_model->check_by(array('user_id' => $v_user), 'tbl_users');
                $params['recipient'] = $login_info->email;
                $this->invoice_model->send_email($params);

                if ($v_user != $this->session->userdata('user_id')) {
                    add_notification(array(
                        'to_user_id' => $v_user,
                        'icon' => 'shopping-cart',
                        'description' => 'not_new_refund_request_for_invoice',
                        'link' => 'admin/return_stock/return_stock_details/' . $data['return_stock_id'],
                        'value' => $invoice_info->reference_no . ' ' . lang('return_stock') . ' ' . lang('reference_no') . ': ' . $data['reference_no'],
                    ));
                }
            }
            show_notification($users);
        }
        $this->invoice_model->send_email($params);
    }

    public function return_stock_details($id)
    {
        $this->load->model('return_stock_model');
        $data['title'] = lang('return_stock') . ' ' . lang('details'); //Page title
        $data['breadcrumbs'] = lang('return_stock') . ' ' . lang('details');
        $data['return_stock_info'] = $this->invoice_model->check_by(array('return_stock_id' => $id), 'tbl_return_stock');
        if (empty($data['return_stock_info'])) {
            set_message('error', lang('there_in_no_value'));
            redirect('client/return_stock/manage_invoice');
        }
        $data['subview'] = $this->load->view('client/invoice/return_stock_details', $data, TRUE);
        $this->load->view('client/_layout_main', $data); //page load
    }

    public function pdf_return_stock($id)
    {
        $this->load->model('return_stock_model');
        $data['return_stock_info'] = $this->return_stock_model->check_by(array('return_stock_id' => $id), 'tbl_return_stock');
        $data['title'] = lang('return_stock') . ' ' . "PDF"; //Page title
        $this->load->helper('dompdf');
        $viewfile = $this->load->view('admin/return_stock/return_stock_pdf', $data, TRUE);

        pdf_create($viewfile, lang('return_stock') . '# ' . $data['return_stock_info']->reference_no);
    }
}
