<?php

namespace App\Http\Controllers\Accounts\Reports;

use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\Accounts\Item\Item;
use Illuminate\Support\Collection;
use App\Http\Controllers\Controller;
use Illuminate\Pagination\Paginator;
use App\Models\Accounts\Charthistory;
use App\Models\Accounts\Expense\Vendor;
use App\Models\Accounts\Income\Invoice;
use App\Models\Accounts\Banking\Account;
use App\Models\Accounts\Banking\Journal;
use App\Models\Accounts\Income\Customer;
use App\Models\Accounts\Income\InvoicePayment;
use App\Models\Accounts\Accounting\Chartofaccounts;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use DateTime;

class StandardReports extends Controller
{
    public $dateFilters;

    public function __construct()
    {
        $this->dateFilters = $this->getDateFilters();
    }

    public function index()
    {
        return view('accounts.reports.standard.index');
    }

    /*Business Overview Functions*/
        public function auditLog(Request $request)
        {
            if($request->date_type == 0){
                $list = Charthistory::get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Charthistory::whereBetween('created_at', $dates)->get();                
            }

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.business.audit-log', compact('list', 'dateFilters'));
        }

        /*Balance sheet Functions*/
            public function balanceSheetCompariosion(Request $request)
            {
                $accounts = Account::whereEnabled(1)->select('name', 'number', 'opening_balance')->get();
                    $invoicSum = Invoice::sum('amount');
                    $invoicePayments = InvoicePayment::sum('amount');
                $accountRecievables = $invoicSum - $invoicePayments;

                return view('accounts.reports.standard.business.balance-sheet-comparision');
            }

            public function balanceSheetDetails(Request $request)
            {
                if($request->date_type == 0){
                    $list = Chartofaccounts::with(['chartofhistory'])->whereIn('account_type_id', [1, 3])->whereEnabled(1)->get();
                }else{
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                    $list = Chartofaccounts::with(['chartofhistory'=>function($q) use($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->whereIn('account_type_id', [1, 3])->whereEnabled(1)->get();               
                }

                $data['assets'] = $list;

                if ($request->date_type == 0) {
                    $llist = Chartofaccounts::with(['chartofhistory'])->whereIn('account_type_id', [6, 8, 10])->whereEnabled(1)->get();
                } else {
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                    $llist = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->whereIn('account_type_id', [6, 8, 10])->whereEnabled(1)->get();
                }

                $data['liabilities'] = $llist;

                $data['dateFilters'] = $this->dateFilters;
                
                return view('accounts.reports.standard.business.balance-sheet-details', $data);
            }

            public function balanceSheet(Request $request)
            {
                if ($request->date_type == 0) {
                    $list = Chartofaccounts::with(['chartofhistory'])->whereIn('account_type_id', [1, 3])->whereEnabled(1)->get();
                } else {
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                    $list = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->whereIn('account_type_id', [1, 3])->whereEnabled(1)->get();
                }

                $data['assets'] = $list;

                if ($request->date_type == 0) {
                    $llist = Chartofaccounts::with(['chartofhistory'])->whereIn('account_type_id', [6, 8, 10])->whereEnabled(1)->get();
                } else {
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                    $llist = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->whereIn('account_type_id', [6, 8, 10])->whereEnabled(1)->get();
                }

                $data['liabilities'] = $llist;

                $data['dateFilters'] = $this->dateFilters;

                return view('accounts.reports.standard.business.balance-sheet', $data);
            }
        /*Balance sheet:- Ends*/

        /*Profit and Loss Functions Starts Here*/
            public function profitLoss(Request $request)
            {
                if ($request->date_type == 0) {
                    $incomes = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 11)->get();
                    $expenses = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 13)->get();
                } else {
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                    $incomes = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 11)->get();
                    $expenses = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->where('account_type_id', 13)->get();
                }
                $dateFilters = $this->dateFilters;

                return view('accounts.reports.standard.business.profit-loss-total-income', compact('incomes', 'expenses', 'dateFilters'));
            }

