/home/smartonegroup/www/system/system/controllers/invoices.php
<?php
/*
|--------------------------------------------------------------------------
| Controller
|--------------------------------------------------------------------------
|
*/
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email as SymfonyEmail;
use Symfony\Component\Mime\Address as SymfonyAddress;

_auth();
$ui->assign('selected_navigation', 'invoices');
$ui->assign('_title', $_L['Sales'] . '- ' . $config['CompanyName']);
$action = $routes['1'];
$user = authenticate_admin();
Event::trigger('invoices');

$sales_all_data = has_access($user->roleid, 'sales', 'all_data');

$data = request()->all();

switch ($action) {
    case 'add':
    case 'edit':
    case 'credit-note':
        $customers_all_data = has_access(
            $user->roleid,
            'customers',
            'all_data'
        );

        $extraHtml = '';

        $app->emit('invoices_add');

        $extra_fields = '';
        $extra_jq = '';

        Event::trigger('add_invoice');

        $ui->assign('extra_fields', $extra_fields);

        $recurring = false;

        $p_cid = '';

        $invoice = false;
        $contact = false;
        $items = false;

        if ($action == 'add') {
            if (isset($routes['2']) && $routes['2'] == 'recurring') {
                $recurring = true;
            }

            if (
                isset($routes['3']) &&
                $routes['3'] != '' &&
                $routes['3'] != '0'
            ) {
                $p_cid = $routes['3'];
                $p_d = ORM::for_table('crm_accounts')->find($p_cid);
                if (!$p_d) {
                    $p_cid = '';
                }
            }
        } elseif ($action == 'edit') {
            $id = route(2);
            $invoice = Invoice::find($id);

            $p_cid = $invoice->userid;

            if ($invoice->r != 0) {
                $recurring = true;
            }
        }

        if ($invoice) {
            $contact = Contact::find($invoice->userid);
            $items = InvoiceItem::where('invoiceid', $invoice->id)
                ->orderBy('id', 'asc')
                ->get();
        }
        $ui->assign('p_cid', $p_cid);

        $ui->assign('recurring', $recurring);



        $c = Contact::select(['id','account','company','email','phone','code'])->where('type','like', '%Customer%')
            ->orderBy('id', 'desc');

        if (!$customers_all_data) {
            $c->where('o', $user->id);
        }

        $c = $c->get()->toArray();

        $ui->assign('c', $c);
        $t = ORM::for_table('sys_tax')->find_array();
        $ui->assign('t', $t);
        $ui->assign('idate', date('Y-m-d'));

        $tax_default = ORM::for_table('sys_tax')
            ->where('is_default', 1)
            ->first();

        $tax_system = $config['tax_system'];

        switch ($tax_system) {
            case 'India':
                $states = Tax::indianStates();

                break;

            default:
                $states = [];
        }

        $pos = route(4);

        $project_id = route(5, false);

        if ($project_id !== '' && $project_id !== '0') {
        }

        Event::trigger('add_invoice_rendering_form');

        $project = false;

        $project_id = $invoice ? $invoice->pid : route(5, false);

        if ($project_id) {
            $project = Project::find($project_id);
        }

        $staffs = User::all()->keyBy('id')->all();

        $invoice_groups = [];

        if(!empty($config['invoice_group']))
        {
            $invoice_groups = InvoiceGroup::all();
        }

        $services = [];

        if(!empty($config['invoice_single_service']))
        {
            $services = Item::all();
        }

        $contracts = Contract::query()
            ->select(['id','title'])
            ->orderBy('id','desc')
            ->limit(500)
            ->get();

        view('invoice', [
            'pos' => $pos,
            'tax_default' => $tax_default,
            'states' => $states,
            'extraHtml' => $extraHtml,
            'currencies' => getActiveCurrencies(),
            'invoice' => $invoice,
            'contact' => $contact,
            'items' => $items,
            'project' => $project,
            'staffs' => $staffs,
            'action' => $action,
            'invoice_groups' => $invoice_groups,
            'services' => $services,
            'contracts' => $contracts,
        ]);

        break;


    case 'pos-receipt':
    case 'pos-pdf':
    case 'pos-print':
        case 'delivery-label':
        case 'delivery-label-pdf':
        case 'delivery-label-print':

    $barcode_generator = new Picqer\Barcode\BarcodeGeneratorPNG();

        $today = date('Y-m-d H:i:s');

        $id = $routes['2'];
        $d = ORM::for_table('sys_invoices')->find($id);
        if ($d) {
            $invoice = Invoice::find($id);

            $render = route(4, 'invoice');

            $items = ORM::for_table('sys_invoiceitems')
                ->where('invoiceid', $id)
                ->order_by_asc('id')
                ->find_many();
            $ui->assign('items', $items);
            //find related transactions
            $trs_c = ORM::for_table('sys_transactions')
                ->where('iid', $id)
                ->count();
//
            $trs = ORM::for_table('sys_transactions')
                ->where('iid', $id)
                ->order_by_desc('id')
                ->find_many();
            $ui->assign('trs', $trs);
            $ui->assign('trs_c', $trs_c);
            $a = ORM::for_table('crm_accounts')->find($d['userid']);
            $ui->assign('a', $a);
            $ui->assign('d', $d);



            $i_credit = $d['credit'];
            $i_due = '0.00';
            $i_total = $d['total'];
            $i_due = $d['credit'] != '0.00' ? $i_total - $i_credit : $d['total'];

            $ui->assign('i_due', $i_due);

            $cf = ORM::for_table('crm_customfields')
                ->where('showinvoice', 'Yes')
                ->order_by_asc('id')
                ->find_many();
            $ui->assign('cf', $cf);
//
            $x_html = '';

            Event::trigger('view_invoice');

            $ui->assign('x_html', $x_html);

            $inv_files = Invoice::files($id);

            $inv_files_c = count($inv_files);

            $ui->assign('inv_files_c', $inv_files_c);

            $ui->assign('inv_files', $inv_files);
//
//            //

            if (!isset($_SESSION['uid'])) {
                $ip = get_client_ip();
                // log invoice access log

                $country = $_L['Unknown'];
                $city = $_L['Unknown'];
                $lat = '';
                $lon = '';

                $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';

                $browser = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';

                if ($config['maxmind_installed'] == 1) {
                    $l_data = Ip2Location::getDetails($ip);

                    $country = $l_data['country'];
                    $city = $l_data['city'];
                    $lat = $l_data['lat'];
                    $lon = $l_data['lon'];
                }

                $ial = ORM::for_table('ib_invoice_access_log')->create();
                $ial->iid = $id;
                $ial->ip = $ip;
                $ial->browser = $browser;
                $ial->referer = $referer;
                $ial->country = $country;
                $ial->city = $city;
                $ial->viewed_at = $today;
                $ial->customer = $d->account;
                $ial->save();
            }

            //

            $company = $a->cid != '' || $a->cid != 0 ? Company::find($a->cid) : false;

            // find the quote

            $quote = false;

            if ($d->quote_id != '0') {
                $quote = ORM::for_table('sys_quotes')->find($d->quote_id);
            }
//
            $plugin_extra_js = '';

            $invoice_url =
                U . 'client/iview/' . $d->id . '/token_' . $d->vtoken;

            $qr_code = (new \chillerlan\QRCode\QRCode())->render($invoice_url);

            $qr_code_admin_url = (new \chillerlan\QRCode\QRCode())->render(U.'invoices/view/'.$d->id);

            $app->emit('client_viewing_invoice', [&$d, &$a]);

            $currencies_all = Currency::getAllCurrencies();

            if (isset($currencies_all[$d->currency_iso_code])) {
                $data_a_sign = $currencies_all[$d->currency_iso_code]['symbol'];
                $data_a_sep =
                    $currencies_all[$d->currency_iso_code][
                    'thousands_separator'
                    ];
                $data_a_dec =
                    $currencies_all[$d->currency_iso_code]['decimal_mark'];

                $data_p_sign = $currencies_all[$d->currency_iso_code] == true ? 'p' : 's';
            } else {
                $data_a_sign = $config['currency_code'];
                $data_a_sep = $config['thousands_sep'];
                $data_a_dec = $config['dec_point'];
                $data_p_sign = $config['currency_symbol_position'];
            }

            $payment_gateways = PaymentGateway::where('status', 'Active')
                ->orderBy('sorder', 'asc')
                ->get();

            $payment_gateways_by_processor = $payment_gateways
                ->keyBy('processor')
                ->toArray();

            $format_currency_override = [];

            if (isset($config['decimal_places_products_and_services'])) {
                $format_currency_override['precision'] =
                    $config['decimal_places_products_and_services'];
            }

            $data = [

                'invoice' => $invoice,
                'company' => $company,
                'quote' => $quote,

                'plugin_extra_js' => $plugin_extra_js,
                'data_a_sign' => $data_a_sign,
                'data_a_sep' => $data_a_sep,
                'data_a_dec' => $data_a_dec,
                'data_p_sign' => $data_p_sign,
                'payment_gateways' => $payment_gateways,
                'payment_gateways_by_processor' => $payment_gateways_by_processor,
                'render' => $render,
                'format_currency_override' => $format_currency_override,
                'qr_code' => $qr_code,
                'barcode_generator' => $barcode_generator,
                'qr_code_admin_url' => $qr_code_admin_url,
            ];

            if($action == 'pos-receipt'){
                \view('invoice_pos_receipt', $data);
            }
            elseif ($action == 'pos-pdf' || $action == 'delivery-label-pdf')
            {
                $pdf_c = '';
                $ib_w_font = 'dejavusanscondensed';
                if ($config['pdf_font'] == 'default') {
                    $pdf_c = 'c';
                    $ib_w_font = 'Helvetica';
                }

                try {
                    $mpdf = new \Mpdf\Mpdf(['mode' => 'utf-8','format' => [80,400],'margin_left' => 5,'margin_right' => 5,'margin_top' => 5,'margin_bottom' => 5,'margin_header' => 0,'margin_footer' => 0]);
                    $mpdf->SetTitle($config['CompanyName'] . ' Invoice');
                    $mpdf->SetAuthor($config['CompanyName']);
                    $mpdf->SetDisplayMode('fullpage');

                    if ($config['rtl'] == 1) {
                        $mpdf->SetDirectionality('rtl');
                    }

                    if ($config['pdf_font'] == 'AdobeCJK') {
                        $mpdf->useAdobeCJK = true;
                        $mpdf->autoScriptToLang = true;
                        $mpdf->autoLangToFont = true;
                    }

                    if($action == 'pos-pdf')
                    {
                        $html = view_render('invoice_pos_receipt_pdf', $data);
                    }
                    elseif ($action == 'delivery-label-pdf')
                    {
                        $html = view_render('invoice_delivery_label_pdf', $data);
                    }


                    $mpdf->WriteHTML($html);

                    $mpdf->Output(date('Y-m-d') . _raid(4) . '.pdf', 'I'); # D

                } catch (\Exception $e) {
                    dd(
                        'An error occurred, probably related to your server! : ',
                        $e->getMessage(),
                        "\n"
                    );
                }
            }
            elseif($action == 'pos-print'){
                view('invoice_pos_receipt_pdf', $data);
            }

            elseif($action == 'delivery-label'){
                view('invoice_delivery_label', $data);
            }

            elseif($action == 'delivery-label-print'){
                view('invoice_delivery_label_pdf', $data);
            }


        }

        break;

    case 'view':
        $extraHtml = '';
        $id = $routes['2'];
        $app->emit('invoices_view', [&$id]);

        $d = Invoice::find($id);
        if ($d) {

            $invoice = $d;

            if (!$sales_all_data && $d->aid != $user->id) {
                permissionDenied();
            }

            $items = ORM::for_table('sys_invoiceitems')
                ->where('invoiceid', $id)
                ->order_by_asc('id')
                ->find_many();
            $ui->assign('items', $items);


            $trs_c = Transaction::where('iid',$id)->count();


            $trs = ORM::for_table('sys_transactions')
                ->where('iid', $id)
                ->order_by_desc('id')
                ->find_many();
            $ui->assign('trs', $trs);
            $ui->assign('trs_c', $trs_c);

            $emls_c = EmailLog::where('iid',$id)->count();

            $emls = ORM::for_table('sys_email_logs')
                ->where('iid', $id)
                ->order_by_desc('id')
                ->find_many();
            $ui->assign('emls', $emls);
            $ui->assign('emls_c', $emls_c);

            $a = Contact::find($d->userid);

            $customer = $a;

            $ui->assign('a', $a);
            $ui->assign('d', $d);
            $i_credit = $d['credit'];
            $i_due = '0.00';
            $i_total = $d['total'];
            $i_due = $d['credit'] != '0.00' ? $i_total - $i_credit : $d['total'];

            $ui->assign('i_due', $i_due);
            $cf = ORM::for_table('crm_customfields')
                ->where('showinvoice', 'Yes')
                ->order_by_asc('id')
                ->find_many();
            $ui->assign('cf', $cf);

            $x_html = '';
            Event::trigger('view_invoice');
            $ui->assign('x_html', $x_html);

            $upload_max_size = ini_get('upload_max_filesize');
            $post_max_size = ini_get('post_max_size');
            $ui->assign('upload_max_size', $upload_max_size);
            $ui->assign('post_max_size', $post_max_size);

            // count attachments

            $inv_files = Invoice::files($id);
            $inv_files_c = count($inv_files);
            $ui->assign('inv_files_c', $inv_files_c);
            $ui->assign('inv_files', $inv_files);


            $access_logs = InvoiceAccessLog::where('iid',$id)->orderBy('id','desc')->get();

            $ui->assign('access_logs', $access_logs);

            $currency_rate = 1;

            // find the company

            $company = $a->cid != '' || $a->cid != 0 ? Company::find($a->cid) : false;

            // find the quote

            $quote = false;

            if ($d->quote_id != '0') {
                $quote = ORM::for_table('sys_quotes')->find($d->quote_id);
            }

            $currencies_all = Currency::getAllCurrencies();

            if (isset($currencies_all[$d->currency_iso_code])) {
                $data_a_sign = $currencies_all[$d->currency_iso_code]['symbol'];
                $data_a_sep =
                    $currencies_all[$d->currency_iso_code][
                        'thousands_separator'
                    ];
                $data_a_dec =
                    $currencies_all[$d->currency_iso_code]['decimal_mark'];

                $data_p_sign = $currencies_all[$d->currency_iso_code] == true ? 'p' : 's';
            } else {
                $data_a_sign = $config['currency_code'];
                $data_a_sep = $config['thousands_sep'];
                $data_a_dec = $config['dec_point'];
                $data_p_sign = $config['currency_symbol_position'];
            }

            $format_currency_override = [];

            if (isset($config['decimal_places_products_and_services'])) {
                $format_currency_override['precision'] =
                    $config['decimal_places_products_and_services'];
            }

            $staffs = User::all()->keyBy('id')->all();
            $sms_templates = SMSTemplate::all();

            $sms_templates_transformed = [];


            foreach ($sms_templates as $sms_template) {

                if($sms_template->tpl == 'Invoice Created')
                {
                    $sms_templates_transformed['created'] = Invoice::genSMS($invoice, 'created', $customer);
                }
                elseif($sms_template->tpl == 'Invoice Payment Reminder')
                {
                    $sms_templates_transformed['reminder'] = Invoice::genSMS($invoice, 'reminder', $customer);
                }
                elseif($sms_template->tpl == 'Invoice Payment Confirmation')
                {
                    $sms_templates_transformed['confirmation'] = Invoice::genSMS($invoice, 'confirmation', $customer);
                }
                elseif($sms_template->tpl == 'Invoice Overdue Notice')
                {
                    $sms_templates_transformed['overdue'] = Invoice::genSMS($invoice, 'overdue', $customer);
                }
                elseif ($sms_template->tpl == 'Invoice Refund Confirmation')
                {
                    $sms_templates_transformed['refund'] = Invoice::genSMS($invoice, 'refund', $customer);
                }

            }


            view('invoices_view', [
                'currencies' => Currency::all(),
                'currency_rate' => $currency_rate,
                'company' => $company,
                'quote' => $quote,
                'extraHtml' => $extraHtml,
                'data_a_sign' => $data_a_sign,
                'data_a_sep' => $data_a_sep,
                'data_a_dec' => $data_a_dec,
                'data_p_sign' => $data_p_sign,
                'format_currency_override' => $format_currency_override,
                'staffs' => $staffs,
                'sms_templates_transformed' => $sms_templates_transformed,
            ]);


        } else {
            r2(U . 'customers/list', 'e', $_L['Account_Not_Found']);
        }

        break;

    case 'add-post':
        $invoice_id = _post('invoice_id');

        $data = request()->all();

        $invoice = false;
        $creating = false;
        $document_type = $data['document_type'] ?? 'invoice';


        if ($invoice_id != '') {
            $invoice = Invoice::find($invoice_id);
        }

        $app->emit('invoices_add_post');

        $cid = _post('cid');

        // find user with cid

        $u = ORM::for_table('crm_accounts')->find($cid);
        $msg = '';
        if ($cid == '') {
            $msg .= $_L['select_a_contact'] . ' <br /> ';
        }

        $notes = _post('notes');

        $show_quantity_as = _post('show_quantity_as');

        // find currency

        $currency_id = _post('currency');
        $currency_find = Currency::where('iso_code', $currency_id)->first();
        if ($currency_find) {
            $currency = $currency_find->id;
            $currency_symbol = $currency_find->symbol;
            $currency_rate = $currency_find->rate;
        } else {
            $currency = 0;
            $currency_symbol = $config['currency_code'];
            $currency_rate = 1.0;
        }

        if (isset($data['amount'])) {
            $amount = $data['amount'];
        } else {
            $msg .= $_L['at_least_one_item_required'] . ' <br /> ';
        }

        $idate = _post('idate');
        $its = strtotime($idate);

        $duedate = _post('duedate');

        $dd = '';

        if (!$invoice) {
            $creating = true;
            if ($duedate == 'due_on_receipt') {
                $dd = $idate;
            } elseif ($duedate == 'days3') {
                $dd = date('Y-m-d', strtotime('+3 days', $its));
            } elseif ($duedate == 'days5') {
                $dd = date('Y-m-d', strtotime('+5 days', $its));
            } elseif ($duedate == 'days7') {
                $dd = date('Y-m-d', strtotime('+7 days', $its));
            } elseif ($duedate == 'days10') {
                $dd = date('Y-m-d', strtotime('+10 days', $its));
            } elseif ($duedate == 'days15') {
                $dd = date('Y-m-d', strtotime('+15 days', $its));
            } elseif ($duedate == 'days30') {
                $dd = date('Y-m-d', strtotime('+30 days', $its));
            } elseif ($duedate == 'days45') {
                $dd = date('Y-m-d', strtotime('+45 days', $its));
            } elseif ($duedate == 'days60') {
                $dd = date('Y-m-d', strtotime('+60 days', $its));
            } else {
                $msg .= 'Invalid Date <br /> ';
            }

            if ($dd === '' || $dd === '0') {
                $msg .= 'Date Parsing Error <br /> ';
            }
        } else {
            $dd = $duedate;
        }

        $repeat = _post('repeat');
        $nd = $idate;
        if ($repeat == '0') {
            $r = '0';
        } elseif ($repeat == 'daily') {
            $r = '+1 day';
            $nd = date('Y-m-d', strtotime('+1 day', $its));
        } elseif ($repeat == 'week1') {
            $r = '+1 week';
            $nd = date('Y-m-d', strtotime('+1 week', $its));
        } elseif ($repeat == 'weeks2') {
            $r = '+2 weeks';
            $nd = date('Y-m-d', strtotime('+2 weeks', $its));
        } elseif ($repeat == 'weeks3') {
            $r = '+3 weeks';
            $nd = date('Y-m-d', strtotime('+3 weeks', $its));
        } elseif ($repeat == 'weeks4') {
            $r = '+4 weeks';
            $nd = date('Y-m-d', strtotime('+4 weeks', $its));
        } elseif ($repeat == 'month1') {
            $r = '+1 month';
            $nd = date('Y-m-d', strtotime('+1 month', $its));
        } elseif ($repeat == 'months2') {
            $r = '+2 months';
            $nd = date('Y-m-d', strtotime('+2 months', $its));
        } elseif ($repeat == 'months3') {
            $r = '+3 months';
            $nd = date('Y-m-d', strtotime('+3 months', $its));
        } elseif ($repeat == 'months6') {
            $r = '+6 months';
            $nd = date('Y-m-d', strtotime('+6 months', $its));
        } elseif ($repeat == 'year1') {
            $r = '+1 year';
            $nd = date('Y-m-d', strtotime('+1 year', $its));
        } elseif ($repeat == 'years2') {
            $r = '+2 years';
            $nd = date('Y-m-d', strtotime('+2 years', $its));
        } elseif ($repeat == 'years3') {
            $r = '+3 years';
            $nd = date('Y-m-d', strtotime('+3 years', $its));
        } else {
            $msg .= 'Date Parsing Error <br /> ';
        }

        if ($msg == '') {
            $business_number = _post('business_number');

            if (
                $business_number != '' &&
                $u->business_number != $business_number
            ) {
                $u->business_number = $business_number;
                $u->save();
            }

            $is_same_state = 1;

            if ($config['tax_system'] == 'India') {
                $place_of_supply = _post('place_of_supply');

                $is_same_state = $place_of_supply == $config['business_location'] ? 1 : 0;
            }

            $qty = $data['qty'];
            $item_number = $data['item_code'];

            $taxed = isset($data['taxed']) ? $data['taxed'] : false;

            $sTotal = '0';
            $taxTotal = '0';
            $i = '0';
            $a = [];

            $taxval = '0.00';
            $taxname = '';
            $taxrate = '0.00';

            $taxed_amount = 0.0;
            $lamount = 0.0;

            $discounts = $data['discount'];

            $discount_type = _post('discount_type');

            $total_discount = 0.0;

            $sub_total_without_discount = 0.0;

            foreach ($amount as $samount) {
                $samount = createFromCurrency($samount, $currency_id);

                $a[$i] = $samount;
                $sqty = $qty[$i];
                $sqty = createFromCurrency($sqty, $currency_id);

                $lTaxRate = $taxed[$i];

                $line_discount = $discounts[$i];

                $line_discount = createFromCurrency(
                    $line_discount,
                    $currency_id
                );

                $line_total = $samount * $sqty;

                $line_total_without_discount = $line_total;

                if ($discount_type == 'p') {
                    $line_discount = $line_total * ($line_discount / 100);
                }

                $line_total -= $line_discount;

                $total_discount += $line_discount;

                $sTotal += $line_total;
                $lamount = $line_total;

                $lTaxVal = ($lamount * $lTaxRate) / 100;

                $taxed_amount += $lTaxVal;

                $sub_total_without_discount += $line_total_without_discount;

                $i++;
            }

            $invoicenum = _post('invoicenum');
            $cn = _post('cn');
            $fTotal = $sTotal;

            $discount_type = _post('discount_type');
            $discount_value = '0.00';

            $fTotal += $taxed_amount;

            $status = _post('status');
            if ($status != 'Draft') {
                $status = 'Unpaid';
            }

            $receipt_number = _post('receipt_number');

            $title = _post('title');

            $datetime = date("Y-m-d H:i:s");

            if (!$invoice) {
                $invoice = new Invoice();

                $vtoken = strtolower(Str::random(20));
                $ptoken = strtolower(Str::random(20));

                $invoice->vtoken = $vtoken;
                $invoice->ptoken = $ptoken;

                $invoice->type = $document_type == 'credit-note' ? 'Credit Note' : 'Invoice';

            }

            $group_id = 0;
            $service_id = 0;

            if(!empty($config['invoice_group']))
            {
                $group_id = _post('group_id');
                $invoice->group_id = $group_id;
            }

            if(!empty($config['invoice_single_service']))
            {
                $service_id = _post('service_id');
                $invoice->service_id = $service_id;
            }

            $contract_id = _post('contract_id',0);

            if(!empty($contract_id))
            {
                $contract = Contract::find($contract_id);
                if($contract)
                {
                    if($contract->contact_id != $cid)
                    {
                        //Duplicate the contract
                        $contract_new = new Contract();
                        $contract_new->uuid = Str::uuid();
                        $contract_new->title = $contract->title;
                        $contract_new->type = $contract->type;
                        $contract_new->contact_id = $cid;
                        $contract_new->start_date = $contract->start_date;
                        $contract_new->expiration_date = $contract->expiration_date;
                        $contract_new->description = $contract->description;
                        $contract_new->save();

                        $contract->id = $contract_new->id;

                    }
                }
            }

            $invoice->userid = $cid;
            $invoice->account = $u['account'];
            $invoice->date = $idate;
            $invoice->duedate = $dd;
            $invoice->datepaid = $datetime;
            $invoice->subtotal = $sub_total_without_discount;
            $invoice->discount_type = $discount_type;
            $invoice->discount_value = $discount_value;
            $invoice->discount = $total_discount;
            $invoice->total = $fTotal;
            $invoice->tax = $taxed_amount;
            $invoice->taxname = '';
            $invoice->taxrate = 0.0;
            $invoice->status = $status;
            $invoice->notes = $notes;
            $invoice->r = $r;
            $invoice->nd = $nd;
            $invoice->aid = $data['aid'] ?? $user->id;
            $invoice->is_same_state = $is_same_state;
            $invoice->show_quantity_as = $show_quantity_as;
            $invoice->invoicenum = $invoicenum;
            $invoice->cn = $cn;
            $invoice->tax2 = '0.00';
            $invoice->taxrate2 = '0.00';
            $invoice->paymentmethod = '';
            $invoice->currency = $currency;
            $invoice->currency_symbol = $currency_symbol;
            $invoice->currency_rate = $currency_rate;
            $invoice->currency_iso_code = $currency_id;
            $invoice->receipt_number = $receipt_number;
            $invoice->title = $title;
            $invoice->pid = _post('pid', 0);
            $invoice->contract_id = $contract_id;
            $invoice->allow_partial_payment = _post('allow_partial_payment',0);
            $invoice->save();

            $invoiceid = $invoice->id;
            $description = $data['desc'];

            $tax_code = isset($data['tax_code']) ? $data['tax_code'] : [];

            $i = '0';

            if ($invoice) {
                InvoiceItem::where('invoiceid', $invoice->id)->delete();
            }

            $staff_id = $data['staff_id'] ?? [];


            $invoicing_allow_staff_selection_for_each_item = $config['invoicing_allow_staff_selection_for_each_item'] ?? false;

            foreach ($description as $item) {
                $samount = $a[$i];

                $actual_line_discount = 0;

                if ($item == '' && $samount == '0.00') {
                    $i++;
                    continue;
                }

                $tax_rate = $taxed[$i];

                $sqty = $qty[$i];
                $sqty = createFromCurrency($sqty, $currency_id);

                $line_discount = $discounts[$i];
                $line_discount = createFromCurrency(
                    $line_discount,
                    $currency_id
                );

                $line_total = $samount * $sqty;

                if ($discount_type == 'p') {
                    $actual_line_discount =
                        $line_total * ($line_discount / 100);
                }

                $line_total -= $actual_line_discount;

                $sTotal += $line_total;
                $lamount = $line_total;

                $lTaxVal = ($lamount * $lTaxRate) / 100;

                $taxed_amount += $lTaxVal;

                $d = new InvoiceItem();
                $d->invoiceid = $invoiceid;
                $d->userid = $cid;
                $d->description = $item;
                $d->qty = $sqty;
                $d->amount = $samount;
                $d->total = $line_total;

                if ($tax_rate == '' || $tax_rate == '0') {
                    $tax_rate = 0.0;
                    $d->taxed = '0';
                } else {
                    $tax_rate = $taxed[$i];
                    $d->taxed = '1';
                }

                $d->tax_rate = $tax_rate;

                $item_taxed_amount = round(
                    ($tax_rate * ($sqty * $samount)) / 100,
                    2
                );

                $d->type = '';
                $d->relid = '0';
                $d->itemcode = $item_number[$i];
                $d->taxamount = $item_taxed_amount;
                $d->duedate = date('Y-m-d');
                $d->paymentmethod = '';
                $d->notes = '';

                $d->discount_type = $discount_type;
                $d->discount_amount = $line_discount;

                $d->tax_code = isset($tax_code[$i]) ? $tax_code[$i] : '';

                if($invoicing_allow_staff_selection_for_each_item)
                {
                    $d->staff_id = $staff_id[$i] ?? 0;
                }

                $d->save();

                Inventory::decreaseByItemNumber($item_number[$i], $sqty);

                $item_r = Item::where('name', $item)->first();
                if ($item_r) {
                    $item_r->sold_count += $sqty;
                    $item_r->total_amount += $samount;
                    $item_r->save();
                }

                $i++;
            }

            $code = _post('cn');

            if ($creating) {

                if($document_type == 'credit-note'){
                    update_option(
                        'credit_note_code_current_number',
                        current_number_would_be($cn)
                    );
                }
                else{
                    update_option(
                        'invoice_code_current_number',
                        current_number_would_be($cn)
                    );
                }


            }

            $app->emit('invoices_add_post_done', [$invoiceid]);

            echo $invoiceid;
        } else {
            echo $msg;
        }

        break;

    case 'list':
    case 'credit-notes':
        $all_data = has_access($user->roleid, 'sales', 'all_data');

        $has_delete_access = false;

        if (has_access($user->roleid, 'sales', 'delete')) {
            $has_delete_access = true;
        }

        $tab = route(3, 'filter');

        $tabs_with_data_tables = [
            'unpaid',
            'paid',
            'cancelled',
            'partially_paid',
            'all',
        ];

    $invoice_groups = [];
    $selected_group_id = 0;
    $services = [];

    if(!empty($config['invoice_group']))
    {
        $selected_group_id = route(2,0);
        $invoice_groups = InvoiceGroup::all()->keyBy('id')->all();
    }

    if(!empty($config['invoice_single_service']))
    {
        $services = Item::all()->keyBy('id')->all();
    }

    $staffs = User::all()
        ->keyBy('id')
        ->all();

        if (in_array($tab, $tabs_with_data_tables)) {
            $paginator = [];
            $mode_css = '';
            $mode_js = '';
            $total_invoice = new Invoice();

            if (!$all_data) {
                $total_invoice = $total_invoice->where('aid', $user->id);
            }

            $total_invoice = $total_invoice->count();

            $ui->assign('total_invoice', $total_invoice);

            $invoices = [];

            $invoices = new Invoice();

            $type = 'Invoice';
            if($action == 'credit-notes'){
                $type = 'Credit Note';
            }

            $invoices = $action == 'credit-notes' ? $invoices->where('type', 'Credit Note') : $invoices->where('type', 'Invoice');

            if (!empty($tab)) {
                if ($tab === 'paid') {
                    $invoices = $invoices->where('status', 'Paid');
                } elseif ($tab === 'unpaid') {
                    $invoices = $invoices->where('status', 'Unpaid');
                } elseif ($tab === 'partially_paid') {
                    $invoices = $invoices->where('status', 'Partially Paid');
                } elseif ($tab === 'cancelled') {
                    $invoices = $invoices->where('status', 'Cancelled');
                }
            }

            if (!$all_data) {
                $invoices = $invoices->where('aid', $user->id);
            }

            $invoices = $invoices->orderBy('id', 'desc')->get();

            $ui->assign('d', $invoices);

            $paid = ORM::for_table('sys_invoices');

            if (!$all_data) {
                $paid->where('aid', $user->id);
            }

            $paid = Invoice::where('status', 'Paid')->where('type',$type)->count();

            $unpaid = Invoice::where('status', 'Unpaid')->where('type',$type);

            if (!$all_data) {
                $unpaid = $unpaid->where('aid', $user->id);
            }

            $unpaid = $unpaid->count();

            $partially_paid = Invoice::where('status', 'Partially Paid')->where('type',$type);

            if (!$all_data) {
                $partially_paid = $partially_paid->where('aid', $user->id);
            }

            $partially_paid = $partially_paid->count();

            $cancelled = Invoice::where('status', 'Cancelled')->where('type',$type);

            if (!$all_data) {
                $cancelled = $cancelled->where('aid', $user->id);
            }

            $cancelled = $cancelled->count();

            $arr = [
                'Paid' => $paid,
                'Unpaid' => $unpaid,
                'Partially Paid' => $partially_paid,
                'Cancelled' => $cancelled,
            ];

            $p = Misc::array_percentage($arr);
            $invoice_paid_amount = Invoice::where('status', 'Paid')->where('type',$type);

            if (!$all_data) {
                $invoice_paid_amount->where('aid', $user->id);
            }

            $invoices_all = Invoice::where('type',$type);
            if (!$all_data) {
                $invoices_all->where('aid', $user->id);
            }

            $invoices_all = $invoices_all->get();

            $currencies = Currency::all()->keyBy('iso_code')->all();

            $invoice_paid_amount = 0.00;
            $invoice_unpaid_amount = 0.00;
            $invoice_partially_paid_amount = 0.00;
            $invoice_cancelled_amount = 0.00;

            foreach($invoices_all as $invoice){
                $invoice_total = $invoice->total*$invoice->currency_rate;
                $credit = $invoice->credit*$invoice->currency_rate;

                if($invoice->status == 'Paid'){
                    $invoice_paid_amount += $invoice_total;
                }

                if($invoice->status == 'Unpaid'){
                    $invoice_unpaid_amount += $invoice_total;
                }

                if($invoice->status == 'Partially Paid'){
                    $invoice_partially_paid_amount += $credit;
                }

                if($invoice->status == 'Cancelled'){
                    $invoice_cancelled_amount += $invoice_total;
                }

            }

            $contact_groups = ContactGroup::all()->keyBy('id')->all();

            $contacts = Contact::all()
                ->keyBy('id')
                ->all();




            \view('invoices_list', [
                'paid' => $paid,
                'unpaid' => $unpaid,
                'partially_paid' => $partially_paid,
                'cancelled' => $cancelled,
                'invoice_paid_amount' => $invoice_paid_amount,
                'invoice_unpaid_amount' => $invoice_unpaid_amount,
                'invoice_cancelled_amount' => $invoice_cancelled_amount,
                'invoice_partially_paid_amount' => $invoice_partially_paid_amount,
                'p' => $p,
                'contacts' => $contacts,
                'tab' => $tab,
                'invoice_groups' => $invoice_groups,
                'selected_group_id' => $selected_group_id,
                'services' => $services,
                'action' => $action,
                'staffs' => $staffs,
            ]);
        }
        elseif ($tab === 'filter') {

            $customers = Contact::customers();


            $contact_groups = ContactGroup::all()
                ->keyBy('id')
                ->all();

            \view('invoices_filter', [
                'customers' => $customers,
                'has_delete_access' => $has_delete_access,
                'action' => $action,
                'staffs' => $staffs,
                'contact_groups' => $contact_groups,
                'invoice_groups' => $invoice_groups,
                'selected_group_id' => $selected_group_id,
                'services' => $services,
            ]);
        }

        break;

    case 'list-recurring':
        $d = ORM::for_table('sys_invoices')
            ->where_not_equal('r', '0')
            ->order_by_desc('id')
            ->find_many();
        $ui->assign('d', $d);

        view('list-recurring-invoices');

        break;

    case 'edit-post':
        Event::trigger('invoices/edit-post/');
        $cid = _post('cid');
        $iid = _post('iid');
        $show_quantity_as = _post('show_quantity_as');

        // find user with cid

        $u = ORM::for_table('crm_accounts')->find($cid);
        $msg = '';
        if ($cid == '') {
            $msg .= $_L['select_a_contact'] . ' <br /> ';
        }

        $notes = _post('notes');
        if (isset($data['amount'])) {
            $amount = $data['amount'];
        } else {
            $msg .= $_L['at_least_one_item_required'] . ' <br /> ';
        }

        // find currency

        $currency_id = _post('currency');
        $currency_find = Currency::where('iso_code', $currency_id)->first();
        if ($currency_find) {
            $currency = $currency_find->id;
            $currency_symbol = $currency_find->symbol;
            $currency_rate = $currency_find->rate;
        } else {
            $currency = 0;
            $currency_symbol = $config['currency_code'];
            $currency_rate = 1.0;
        }

        $idate = _post('idate');
        $its = strtotime($idate);
        $duedate = _post('ddate');
        $repeat = _post('repeat');
        $nd = $idate;
        if ($repeat == '0') {
            $r = '0';
        } elseif ($repeat == 'daily') {
            $r = '+1 day';
            $nd = date('Y-m-d', strtotime('+1 day', $its));
        } elseif ($repeat == 'week1') {
            $r = '+1 week';
            $nd = date('Y-m-d', strtotime('+1 week', $its));
        } elseif ($repeat == 'weeks2') {
            $r = '+2 weeks';
            $nd = date('Y-m-d', strtotime('+2 weeks', $its));
        } elseif ($repeat == 'weeks3') {
            $r = '+3 weeks';
            $nd = date('Y-m-d', strtotime('+3 weeks', $its));
        } elseif ($repeat == 'weeks4') {
            $r = '+4 weeks';
            $nd = date('Y-m-d', strtotime('+4 weeks', $its));
        } elseif ($repeat == 'month1') {
            $r = '+1 month';
            $nd = date('Y-m-d', strtotime('+1 month', $its));
        } elseif ($repeat == 'months2') {
            $r = '+2 months';
            $nd = date('Y-m-d', strtotime('+2 months', $its));
        } elseif ($repeat == 'months3') {
            $r = '+3 months';
            $nd = date('Y-m-d', strtotime('+3 months', $its));
        } elseif ($repeat == 'months6') {
            $r = '+6 months';
            $nd = date('Y-m-d', strtotime('+6 months', $its));
        } elseif ($repeat == 'year1') {
            $r = '+1 year';
            $nd = date('Y-m-d', strtotime('+1 year', $its));
        } elseif ($repeat == 'years2') {
            $r = '+2 years';
            $nd = date('Y-m-d', strtotime('+2 years', $its));
        } elseif ($repeat == 'years3') {
            $r = '+3 years';
            $nd = date('Y-m-d', strtotime('+3 years', $its));
        } else {
            $msg .= 'Date Parsing Error <br /> ';
        }

        if ($msg == '') {
            $business_number = _post('business_number');

            if (
                $business_number != '' &&
                $u->business_number != $business_number
            ) {
                $u->business_number = $business_number;
                $u->save();
            }

            $is_same_state = 1;

            if ($config['tax_system'] == 'India') {
                $place_of_supply = _post('place_of_supply');

                $is_same_state = $place_of_supply == $config['business_location'] ? 1 : 0;
            }

            $qty = $data['qty'];
            $item_number = $data['item_code'];
            $taxed = isset($data['taxed']) ? $data['taxed'] : false;

            $sTotal = '0';
            $taxTotal = '0';
            $i = '0';
            $a = [];
            $taxval = '0.00';
            $taxname = '';
            $taxrate = '0.00';

            $taxed_amount = 0.0;
            $lamount = 0.0;

            $taxval = '0.00';
            $taxname = '';

            foreach ($amount as $samount) {
                $samount = Finance::amount_fix($samount);
                $a[$i] = $samount;
                $sqty = $qty[$i];
                $sqty = Finance::amount_fix($sqty);

                $lTaxRate = $taxed[$i];

                $lTaxRate = Finance::amount_fix($lTaxRate);

                $sTotal += $samount * $sqty;
                $lamount = $samount * $sqty;

                $lTaxVal = ($lamount * $lTaxRate) / 100;

                $taxed_amount += $lTaxVal;

                $i++;
            }

            $invoicenum = _post('invoicenum');
            $cn = _post('cn');
            $fTotal = $sTotal;

            $discount_amount = _post('discount_amount');
            $discount_type = _post('discount_type');
            $discount_value = '0.00';
            if ($discount_amount == '0' || $discount_amount == '') {
                $actual_discount = '0.00';
            } elseif ($discount_type == 'f') {
                $actual_discount = $discount_amount;
                $discount_value = $discount_amount;
            } else {
                $discount_type = 'p';
                $actual_discount = ($sTotal * $discount_amount) / 100;
                $discount_value = $discount_amount;
            }

            $actual_discount = number_format(
                (float) $actual_discount,
                2,
                '.',
                ''
            );
            $fTotal = $fTotal + $taxed_amount - $actual_discount;

            $status = _post('status');

            $receipt_number = _post('receipt_number');

            $title = _post('title');

            $d = ORM::for_table('sys_invoices')->find($iid);
            if ($d) {
                $d->userid = $cid;
                $d->account = $u['account'];
                $d->date = $idate;
                $d->duedate = $duedate;
                $d->discount_type = $discount_type;
                $d->discount_value = $discount_value;
                $d->discount = $actual_discount;
                $d->subtotal = $sTotal;
                $d->total = $fTotal;
                $d->tax = $taxed_amount;
                $d->taxname = '';
                $d->taxrate = 0.0;
                $d->notes = $notes;
                $d->r = $r;
                $d->nd = $nd;
                $d->invoicenum = $invoicenum;
                $d->cn = $cn;

                if ($status == 'Draft') {
                    $d->status = 'Draft';
                } elseif ($status == 'Published') {
                    $d->status = 'Unpaid';
                } else {
                }

                $d->currency = $currency;
                $d->currency_symbol = $currency_symbol;
                $d->currency_rate = $currency_rate;
                $d->show_quantity_as = $show_quantity_as;

                $d->currency_iso_code = $currency_id;

                $d->receipt_number = $receipt_number;

                $d->title = $title;

                $d->save();

                $invoiceid = $iid;
                $description = $data['desc'];
                $i = '0';
                $inventory_items_adjust = ORM::for_table('sys_invoiceitems')
                    ->where('invoiceid', $iid)
                    ->find_array();
                foreach ($inventory_items_adjust as $i_adjust) {
                    Inventory::increaseByItemNumber(
                        $i_adjust['itemcode'],
                        $i_adjust['qty']
                    );
                }

                $x = ORM::for_table('sys_invoiceitems')
                    ->where('invoiceid', $iid)
                    ->delete_many();

                foreach ($description as $item) {
                    $samount = $a[$i];
                    $samount = Finance::amount_fix($samount);
                    if ($item == '' && $samount == '0.00') {
                        $i++;
                        continue;
                    }

                    $tax_rate = $taxed[$i];

                    $sqty = $qty[$i];
                    $sqty = Finance::amount_fix($sqty);
                    $ltotal = $samount * $sqty;
                    $d = ORM::for_table('sys_invoiceitems')->create();
                    $d->invoiceid = $invoiceid;
                    $d->userid = $cid;
                    $d->description = $item;
                    $d->qty = $sqty;
                    $d->amount = $samount;
                    $d->total = $ltotal;
                    if ($tax_rate == '' || $tax_rate == '0') {
                        $tax_rate = 0.0;
                        $d->taxed = '0';
                    } else {
                        $tax_rate = $taxed[$i];
                        $d->taxed = '1';
                    }

                    $item_taxed_amount = round(
                        ($tax_rate * 100) / ($sqty * $samount),
                        2
                    );

                    $d->type = '';
                    $d->relid = '0';
                    $d->itemcode = $item_number[$i];
                    $d->taxamount = $item_taxed_amount;
                    $d->tax_rate = $tax_rate;
                    $d->duedate = date('Y-m-d');
                    $d->paymentmethod = '';
                    $d->notes = '';
                    $d->save();

                    // decrease inventory

                    Inventory::decreaseByItemNumber($item_number[$i], $sqty);
                    $i++;
                }

                $app->emit('invoices_edit_post_done', [$invoiceid]);
                echo $invoiceid;
            }
        } else {
            echo $msg;
        }

        break;

    case 'delete':
        Event::trigger('invoices/delete/');
        $id = $routes['2'];
        if (APP_STAGE == 'Demo') {
            r2(
                U . 'accounts/list',
                'e',
                'Sorry! Deleting Account is disabled in the demo mode.'
            );
        }

        $d = ORM::for_table('crm_accounts')->find($id);
        if ($d) {
            $d->delete();
            r2(U . 'accounts/list', 's', $_L['account_delete_successful']);
        }

        break;

    case 'print':
        Event::trigger('invoices/print/');
        $id = $routes['2'];
        $d = ORM::for_table('sys_invoices')->find($id);
        if ($d) {
            // find all activity for this user

            $items = ORM::for_table('sys_invoiceitems')
                ->where('invoiceid', $id)
                ->order_by_asc('id')
                ->find_many();

            // find the user

            $a = ORM::for_table('crm_accounts')->find($d['userid']);
            require APP_SYSTEM_PATH . '/lib/invoices/render.php';
        } else {
            r2(U . 'customers/list', 'e', $_L['Account_Not_Found']);
        }

        break;

    case 'pdf':
        Event::trigger('invoices/pdf/');
        $id = $routes['2'];
        $d = ORM::for_table('sys_invoices')->find($id);
        if ($d) {
            // find all activity for this user

            $items = ORM::for_table('sys_invoiceitems')
                ->where('invoiceid', $id)
                ->order_by_asc('id')
                ->find_many();
            $trs_c = ORM::for_table('sys_transactions')
                ->where('iid', $id)
                ->count();
            $trs = ORM::for_table('sys_transactions')
                ->where('iid', $id)
                ->order_by_desc('id')
                ->find_many();

            // find the user

            $a = ORM::for_table('crm_accounts')->find($d['userid']);
            $i_credit = $d['credit'];
            $i_due = '0.00';
            $i_total = $d['total'];
            $i_due = $d['credit'] != '0.00' ? $i_total - $i_credit : $d['total'];

            $i_due = number_format(
                $i_due,
                2,
                $config['dec_point'],
                $config['thousands_sep']
            );
            $cf = ORM::for_table('crm_customfields')
                ->where('showinvoice', 'Yes')
                ->order_by_asc('id')
                ->find_many();
            $dispid = $d['cn'] != '' ? $d['cn'] : $d['id'];

            $in = $d['invoicenum'] . $dispid;
            define('_MPDF_PATH', 'system/lib/mpdf/');
            require APP_SYSTEM_PATH . '/lib/mpdf/mpdf.php';

            $pdf_c = '';
            $ib_w_font = 'dejavusanscondensed';
            if ($config['pdf_font'] == 'default') {
                $pdf_c = 'c';
                $ib_w_font = 'Helvetica';
            }

            $mpdf = new mPDF($pdf_c, 'A4', '', '', 20, 15, 15, 25, 10, 10);
            $mpdf->SetProtection(['print']);
            $mpdf->SetTitle($config['CompanyName'] . ' Invoice');
            $mpdf->SetAuthor($config['CompanyName']);
            $mpdf->SetWatermarkText(ib_lan_get_line($d['status']));
            $mpdf->showWatermarkText = true;
            $mpdf->watermark_font = $ib_w_font;
            $mpdf->watermarkTextAlpha = 0.1;
            $mpdf->SetDisplayMode('fullpage');
            if ($config['pdf_font'] == 'AdobeCJK') {
                $mpdf->useAdobeCJK = true;
                $mpdf->autoScriptToLang = true;
                $mpdf->autoLangToFont = true;
            }

            Event::trigger('invoices/before_pdf_render/');
            ob_start();
            require APP_SYSTEM_PATH . '/lib/invoices/pdf-x2.php';

            $html = ob_get_contents();
            ob_end_clean();
            $mpdf->WriteHTML($html);
            $pdf_return = 'inline';
            $r_type = isset($routes[3]) ? $routes[3] : 'inline';

            if ($r_type == 'dl') {
                $mpdf->Output(date('Y-m-d') . _raid(4) . '.pdf', 'D'); // D
            } elseif ($r_type == 'inline') {
                $mpdf->Output(date('Y-m-d') . _raid(4) . '.pdf', 'I'); // D
            } elseif ($r_type == 'store') {
                $mpdf->Output('storage/temp/Invoice_' . $in . '.pdf', 'F'); // D
            } else {
                $mpdf->Output(date('Y-m-d') . _raid(4) . '.pdf', 'I'); // D
            }
        }

        break;

    case 'markpaid':
        $iid = _post('iid');
        $d = ORM::for_table('sys_invoices')->find($iid);
        if ($d) {
            // previous status
            $prev_status = $d->status;

            if ($prev_status == 'Cancelled') {
                // update the inventory again

                $items = InvoiceItem::where('invoiceid', $iid)->get();

                foreach ($items as $item) {
                    if ($item->itemcode != '') {
                        Inventory::decreaseByItemNumber(
                            $item->itemcode,
                            $item->qty
                        );
                    }
                }
                //
            }

            //

            $d->status = 'Paid';
            $d->save();
            Event::trigger('invoices/markpaid/', $invoice = $d);
            _msglog('s', 'Invoice marked as Paid');
        } else {
            _msglog('e', 'Invoice not found');
        }

        break;

    case 'markunpaid':
        Event::trigger('invoices/markunpaid/');
        $iid = _post('iid');
        $d = ORM::for_table('sys_invoices')->find($iid);
        if ($d) {
            // previous status
            $prev_status = $d->status;

            if ($prev_status == 'Cancelled') {
                // update the inventory again

                $items = InvoiceItem::where('invoiceid', $iid)->get();

                foreach ($items as $item) {
                    if ($item->itemcode != '') {
                        Inventory::decreaseByItemNumber(
                            $item->itemcode,
                            $item->qty
                        );
                    }
                }
                //
            }

            //

            $d->status = 'Unpaid';
            $d->save();
            _msglog('s', 'Invoice marked as Un Paid');
        } else {
            _msglog('e', 'Invoice not found');
        }

        break;

    case 'markcancelled':
        Event::trigger('invoices/markcancelled/');

        $iid = _post('iid');
        $d = ORM::for_table('sys_invoices')->find($iid);
        if ($d) {
            $d->status = 'Cancelled';
            $d->save();

            $items = InvoiceItem::where('invoiceid', $iid)->get();

            foreach ($items as $item) {
                if ($item->itemcode != '') {
                    Inventory::increaseByItemNumber(
                        $item->itemcode,
                        $item->qty
                    );
                }
            }

            $invoice = $d;
            $app->emit('invoice_cancelled', [&$invoice]);

            _msglog('s', 'Invoice marked as Cancelled');
        } else {
            _msglog('e', 'Invoice not found');
        }

        break;

    case 'markpartiallypaid':
        Event::trigger('invoices/markpartiallypaid/');
        $iid = _post('iid');
        $d = ORM::for_table('sys_invoices')->find($iid);
        if ($d) {
            $d->status = 'Partially Paid';
            $d->save();
            _msglog('s', 'Invoice marked as Partially Paid');
        } else {
            _msglog('e', 'Invoice not found');
        }

        break;

    case 'set-status':

        $invoice_id = _post('invoice_id');
        $invoice = Invoice::find($invoice_id);
        if($invoice)
        {
            $invoice->status = _post('status');
            $invoice->save();
            _msglog('s', __('Data updated.'));
        }

        break;

    case 'set-purchase-status':

        $invoice_id = _post('invoice_id');
        $invoice = Invoice::find($invoice_id);
        if($invoice)
        {
            $invoice->purchase_status = _post('status');
            $invoice->save();
            _msglog('s', __('Data updated.'));
        }

        break;

        case 'set-shipping-status':

            $invoice_id = _post('invoice_id');
            $invoice = Invoice::find($invoice_id);
            if($invoice)
            {
                $invoice->shipping_status = _post('status');
                $invoice->save();
                _msglog('s', __('Data updated.'));
            }

            break;

    case 'add-payment':
        $customers_all_data = has_access(
            $user->roleid,
            'customers',
            'all_data'
        );

        Event::trigger('invoices/add-payment/');
        $sid = $routes['2'];
        $d = Invoice::find($sid);
        if ($d) {
            $itotal = $d['total'];
            $ic = $d['credit'];
            $np = $itotal - $ic;
            $a_opt = '';

            $a = ORM::for_table('sys_accounts');

            if (!$customers_all_data) {
                $a->where('o', $user->id);
            }

            $a = $a->find_many();

            foreach ($a as $acs) {
                $a_opt .=
                    '<option value="' .
                    $acs['id'] .
                    '">' .
                    $acs['account'] .
                    '</option>';
            }

            $pms_opt = '';

            $pms = ORM::for_table('sys_pmethods')
                ->order_by_asc('sorder')
                ->find_many();
            foreach ($pms as $pm) {
                $pms_opt .=
                    '<option value="' .
                    $pm['name'] .
                    '">' .
                    $pm['name'] .
                    '</option>';
            }

            $cats_opt = '';
            $cats = ORM::for_table('sys_cats')
                ->where('type', 'Income')
                ->order_by_asc('sorder')
                ->find_many();
            foreach ($cats as $cat) {
                $cats_opt .=
                    '<option value="' .
                    $cat['id'] .
                    '">' .
                    $cat['name'] .
                    '</option>';
            }

            $currency_opt = '';
            $currencies = Currency::all();

            $currency_iso_code = $d['currency_iso_code'];

            $currency = Currency::getAllCurrencies();

            $invoice_display_id = Invoice::getInvoiceNumberById($sid);

            $currency_symbol = $config['currency_code'];
            $currency_decimal_point = $config['dec_point'];
            $thousands_separator = $config['thousands_sep'];

            if (isset($currency[$currency_iso_code])) {
                $selected_currency = $currency[$currency_iso_code];
                $currency_symbol = $selected_currency['symbol'];
                $currency_decimal_point = $selected_currency['decimal_mark'];
                $thousands_separator =
                    $selected_currency['thousands_separator'];
            }

            $currency_opt =
                '<div class="mb-3">
    <label for="amount">' .
                $_L['Amount'] .
                ' [' .
                $currency_iso_code .
                ']</label>
    <input type="text" id="amount" name="amount" class="form-control amount"   data-a-sign="' .
                $currency_symbol .
                ' " data-a-dec="' .
                $currency_decimal_point .
                '" data-a-sep="' .
                $thousands_separator .
                '"
data-d-group="3" value="">
  </div>';

            $secondary_currency = secondary_currency();
            $payment_amount = $np;
            $invoice_currency = $d['currency_symbol'] == '' ? $config['currency_code'] : $d['currency_symbol'];

            echo '<div class="mx-auto" style="max-width: 650px;">
<div class="panel mb-0 rounded-0">
<div class="panel-hdr">
<h2>#' .
                $invoice_display_id .
                '</h2>
</div>
<div class="panel-container">
<div class="panel-content">

<h3>' .
                $_L['Invoice Total'] .
                ': <span class="amount" data-a-sign="' .
                $invoice_currency .
                ' ">' .
                $d['total'] .
                '</span></h3>
<hr>
<form class="form-horizontal" role="form" id="form_add_payment" method="post">
<div class="mb-3">
    <label for="subject">' .
                $_L['Account'] .
                '</label>
    <select id="account" name="account">
                            <option value="">' .
                $_L['Choose an Account'] .
                '</option>

' .
                $a_opt .
                '

                        </select>
  </div>

<div class="mb-3">
    <label for="date">' .
                $_L['Date'] .
                '</label>
    <input type="text" class="form-control datepicker"  value="' .
                date('Y-m-d') .
                '" name="date" id="date" datepicker data-date-format="yyyy-mm-dd" data-auto-close="true">
  </div>

<div class="mb-3">
    <label for="description">' .
                $_L['Description'] .
                '</label>
    <input type="text" id="description" name="description" class="form-control" value="' .
                $invoice_display_id .
                ' ' .
                $_L['Payment'] .
                '">
  </div>
  
  
' .
                $currency_opt .
                '



  
  
<div class="mb-3">
    <label for="cats">' .
                $_L['Category'] .
                '</label>
    <select id="cats" name="cats">
                             <option value="0">' .
                $_L['Uncategorized'] .
                '</option>

' .
                $cats_opt .
                '

                        </select>
  </div>
  <div class="mb-3">
    <label for="payer_name">' .
                $_L['Payer'] .
                '</label>
    <input type="text" id="payer_name" name="payer_name" class="form-control" value="' .
                $d['account'] .
                '" disabled>
  </div>
  

   <div class="mb-3">
    <label for="subject">' .
                $_L['Method'] .
                '</label>
    <select id="pmethod" name="pmethod">
                                <option value="">' .
                $_L['Select Payment Method'] .
                '</option>


                                ' .
                $pms_opt .
                '


                            </select>
  </div>
  
  <div class="mb-3">
                                    <label for="ref">'.$_L['Ref'].'#</label>
                                    <input type="text" class="form-control" id="ref" name="ref">
                                    
                                </div>

<input type="hidden" name="iid" value="' .
                $d['id'] .
                '">
<input type="hidden" name="payer" value="' .
                $d['userid'] .
                '">
<input type="hidden" name="currency" value="' .
                $d['currency_iso_code'] .
                '">
<button id="save_payment" class="btn btn-primary">' .
                $_L['Save'] .
                '</button>
</form>






</div>
</div>
</div>
</div>';
        } else {
            exit('Invoice Not Found');
        }

        break;



    case 'add-payment-post':
        Event::trigger('invoices/add-payment-post/');
        $msg = '';
        $iid = _post('iid');
        $account = _post('account');

        if ($account == '') {
            $msg .= $_L['Select An Account'] . '<br />';
        }

        $date = _post('date');
        $amount = _post('amount');

        $currency_iso_code = _post('currency');

        $i = ORM::for_table('sys_invoices')->find($iid);

        if(empty($currency_iso_code))
        {
            $currency_iso_code = $i['currency_iso_code'] ?? $config['home_currency'];
        }

        $amount = createFromCurrency($amount, $currency_iso_code);

        $rate = 1.00;

        if(!empty($currency_iso_code) && ($currency_iso_code != $config['home_currency'])){
            $find_currency = Currency::where('iso_code',$currency_iso_code)->first();
            if($find_currency)
            {
                $rate = $find_currency->rate;
            }
        }

        $payerid = _post('payer');
        $pmethod = _post('pmethod');
        $ref = _post('ref');
        if ($payerid == '') {
            $payerid = '0';
        }

        $payer = '';

        if ($payerid != '0') {
            $payer_find = Contact::find($payerid);

            if ($payer_find) {
                $payer = $payer_find->account;
            }
        }

        $currencies = Currency::all();
        $tr_currency = '0';
        $tr_currency_symbol = '';
        $tr_currency_rate = '1.0000';

        $cat = _post('cats',0);
        $category_name = '';
        $cat_id = 0;
        if(!empty($cat)) {
            $catetory = TransactionCategory::find($cat);
            if($catetory)
            {
                $category_name = $catetory->name;
                $cat_id = $catetory->id;
            }
        }



        $invoice = Invoice::find($iid);

        $currency_iso_code = $config['home_currency'];

        if ($invoice && $invoice->currency_iso_code) {
            $currency_iso_code = $invoice->currency_iso_code;
        }

        if ($payerid == '') {
            $msg .= 'Payer Not Found<br />';
        }

        $description = _post('description');

        if ($description == '') {
            $msg .= $_L['description_error'] . '<br />';
        }

        if ($account == '') {
            $msg .= 'Please choose an Account<br />';
        }

        if (is_numeric($amount) == false) {
            $msg .= $_L['amount_error'] . '<br />';
        }

        if ($msg == '') {
            $account_find = Account::find($account);
            $d = new Transaction();
            $d->account = $account_find->account;
            $d->account_id = $account_find->id;
            $d->type = 'Income';
            $d->payerid = $payerid;
            $d->amount = $amount;
            $d->category = $category_name;
            $d->cat_id = $cat_id;
            $d->method = $pmethod;
            $d->ref = $ref;
            $d->tags = '';
            $d->description = $description;
            $d->date = $date;
            $d->dr = '0.00';
            $d->cr = $amount;

            $d->iid = $iid;
            $d->currency = $tr_currency;
            $d->currency_symbol = $tr_currency_symbol;
            $d->currency_rate = $rate;

            $d->currency_iso_code = $currency_iso_code;

            $d->payer = $payer;
            $d->payee = '';

            $d->status = 'Cleared';
            $d->tax = '0.00';
            $d->aid = $user->id;

            $d->vid = _raid(8);

            $d->updated_at = date('Y-m-d H:i:s');

            $d->save();
            $tid = $d->id;
            _log(
                'New Deposit: ' .
                    $description .
                    ' [TrID: ' .
                    $tid .
                    ' | Amount: ' .
                    $amount .
                    ']',
                'Admin',
                $user->id
            );
            _msglog('s', 'Transaction Added Successfully');

            $i = ORM::for_table('sys_invoices')->find($iid);
            if ($i) {
                $pc = $i['credit'];
                $it = $i['total'];
                $dp = $it - $pc;
                $i->status = $dp == $amount || $dp < $amount ? 'Paid' : 'Partially Paid';
                $i->credit = $pc + $amount;
                $i->save();
            }

            echo $tid;
        } else {
            echo '<div class="alert alert-danger fade in">' . $msg . '</div>';
        }

        break;

    case 'mail_invoice_':
        Event::trigger('invoices/mail_invoice_/');
        $sid = $routes['2'];
        $etpl = $routes['3'];
        $d = ORM::for_table('sys_invoices')->find($sid);
        if ($d) {
            $a = ORM::for_table('crm_accounts')->find($d['userid']);
            $msg = Invoice::gen_email($sid, $etpl);
            if ($msg) {
                $subj = $msg['subject'];
                $message_o = $msg['body'];
                $email = $msg['email'];
                $name = $msg['name'];
            } else {
                $subj = '';
                $message_o = '';
                $email = '';
                $name = '';
            }

            $dispid = $d['cn'] != '' ? $d['cn'] : $d['id'];

            $in = $d['invoicenum'] . $dispid;

            if ($a['secondary_email'] != '') {
                $email = $a['secondary_email'];
            }

            $inv_files = Invoice::files($sid);

            $attachments_html = '';

            if (count($inv_files) > 0) {
                $attach_file_option = '';
                foreach ($inv_files as $inv_file) {
                    $attach_file_option .=
                        '<div class="checkbox c-checkbox">
                          <label>
                            <input type="checkbox" name="attach_file[]" value="' .
                        $inv_file->id .
                        '" checked><span class="fa fa-check"></span>  <i class="fa fa-paperclip"></i> ' .
                        $inv_file->title .
                        '
                          </label>
                        </div>';
                }

                $attachments_html =
                    ' <div class="hr-line-dashed"></div>
  
  <div class="mb-3">
    <label for="attach_pdf">Other Files</label>
    ' .
                    $attach_file_option .
                    '
  </div>';
            }

            echo '


<div class="mx-auto" style="max-width: 650px;">
    <div class="panel mb-0 rounded-0">
    
    <div class="panel-hdr">
    <h3>' .
                $_L['Invoice'] .
                ' #' .
                $d['id'] .
                '</h3>
</div>

<div class="panel-container">
<div class="panel-content">
<form class="form-horizontal" role="form" id="email_form" method="post">


<div class="mb-3">
    <label for="toemail">' .
                $_L['To'] .
                '</label>
    <input type="email" id="toemail" name="toemail" class="form-control" value="' .
                $email .
                '">
  </div>

  <div class="mb-3">
    <label for="ccemail">' .
                $_L['Cc'] .
                '</label>
    <input type="email" id="ccemail" name="ccemail" class="form-control" value="">
  </div>

  <div class="mb-3">
    <label for="bccemail">' .
                $_L['Bcc'] .
                '</label>
    <input type="email" id="bccemail" name="bccemail" class="form-control" value="">
      <span class="help-block"><a href="#" id="send_bcc_to_admin">' .
                $_L['Send Bcc to Admin'] .
                '</a></span>
  </div>

    <div class="mb-3">
    <label for="subject">' .
                $_L['Subject'] .
                '</label>
    <input type="text" id="subject" name="subject" class="form-control" value="' .
                $subj .
                '">
  </div>

  <div class="mb-3">
    <label for="subject" class="mb-3">' .
                $_L['Message Body'] .
                '</label>
    <textarea class="form-control sysedit" rows="3" name="message" id="message">' .
                $message_o .
                '</textarea>
      <input type="hidden" id="toname" name="toname" value="' .
                $name .
                '">
      <input type="hidden" id="i_cid" name="i_cid" value="' .
                $a['id'] .
                '">
      <input type="hidden" id="i_iid" name="i_iid" value="' .
                $d['id'] .
                '">
  </div>


<div class="mb-3">

    <label for="attach_pdf"></label>
    <div class="custom-checkbox c-checkbox">
                          <label>
                            <input type="checkbox" name="attach_pdf" id="attach_pdf" value="Yes" checked> ' .
                $_L['Invoice'] .
                '_' .
                $in .
                '.pdf
                          </label>
                        </div>
  </div>
  
' .
                $attachments_html .
                '

<button id="send" class="btn btn-primary">' .
                $_L['Send'] .
                '</button>
</form>
</div>
</div>
    
</div>

</div>




';
        } else {
            exit('Invoice Not Found');
        }

        break;

    case 'send_email':
        Event::trigger('invoices/send_email/');
        $msg = '';
        $email = _post('toemail');
        $cc = _post('ccemail');
        $bcc = _post('bccemail');
        $subject = _post('subject');
        $toname = _post('toname');
        $cid = _post('i_cid');
        $iid = _post('i_iid');
        $d = ORM::for_table('sys_invoices')->find($iid);
        $dispid = $d['cn'] != '' ? $d['cn'] : $d['id'];

        $in = $d['invoicenum'] . $dispid;
        $message = $data['message'];

        $attach_pdf = _post('attach_pdf');
        $attachment_path = '';
        $attachment_file = '';
        if ($attach_pdf == 'Yes') {
            Invoice::pdf($iid, 'store');
            $attachment_path =
                'storage/temp/' . __('Invoice') . '_' . $in . '.pdf';
            $attachment_file = __('Invoice') . '_' . $in . '.pdf';
            ray($attachment_file, $attachment_path);
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $msg .= 'Invalid Email <br />';
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $cc = '';
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $bcc = '';
        }

        if ($subject == '') {
            $msg .= 'Subject is Required <br />';
        }

        if ($message == '') {
            $msg .= 'Message is Required <br />';
        }

        if ($msg == '') {
            $email_config = EmailConfig::first();

//            if ($email_config) {
//                if ($email_config->method == 'smtp') {
//                    $transport = (new Swift_SmtpTransport(
//                        $email_config->host,
//                        $email_config->port,
//                        $email_config->secure
//                    ))
//                        ->setUsername($email_config->username)
//                        ->setPassword($email_config->password)
//                        ->setStreamOptions([
//                            'ssl' => [
//                                'allow_self_signed' => true,
//                                'verify_peer' => false,
//                            ],
//                        ]);
//                } else {
//                    $transport = new Swift_SendmailTransport(
//                        '/usr/sbin/sendmail -bs'
//                    );
//                }
//
//                $mailer = new Swift_Mailer($transport);
//
//                $receiver = [];
//
//                $receiver[] = [
//                    $email => $toname,
//                ];
//
//                $message_object = (new Swift_Message($subject))
//                    ->setFrom([$config['sysEmail'] => $config['CompanyName']])
//                    ->setTo([$email => $toname])
//                    ->setBody($message, 'text/html');
//
//                if (!empty($cc)) {
//                    $message_object->setCc([$cc]);
//                }
//
//                if (!empty($bcc)) {
//                    $message_object->setBcc([$bcc]);
//                }
//
//                if ($attachment_path != '') {
//                    $message_object->attach(
//                        Swift_Attachment::fromPath($attachment_path)
//                    );
//                }
//
//                if (isset($data['attach_file'])) {
//                    $other_files = $data['attach_file'];
//
//                    foreach ($other_files as $other_file) {
//                        $file = Document::find($other_file);
//
//                        if ($file) {
//                            $message_object->attach(
//                                Swift_Attachment::fromPath(
//                                    'storage/docs/' . $file->file_path
//                                )->setFilename(
//                                    $file->title . '.' . $file->file_mime_type
//                                )
//                            );
//                        }
//                    }
//                }
//
//                $result = $mailer->send($message_object);
//            }

            if ($email_config) {
                // Set up transport based on SMTP or Sendmail method
                if ($email_config->method == 'smtp') {
                    $dsn = sprintf(
                        'smtp://%s:%s@%s:%d?encryption=%s',
                        urlencode($email_config->username),
                        urlencode($email_config->password),
                        $email_config->host,
                        $email_config->port,
                        $email_config->secure
                    );
                    $transport = Transport::fromDsn($dsn);
                } else {
                    $transport = Transport::fromDsn('sendmail://default');
                }

                $mailer = new Mailer($transport);

                // Create the email message
                $email_message = (new SymfonyEmail())
                    ->from(new SymfonyAddress($config['sysEmail'], $config['CompanyName']))
                    ->to(new SymfonyAddress($email, $toname))
                    ->subject($subject)
                    ->html($message);

                // Add CC and BCC if provided
                if (!empty($cc)) {
                    $email_message->cc($cc);
                }

                if (!empty($bcc)) {
                    $email_message->bcc($bcc);
                }

                // Attach main attachment if provided
                if ($attachment_path != '') {
                    $email_message->attachFromPath($attachment_path);
                }

                // Attach additional files from data if available
                if (isset($data['attach_file'])) {
                    $other_files = $data['attach_file'];
                    foreach ($other_files as $other_file) {
                        $file = Document::find($other_file);
                        if ($file) {
                            $file_path = 'storage/docs/' . $file->file_path;
                            $filename = $file->title . '.' . $file->file_mime_type;
                            $email_message->attachFromPath($file_path, $filename);
                        }
                    }
                }

                // Send the email and get the result
                $mailer->send($email_message);
            }


            Email::_log($user->id, $email, $subject, $message, $iid);

            echo $_L['Email Sent'];
        } else {
            echo $msg;
        }

        break;

    case 'stop_recurring':
        Event::trigger('invoices/stop_recurring/');
        $id = $routes['2'];
        $id = str_replace('sid', '', $id);
        $d = ORM::for_table('sys_invoices')->find($id);
        if ($d) {
            $d->r = '0';
            $d->save();
            r2(U . 'invoices/list-recurring', 's', $_L['Data Updated']);
        } else {
            echo 'Invoice not found';
        }

        break;

    case 'export_csv':
        $fileName = 'transactions_' . time() . '.csv';
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header('Content-Description: File Transfer');
        header("Content-type: text/csv");
        header("Content-Disposition: attachment; filename={$fileName}");
        header("Expires: 0");
        header("Pragma: public");
        $fh = @fopen('php://output', 'w');
        $headerDisplayed = false;

        // $results = ORM::for_table('crm_Accounts')->find_array();

        $results = db_find_array('sys_invoices');
        foreach ($results as $data) {
            // Add a header row if it hasn't been added yet

            if (!$headerDisplayed) {
                // Use the keys from $data as the titles

                fputcsv($fh, array_keys($data));
                $headerDisplayed = true;
            }

            // Put the data into the stream

            fputcsv($fh, $data);
        }

        // Close the file

        fclose($fh);
        break;

    case 'payments':
        $d = ORM::for_table('sys_transactions')
            ->where_not_equal('iid', '0')
            ->limit(2500)
            ->find_array();
        $ui->assign('d', $d);
        view('payments');
        break;

    case 'clone':
        $id = route(2);
        $new_id = Invoice::cloneInvoice($id);
        if ($new_id) {
            r2(U . 'invoices/edit/' . $new_id, 's', $_L['Cloned successfully']);
        }

        break;

    case 's':
        is_dev();
        $t = new Schema('ib_invoice_access_log');
        $t->drop();
        $t->add('lid', 'int', '11', '0');
        $t->add('cid', 'int', '11', '0');
        $t->add('iid', 'int', '11', '0');
        $t->add('company_id', 'int', '11', '0');
        $t->add('customer', 'varchar', '200');
        $t->add('ip', 'varchar', '50');
        $t->add('browser', 'varchar', '200');
        $t->add('referer', 'varchar', '200');
        $t->add('city', 'varchar', '200');
        $t->add('postal_code', 'varchar', '50');
        $t->add('country', 'varchar', '200');
        $t->add('country_iso', 'varchar', '20');
        $t->add('viewed_at', 'varchar', '200');
        $t->add('lat', 'varchar', '100');
        $t->add('lon', 'varchar', '100');
        $t->save();
        add_option('maxmind_installed', '0');
        add_option('maxmind_db_version', '');
        break;

    case 'pos':
        $extra_fields = '';
        $extra_jq = '';
        $ui->assign('extra_fields', $extra_fields);
        $recurring = isset($routes['2']) && $routes['2'] == 'recurring';

        $currencies = Currency::all();
        $ui->assign('recurring', $recurring);
        $ui->assign('currencies', $currencies);
        if (isset($routes['3']) && $routes['3'] != '') {
            $p_cid = $routes['3'];
            $p_d = ORM::for_table('crm_accounts')->find($p_cid);
            if ($p_d) {
                $ui->assign('p_cid', $p_cid);
            }
        } else {
            $ui->assign('p_cid', '');
        }

        $c = ORM::for_table('crm_accounts')
            ->select('id')
            ->select('account')
            ->select('company')
            ->select('email')
            ->order_by_desc('id')
            ->find_many();
        $ui->assign('c', $c);
        $t = ORM::for_table('sys_tax')->find_many();
        $ui->assign('t', $t);
        $ui->assign('idate', date('Y-m-d'));
        Event::trigger('add_invoice_rendering_form');
        view('pos');
        break;

    case 'sms_invoice_':
        $sid = $routes['2'];
        $mtpl = $routes['3'];

        $sms = Invoice::genSMS($sid, $mtpl);

        if ($sms) {
            $message = $sms['sms'];
            $to = $sms['to'];
        } else {
            $message = '';
            $to = '';
        }
        view('modal_sms_invoice', [
            'message' => $message,
            'to' => $to,
            'invoice_id' => $sid,
        ]);

        break;

    case 'create-from-ticket':
        if (!has_access($user->roleid, 'sales', 'all_data')) {
            permissionDenied();
        }

        $ticket_id = route(2);

        $receipt_number = _post('receipt_number');

        $save = Invoice::fromTicket($ticket_id, [
            'receipt_number' => $receipt_number,
        ]);

        if ($save['success']) {
            api_response([
                'success' => true,
                'url' => U . 'invoices/edit/' . $save['invoice'],
                's',
                'Invoice created, now you can edit the invoice.',
            ]);
        } else {
            api_response([
                'success' => true,
                'url' => U . 'tickets/admin/view/' . $ticket_id,
                'e',
                $save['error'],
            ]);
        }

        break;

    case 'filter':
        $data = request()->all();
        $report_range = $data['reportrange'];
        $report_range = explode('-', $report_range);
        $from = trim($report_range[0]);
        $to = trim($report_range[1]);

        $invoice_group_id = null;

        if(!empty($config['invoice_group']))
        {
            $invoice_group_id = $data['invoice_group_id'] ?? null;
        }


        $staff_id = $data['staff_id'] ?? null;

        $invoices = Invoice::whereBetween('date', [$from, $to]);

        $type = $data['type'] ?? null;

        $invoices = $type == 'credit-notes' ? $invoices->where('type', 'Credit Note') : $invoices->where('type', 'Invoice');

        

        if (!empty($data['customer'])) {
            $customer = (int) $data['customer'];
            if ($customer !== 0) {
                $invoices = $invoices->where('userid', $customer);
            }
        }

        if (!empty($data['status'])) {
            $status = $data['status'];
            $invoices = $invoices->where('status', $status);
        }

        

        if(!empty($config['invoice_items_purchasing'])){
            if (!empty($data['purchase_status'])) {
                if($data['purchase_status'] == 'Unknown')
                {
                    $invoices = $invoices->whereNull('purchase_status');
                }
                else{
                    $invoices = $invoices->where('purchase_status', $data['purchase_status']);
                }
            }
        }

        if(!empty($config['invoice_items_shipping'])){
            if (!empty($data['shipping_status'])) {
                if($data['shipping_status'] == 'Unknown')
                {
                    $invoices = $invoices->whereNull('shipping_status');
                }
                else{
                    $invoices = $invoices->where('shipping_status', $data['shipping_status']);
                }
            }
        }

        if(!empty($staff_id))
        {
            $invoices = $invoices->where('aid', $staff_id);
        }

        if(!empty($invoice_group_id))
        {
            $invoices = $invoices->where('group_id', $invoice_group_id);
        }

        if(!empty($config['invoice_single_service']))
        {
            $service_id = $data['service_id'] ?? null;
            if($service_id)
            {
                $invoices = $invoices->where('service_id', $service_id);
            }
        }

        $group_id = $data['group_id'] ?? null;

        $contact_ids = [];

        if(!empty($group_id))
        {
            $contact_ids = Contact::where('gid', $group_id)
                ->select('id')
                ->get()
                ->pluck('id')
                ->toArray();

        }

        if (!empty($contact_ids)) {
            $invoices = $invoices->whereIn('userid', $contact_ids);
        }

        $invoices = $invoices->orderBy('id', 'desc')->get();

        


        $invoices_by_currency = $invoices->groupBy('currency_iso_code')->all();
        // Total by currency
        $total_by_currency = array_map(function ($invoice_by_currency) {
            return $invoice_by_currency->sum('total');
        }, $invoices_by_currency);

        $total_invoices_found = $invoices->count();

        $customers = Contact::customers()
            ->keyBy('id')
            ->all();

        $has_delete_access = false;
        if (has_access($user->roleid, 'sales', 'delete')) {
            $has_delete_access = true;
        }

        $invoice_groups = [];

        if(!empty($config['invoice_group']))
        {
            $invoice_groups = InvoiceGroup::all()->keyBy('id')->all();
        }

        $services = [];

        if(!empty($config['invoice_single_service']))
        {
            $services = Item::all()->keyBy('id')->all();
        }

        $staffs = User::all()->keyBy('id')->all();


        view('invoices_filter_result', [
            'invoices' => $invoices,
            'customers' => $customers,
            'has_delete_access' => $has_delete_access,
            'type' => $type,
            'invoice_groups' => $invoice_groups,
            'services' => $services,
            'staffs' => $staffs,
            'total_invoices_found' => $total_invoices_found,
            'total_by_currency' => $total_by_currency,
        ]);
        break;

    case 'mass-delete':
        if (!has_access($user->roleid, 'sales', 'all_data')) {
            permissionDenied();
        }
        if (!has_access($user->roleid, 'sales', 'delete')) {
            permissionDenied();
        }

        $data = request()->all();
        $ids = $data['invoice_ids'] ?? '';
        $ids = explode(',', $ids);
        foreach ($ids as $id) {
            $id = (int) $id;
            if ($id !== 0) {
                $invoice = Invoice::find($id);
                if ($invoice) {
                    InvoiceItem::where('invoiceid', $id)->delete();
                    $invoice->delete();
                }
            }
        }

        r2(U . 'invoices/list', 's', $_L['delete_successful']);

        break;

    case 'save-purchase-info':

        $data = request()->all();
        $invoice_id = (int) $data['invoice_id'];

        $invoice = Invoice::find($invoice_id);

        $purchase_cost = $data['purchase_cost'] ?? 0;
        $purchase_cost = (float) $purchase_cost;
        $staff_id = $data['staff_id'] ?? 0;
        $staff_id = (int) $staff_id;

        if ($invoice) {

            $invoice->purchase_id = $data['purchase_id'] ?? null;
            $invoice->purchase_date = (empty($data['purchase_date']) ? null : $data['purchase_date']);
            $invoice->purchase_cost = (empty($data['purchase_cost']) ? null : $data['purchase_cost']);
            $invoice->purchase_staff_id = $staff_id;
            $invoice->purchase_notes = $data['purchase_notes'] ?? null;
            $invoice->save();

            redirect_to('invoices/view/' . $invoice_id);

        }

        break;

        case 'save-shipping-info':

            $data = request()->all();
            $invoice_id = (int) $data['invoice_id'];

            $invoice = Invoice::find($invoice_id);

            $shipping_cost = $data['shipping_cost'] ?? 0;
            $shipping_cost = (float) $shipping_cost;

            if ($invoice) {

                $invoice->shipping_date = (empty($data['shipping_date']) ? null : $data['shipping_date']);
                $invoice->shipping_cost = (empty($data['shipping_cost']) ? null : $data['shipping_cost']);
                $invoice->shipping_weight = $data['shipping_weight'] ?? null;
                $invoice->shipping_notes = $data['shipping_notes'] ?? null;
                $invoice->save();

                redirect_to('invoices/view/' . $invoice_id);

            }

            break;

    default:
        echo 'action not defined';
}