            public function profitLossDetails(Request $request)
            {
                if ($request->date_type == 0) {
                    $incomes = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 11)->get();
                    $expenses = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 13)->get();
                }else {
                    $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                    $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                    $incomes = Chartofaccounts::with(['chartofhistory'])->where('account_type_id', 11)->get();
                    $expenses = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                        $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                    }])->where('account_type_id', 13)->get();
                }

                $dateFilters = $this->dateFilters;

                return view('accounts.reports.standard.business.profit-loss-details', compact('incomes', 'expenses', 'dateFilters'));
            }
        /* Profit and loss:- Ends */

        public function statementCashFlows()
        {
            return view('accounts.reports.standard.business.statement-cash-flows');
        }
    /*Ends Here*/

    /*Who Owes You Functions*/
        public function accountsRecievables(Request $request)
        {
            if ($request->date_type == 0) {
                $data['invoices'] = Charthistory::with(['invoice'])->where('account_type_id', 1)->whereTransaction_type('Invoice')->get();
                $data['others'] = Charthistory::where('account_type_id', 1)->where('transaction_type', '!=', 'Invoice')->get();
            } else {
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $data['invoices'] = Charthistory::with(['invoice'])->whereBetween('created_at', $dates)->where('account_type_id', 1)->whereTransaction_type('Invoice')->get();
                $data['others'] = Charthistory::where('account_type_id', 1)->whereBetween('created_at', $dates)->where('transaction_type', '!=', 'Invoice')->get();                
            }

            $data['dateFilters'] = $this->dateFilters;

            return view('accounts.reports.standard.owes.accounts-recievables', $data);
        }

        public function accountsRecievableSummary()
        {            
            $thirty = [ Carbon::today()->subDays(30)->format('Y-m-d'),Carbon::today()->subDay()->format('Y-m-d')];
            $sixty = [ Carbon::today()->subDays(60)->format('Y-m-d'),Carbon::today()->subDays(31)->format('Y-m-d')];
            $ninty = [Carbon::today()->subDays(90)->format('Y-m-d'),Carbon::today()->subDays(61)->format('Y-m-d') ];
            $overninty = Carbon::today()->subDays(91)->format('Y-m-d');

            $customers = Customer::select('name', 'id', 'parent_id')->get();
            
            $all = [];

            foreach ($customers as $customer) {
                $customerSum['id'] = $customer->id;
                $customerSum['name'] = $customer->name;
                $customerSum['parent_id'] = $customer->parent_id;

                    $invoiceIds = Invoice::whereDate('due_at', '>=', date('Y-m-d'))->whereCustomer_id($customer->id)->pluck('id', 'amount')->all();
                    $ids = array_values($invoiceIds);
                    $invoiceSum = array_sum(array_keys($invoiceIds));
                    $paymentSum = InvoicePayment::whereIn('invoice_id', $ids)->sum('amount');
                    $customerSum['currentTotal'] = $invoiceSum - $paymentSum;
                 

                    $invoiceIds = Invoice::whereBetween('due_at', $thirty)->whereCustomer_id(2)->pluck('id', 'amount')->all();
                    $ids = array_values($invoiceIds);
                    $invoiceSum = array_sum(array_keys($invoiceIds));
                    $paymentSum = InvoicePayment::whereIn('invoice_id', $ids)->sum('amount');
                    $customerSum['thirtyTotal'] = $invoiceSum - $paymentSum;

                    $invoiceIds = Invoice::whereBetween('due_at', $sixty)->whereCustomer_id($customer->id)->pluck('id', 'amount')->all();
                    $ids = array_values($invoiceIds);
                    $invoiceSum = array_sum(array_keys($invoiceIds));
                    $paymentSum = InvoicePayment::whereIn('invoice_id', $ids)->sum('amount');
                    $customerSum['sixtyTotal'] = $invoiceSum - $paymentSum;

                    $invoiceIds = Invoice::whereBetween('due_at',$ninty)->whereCustomer_id($customer->id)->pluck('id', 'amount')->all();
                    $ids = array_values($invoiceIds);
                    $invoiceSum = array_sum(array_keys($invoiceIds));
                    $paymentSum = InvoicePayment::whereIn('invoice_id', $ids)->sum('amount');
                    $customerSum['nintyTotal'] = $invoiceSum - $paymentSum;

                    $invoiceIds = Invoice::whereDate('due_at', '<', $overninty)->whereCustomer_id($customer->id)->pluck('id', 'amount')->all();
                    $ids = array_values($invoiceIds);
                    $invoiceSum = array_sum(array_keys($invoiceIds));
                    $paymentSum = InvoicePayment::whereIn('invoice_id', $ids)->sum('amount');
                $customerSum['overNintyTotal'] = $invoiceSum - $paymentSum;

                array_push($all, $customerSum);
            }
         
              $items = $this->bulidCustomer($all);

            return view('accounts.reports.standard.owes.accounts-recievable-summary', compact('items') );
        }
        
        public function collectionsReports(Request $request)
        {
            if($request->date_type == 0){
                $date = $this->date_format_change_unique(date('Y-m-d'));
                
                $customers = Customer::with(['invoices' => function($q) use($date) {
                    $q->where('invoices.invoice_status_code', '!=', 'paid'); 
                }])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $customers = Customer::with(['invoices' => function($q) use($dates) {
                    $q->whereBetween('invoices.due_at', $dates);
                    $q->where('invoices.invoice_status_code', '!=', 'paid'); 
                }])->get();
            }                        

            $dateFilters = $this->dateFilters;
            
            return view('accounts.reports.standard.owes.collections-reports', compact('customers', 'dateFilters'));
        }
        
        public function customerBalanceSummary(Request $request)
        {
            if($request->date_type == 0){
                $customers = Customer::with(['invoices_total','payments_total'])->get()->toArray();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $customers = Customer::with(['invoices_total'=>function($q) use($dates) {
                    $q->whereBetween('invoices.created_at', $dates);
                },'payments_total'])->get()->toArray();
            }   

            $items = $this->bulidCustomer($customers);                       

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.owes.customer-balance-summary', compact('customers', 'items', 'dateFilters'));
        }

        public function invoiceList(Request $request)
        {
            if($request->date_type == 0){
                $list = Invoice::with(['payments_total'])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Invoice::with(['payments_total'])->whereBetween('invoiced_at', $dates)->get();
            }   
                                   
            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.owes.invoice-list', compact('list', 'dateFilters'));
        }

        public function invoiceRecievePayments(Request $request)
        {
            if($request->date_type == 0){
                $list = Customer::with(['invoices', 'invoices.payments'])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Customer::with(['invoices'=>function($q) use($dates) {
                    $q->whereBetween('invoices.created_at', $dates);
                }, 'invoices.payments'])->get();            
            }            

            $dateFilters = $this->dateFilters;
            
            return view('accounts.reports.standard.owes.invoice-recieve-payments', compact('list', 'dateFilters'));
        }

        public function openInvoices(Request $request)
        {
            if($request->date_type == 0){
                $list = Customer::with(['invoices'=>function($q) {
                        $q->where('invoice_status_code', '!=', 'paid');
                    }, 'invoices.payments_total'])->get(); 
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Customer::with(['invoices'=>function($q) use($dates) {
                    $q->where('invoice_status_code', '!=', 'paid');
                    $q->whereBetween('invoices.created_at', $dates);
                }, 'invoices.payments_total'])->get();         
            } 
            
            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.owes.open-invoices', compact('list', 'dateFilters'));
        }
    /*Ends Here*/

    /*Sales Customer Functions*/
        public function customerContactList(Request $request)
        {
            if($request->date_type == 0){
                $list = Customer::select('id', 'name', 'phone', 'customer_email', 'address', 'shipping_address', 'parent_id')->get()->toArray();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Customer::select('id', 'name', 'phone', 'customer_email', 'address', 'shipping_address', 'parent_id')->whereBetween('created_at', $dates)->get()->toArray(); 
            }                     
            
            $items = $this->bulidCustomer($list);

            $dateFilters = $this->dateFilters; 

            return view('accounts.reports.standard.sales-customer.customer-contact-list', compact('items', 'dateFilters'));
        }

        public function depositDetails(Request $request)
        {
            if($request->date_type == 0){
                $list = Chartofaccounts::with(['chartofhistory' => function ($q) {
                    $q->where('ac_chartofaccount_history.transaction_type', 'Deposite');
                }])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Chartofaccounts::with(['chartofhistory' => function ($q) use ($dates) {
                    $q->where('ac_chartofaccount_history.transaction_type', 'Deposite');
                    $q->whereBetween('ac_chartofaccount_history.created_at', $dates);
                }])->get();
            }  

            $dateFilters = $this->dateFilters;             

            return view('accounts.reports.standard.sales-customer.deposit-details', compact('list', 'dateFilters'));
        }

        public function producService(Request $request)
        {
            if($request->date_type == 0){
                $list = Item::select('name', 'source_type', 'description', 'sale_price')->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Item::select('name', 'source_type', 'description', 'sale_price')->whereBetween('created_at', $dates)->get();
            }  

            $dateFilters = $this->dateFilters;  
            
            $sourceTypes = ['0'=>'Inventory','1'=>'Non-Inventory','2'=>'Service','3'=>';Bundle'];

            return view('accounts.reports.standard.sales-customer.product-service', compact('list', 'sourceTypes', 'dateFilters'));
        }

        public function salesCustomerSummary(Request $request)
        {
            if($request->date_type == 0){
                $list = Customer::with('invoices_total')->get()->toArray();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Customer::with(['invoices_total'=>function($q) use($dates) {
                    $q->whereBetween('invoices.created_at', $dates);
                }])->get()->toArray();
            }  

            $dateFilters = $this->dateFilters;

            $items = $this->bulidCustomer($list);

            return view('accounts.reports.standard.sales-customer.sales-customer-summary', compact('items', 'dateFilters'));
        }

        public function salesCustomerSummaryDetail(Request $request)
        {
            if($request->date_type == 0){
                $list = Customer::with('invoices_total')->get()->toArray();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];
                $list = Customer::with(['invoices_total'=>function($q) use($dates) {
                    $q->whereBetween('invoices.created_at', $dates);
                }])->get()->toArray();
            }  

            $dateFilters = $this->dateFilters;

            $items = $this->bulidCustomer($list);

            return view('accounts.reports.standard.sales-customer.sales-customer-summary-details', compact('items', 'dateFilters'));
        }

        public function salesProductSummary(Request $request)
        {
            if($request->date_type == 0){
                $list = Item::get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Item::whereBetween('created_at', $dates)->get();
            }

            $ttl = [];

            foreach ($list as $value) {
                array_push($ttl, $value->quantitysum * $value->sale_price);
            }

            $total = array_sum($ttl); 

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.sales-customer.sales-product-summary', compact('list', 'total', 'dateFilters'));
        }
    /*Ends Here*/

    /*Expenses and Vendors Functions*/

        public function checkDetails(Request $request)
        {
            if($request->date_type == 0){
                $list = Chartofaccounts::with(['chartofhistory'=>function($q) {
                    $q->where('transaction_type', 'Cheques');
                }])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Chartofaccounts::with(['chartofhistory'=>function($q) use($dates) {
                    $q->whereBetween('created_at', $dates);
                    $q->where('transaction_type', 'Cheques');
                }])->get();
            }

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.expenses-vendors.check-details', compact('list', 'dateFilters'));
        }

        public function transactionVendor(Request $request)
        {
            if($request->date_type == 0){
                $list = Vendor::with(['transactions'])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Vendor::with(['transactions'=>function($q) use($dates) {
                    $q->whereBetween('created_at', $dates);
                }])->get();
            }

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.expenses-vendors.transaction-vendor', compact('list', 'dateFilters'));
        }

        public function vendorContactList(Request $request)
        {
            if($request->date_type == 0){
                $list = Vendor::get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Vendor::whereBetween('created_at', $dates)->get();
            }

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.expenses-vendors.vendor-contact-list', compact('list', 'dateFilters'));
        }
    /*Ends Here*/

    /*Accountant Functions*/
        public function accountList(Request $request)
        {
            if($request->date_type == 0){
                $list = Account::get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $list = Account::whereBetween('created_at', $dates)->get();
            }

            $dateFilters = $this->dateFilters;

            return view('accounts.reports.standard.accountant.account-list', compact('list', 'dateFilters'));
        }

        public function generalLedger(Request $request)
        {
            if($request->date_type == 0){
                $lists = Chartofaccounts::with(['chartofhistory'])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $lists = Chartofaccounts::with(['chartofhistory'=>function($q) use($dates) {
                    $q->whereBetween('created_at', $dates);
                }])->get();
            }

            $dateFilters = $this->dateFilters;
            return view('accounts.reports.standard.accountant.general-ledger', compact('lists', 'dateFilters'));
        }

        public function journal(Request $request)
        {
            if($request->date_type == 0){
                $lists = Journal::with(['items'])->get();
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $lists = Journal::with(['items'])->whereBetween('journal_date', $dates)->get();
            }

            $dateFilters = $this->dateFilters;
            return view('accounts.reports.standard.accountant.journal', compact('lists', 'dateFilters'));
        }

        public function reconciliationReports()
        {
            return view('accounts.reports.standard.accountant.reconciliation-reports');
        }

        public function transactionDate(Request $request)
        {
            if($request->date_type == 0){
                $lists = Charthistory::with(['account'])->get()->groupBy('transaction_type');
            }else{
                $date = $this->date_format_change_unique($request->from_date, $request->to_date);
                $dates = [date('Y-m-d', strtotime($date[0])), date('Y-m-d', strtotime($date[1]))];

                $lists = Charthistory::with(['account'])->whereBetween('created_at', $dates)->get()->groupBy('transaction_type');
            }

            $dateFilters = $this->dateFilters;
            return view('accounts.reports.standard.accountant.transaction-date', compact('dateFilters', 'lists'));
        }

        public function trialBalance(Request $request)
        {
            $list = Chartofaccounts::get();
            $creditTypes = config('accounts.credit_types'); // (DEBIT  =+ && CREDIT =-)
            $debitTypes =  config('accounts.debit_types'); // (DEBIT =- && CREDIT=+)

            return view('accounts.reports.standard.accountant.trial-balance', compact('list', 'creditTypes', 'debitTypes'));
        }
    /*Reports Ends Here*/

    /*Payroll Functions*/
        public function payrollEmployeeContacts()
        {
            return view('accounts.reports.standard.payroll.employee-contacts');
        }
    /*Ends Here*/
    
    function bulidCustomer(array $elements, $parentId = NULL) {

            $child = array();
        
            foreach ($elements as $element) {
                if ($element['parent_id'] == $parentId) {

                    $children = $this->bulidCustomer($elements, $element['id']);

                        if (!empty($children) > 0 ) {
                            $element['children'] = $children;
                        }

                    $child[] = $element;
                }
            }

        return $child;
    }

        /**
     * Generate a pagination collection.
     *
     * @param array|Collection      $items
     * @param int   $perPage
     * @param int   $page
     * @param array $options
     *
     * @return LengthAwarePaginator
     */
    public function paginate($items, $perPage = 25, $page = null, $options = [])
    {
        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);

        $items = $items instanceof Collection ? $items : Collection::make($items);

        return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
    }

    /**
     * Getting Dates for Dropdown
     */
    function getDateFilters()
    {
        $today = Carbon::today()->format('Y-m-d').' '.Carbon::today()->format('Y-m-d');

        $yesterday = Carbon::yesterday()->format('Y-m-d').' '.Carbon::yesterday()->format('Y-m-d');

        $thisWeek = $this->firstDayOf('week').' '.$this->lastDayOf('week');

        $thisMonth = $this->firstDayOf('month').' '.$this->lastDayOf('month');

        $thisQuarter = $this->firstDayOf('quarter').' '.$this->lastDayOf('quarter');

        $thisYear = $this->firstDayOf('year').' '.$this->lastDayOf('year');

        $nw = date_sub(new DateTime($this->firstDayOf('week')), date_interval_create_from_date_string("1 days"));
        $lastWeek = $this->firstDayOf('week', $nw).' '.$this->lastDayOf('week', $nw);

        $nm = date_sub(new DateTime($this->firstDayOf('month')), date_interval_create_from_date_string("1 days"));
        $lastMonth = $this->firstDayOf('month', $nm).' '.$this->lastDayOf('month', $nm);

        $nq = date_sub(new DateTime($this->firstDayOf('quarter')), date_interval_create_from_date_string("1 days"));
        $lastQuarter = $this->firstDayOf('quarter', $nq).' '.$this->lastDayOf('quarter', $nq);

        $ny = date_sub(new DateTime($this->firstDayOf('year')), date_interval_create_from_date_string("1 days"));
        $latsYear = $this->firstDayOf('year', $ny).' '.$this->lastDayOf('year', $ny);

        $dateFilters = [
            ''=>'Select', 
            0=>'All Dates', 
            1=>'Custom', 
            $today=>'Today', 
            $yesterday=>'Yesterday', 
            $thisWeek=>'This Week', 
            $thisMonth=>'This Month', 
            $thisQuarter=>'This Quarter', 
            $thisYear=>'This Year', 
            $lastWeek=>'Last Week', 
            $lastMonth=>'Last Month', 
            $lastQuarter=>'Last Quarter', 
            $latsYear=>'Last Year'
        ];

        return $dateFilters;
    }

    /**
     * Return the first day of the Week/Month/Quarter/Year that the
     * current/provided date falls within
     *
     * @param string   $period The period to find the first day of. ('year', 'quarter', 'month', 'week')
     * @param DateTime $date   The date to use instead of the current date
     *
     * @return DateTime
     * @throws InvalidArgumentException
     */
    function firstDayOf($period, DateTime $date = null)
    {
        $period = strtolower($period);
        $validPeriods = array('year', 'quarter', 'month', 'week');

        if ( ! in_array($period, $validPeriods))
            throw new InvalidArgumentException('Period must be one of: ' . implode(', ', $validPeriods));

        $newDate = ($date === null) ? new DateTime() : clone $date;

        switch ($period) {
            case 'year':
                $newDate->modify('first day of january ' . $newDate->format('Y'));
                break;
            case 'quarter':
                $month = $newDate->format('n') ;

                if ($month < 4) {
                    $newDate->modify('first day of january ' . $newDate->format('Y'));
                } elseif ($month > 3 && $month < 7) {
                    $newDate->modify('first day of april ' . $newDate->format('Y'));
                } elseif ($month > 6 && $month < 10) {
                    $newDate->modify('first day of july ' . $newDate->format('Y'));
                } elseif ($month > 9) {
                    $newDate->modify('first day of october ' . $newDate->format('Y'));
                }
                break;
            case 'month':
                $newDate->modify('first day of this month');
                break;
            case 'week':
                $newDate->modify(($newDate->format('w') === '0') ? 'monday last week' : 'monday this week');
                break;
        }

        return $newDate->format('Y-m-d');
    }

    /**
     * Return the last day of the Week/Month/Quarter/Year that the
     * current/provided date falls within
     *
     * @param string   $period The period to find the last day of. ('year', 'quarter', 'month', 'week')
     * @param DateTime $date   The date to use instead of the current date
     *
     * @return DateTime
     * @throws InvalidArgumentException
     */
    function lastDayOf($period, DateTime $date = null)
    {
        $period = strtolower($period);
        $validPeriods = array('year', 'quarter', 'month', 'week');

        if ( ! in_array($period, $validPeriods))
            throw new InvalidArgumentException('Period must be one of: ' . implode(', ', $validPeriods));

        $newDate = ($date === null) ? new DateTime() : clone $date;

        switch ($period)
        {
            case 'year':
                $newDate->modify('last day of december ' . $newDate->format('Y'));
                break;
            case 'quarter':
                $month = $newDate->format('n') ;

                if ($month < 4) {
                    $newDate->modify('last day of march ' . $newDate->format('Y'));
                } elseif ($month > 3 && $month < 7) {
                    $newDate->modify('last day of june ' . $newDate->format('Y'));
                } elseif ($month > 6 && $month < 10) {
                    $newDate->modify('last day of september ' . $newDate->format('Y'));
                } elseif ($month > 9) {
                    $newDate->modify('last day of december ' . $newDate->format('Y'));
                }
                break;
            case 'month':
                $newDate->modify('last day of this month');
                break;
            case 'week':
                $newDate->modify(($newDate->format('w') === '0') ? 'now' : 'sunday this week');
                break;
        }

        return $newDate->format('Y-m-d');
    }
}
